ReserveGrid OS v1.0.0
ReserveGrid OS v1.0.0 — Forge
First stable release of ReserveGrid OS. Full template verification pipeline, three deployment modes, Stratum V2 gateway with Noise encryption, operator dashboard, and production security hardening across 14 workspace crates and 9 Docker services.
Scope
ReserveGrid OS sits between a mining pool's block template source (bitcoind or relay) and its Stratum V2 gateway. It verifies every candidate block template against a configurable policy before the template reaches miners, giving pool operators real time visibility into template quality and the ability to enforce standards on what their miners work on.
The system is designed for progressive deployment. Operators start in shadow mode (read only evaluation), move to observe mode (non enforcing with live pool data), and graduate to inline mode (full enforcement in the block construction pipeline).
Architecture
Core pipeline:
bitcoind → template-manager → pool-verifier → sv2-gateway → miners
Services
| Service | Role |
|---|---|
| pool-verifier | Template verification engine with configurable TOML policy |
| sv2-gateway | Stratum V2 gateway with Noise NX encryption and share lifecycle |
| template-manager | bitcoind RPC integration for block templates |
| rg-auth | Authentication, license keys, per endpoint rate limiting |
| rg-dashboard | Operator dashboard with embedded React frontend and API proxy |
| rg-demo-feed | Synthetic GBT generator for shadow mode evaluation |
| rg-feed-adapter | WebSocket to JSON RPC bridge |
| rg-feed-server | Authenticated template feed relay for observe mode |
| rg-load-test | HTTP load generator for benchmarking |
Libraries
rg-protocol— shared wire types,TemplatePropose/TemplateVerdict, and canonical reason codesreservegrid-common— reason code registry, config parsing, CSV/NDJSON/Prometheus exportssv2-bridge— Stratum V2 protocol bridge with Noise NX handshakereservegrid-gateway— legacy gateway (superseded by sv2-gateway in v1.0.0)
Deployment modes
| Mode | Risk | Data Source | Enforcement |
|---|---|---|---|
| Shadow | None | Synthetic (rg-demo-feed) | Read only |
| Observe | None | Live pool (rg-feed-server) | Logging only |
| Inline | Production | bitcoind (direct) | Full enforcement |
Shadow mode runs entirely offline against synthetic templates generated by rg-demo-feed. Observe mode connects to a live pool's template stream through rg-feed-server with HMAC authentication but never touches the block construction path. Inline mode sits directly in the pipeline between template-manager and sv2-gateway and can reject templates before they reach miners.
Stratum V2 gateway
Connection lifecycle
Miners connect over TCP with Noise NX encryption negotiated on the first handshake. Each connection opens a standard mining channel. The gateway validates share submissions against the current job, enforces per channel rate limits, and forwards accepted shares upstream.
Share verification
Every submitted share is checked for nonce uniqueness (HMAC replay protection), job freshness, difficulty target, and version mask compliance. Invalid shares receive a structured rejection with a canonical reason_code and human readable reason_detail.
Rate limiting
- Per channel token bucket for share submission rate
- Per IP TCP accept rate limiting at the listener level
- Both configurable via environment variables
Reason codes
19 gateway share and connection reason codes covering: share_accepted, share_rejected_low_difficulty, share_rejected_stale_job, share_rejected_duplicate_nonce, share_rejected_invalid_version_mask, connection_rejected_rate_limit, and others. All codes are canonical snake_case and stable across Prometheus labels and structured logs.
Template verification
Policy engine
The pool-verifier evaluates every TemplatePropose against a flat TOML policy. 15 verdict reason codes cover economic checks (fee delta, tx count, coinbase value), structural checks (version, prevhash, merkle root), and consensus safety checks (weight ratio, template staleness, sigops budget).
Evaluation order
Safety checks run after the 8 economic and structural checks in a fixed, deterministic order. evaluate_dynamic accepts an explicit now_ms: u64 parameter for testability. The production wrapper evaluate() calls now_unix_ms() internally, preserving existing call sites.
Enforced checks
weight_ratio_exceeded— activates when template weight divided by max block weight (4,000,000 WU) exceedssafety.max_weight_ratiotemplate_stale— activates when current time minuscreated_at_unix_msexceedssafety.max_template_age_ms- Each check gated by
safety.enforce_weight_ratioandsafety.enforce_template_agebooleans in policy TOML, both defaultfalse - When
enforce = false, structured warning log emitted with metric values but verdict stays accept
Observed checks (log and dashboard only)
- Sigops headroom: warns when
total_sigopsexceedssafety.warn_sigops_ratioof the 80,000 consensus limit - Coinbase sigops anomaly: warns when
coinbase_sigopsexceedssafety.warn_coinbase_sigops_max - Both thresholds configurable under
[policy.safety] - Warnings carry full policy context for traceability
New environment variables
VELDRA_TLS_CERT— path to PEM certificate fileVELDRA_TLS_KEY— path to PEM private key fileVELDRA_TLS_SELF_SIGNED— set to1to auto-generate a self-signed cert for devVELDRA_API_KEY— bearer token required for non-health endpoints (localhost bypasses)VELDRA_POLICY_FILE— path to policy TOML file
Verification and observability
15 template verdict reason codes and 19 gateway share/connection reason codes. All canonical snake_case, stable across protocol, verifier, Prometheus labels, NDJSON WAL, CSV exports, and dashboard queries.
Every rejection is 100% traceable: machine readable reason_code plus human readable reason_detail, with full policy context in structured logs.
Exports
- Prometheus metrics with
reason_codelabels on all verdict and share counters - NDJSON event stream (crash durable write ahead log)
- CSV verdict history via
/verdicts.csv - Embedded dashboard with 3 second live polling
Readiness probes
/ready returns 200 when the verifier is operationally healthy, 503 when degraded. Response is JSON:
{
"ready": true,
"policy_loaded": true,
"mempool_reachable": true,
"mempool_last_ok_age_secs": 2
}/health remains a simple liveness probe returning "ok" unconditionally. Both endpoints bypass API key authentication.
Dashboard
Built-in operator dashboard
rg-dashboard serves an embedded React frontend proxied behind the same auth layer as the API. Live verdict stream, reason code aggregates with collapsible drill-down, consensus safety panel (weight utilization gauge, sigops headroom bar, template age, coinbase sigops), and tier cards for mempool context.
Observe mode public dashboard
The public observe mode dashboard (veldra-site-v3) reaches full feature parity with the built-in dashboard. Enforcement mode badges, mempool context bar, CSV/NDJSON export links, and stale data overlay across all panels. Auth bypass restricted to localhost only.
Security
- Noise NX encryption on all miner connections (Stratum V2)
- Native TLS via
VELDRA_TLS_CERTandVELDRA_TLS_KEYenvironment variables (rustls) - Self-signed cert generation for dev via
VELDRA_TLS_SELF_SIGNED=1 - mTLS support for remote verifier channel
- HMAC nonce replay protection on share submissions
- Per channel share rate limiting (token bucket)
- Per IP TCP accept rate limiting
- Per endpoint auth rate limiting (sliding window, fail closed)
- API key authentication via
VELDRA_API_KEY(Bearer token, localhost bypasses) - Argon2id password hashing for rg-auth accounts
- Constant time API key comparison
- CORS wildcard hard error at startup
- SQL parameterization enforced (no string interpolation with user input)
unsafe_code = "deny"across entire workspace
Policy configuration
All verification thresholds configurable via a flat TOML [policy] table. 18 policy keys across [policy] and [policy.safety]. No code changes required to adjust thresholds. Switch policy files by setting the VELDRA_POLICY_FILE environment variable.
Policy TOML keys under [policy.safety]
max_weight_ratio— float, default0.999max_template_age_ms— maximum acceptable template age in millisecondsenforce_weight_ratio— boolean, defaultfalseenforce_template_age— boolean, defaultfalsewarn_sigops_ratio— float, default0.95(warn at 95% of consensus limit)warn_coinbase_sigops_max— integer, default400
Policy profiles included
policy-strict.toml— all enforcement enabled, strict thresholdsdemo-open-policy.toml— permissive policy for demo/evaluationdemo-showcase-policy.toml— balanced policy for live demonstrationsdemo-strict-policy.toml— aggressive policy for rejection showcase
Authentication (rg-auth)
Standalone auth service with Argon2id password hashing, JWT session tokens, license key validation, and per endpoint sliding window rate limiting that fails closed on threshold breach. Supports account creation, login, token refresh, and key activation flows.
CI and quality
Full GitHub Actions matrix: build, test, clippy pedantic, rustfmt, cargo audit, cargo deny, cargo vet, gitleaks secrets scan. Integration test suites for all three deployment modes.
| Suite | Tests |
|---|---|
| Inline mode smoke | 14 |
| Observe mode smoke | 9 |
| Auth lifecycle | 20 |
| Endpoint contracts | 22 |
| Shadow integration | CI job |
Performance
Release build benchmarks on single machine loopback (Docker Compose):
| Scenario | Connections | TPS | Avg | p99 | Max |
|---|---|---|---|---|---|
| Baseline valid | 10 | 100 | 5.34ms | 15ms | 60ms |
| Stress valid | 50 | 1,000 | 3.66ms | 9ms | 30ms |
| High concurrency burst | 100 | 2,000 | 5.14ms | 35ms | 75ms |
| 100% rejection (prevhash) | 10 | 100 | 5.10ms | 16ms | 17ms |
| Mixed 30% rejection | 10 | 100 | 5.20ms | 14ms | 15ms |
All scenarios remain under the 100ms SLA target. The rejection path adds no measurable latency overhead compared to the acceptance path. At 10x load (50 connections, 1,000 TPS) average latency decreases to 3.66ms due to connection pooling amortization.
Dependencies
Key runtime dependencies:
axum0.8 withtokioruntimeaxum-server0.7 withtls-rustlsfeatureserde/serde_jsonfor all serializationtracing/tracing-subscriberfor structured loggingclapfor CLI argument parsingrcgen0.13 for self-signed certificate generationargon2for password hashingbitcoincore-rpc0.18.0 for getblocktemplate integration
Requirements
- Rust 1.92+ (2024 edition)
- Docker and Docker Compose
- bitcoind (for inline mode)
Getting started
git clone https://github.com/LeavesJ/veldra.git
cd veldra
cp .env.example .env
# Edit .env with your settings
docker compose up -dSee the README for full setup instructions including all three deployment modes.
Known limitations
- Extended channels (multiple jobs per connection) are deferred to v1.1
- Variable difficulty (vardiff) is deferred to v1.1
- Grafana dashboard JSON provisioning is not yet included (embedded dashboard is functional)
- Rate limiter state is in process only (acceptable for single instance, shared state deferred to v1.1)
- Sustained load testing (hours, not seconds) has not been performed
- Two host deployment with network latency has not been benchmarked
License
Veldra Source Available License v1.0. See LICENSE for terms.