Rust Bitcoin Solo Mining Pool
Stratum V1 + V2 · PWA Operator UI · 1021 Tests · Reproducible Builds
dvb-WarpPool is a from-scratch Rust solo Bitcoin mining pool. The block reward flows directly to your wallet via the coinbase — the pool never holds, forwards, or aggregates your sats. No accounts, no custody, no settlement: when your miners find a block, the reward is yours the moment Bitcoin Core accepts it.
Built for self-hosted operators on hardware ranging from a Raspberry Pi 5 to a Ryzen 7 server. Single binary that runs alongside your own Bitcoin Node, exposes a modern PWA admin cockpit, and ships with end-to-end signed, reproducible builds.
Dashboard — live pool stats, energy + solar surplus, hashrate chart.
More screenshots (hashrate, overview, workers, hardware detection, miner telemetry, admin)

Hashrate — 1-minute buckets with best-share overlay.

Workers + best-shares leaderboard.

Hardware detection — auto-recommends Small / Medium / Large / Enterprise profile.

Profile comparison — connection cap, RAM target, VarDiff, retention windows.

Miners — live vendor telemetry (temp / power / fan / hashrate).

Devices — registered miners with discovery via mDNS.

Admin → Profile — hot-switch Small / Medium / Large / Enterprise + electricity tariff.

