Zeeka saysA VRF is a keyed hash that proves its own output: a secret key yields a random-looking value plus a proof anyone can check with the public key.
A verifiable random function produces, from a secret key and an input, an output that looks uniformly random to everyone else — yet comes with a proof that the public key can verify. It is deterministic per (key, input), so the same slot always yields the same draw, but unpredictable to outsiders and impossible to grind, because you cannot try inputs to fish for a favorable result without committing your key first.
This is the heart of modern leader election: Algorand and Ethereum-style committees use VRFs for private, stake-weighted sortition — you privately learn you were selected, then prove it. The demo shows the deterministic, stake-weighted draw; the verify-with-public-key step is what makes it a VRF rather than a plain hash, and is described in the lesson.
Power-ups you unlock
Output is deterministic per (secret key, input)
Looks uniformly random to anyone without the key
Comes with a proof verifiable by the public key
Used for leader election / committee sortition (Algorand, eth)
No one can grind or predict the result in advance
The Collision attacks — common mistakes
Using a plain hash with no proof — not verifiable, so not a VRF
Letting the input be chosen after the key is known (grinding)
Assuming determinism means predictable to outsiders
Skipping the public verification step on-chain
Boss battleBuild a deterministic stake-weighted draw where the same (key, slot) always yields the same selection result.
Example code
<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
// VRF sortition (illustrative): a real VRF emits (output, proof) checkable by pk.
// Here we show the deterministic, unbiased DRAW; verification is described in the lesson.
const H = (s)=>{ let h=2166136261>>>0; for(const c of s){ h^=c.charCodeAt(0); h=Math.imul(h,16777619); } return h>>>0; };
const MAX = 2**32;
const draw = (sk, slot)=> H(sk + ':' + slot) / MAX; // deterministic value in [0,1)
const stake = 0.20; // this validator holds 20%
let wins = 0; const rows = [];
for(let slot=0; slot<10; slot++){
const d = draw('sk-validator-7', slot);
const won = d < stake; // selected if draw < stake
if(won) wins++;
if(slot<5) rows.push('slot ' + slot + ': draw=' + d.toFixed(3) + (won?' ← LEADER':''));
}
rows.push('… over 10 slots won ' + wins + ' (≈ ' + (stake*100) + '% expected)');
rows.push('same (sk, slot) ALWAYS gives the same draw → deterministic & verifiable');
document.getElementById('o').textContent = rows.join('\n');
</script></body></html>