Skip to content

Add network field to GlobalInfo (GET /api/v1/global)#367

Open
vnprc wants to merge 3 commits intostratum-mining:mainfrom
vnprc:feat/globalinfo-network
Open

Add network field to GlobalInfo (GET /api/v1/global)#367
vnprc wants to merge 3 commits intostratum-mining:mainfrom
vnprc:feat/globalinfo-network

Conversation

@vnprc
Copy link
Copy Markdown

@vnprc vnprc commented Mar 24, 2026

Summary

  • Add network: Option<String> to GlobalInfo so the Bitcoin network is machine-readable from the monitoring REST API without inspecting config files or Prometheus metrics
  • Pool populates it from its [pool] TOML config (network = "regtest")
  • Translator propagates it by polling GET <upstream_monitoring_url>/api/v1/global every 60 seconds in a background task

Motivation

Downstream consumers of the monitoring API (dashboards, alerting tools, and same for translator proxy) need to know which Bitcoin network the pool is operating on. Today this requires reading config files out-of-band. Exposing it in GlobalInfo makes it a first-class, machine-readable API field.

Changes

stratum-apps

  • GlobalInfo.network: Option<String> (serializes to null when not configured)
  • ServerState.network: Arc<RwLock<Option<String>>> for runtime updates
  • MonitoringServer::with_network() — builder method for static configuration
  • MonitoringServer::network_handle() — returns an Arc clone for background tasks that need to update the field after run() consumes self

pool-apps/pool

  • PoolConfig.network: Option<String> with #[serde(default)] (backward-compatible)
  • Pool calls .with_network(config.network()) on startup

miner-apps/translator

  • TranslatorConfig.upstream_monitoring_url: Option<String> with #[serde(default)]
  • On startup, calls monitoring_server.network_handle() then spawns poll_network_from_pool(): fetches pool's /api/v1/global immediately, then every 60 seconds; exits cleanly on cancellation
  • Applied to both the primary startup path and the fallback-restart path
  • reqwest added as a dependency (default-features = false, features = ["json"])

integration-tests

  • start_pool_with_network and start_sv2_translator_with_upstream_monitoring helpers added (existing helpers unchanged, delegate to new ones)
  • global_info_exposes_network test: starts pool with network = "regtest", starts translator pointing at pool's monitoring server, asserts pool exposes "regtest" immediately and translator propagates it within 10 seconds

Network value convention

Values follow bitcoin-cli -getinfo / bitcoin-cli getblockchaininfo convention: "main", "test", "testnet4", "regtest", "signet". The field is null if not configured.

Test plan

  • cargo clippy --manifest-path stratum-apps/Cargo.toml -- -D warnings -A dead-code — clean
  • cargo test --manifest-path stratum-apps/Cargo.toml — 29/29 pass
  • cargo fmt --manifest-path stratum-apps/Cargo.toml -- --check — clean
  • Pool and translator build cleanly with reqwest added
  • global_info_exposes_network integration test passes end-to-end
  • Existing monitoring integration tests unaffected

vnprc added 3 commits March 23, 2026 22:44
Add `network: Option<String>` to `GlobalInfo` so the Bitcoin network
is machine-readable from `GET /api/v1/global` without consulting
Prometheus or config files.

- `GlobalInfo` gets `pub network: Option<String>`
- `ServerState.network`: `Option<String>` → `Arc<RwLock<Option<String>>>`
- `MonitoringServer::with_network(self, Option<String>)` writes into
  the existing Arc so any handle obtained via `network_handle()` remains
  valid after the call
- `MonitoringServer::network_handle()` returns a clone of the Arc for
  background tasks that need to update network after `run()` consumes self
- `handle_global` reads via `.read().unwrap().clone()`
- Tests: `global_endpoint_with_no_sources` asserts network is null;
  new `global_endpoint_network_field` asserts null and populated cases
Pool is the authoritative source of network identity — it is directly
connected to the Bitcoin node via the template provider.

Pool:
- `PoolConfig` gains `network: Option<String>` with `#[serde(default)]`
- Pool calls `.with_network(config.network())` on its `MonitoringServer`

Translator:
- `TranslatorConfig` gains `upstream_monitoring_url: Option<String>`
  with `#[serde(default)]` and `with_upstream_monitoring_url()` builder
- After building `MonitoringServer`, calls `.network_handle()`
- Spawns `poll_network_from_pool()` background task: fetches
  `GET <upstream_monitoring_url>/api/v1/global` immediately then every
  60s, writes `global.network` into the Arc; trims trailing slash;
  shuts down cleanly on cancellation token
- Applied to both startup and fallback-restart code paths
- `reqwest` added as a dep

Integration test `global_info_exposes_network`:
- Starts pool with `network = "regtest"`
- Starts translator with `upstream_monitoring_url` pointing at pool
- Asserts pool `/api/v1/global` immediately returns `network = "regtest"`
- Polls translator `/api/v1/global` up to 10s for propagation
- `start_pool_with_network` and `start_sv2_translator_with_upstream_monitoring`
  helpers added; existing helpers unchanged
- `serde_json` added to integration-tests `Cargo.toml`
Long lines in the new test exceeded the stable rustfmt line limit.
Break up start_pool_with_network, start_sv2_translator_with_upstream_monitoring,
assert_eq!, and panic! calls to match the project's formatting style.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant