← Back to lotto

Provably-fair proof

This page reproduces the winner computation from public inputs. You can recompute every step in your browser's DevTools — don't trust our math, verify it.

1. Pre-commit (server_seed_hash)

Published when the lotto went live (2026-04-17T02:14:54.177Z).

ceeded0baaea23af17f0684da4202c3d70f70b8a4b09766a6958b248cc994de3

2. Reveal (server_seed)

Revealed after draw (2026-04-18T03:54:37.271Z).

3535d9e1e08fab8b66a31e48f9ead297a92186c9067a30f72c0f6a302239c648

Hash check: ✓ sha256(server_seed) === published hash

3. Client seed inputs (all sold tickets)

#WalletWinner?
2did:pr...1fei
8did:pr...1fei
24did:pr...1fei
26did:pr...1fei
28did:pr...1fei
30did:pr...1fei
33did:pr...1fei
35did:pr...1fei
37did:pr...1fei
41did:pr...1fei
45did:pr...1fei
47did:pr...1fei
51did:pr...1fei
55did:pr...1fei
66did:pr...1fei
72did:pr...1fei
73did:pr...1fei
76did:pr...1fei
88did:pr...1fei
89did:pr...1fei
90did:pr...1fei
91did:pr...1fei🎉
92did:pr...1fei
94did:pr...1fei
127did:pr...1fei
134did:pr...1fei
136did:pr...1fei
157did:pr...1fei
160did:pr...1fei
169did:pr...1fei
172did:pr...1fei
180did:pr...1fei
184did:pr...1fei
190did:pr...1fei
206did:pr...1fei
209did:pr...1fei
213did:pr...1fei
214did:pr...1fei
233did:pr...1fei
238did:pr...1fei
239did:pr...1fei
242did:pr...1fei
243did:pr...1fei
249did:pr...1fei
258did:pr...1fei
262did:pr...1fei
269did:pr...1fei
274did:pr...1fei
276did:pr...1fei
279did:pr...1fei
285did:pr...1fei
286did:pr...1fei
287did:pr...1fei
294did:pr...1fei
309did:pr...1fei
315did:pr...1fei
317did:pr...1fei
318did:pr...1fei
322did:pr...1fei
329did:pr...1fei
330did:pr...1fei
332did:pr...1fei
347did:pr...1fei
352did:pr...1fei
357did:pr...1fei
361did:pr...1fei

4. Derived client_seed

client_seed = sha256(sorted by entry_number, joined as "N:wallet" with '|')

dac65d0bba488f884748987ea262d8d09e64aa7d4850ca1974a345b92fee0983

5. External entropy (Bitcoin block)

Mixed into the HMAC input so the draw depends on a value the operator could not have known when the server seed was committed ( 2026-04-17T02:14:54.177Z). Any Bitcoin block mined after the commit works — we take the tip at draw time.

sourcemempool.spaceheight945,561hash000000000000000000005fc0717695a4ceee2033290ab2a847ed225e15ff172eblock time2026-04-18T03:54:07.000Z

Cross-check on mempool.space or blockstream.info.

6. Winner computation

HMAC-SHA256(server_seed, "client_seed:lotto_id:source:height:hash"), first 16 hex chars, mod sold_count (66).

hmac = 0173151fa6b857616abbedb1137d75865d5ccf4419408f063d38850c5f2e2c12

Computed index: 21 → winning entry: #91

7. Independent verification

Show JS snippet (paste into DevTools)
const seed = "3535d9e1e08fab8b66a31e48f9ead297a92186c9067a30f72c0f6a302239c648";
const hashStr = "ceeded0baaea23af17f0684da4202c3d70f70b8a4b09766a6958b248cc994de3";
const clientSeed = "dac65d0bba488f884748987ea262d8d09e64aa7d4850ca1974a345b92fee0983";
const lottoId = "4d140c15-3cdd-432e-ae8f-aa84eb952c2d";
const sold = 66;
const entropy = "mempool.space:945561:000000000000000000005fc0717695a4ceee2033290ab2a847ed225e15ff172e";

async function run() {
  const enc = new TextEncoder();
  const seedBytes = enc.encode(seed);
  const hashed = await crypto.subtle.digest("SHA-256", seedBytes);
  const recomputed = [...new Uint8Array(hashed)]
    .map((b) => b.toString(16).padStart(2, "0")).join("");
  console.log("hashOk:", recomputed === hashStr);

  const key = await crypto.subtle.importKey(
    "raw", seedBytes, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]
  );
  const message = entropy
    ? clientSeed + ":" + lottoId + ":" + entropy
    : clientSeed + ":" + lottoId;
  const sig = await crypto.subtle.sign("HMAC", key, enc.encode(message));
  const hex = [...new Uint8Array(sig)]
    .map((b) => b.toString(16).padStart(2, "0")).join("");
  const idx = Number(BigInt("0x" + hex.slice(0, 16)) % BigInt(sold));
  console.log("hmac:", hex);
  console.log("winnerIndex:", idx);
}
run();