Architektur

dvb-WarpPool ist ein Rust-Workspace mit 16 Library-Crates + 6 Binaries. Eine klare Schichtung — von puren Schema-Crates ohne async unten bis zu den async-orchestrierten Binaries oben — macht das System gut testbar und ermöglicht Sub-Crates separat zu betreiben (z.B. der Translator als sidecar ohne Pool-Daemon).

Crate-Übersicht

Schema + Foundation (ohne Async)

CrateWas
warppool-profilesAdmin-Profile (Klein/Mittel/Gross/Enterprise) — capacity + defaults
warppool-configTOML-Schema (PoolConfig + Sub-Configs + Secrets)
warppool-hwdetectHardware-Detection via sysinfo → Profile-Empfehlung

Core Mining-Layer

CrateWas
warppool-bitcoin-rpcJSON-RPC + ZMQ-Subscribe für Bitcoin Core
warppool-job-builderCoinbase-Tx + Merkle-Tree + Stratum-Job-Konstruktion
warppool-share-validatorShare-PoW-Check + Block-Found-Detection
warppool-stratum-v1TCP-Listener, Session-State-Machine, VarDiff
warppool-stratum-v2NOISE-NX-Handshake, binary-framing, Mining-Subprotocol
warppool-translatorV1↔V2-Sidecar (Pool kann nur Sv2 anbieten, V1-Miner via Translator)

Storage + API

CrateWas
warppool-storageSQLite via sqlx, alle Tabellen + Migrations
warppool-apiAxum-HTTP-API (REST + SSE-Stream + statisches UI-serving)

Operationale Subsysteme

CrateWas
warppool-healthBitcoin-Core-Multi-RPC-Health + bitcoin.conf-Parser + Snippet-Generator
warppool-autoupdateVersion-Parser + GitHub-Release-Client + atomic_swap + Cosign-Hook
warppool-notifierPush-Sinks (ntfy/Telegram/Discord/Slack/Email) + Counter-Metrics
warppool-telemetryVendor-API-Probes (AxeOS, NerdNOS, ...) + mDNS-Discovery + PoolMetrics

Tools

CrateWas
warppool-simulatorSim-Miner (Vendor-Personas) + Sim-Node + Scenarios

Binaries

BinaryZweck
dvb-warppool-daemonDer Pool — orchestriert alle Subsysteme
dvb-warppool-cliOperator-Tools (hash-password, token-create, set-profile, check-update, ...)
dvb-warppool-setupFirst-Run-Wizard (Axum, Modern-UI, embedded HTML)
dvb-warppool-translatorV1→V2 Sidecar (clap-CLI, kann als systemd-service laufen)
dvb-warppool-simSimulations-Runner (scenario list / run)

Datenfluss (Happy Path)

                            +---------------------+
                            | Bitcoin Core        |
                            | (mainnet / regtest) |
                            +---------------------+
                              | RPC          | ZMQ pub
                              v              v
                            +---------------------+
                            | bitcoin-rpc         |
                            |  - getblocktemplate  |
                            |  - submitblock       |
                            |  - hashblock watch   |
                            +---------------------+
                                   |
                                   v
                            +---------------------+
                            | job-builder         |
                            |  - coinbase splits  |
                            |  - merkle tree      |
                            |  - StratumJob       |
                            +---------------------+
                                   |
                       +-----------+-----------+
                       v                       v
              +------------------+   +------------------+
              | stratum-v1       |   | stratum-v2       |
              |  TCP / TCP+TLS   |   |  TCP+NOISE-NX    |
              +------------------+   +------------------+
                       |                       |
                       v                       v
               V1 Miner (Bitaxe,       V2 Miner / Translator
               NerdNOS, AntminerS23)
                       |                       |
                       v                       v
                      submit (extranonce, nonce, ntime)
                                   |
                                   v
                            +---------------------+
                            | share-validator     |
                            |  - PoW check        |
                            |  - block detection  |
                            +---------------------+
                                   |
                       +-----------+-----------+
                       v                       v
              +------------------+   +------------------+
              | storage          |   | block-submit-loop|
              |  - record_share  |   |  - assemble block|
              |  - vardiff_state |   |  - submitblock   |
              +------------------+   +------------------+
                                              |
                                              v on success
                            +---------------------+
                            | notifier            |
                            |  fire BlockFound    |
                            +---------------------+
                              |    |    |    |    |
                              v    v    v    v    v
                            ntfy tg disc slack email

