rpc to our own nodes: endpoint list, tls, reconnect and a runtime-version watch #20

Closed
opened 2026-09-15 12:38:08 +00:00 by grenade · 2 comments
Owner

Parent: #3

Scope

A connection manager that takes a profile's endpoint list, connects over wss with rustls, fails over on error, reconnects with backoff and jitter, and re-reads state_getRuntimeVersion on connect and on the RuntimeUpgraded signal so the signing context and metadata are never stale. Health is exposed to the UI as a small status (connected to which host, block height, lag).

Operator decision to record here before starting

Which hosts serve the wallet, and how the wallet authenticates to them: mTLS client certificate, a bearer token in the WebSocket handshake, or open behind the mesh only. Document the answer as a comment on this issue.

Acceptance

Kill the node the wallet is on; it is on another within the backoff window and the UI status says so. A runtime upgrade on the dev node changes the reported spec version without a restart.

Depends on

Chain profiles.

Parent: #3 ## Scope A connection manager that takes a profile's endpoint list, connects over `wss` with rustls, fails over on error, reconnects with backoff and jitter, and re-reads `state_getRuntimeVersion` on connect and on the `RuntimeUpgraded` signal so the signing context and metadata are never stale. Health is exposed to the UI as a small status (connected to which host, block height, lag). ## Operator decision to record here before starting Which hosts serve the wallet, and how the wallet authenticates to them: mTLS client certificate, a bearer token in the WebSocket handshake, or open behind the mesh only. Document the answer as a comment on this issue. ## Acceptance Kill the node the wallet is on; it is on another within the backoff window and the UI status says so. A runtime upgrade on the dev node changes the reported spec version without a restart. ## Depends on Chain profiles.
grenade added the child label 2026-09-15 12:39:02 +00:00
Author
Owner

Operator decision, 2026-09-15

Node RPC and WebSocket are public, no auth, throttled. One name per chain, so the convention scales to every chain the wallet learns:

  • quantus.blackbeard.observer for mainnet
  • planck.blackbeard.observer for the testnet leg, so a two-chain wallet is testable end to end even though Planck is a testnet

Each name is TLS-terminated with Let's Encrypt on oolon's nginx, configured as an IP load balancer (an upstream per chain) that routes to the single node on bob for now and gains servers as nodes are added. Fairness comes from nginx throttling (limit_req on the HTTP JSON-RPC path, limit_conn per client on the WebSocket upgrade, since limit_req only sees the handshake), not from credentials.

Consequences for this issue: the endpoint list in the mainnet and Planck profiles is exactly those two names; the wallet does no authentication; failover is nginx's job on the server side and reconnect-with-backoff on the wallet's. The infrastructure itself is filed separately as a child of #3.

Caveat to resolve before the Planck name goes live

The observer's config.toml records that the one node we ran for Planck now mines mainnet, and that Heisenberg is served from a Quantus-team endpoint (a1-heisenberg.quantus.cat), not ours. So planck.blackbeard.observer needs a Planck node stood up on our infra first, and it is worth confirming Planck is still the testnet Quantus keeps alive (the mobile app, the extension fork and the observer all test against Heisenberg today). If Heisenberg is the better-supported testnet, the same convention gives heisenberg.blackbeard.observer and nothing else changes.

## Operator decision, 2026-09-15 Node RPC and WebSocket are **public, no auth, throttled**. One name per chain, so the convention scales to every chain the wallet learns: - `quantus.blackbeard.observer` for mainnet - `planck.blackbeard.observer` for the testnet leg, so a two-chain wallet is testable end to end even though Planck is a testnet Each name is TLS-terminated with Let's Encrypt on **oolon**'s nginx, configured as an IP load balancer (an `upstream` per chain) that routes to the single node on **bob** for now and gains servers as nodes are added. Fairness comes from nginx throttling (`limit_req` on the HTTP JSON-RPC path, `limit_conn` per client on the WebSocket upgrade, since `limit_req` only sees the handshake), not from credentials. Consequences for this issue: the endpoint list in the mainnet and Planck profiles is exactly those two names; the wallet does no authentication; failover is nginx's job on the server side and reconnect-with-backoff on the wallet's. The infrastructure itself is filed separately as a child of #3. ## Caveat to resolve before the Planck name goes live The observer's `config.toml` records that the one node we ran for Planck now mines mainnet, and that Heisenberg is served from a Quantus-team endpoint (`a1-heisenberg.quantus.cat`), not ours. So `planck.blackbeard.observer` needs a Planck node stood up on our infra first, and it is worth confirming Planck is still the testnet Quantus keeps alive (the mobile app, the extension fork and the observer all test against Heisenberg today). If Heisenberg is the better-supported testnet, the same convention gives `heisenberg.blackbeard.observer` and nothing else changes.
Author
Owner

Correction, 2026-09-15

The caveat above was wrong on two counts, and the correction belongs here rather than in a diff.

  1. Planck has official public endpoints: a1-planck.quantus.cat and a2-planck.quantus.cat both answer system_chainPlanck today, as do a1/a2-heisenberg. The observer's deployed config template already lists both pairs; the stale working copy I read did not.
  2. We run no testnet node and do not intend to. For testnets, nginx on oolon load-balances and proxies to the official Quantus endpoints. Only mainnet routes to our own node on bob.

Planck's role is narrow and deliberate: it exists in the wallet purely to prove the multi-chain UX works, until a real post-quantum mainnet that is not Quantus is supported. It is not a second product surface.

So: quantus.blackbeard.observer → bob; planck.blackbeard.observera1/a2-planck.quantus.cat. Same convention, same throttling, no auth on either. #53 is updated to match.

## Correction, 2026-09-15 The caveat above was wrong on two counts, and the correction belongs here rather than in a diff. 1. Planck has official public endpoints: `a1-planck.quantus.cat` and `a2-planck.quantus.cat` both answer `system_chain` → `Planck` today, as do `a1`/`a2-heisenberg`. The observer's deployed config template already lists both pairs; the stale working copy I read did not. 2. We run no testnet node and do not intend to. For testnets, nginx on oolon load-balances and proxies to the official Quantus endpoints. Only mainnet routes to our own node on bob. Planck's role is narrow and deliberate: it exists in the wallet purely to prove the multi-chain UX works, until a real post-quantum mainnet that is not Quantus is supported. It is not a second product surface. So: `quantus.blackbeard.observer` → bob; `planck.blackbeard.observer` → `a1`/`a2-planck.quantus.cat`. Same convention, same throttling, no auth on either. #53 is updated to match.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: blackbeard/wallet#20