Fairness audit
Fairness Audit — Mental-Poker Shuffle
Verdict: PASS — the shuffle is statistically indistinguishable from a uniformly random 52-card permutation at significance level α = 0.001.
- Generated: 2026-07-12T00:00:00Z
- Seed:
1337(deterministic; reproducible on any machine) - Players: 2
- Deck size: 52
- Hands sampled: 200,000
1. What this proves
A poker deal is only fair if, after the shuffle, every card is equally likely to land in every position and no coalition short of all players can predict or bias the outcome. This audit measures exactly that property on the shuffle produced by @poker/engine's multiparty ceremony.
For each of 200,000 independent hands we run the full ceremony: an ordered deck is trivially encrypted under the players' aggregate public key; each player in turn re-encrypts and permutes the whole deck (shuffleDeck); then the deck is fully decrypted using every player's decryption share (decryptionShare + combineShares) and decoded back to card indices. We tally, for every (position, card) pair, how often card v landed at position p, and test that distribution against the uniform expectation with a Pearson chi-square goodness-of-fit test.
2. Trust model (n-of-n)
The deck is encrypted under the aggregate key P = Σ Pᵢ of all seated players. Decryption requires every player's share, so:
- A single honest player is enough to keep cards secret before they are opened.
- A single honest shuffle is enough to make the final order uniform: composing any permutation with one uniformly random permutation yields a uniform permutation.
This audit reflects both properties. In particular the one-honest-player result below is generated with one seat shuffling honestly and the other applying the identity permutation — the deck is still uniformly mixed.
3. Scope and honesty
This audit certifies the uniformity of the shuffle given honest re-encryption: that the ceremony's re-encryption-and-permute step, followed by full decryption, yields a uniform permutation and never corrupts the deck. It does not by itself force players to re-encrypt honestly on-chain — that is the job of the zero-knowledge verifiable-shuffle proof (Bayer–Groth) checked at the verifyShuffle seam and enforced by the on-chain arbiter. That ZK component is a separate, independently specified part of the system; this report is the statistical half of the fairness claim, not the whole of it.
Method note: crypto vs. fast path
The EC-ElGamal re-encryption shuffle is a plaintext-preserving bijection: the decrypted order depends only on the composed permutations, never on the encryption blinding. We exploit this to make a large sample tractable. A 6-hand sample is run through the full cryptographic round-trip and compared hand-for-hand against the integer permutation composition; they matched: yes. The large 200,000-hand statistical sample is then computed over the verified-equivalent integer path. The committed test suite re-runs both and asserts the equivalence, so the statistics stand on the real ceremony, not a simplified model.
4. Results
Validity
- Valid 52-card permutations: 200,000 / 200,000 (100%)
- No duplicate or missing card in any hand.
- Identity (unshuffled) outcomes: 0 — the deck is always mixed.
- Average fixed points per hand: 1 (a uniform permutation expects 1.0).
Uniformity — pooled chi-square goodness-of-fit
| Quantity | Value |
|---|---|
| Chi-square statistic (X²) | 2654.42 |
| Degrees of freedom | 2652 |
| Expected count per cell | 3846.15 |
| Critical value (α = 0.001) | 2882.78 |
| p-value | 4.831e-1 |
| Result | PASS (X² < critical) |
The 52×52 table of (position, card) counts is tested against a flat expectation of 3846.15 per cell. Degrees of freedom = 52 × 51 = 2652 (one linear constraint per position row). Because each hand is a permutation the position rows are weakly dependent, so this pooled statistic is a conservative summary rather than an exact joint law; the per-position tests below are exact goodness-of-fit tests.
Uniformity — per-position summary
- Positions passing an individual goodness-of-fit test (df = 51, α = 0.001, critical ≈ 88.05): 52 / 52.
One honest player suffices
With one seat shuffling honestly and the other applying the identity permutation:
- Chi-square statistic: 2577.15 (critical 2882.78)
- Result: PASS — a single honest shuffle uniformly mixes the deck.
5. Reproduce
# Deterministic gate (fast; asserts the thresholds below):
pnpm --filter @poker/engine run test
# Regenerate this report (larger sample):
pnpm --filter @poker/engine run fairness:report -- --seed 1337 --rounds 200000
Because the audit is fully seeded, re-running with the same seed reproduces these numbers exactly. The committed test src/tests/fairness.test.ts pins seed 1337, 20,000 hands and α = 0.001.
Machine-readable results: latest.json.