Daemon-Task-Topologie

dvb-warppool-daemon ist ein Tokio-Multi-Reactor mit ~10 langlebigen Tasks plus pro-Verbindung-Tasks. Alle Tasks teilen sich einen CancellationToken für graceful shutdown.

                  +------- main() async -------+
                  |                            |
                  +- spawn ---------+----------+
                          |         |
                  +-------+-------+ +------------------+
                  | Stratum-V1     | Stratum-V2        |
                  | accept-loop    | accept-loop       |
                  | (+ TLS)        | (+ NOISE-NX)      |
                  +----------------+ +-----------------+
                          |               |
                  pro Connection: Session-Task
                          |               |
                          v               v
                  +---------------------------------+
                  | block_found_tx broadcast        |
                  +---------------------------------+
                          |
                  +-------+--------+
                  | block_submit_  |
                  | loop           |
                  +----------------+
                          |
                  Bitcoin Core RPC submitblock
                          |
                  +-------+--------+
                  | notifier.notify(BlockFound)     |

                  +- spawn ---------+----------+
                  | job_refresh_loop                |
                  |  - poll getblocktemplate (60s)  |
                  |  - ZMQ hashblock fast-path      |
                  |  - drain & build job            |
                  |  - push to stratum handles      |
                  +---------------------------------+

                  +- spawn ---------+----------+
                  | aggregate_loop (60s tick)       |
                  |  - storage.aggregate_5min       |
                  |  - SharesAccepted SSE event     |
                  +---------------------------------+

                  +- spawn ---------+----------+
                  | health_check_loop (60s tick)    |
                  |  - check_bitcoin_health         |
                  |  - SSE HealthSnapshot           |
                  |  - RpcDown/Recovered notify     |
                  +---------------------------------+

                  +- spawn ---------+----------+
                  | periodic_update_check (24h)     |
                  |  - GitHub Releases API          |
                  |  - SSE UpdateAvailable          |
                  +---------------------------------+

                  +- spawn ---------+----------+
                  | miner_poll_loop (vendor probes) |
                  +---------------------------------+

                  +- spawn ---------+----------+
                  | HTTP API (Axum on :18334)       |
                  |  - REST endpoints               |
                  |  - SSE /api/events              |
                  |  - static UI from --ui-dir      |
                  +---------------------------------+

Shared State

Tokio-Tasks teilen Arc<...>-Handles statt globaler Statics:

HandleTypGenutzt von
notifier: Arc<Notifier>shared via cloneblock_submit_loop, health_check_loop, periodic_update_check, NotifierConnectionSink, API
pool_metrics: Arc<PoolMetrics>atomic countersNotifierConnectionSink, BitcoinRpc, API /metrics-handler
event_bus: Arc<PoolEventBus>broadcast::Senderalle Subsysteme — publish; API → subscribers (SSE)
storage: Arc<Storage>sqlx-Poolshare-recording, audit-log, vardiff-state, settings
snapshot: Arc<RwLock<NetworkSnapshot>>RwLock-Snapshotjob_refresh_loop schreibt; API liest
profile_kind: Arc<RwLock<ProfileKind>>hot-switchableAPI admin-route + display
cancel: CancellationTokenpropagationalle tasks (graceful shutdown)

Storage-Schema

Tabellen aus den Phasen 1-15. Migrations in crates/storage/migrations/.