Admin → Uninstall — cross-platform uninstall preview with optional Bitcoin Core + blockchain (new in v1.0.10).
- Stratum V1 (plain + TLS 1.3) listener with persisted EMA-smoothed VarDiff — per-worker difficulty is restored across reconnects and restarts.
- Stratum V2 server (NOISE_NX encrypted handshake) with both extended and standard channels. Real per-channel Merkle root, full PoW check, and a working block-submit path on both V1 and Sv2.
- V1↔V2 translator sidecar — legacy V1 miners can talk to V2 pools and vice-versa, with BIP-320 version-rolling.
getblocktemplate+ ZMQhashblockfor low-latency job refresh: fresh templates go out within milliseconds of Bitcoin Core seeing a new tip.- Coinbase construction with optional pool-fee and operator-donation splits. Default: 100 % to the miner address.
- Standards-compliant block construction: BIP-34 coinbase height, SegWit
witness commitment, and BIP-310 version-rolling (overt ASICBoost) — plus a
BIP-54-forward-compatible coinbase locktime (
nLockTime = height − 1,nSequence ≠ 0xffffffff): Consensus-Cleanup-ready ahead of activation, and valid under today's rules (verified end-to-end against a real regtest block). - Network-aware: regtest, signet, testnet4, mainnet —
getblocktemplaterules switch automatically (thesignetrule is added on signet; a real source of "no template" bugs we ran into and fixed).
- Live Server-Sent Events stream for hashrate, blocks-found, share rate, miner status — no polling, no page reloads.
- Hashrate charts with 24-hour smoothing, per-record best-share dots on a dedicated difficulty axis, top-3 worker medals, per-worker breakdown including coinbase-decoder for the current job.
- i18n (8 languages: EN, DE, ES, FR, IT, JA, PT-BR, ZH) with locale
auto-detect + manual switcher, persisted in
localStorage. - Admin cockpit: profile hot-switch, notifier test-fires, audit-log viewer, API-token CRUD, 2FA setup with QR code, retention/eviction config.
- Mobile-first responsive design — installable as a PWA, with service worker
- Web-Push subscriptions.
- Full-screen screensaver for wall / kiosk displays — idle-triggered
looping splash video with a live stat bar (best share, hashrate, miners,
blocks, version/update). Configurable per device (idle timeout 5/10/15/30 min,
off by default); respects
prefers-reduced-motion.
- Argon2id password hashing + JWT session cookie (
HttpOnly, optionalSecureflag behind TLS). - API tokens with sha256-only storage (cleartext shown once on creation), per-token scopes, optional expiry.
- 2FA TOTP (RFC 6238) with ±1 step skew and one-shot reuse prevention.
- Audit log for every admin action (login, token-create / revoke, profile-switch, update-applied), filterable per actor.
- HTTP login throttle with constant-time response (no user enumeration).
- Stratum DoS hardening: line cap (16 KiB), pre-auth handshake timeout,
dedup-set bound, Sv2 connection cap +
read_bufcap. - Web Push receivers go through an SSRF guard (private / loopback / link-local / CGNAT / localhost are blocked) plus a DNS-rebinding resolve check.
- SQLite DB + data directory locked down with restrictive POSIX permissions (0600 / 0700, unix-gated).
- Setup wizard refuses to overwrite an existing
secrets.toml. - Full security-audit pass on v1.0 (5 attack surfaces, double-verified) — see docs/SECURITY.md for the threat-mitigation matrix.
Block-found, share-spike, anomaly and admin events fan out to any combination of sinks:
- ntfy (push) · Telegram · Discord · Slack (incoming webhooks)
- Email (SMTP with STARTTLS) · VAPID Web Push to the PWA
- (APNs scaffold present in
crates/notifier/for an iOS sidecar)
Every sink is independently configurable, individually testable from the UI
(notifier-test ntfy|telegram|…|all), and rate-limited per sink.
- Auto-detects CPU / RAM / NVMe / SATA at startup and recommends an admin
profile: Small, Medium, Large, or Enterprise (config ids:
klein/mittel/gross/enterprise; the UI shows localized names). - Each profile maps to a coherent set of runtime parameters: connection cap, share-validation Rayon pool size, retention windows, network-probe cadence.
- Hot-switch at runtime via the admin cockpit — V1 and V2 connection caps resize live, no restart needed.
- Vendor probes for AxeOS / NerdNOS / BitMain / Whatsminer / AvalonQ / BraiinsOS miners surface temps, fan, hashrate, last-share-age in the UI.
- Vendor-aware VarDiff: the
user_agentpicks a per-class starting difficulty and target interval — from Antminer-class ASICs down to a NerdMiner V2 ESP32 (~250 KH/s), which uses sub-1 difficulty so it still submits a share roughly every 30 seconds instead of once an hour. Miner requests are honored too:suggest_difficultyseeds the session,d=<x>in the password pins it (both class-clamped), and an idle decay walks quiet workers back down instead of stranding them. - mDNS-based LAN discovery rounds out the picture: new miners on the subnet show up automatically.
- Real-time electricity-tariff integration (incl. solar-surplus signal via Home Assistant) — the admin UI shows running cost and net margin.
- Health-anomaly detection: peer-count, ZMQ-hashblock lag,
share-acceptance rate, vendor-probe failures — each surfaces in
/healthzand as warnings in the UI. - First-run setup wizard with Bitcoin Core health probes (RPC,
ZMQ
hashblock, ZMQrawblock) and optional UPnP port forwarding.
dvb-warppool-cli check-update+download-updatefor the manual workflow.- Daemon-side
/api/admin/update-check+/api/admin/updatewith optional server-side Cosign verification ofSHA256SUMS. - Periodic background check (configurable cadence, default 24 h) emits an
update_availableSSE event — the UI shows a banner without operator polling. - Atomic swap (
<target>.new→ POSIX rename →<target>), optional backup of the old binary, systemdOnFailurerollback hook.
- Cosign keyless OIDC signatures on
SHA256SUMS(verifiable against the workflow-URL identity — no key rotation drama). - SLSA Level 3 provenance via
slsa-github-generator, attached to every GitHub release. - SBOM (SPDX) generated per release via
anchore/sbom-action. - Reproducible builds — same input → byte-identical output, verifiable
via
scripts/verify-reproducible.sh. - Multi-arch Docker image on
ghcr.io/dvb-projekt/dvb-warppool(linux/amd64 + linux/arm64). - Native installers across all major platforms (see Install).
A self-hosted solo pool usually comes down to four open-source options. Short version below; the full, source-verified table (with a fair "when the others are the better pick" section) lives in the Comparison handbook page.
| WarpPool | ckpool | public-pool | mkpool | |
|---|---|---|---|---|
| Coins | BTC | BTC | BTC | 9 chains |
| Mainnet track record | not yet | since 2014 | yes | live |
| Stratum V2 (2024 spec) | ✅ | ❌ | ✅ | |
| TLS for miners | ✅ | ❌ | ❌ | ✅ |
| Operator Web UI / API | ✅ PWA, 8 langs | ❌ | ✅ | ❌ engine only |
| Device telemetry + energy | ✅ | ❌ | ❌ | ❌ |
| Multi-node failover | ✅ | ✅ | ❌ | ❌ |
| Difficulty persistence (reconnect + restart) | ✅ | ❌ | ❌ | ❌ |
| Tests gating CI | ✅ 1021 | ❌ | ❌ | ❌ |
| Signed + reproducible releases | ✅ | ❌ | ❌ | ❌ |
| License | AGPLv3 + commercial | GPLv3 | GPLv3 | GPLv3 |
mkpool is the other modern engine — multi-coin and already on mainnet; WarpPool trades multi-coin for a full operator experience (UI, telemetry, energy, signed packages) on Bitcoin.
| Platform | How |
|---|---|
| Umbrel | Add the DVB Projekt Community App Store → install dvb-WarpPool. |
| Docker | docker pull ghcr.io/dvb-projekt/dvb-warppool:1.12.2 (multi-arch amd64 + arm64). |
| Debian / Ubuntu | Download .deb from the releases page → sudo apt install ./dvb-warppool_*.deb. |
| Fedora / RHEL | Download .rpm → sudo dnf install ./dvb-warppool-*.rpm. |
| Linux (other) | .AppImage for x86_64 and aarch64. |
| macOS | .dmg for Apple Silicon and Intel — see macOS install notes below. |
| Windows | .msi for x64 (unsigned for now — SmartScreen warning is expected). |
| From source | See Build from source below. |
Every release artifact ships with SHA256SUMS + a Cosign keyless OIDC
signature and a SLSA 3 provenance attestation — see docs/PACKAGING.md
for the verification recipes.
On first start the daemon serves a one-page setup wizard on the app port until your config is saved (8 languages, auto-detected):
| Part 1 — hardware, mining, location, electricity | Part 2 — PV, Bitcoin Core detection, live checks |
|---|---|
![]() |
![]() |
Hardware detection picks a profile recommendation; payout address,
expected miners, pool fee, server location and electricity tariff follow.
The Bitcoin Core card probes RPC + ZMQ live and offers one-click
bitcoin.conf recommendations. The shots show the macOS variant (local
bitcoind auto-detected, sleep-prevention card) — on Umbrel/Docker the
Bitcoin fields come pre-filled from the container environment instead.
The .dmg is not yet signed with an Apple Developer ID. Without that
signature macOS Gatekeeper refuses to verify the bundle and shows the
misleading dialog "dvb-WarpPool is damaged and can't be opened".
The app itself is fine — Gatekeeper is reacting to the com.apple.quarantine
extended attribute that Safari (and any browser) attaches to downloads.
One-line install (recommended):
-
Download
dvb-WarpPool-v1.12.2-aarch64.dmg(Apple Silicon) or…-x86_64.dmg(Intel) from the releases page. -
Run:
curl -fsSL https://raw.githubusercontent.com/dvb-projekt/dvb-WarpPool/main/scripts/macos-install.sh \ | bash
That downloads + runs scripts/macos-install.sh,
which auto-picks the newest dvb-WarpPool-v*.dmg from ~/Downloads/,
strips the quarantine attribute, copies the .app into /Applications/,
re-registers it with LaunchServices, and unmounts the disk image. After
it finishes, double-click the app in /Applications or run
open /Applications/dvb-WarpPool.app.
Manual fallback, if you prefer to read what's happening:
# 1. Strip quarantine from the downloaded .dmg
xattr -dr com.apple.quarantine ~/Downloads/dvb-WarpPool-v*.dmg
# 2. Open the .dmg + drag dvb-WarpPool.app into /Applications via Finder
# 3. Strip quarantine from the installed .app too
xattr -dr com.apple.quarantine /Applications/dvb-WarpPool.app
# 4. Open
open /Applications/dvb-WarpPool.appApple Developer ID signing + notarization is on the roadmap (Phase B) — once that ships, the workaround disappears.
Sleep prevention. The Mac launcher automatically prevents system sleep
while the daemon is running (via macOS caffeinate). Without it, the
default 3h idle timeout would suspend Bitcoin Core overnight, RPC calls
fail, and the hashrate graph drops to 0. Display sleep keeps working — you
can let the screen go dark. Visible status: green info card on the admin
profile page ("✓ macOS sleep mode disabled").
| Platform | Architecture | Max profile¹ |
|---|---|---|
| Umbrel Home (16 GB) | x86_64 | Enterprise¹ |
| Umbrel Pro (16 GB) | x86_64 | Enterprise¹ |
| macOS (Apple Silicon, 8 + cores) | aarch64 | Enterprise¹ |
| macOS (Intel, 8 + cores) | x86_64 | Enterprise¹ |
| Raspberry Pi 5 (16 GB, 4 cores) | aarch64 | Large¹ (cores cap, not RAM) |
| Raspberry Pi 5 (8 GB, 4 cores) | aarch64 | Large¹ (NVMe HAT recommended) |
| Raspberry Pi 4 (4 GB, 4 cores) | aarch64 | Large¹ (Pi 5 + NVMe HAT preferred) |
| Docker multi-arch | amd64 + arm64 | depends on host |
¹ Max profile = the hardware ceiling, not the profile you must run.
The profile primarily scales pool resource allocations (connection cap,
RAM target, Tokio thread pools, share-validator parallelism, retention
windows) — see the Profile-Comparison table on /hardware for the
concrete per-tier numbers. Solo and Solo + Friends setups happily run
at Small or Medium on any of the platforms above. The higher
tiers (Large, Enterprise) are designed for community-pool and
public-pool scenarios and need commercial extensions that are not
part of the OSS scope — reverse-proxy with per-IP rate-limit, payout
engine, multi-admin RBAC, DDoS mitigation, T&C / privacy templates,
SLA support. See docs/scaling.md for the tier
matrix.
The hardware ceiling itself is computed by crates/hwdetect
from RAM + logical-core count:
| Ceiling | RAM | Logical cores |
|---|---|---|
| Enterprise | ≥ 8 GB | ≥ 8 |
| Large | ≥ 2 GB | ≥ 4 |
| Medium | ≥ 512 MB | ≥ 2 |
| Small | < 512 MB or < 2 cores | — |
Full install guide + storage recommendations (NVMe HAT for Pi): see docs/PACKAGING.md.
The OSS stack is ready for a small TLS-secured pool where 5-10 trusted friends point their miners at your home setup over the internet. You need:
- A free DuckDNS subdomain (1 min signup)
- Router port-forward for
:3334(TCP, 3 min) - A real Let's Encrypt certificate — fetched automatically by the bundled setup script
./scripts/setup-tls-public.shThe script installs acme.sh, issues the cert via DNS-01 challenge, drops it
into the right place, and sets up 60-day auto-renewal. After a daemon
restart, friends point their miners at <yoursubdomain>.duckdns.org:3334
with "TLS: Enabled (Bundled CA)" and they're in.
Full step-by-step guide: docs/solo-friends-setup.md (deutsche Version: docs/solo-friends-setup-de.md)
For larger deployments (community pool, public service) see docs/scaling.md — those tiers need extensions that are available as a commercial service via a GitHub issue.
dvb-WarpPool/
├── crates/
│ ├── profiles/ # Small/Medium/Large/Enterprise resource tuning
│ ├── config/ # TOML schema (ported from dvb-gopool)
│ ├── hwdetect/ # Hardware detection + profile auto-recommendation
│ ├── stratum-v1/ # Stratum V1 + TLS listener + VarDiff + rate limit
│ ├── stratum-v2/ # Stratum V2 (NOISE_NX) server + client + sessions
│ ├── translator/ # V1 ↔ V2 translator proxy (extended channels)
│ ├── bitcoin-rpc/ # Bitcoin Core JSON-RPC + ZMQ
│ ├── job-builder/ # Block template → Stratum job
│ ├── share-validator/ # SHA256d share check (parallel)
│ ├── storage/ # SQLite + tiered retention + audit log
│ ├── api/ # Axum HTTP + SSE + auth (JWT, 2FA, API tokens)
│ ├── telemetry/ # Prometheus + miner vendor APIs
│ ├── notifier/ # ntfy/Telegram/Discord/APNs/SMTP
│ ├── health/ # Bitcoin Core health checks + anomaly detection
│ ├── autoupdate/ # Self-update: release-asset check + download/swap
│ ├── uninstall/ # Cross-platform uninstall helper
│ └── simulator/ # Sim miner, sim node, sim failures
├── apps/
│ ├── dvb-warppool-daemon/ # Main pool binary (V1+V2 hostable in parallel)
│ ├── dvb-warppool-cli/ # Admin CLI
│ ├── dvb-warppool-sim/ # Test-simulator CLI
│ ├── dvb-warppool-setup/ # First-run setup wizard
│ ├── dvb-warppool-translator/ # V1↔V2 translation-proxy sidecar
│ └── dvb-warppool-mac-launcher/ # macOS app-bundle launcher (caffeinate + supervision)
├── ui/ # SvelteKit PWA
└── docs/ # ARCHITECTURE.md, SECURITY.md, TESTING.md
cargo build --release
cargo test --workspace
cargo run --bin dvb-warppool-daemon -- --config packaging/etc/config.example.toml
cargo run --bin dvb-warppool-sim -- scenario solo-block-foundBuild artifacts land in ~/.cache/dvb-WarpPool/target (outside iCloud, see .cargo/config.toml).
The full documentation (Architecture / Getting Started / Packaging / Security / Sv2 phase history / Roadmap) is published via mdBook:
- Online: dvb-projekt.github.io/dvb-WarpPool (auto-deploy via .github/workflows/docs.yml)
- Source: docs/book/ — Markdown under
docs/book/src/ - Build locally:
mdbook build docs/book && open docs/book/out/index.html
dvb-WarpPool is dual-licensed:
- Open source — AGPL-3.0-or-later. Use, modify, and self-host it freely. The AGPL's copyleft (including its network-use clause) means that if you run a modified version as a network service, you must offer your users the corresponding source. Running it unmodified, or self-hosting privately, or publishing your changes under the AGPL, needs nothing further.
- Commercial license. If the AGPL doesn't fit your deployment — e.g. running a closed-source modified pool as a service, or bundling WarpPool into a proprietary product — a commercial license is available. See COMMERCIAL-LICENSE.md, contact dvbprojekt@gmx.de.
Releases up to and including v1.5.0 were published under MIT OR Apache-2.0
and remain available under those terms; the AGPL applies from the following
commit onward.
Unless you state otherwise, any contribution you intentionally submit for inclusion in this work is licensed under AGPL-3.0-or-later, and you grant DVB-Projekt the right to also distribute it under the commercial license above, so the dual-licensing model can be maintained. See CONTRIBUTING.md.




