83 lines
5.8 KiB
Markdown
83 lines
5.8 KiB
Markdown
# Validations Proxy
|
|
|
|
An active-active WebSocket relay for the XAHAUD `validations` stream. It maintains connections to one or more XAHAUD nodes and broadcasts each unique `validationReceived` message to downstream clients. Validation versions are the only persisted data.
|
|
|
|
Validation messages are forwarded byte-for-byte as text frames. The proxy does not add, remove, rename, or resolve fields, so consumers receive XAHAUD's original `master_key`, `server_version`, flag-ledger fields, and any fields added by future XAHAUD versions.
|
|
|
|
The root HTTP page is a live validation dashboard. It shows validator master keys, manifest domains, activity, ledgers, the next 256-ledger flag boundary, and decoded XAHAUD versions. Validators published by `vl.xahau.org` appear first. The activity table defaults to base-domain ordering, so a host such as `validator.example.org` sorts under `example.org`; the full hostname is used as a tie-breaker. Browser data is memory-only and disappears when the page closes. Validator versions are persisted atomically to `data/validator-versions.json` inside the project directory; validations, domains, activity, and validator-list data are not persisted. Relative `VERSION_STORE_PATH` values are always resolved inside the project directory. The dashboard defaults to a restrained light theme with an optional non-persistent dark mode.
|
|
|
|
The dashboard and WebSocket share the same root path: an ordinary HTTP request receives the page, while a WebSocket upgrade receives the live stream. TLS is normally terminated by a reverse proxy.
|
|
|
|
## WebSocket streams
|
|
|
|
- `ws://localhost:8080/` forwards XAHAUD `validationReceived` messages unchanged. Use the same root path on your deployment's public `wss://` address. There is no replay.
|
|
- `ws://localhost:8080/?dashboard=1` sends the same validation stream plus `validatorMetadata` messages used by the sample dashboard. Use the same query parameter on your deployment's public `wss://` address. A metadata frame identifies the validator with `master_key` and may contain its manifest `domain`, `listed` status from `vl.xahau.org`, explicit `offline` status, last known encoded `server_version`, latest `ledger_index`, relay-observed `last_seen` time, and `monitoring_since` timestamp.
|
|
|
|
When a dashboard connection opens, the relay immediately sends every metadata record it currently knows. Persisted versions can therefore appear before a new validation from that validator. A previously unknown domain is sent after the validator is first observed and the relay resolves its manifest. Listing status is based on the relay's periodically refreshed `vl.xahau.org` list and is sent again when that status changes. Version metadata is sent when a validation announces `server_version`; XAHAUD normally includes this on flag-ledger validations rather than every validation.
|
|
|
|
Every validator in the current VL is represented in dashboard metadata even when it has not sent a validation. The relay immediately sets `offline: true` for a listed validator that has never been observed. An observed validator is marked offline after falling two ledgers behind the leading ledger, with a 15-second timeout used until ledger activity is available. The relay broadcasts another `validatorMetadata` frame whenever this status changes; the browser only renders the server-provided status. Availability state is held in memory; only versions are persisted.
|
|
|
|
The metadata is public enrichment rather than part of XAHAUD's validation message format. Consumers that require the original stream should use the root endpoint. Consumers must tolerate duplicate validations around relay restarts and fields added by future XAHAUD releases.
|
|
|
|
When multiple upstreams deliver the same signed validation, the first original message is forwarded and subsequent copies are dropped. Deduplication uses the signed `data` field and a five-minute in-memory cache by default. This cache is empty after a restart, so consumers should still tolerate occasional duplicates.
|
|
|
|
## Run
|
|
|
|
Requires Node.js 20 or newer.
|
|
|
|
```sh
|
|
npm install
|
|
cp .env.example .env
|
|
set -a; . ./.env; set +a
|
|
npm start
|
|
```
|
|
|
|
Set `XAHAUD_WS_URLS` to a comma-separated list of XAHAUD node endpoints. You can collect validations from the public `wss://xahau.network` endpoint, a local node, or multiple nodes for redundancy. For example:
|
|
|
|
```sh
|
|
XAHAUD_WS_URLS=wss://xahau.network,ws://127.0.0.1:6008
|
|
```
|
|
|
|
The relay remains ready while at least one node is connected. To prevent arbitrary clients from using the relay, set `DOWNSTREAM_AUTH_TOKEN` to a strong secret. Browser deployments should also set `ALLOWED_ORIGINS`.
|
|
|
|
Connect a consumer to `ws://localhost:8080/` with an authorization header:
|
|
|
|
```js
|
|
import WebSocket from 'ws';
|
|
|
|
const socket = new WebSocket('ws://localhost:8080/', {
|
|
headers: { Authorization: `Bearer ${process.env.VALIDATIONS_TOKEN}` },
|
|
});
|
|
|
|
socket.on('message', (data) => console.log(JSON.parse(data)));
|
|
```
|
|
|
|
Web browsers cannot set an `Authorization` header in the native WebSocket API. For browser consumers, put the relay behind an authenticating reverse proxy that injects the header, or use a cookie-aware gateway.
|
|
|
|
## Endpoints
|
|
|
|
- `GET /` — live validation dashboard
|
|
- `GET /healthz` — process liveness
|
|
- `GET /readyz` — returns 200 while at least one XAHAUD node is connected
|
|
- `GET /status` — per-node connection state plus relay and deduplication counters
|
|
- `WS /` — live validation messages only; no replay
|
|
- `WS /?dashboard=1` — live validations plus public validator metadata
|
|
|
|
The proxy automatically reconnects to XAHAUD with exponential backoff and jitter. Slow downstream clients are disconnected instead of allowing unbounded memory growth.
|
|
|
|
## Test
|
|
|
|
```sh
|
|
npm test
|
|
```
|
|
|
|
## Docker
|
|
|
|
```sh
|
|
docker build -t validations-proxy .
|
|
docker run --rm -p 8080:8080 \
|
|
-e XAHAUD_WS_URLS=ws://host.docker.internal:6008,ws://xahaud-standby:6008 \
|
|
-e DOWNSTREAM_AUTH_TOKEN=replace-me \
|
|
validations-proxy
|
|
```
|