Appearance
Accounts & layouts
Byte offsets are exported as constants by the zero-dependency vrand-interface crate and pinned by layout tests — the numbers below are documentation of those constants, not a second source of truth.
Request (460 bytes)
One randomness request. PDA: ["request", requester, seed].
| Field | Offset | Size | Meaning |
|---|---|---|---|
| discriminator | 0 | 8 | [125, 172, 150, 161, 162, 115, 39, 71] |
requester | 8 | 32 | identity bound into alpha; only signer that can close |
payer | 40 | 32 | paid rent + fee; receives them back at close |
comp_dest | 72 | 32 | receives slash compensation |
prover | 104 | 32 | the prover PDA this request pins |
vrf_pubkey | 136 | 32 | the exact key the proof must verify under |
key_epoch | 168 | 8 | prover key epoch at request time |
seed | 176 | 32 | your 32-byte seed |
alpha | 208 | 32 | the frozen VRF input |
request_slot | 240 | 8 | slot the request landed in |
at_risk_lamports | 248 | 8 | coverage bought |
fee_lamports | 256 | 8 | escrowed fee |
fulfill_window_slots | 264 | 8 | deadline window, snapshotted |
state | 272 | 1 | 0 = PENDING, 1 = FULFILLED, 2 = SLASHED |
fulfilled_slot | 273 | 8 | slot the proof landed |
tai_ctr | 281 | 2 | hash-to-curve counter; 0xffff = fallback-resolved |
proof | 283 | 80 | the VRF proof (zeroed until fulfilled) |
beta | 363 | 64 | the VRF output — only meaningful when state = FULFILLED |
bump | 427 | 1 | |
slothash | 428 | 32 | the bank-hash entry alpha commits to (persisted because no RPC serves bank hashes) |
Readers must check the account owner is the VRAND program before trusting any offset, and must treat beta as absent unless state == FULFILLED — the SDK accessors enforce both.
Address reuse is intentional
After a resolved request is closed, the same (requester, seed) re-derives the same address and can be created afresh with an independent outcome. Key your application state on outcome data (beta, fulfilled_slot), never on the request address alone.
Network (singleton)
Admin key, pause flag (new requests only — never resolution), and the parameters, each bounded on-chain so no setting can become a shutdown.
Prover
PDA: ["prover", operator].
| Field | Meaning |
|---|---|
operator | the operator's wallet — receives fees, controls the bond |
vrf_pubkey, key_epoch | the registered key (rotation bumps the epoch; in-flight requests stay pinned to the old key) |
status | 0 = ACTIVE, 1 = UNBONDING, 2 = REVOKED — only ACTIVE provers take new requests |
bond_lamports | total bonded SOL (held as PDA lamports) |
reserved_lamports | committed to open requests; invariant bond ≥ reserved |
pending_requests | open-request counter; withdrawal requires 0 |
Available coverage for a new request = bond − reserved (and per-request at most max_single_at_risk_bps of the bond).
TermsState & Acknowledgment
TermsState (["terms"], singleton) holds the current terms version and SHA-256 hash. Acknowledgment (["ack", wallet], 83 bytes) records a wallet's acceptance of a specific version+hash; request requires the payer's acknowledgment to match the current terms exactly.