TabellePhaseWas
workers1Worker-Liste (user, last_seen_at, shares_accepted/rejected, blocks_found)
shares_raw1Letzte 1h roh-shares — basis für hashrate-Berechnung
shares_5min1Aggregierte 5min-Buckets — Hashrate-Chart-Daten
blocks_found1Block-History (height, hash, coinbase_value_sats, found_at)
pool_settings2.5Generisches KV-Store (active_profile_kind, etc.)
vardiff_state2.5Pro-Worker VarDiff-Snapshots (current_diff, ema, last_share_unix)
audit_log3Admin-Actions (actor, action, target, peer_ip, ok, details)
api_tokens3.2Persistente Bearer-Tokens (token_hash, name, scope, last_used_at, revoked_at)
admin_2fa3.3TOTP-Secrets per User (secret_base32, enabled)
push_subscriptions1Web-Push-Subscriptions (PWA, Phase B nicht aktiv)

Sv2-Stack im Detail

Stratum V2 ist ein binary-framed protocol mit NOISE-NX-handshake davor. Im Pool-Kontext relevant sind zwei Subprotocols:

  1. Mining-Subprotocol (implementiert) — Channel-basiert, Extranonce-aware, Version-Rolling per BIP-320, Set-Target pro Channel.
  2. Template-Distribution-Protocol (TDP, Foundation in Phase 7.6a, Wiring in 7.6b deferred) — Ersetzt getblocktemplate durch push-driven Template- Updates direkt vom Bitcoin-Node.
V1-Miner ----TCP plain---->  stratum-v1 server  ----------+
                                                          |
V1-Miner ----TCP+TLS------>  stratum-v1 TLS-server -------+
                                                          |
                                                          v
                                              +------------------+
                                              |  job-builder     |
                                              |  share-validator |
                                              +------------------+
                                                          ^
                                                          |
V2-Miner ----TCP+NOISE----> stratum-v2 server (port 3334) +
                                                          |
V1-Miner ----TCP--+                                       |
                  |                                        |
                  v                                        |
     dvb-warppool-translator (sidecar) --TCP+NOISE--------+
       - SetupConnection
       - OpenExtendedMiningChannel mit user_identity
       - SubmitSharesExtended mit miner-extranonce
       - Receives NewExtendedMiningJob + SetNewPrevHash
       - Maps to V1 mining.notify + slushpool prev_hash + BIP-320 version-rolling

Konkretes Wire-Format ist in crates/stratum-v2/src/messages.rs mit Roundtrip-Tests. NOISE-Handshake in crates/stratum-v2/src/noise.rs mit snow-crate (pure-Rust, kein OpenSSL).

Connection-Lifecycle-Hooks

Beide Stratum-Server haben einen optionalen ConnectionSink-Trait. Bei authentifizierten Workers (V1: mining.authorize, V2: OpenChannel mit user_identity) feuert on_authorized; bei Verbindungsende on_disconnect.

Daemon implementiert eine NotifierConnectionSink-Struct die beide Traits implementiert. Pro-Worker-Debounce (default 30s) verhindert dass flappende Miner pro Reconnect eine Notification feuern.

   v1.Session::run
         |
   handle_authorize → connection_sink.on_authorized
         |
   ... shares ...
         |
   loop exit → connection_sink.on_disconnect

   v2.handle_connection
         |
   process_frame → channels().iter() → new user_identity?
         |                                    → on_authorized
   ... shares ...
         |
   loop exit → for each notified_user → on_disconnect

Event-Bus + SSE

PoolEventBus ist ein tokio-broadcast-channel mit PoolEvent-Variants:

EventSource
BlockFoundblock_submit_loop
NewJobjob_refresh_loop
SharesAcceptedaggregate_loop
HealthSnapshothealth_check_loop (Phase 13b)
UpdateAvailableperiodic_update_check (Phase 8e)

API /api/events öffnet pro Client einen SSE-Stream mit dem aktuellen Subscription-Set. UI nutzt das für HealthBanner + UpdateBanner + Toast- Events.

Konfigurations-Layer

