Running the entropy aggregator¶
The entropy aggregator is a small HTTP service that:
- Pulls bytes from one or more upstream entropy sources (drand, QRNG hardware, future federated beacons)
- XOR-mixes them into a single byte pool
- Serves the pool to miners via the chain's standard REST contract
Run it whenever you don't want to depend on the public testnet aggregator (entropy.waveledger.net) — for control, for redundancy, or because you have your own hardware to plug in.
Run the reference aggregator¶
That's it. The reference setup wires in drand as the sole source. Miners on the same machine can now point at 127.0.0.1:8420; miners elsewhere need the host reachable (firewall + DNS).
On boot it warms up by fetching a drand round; that takes ~2 seconds.
Endpoints¶
See QRNG and entropy → REST contract for the full surface. Three endpoints:
| Endpoint | Use |
|---|---|
GET /api/health | Pool fill status, source health, last refill metadata |
GET /api/random/bytes?n=N | Raw entropy (binary) |
GET /api/random/hex?n=N | Same, hex-encoded |
Adding sources¶
The aggregator picks up sources from make_aggregator() in qrng_aggregator_service.py:
from quantum.providers.drand_provider import DrandProvider
from quantum.providers.local_qrng_provider import LocalQRNGProvider
from quantum.providers.aggregator_provider import AggregatorProvider
def make_aggregator():
return AggregatorProvider(
sources=[
DrandProvider(),
LocalQRNGProvider(host='10.0.0.5', port=8421), # your QRNG box
# AnotherProvider(...),
],
min_quorum=2, # require at least 2 sources to return valid bytes
)
Each source must implement async def generate_qrng(num_bits: int) returning a QRNGResult (see quantum/providers/local_qrng_provider.py for the reference impl).
min_quorum=2 means at least 2 of the configured sources must respond successfully before the aggregator serves output. Failing closed is the right default for entropy.
Pool sizing¶
The aggregator maintains a 64 KB pool by default. When the pool drops below ~50% full, a background coroutine refills from all configured sources (XOR-mixed).
| Knob | Default | When to change |
|---|---|---|
pool max size | 65536 bytes | Raise for high-throughput chains; lower for memory-constrained boxes |
refill threshold | 50% | Raise for jittery upstreams |
refill batch | 32 KB per source | — |
A performance-1x fly VM serves ~10 MB/sec of entropy from this pool; plenty for any plausible miner count.
Running on fly¶
# From the WaveLedger repo, with fly.entropy.toml in place
flyctl apps create my-entropy
flyctl ips allocate-v6 --config fly.entropy.toml
flyctl ips allocate-v4 --config fly.entropy.toml --shared
flyctl deploy --config fly.entropy.toml --ha=false
flyctl certs add entropy.example.com --config fly.entropy.toml
Then add DNS pointing entropy.example.com at fly. See Self-hosting on Fly.io for the full walkthrough.
Running on a VPS¶
# As root on Ubuntu 22.04+
git clone https://github.com/DosseyRichards/Fermi-Mining-ASIC-Software.git /opt/waveledger
sudo bash /opt/waveledger/deploy/testnet/setup_entropy_vps.sh
# Then put TLS in front:
ENTROPY_HOST=entropy.example.com sudo -E bash /opt/waveledger/deploy/testnet/setup_entropy_proxy.sh
The setup scripts use systemd + Caddy. See the VPS guide for the breakdown.
Trust list considerations¶
A new aggregator's source ID (the source field in its /api/health) must be in the chain's trust list before its blocks are accepted by miners. The testnet trust list includes aggregator:drand-default and a handful of placeholder IDs.
Running an aggregator for your own miners only is unconstrained — the trust list matters only when you want other people's miners to accept attestations from your source.