Solana · Commit–Reveal Randomness
Entropy API
A verifiable randomness provider for the on-chain entropy program. It commits to a seed in advance, then reveals it once the consuming Var account's reveal window has passed — so the random value can never be known or biased before it's locked in.
How it works
Randomness uses a classic commit–reveal scheme backed by a one-way keccak-256 hash chain. The provider builds a chain of length n (one link per round) entirely offline:
seed_n = random 32 bytes (the secret "tail")
seed_i = keccak256(seed_{i+1}) for i = n-1 … 1
commit = keccak256(seed_1) (published on-chain at creation)Because keccak is one-way, knowing commit tells you nothing about any seed_i. But anyone can verify a revealed seed: hashing it the right number of times must reproduce the published commitment. Rounds are consumed in reverse order — round k reveals seed_k, and keccak256(seed_k) chains back toward the commit.
Checkpoints
Storing every seed would be wasteful, so only the tail and every N-th seed (the checkpoint_interval, default 100) are persisted. To serve round k, the API loads the nearest checkpoint at index ≥ k and re-derives seed_k with at most checkpoint_interval keccak hashes. Revealed seeds are then cached so each is computed once.
The reveal gate
A request for a seed only succeeds when the on-chain Var account says it's safe to reveal. The API enforces, in order:
- the account is owned by the entropy program;
- its
providermatches this provider's pubkey; - the value is not yet finalized (
valueis all-zero); - the current slot is past
end_at(reveal window closed); - samples remain and the seed hasn't already been revealed on-chain.
The round index is computed from how many samples have been consumed: k = total_samples − samples_remaining + 1. Before serving, the API re-checks keccak256(seed) === commit and rejects on any mismatch.
Endpoints
Database + Solana RPC connectivity. Returns 200 when both are healthy, 503 otherwise. Add ?quick=1 to skip the RPC probe (DB only).
Decodes and returns the on-chain Var account at address (authority, id, provider, commit, seed, slot_hash, value, samples, timings) as hex/strings.
The reveal endpoint. Validates the gate above, derives the seed for the current round from the hash chain, verifies it against the commitment, caches it, and returns the seed bytes. Common statuses: 403 provider mismatch, 409 already finalized / no samples / already revealed, 425 not yet past the reveal window, 422 commit mismatch, 404 no chain found.
Look up an already-revealed seed by its 64-char hex commitment. Returns the seed plus created_at / served_at timestamps, or 404 if it was never served.
Verifying a revealed seed
Given the published commit and a revealed seed for round k of a chain of length n, recompute the commitment yourself:
import { keccak_256 } from "@noble/hashes/sha3";
let h = seed; // seed_k (32 bytes)
for (let i = k; i > 1; i--) h = keccak_256(h); // walk back to seed_1
const recomputed = keccak_256(h); // == commit ?If recomputed equals the on-chain commitment, the reveal is authentic.