/etc/dvb-warppool/
├── config.toml         # nicht-sensitive Settings
├── secrets.toml        # chmod 600 — admin-hash, jwt-secret, rpc-pass, sv2-key
└── pool.db             # SQLite (Path konfigurierbar)

Env-vars für opt-in subsysteme (siehe Configuration Reference): WARPPOOL_HEALTH_CHECK_INTERVAL_SECONDS, WARPPOOL_AUTOUPDATE_REPO, WARPPOOL_DISCONNECT_DEBOUNCE_SECS, sink-spezifische tokens, etc.

Lifecycle (Daemon-Boot)

  1. Parse CLI (clap) + ENV
  2. Load config.toml + (optional) secrets.toml
  3. Validate config (mining.payout_address pflicht, ratelimit constraints, ...)
  4. Init tracing-subscriber (JSON wenn logging.json)
  5. Open SQLite + run migrations
  6. Resolve admin profile (persisted in pool_settings schlägt config-default)
  7. Construct BitcoinRpc mit with_metrics(pool_metrics)
  8. Probe RPC (warning bei Fail, Daemon startet trotzdem)
  9. Construct Notifier aus config
  10. Construct PoolMetrics (Arc-shared)
  11. Build initial job (oder skip wenn RPC fail)
  12. Spawn Stratum-V1-Listener (+ TLS-listener wenn cert/key configured)
  13. Spawn Stratum-V2-Listener wenn sv2_listen configured + sv2_static_priv_key_hex da
  14. Spawn job_refresh_loop (poll + optional ZMQ)
  15. Spawn block_submit_loop
  16. Spawn aggregate_loop (60s)
  17. Spawn health_check_loop wenn WARPPOOL_HEALTH_CHECK_INTERVAL_SECONDS > 0
  18. Spawn periodic_update_check wenn WARPPOOL_AUTOUPDATE_REPO + interval > 0
  19. Spawn HTTP API (Axum auf status_listen)
  20. Install signal-handlers (SIGTERM → cancel.cancel() → alle tasks shutdown)
  21. tokio::main event-loop läuft bis cancel

Crate-Abhängigkeiten (DAG)

Vereinfachtes Crate-Graph (nicht alle Edges; keine zyklischen Deps):

profiles --+
hwdetect --+--> config
              |
              +--> storage
              +--> bitcoin-rpc --+
              +--> job-builder   |
              +--> share-validator
              +--> stratum-v1 -----+
              +--> stratum-v2 -----+
              +--> translator -----+
              +--> telemetry -----+
              +--> notifier ------+
              +--> autoupdate ----+
              +--> health --------+
              +--> api -----------+
              +--> simulator -----+
                                 |
                                 v
                  dvb-warppool-daemon
                  dvb-warppool-cli
                  dvb-warppool-setup
                  dvb-warppool-translator
                  dvb-warppool-sim

Crates und ihre einseitigen Deps:

  • telemetry ← keine (foundation für metrics)
  • bitcoin-rpctelemetry (für RPC-Latency-Histogram, Phase 16.3)
  • apinotifier + autoupdate + telemetry + storage + ...
  • daemon → alle library-Crates plus runtime-deps (tokio, sqlx, ...)

Testing-Strategie

Drei Ebenen, plus eine zusätzliche operator-driven Ebene:

EbeneWasToolTest-Count
UnitPure-logic pro Cratecargo test -p warppool-<crate>~330
IntegrationMehrere Crates in-process, axum-Mock-Servertests/ pro Crate~115
SimGegen den echten Daemon-Prozess, Vendor-Personasdvb-warppool-sim scenario <name>5 scenarios
Regtest E2EGegen echtes bitcoind im regtestscripts/regtest-up.sh + --ignored3 tests (opt-in)

Stand: 447 Tests + 3 ignored, alle grün. UI-side: pnpm svelte-check → 294 files, 0 errors.

Siehe TESTING.md für Details + Simulator-Workflow.