DOCS/LAB-READINESS — GLI-19 §3 POINT BY POINT
sdk-v2/docs/LAB-READINESS.md · commit 96368332 · GLI CSR §2.2: Readiness · ← package index · raw on GitHub ↗RAIN RNG v2.1 — test-lab readiness (GLI-19 chapter 3, RNG)
An honest point-by-point map of the GLI-19 "Interactive Gaming Systems" RNG requirements (chapter 3 in GLI-19 v3.0; the same substance appears in GLI-11 §3 and most jurisdictional RNG standards) to what this SDK does, what only a lab can attest, and what is the operator's problem, not ours. Section numbers below follow GLI-19 v3.0 headings by topic; check the exact numbering against the lab's edition — we describe requirements, not clause IDs.
Status summary: the design satisfies every RNG requirement we know how to satisfy in software; none of it is certified. Nothing in this repo has been evaluated by GLI, BMM, iTech Labs, eCOGRA or any regulator. The submission package is in lab/ (lab/README.md index, mapped to GLI CSR v2.0 §2.2): RNG description in GLI-19 §3 vocabulary (lab/RNG-DESCRIPTION.md), statistical report with raw logs (lab/REPORT-STATISTICAL.md, lab/results/), collection tools, scaling inventory, reproducible build + fingerprints, runtime KATs/self-verification in rng-node, process documents. The before/after checklist is docs/LAB-SUBMISSION-REQUIREMENTS.md §7 (HAVE 13 · PARTIAL 5 · MISSING 2 — pen-test and external audit).
| # | GLI-19 §3 topic (paraphrased) | What RAIN does | Status |
|---|---|---|---|
| 3.1 | Scope / applicability — RNG applies to any outcome that affects a wager | RAIN provides r per round (256 bits) and the draw layer drbg(r, gameId); every game outcome derives from it and nothing else (the engines take no other randomness — the slot example uses one cursor) |
✅ by construction; lab confirms per game |
| 3.2 | Statistical randomness — RNG output must pass recognised statistical tests (chi-square, equidistribution, gap, poker, coupon, permutation, runs, spectral, serial correlation…) at 99 % confidence | Output is HMAC_DRBG (SP 800-90A) or ChaCha20 over a 256-bit key; both are standard, cryptographically strong PRFs. Pre-certification evidence shipped (self-run, 2026-09-13/14): Dieharder 3.31.1 full battery on an unbounded stream (-g 200, never rewinds): chacha20 90 PASSED / 5 WEAK / 0 FAILED (61 of 80 test/ntuple combinations; rgb_lagged_sum 14–32 not run — ≈ 200 GB), hmac-drbg partial (0 FAILED on the tests run); NIST STS 2.1.2 1000 × 10⁶ bits all 15 tests: both mechanisms 188/188 lines inside the confidence interval, all uniformity P ≥ 10⁻⁴; TestU01 SmallCrush 15/15 both mechanisms (Crush/BigCrush not run — data volume); scaled outcomes 10⁸ per game (chacha20) / 2 × 10⁷ (hmac-drbg) + 3 adversarial-player modes: every total-distribution χ² passes at 99 % — lab/REPORT-STATISTICAL.md, raw logs in lab/results/. Two earlier Dieharder file-input runs that rewound are quarantined as invalid (report §8) |
🧪 lab repeats with its own suite on data from lab/tools/collect-raw.mjs / collect-outcomes.mjs (deterministic by seed) |
| 3.3 | Unpredictability — it must be computationally infeasible to predict the next output from previous ones | draw(i) is a PRF output under a key derived from r; r itself needs both parties' unrevealed secrets; secrets are 256-bit, from Web Crypto / OS CSPRNG (randomBytes32) or wallet-derived material |
✅ design; lab reviews source (no third-party crypto; ~400 lines) |
| 3.4 | Non-repeating cycle / period — the RNG period must be sufficiently long that cycles cannot be exploited | Each round has a fresh 256-bit r; within a round the counter i addresses up to 2^53 (HMAC) / 2^32 (ChaCha) independent draws; chains are consumed once and rotate at 90 % (65,536 default) |
✅ |
| 3.5 | Seeding / background cycling / re-seeding — seeds must be unpredictable; RNG may not be seeded from a fixed value; reseeding must not weaken output | Reseed per round, never per session (builder point c): r_k differs for every k and depends on fresh reveals from both chains; the session seed alone predicts nothing. No time-based or fixed seeds. Background cycling is unnecessary and undesirable: outputs are demand-driven by index, and there is no hidden state whose cycle timing could leak |
✅ design (GLI's "background cycling" expectation is satisfied by the per-round reseed argument — expect to explain this) |
| 3.6 | Scaling / mapping — mapping raw output to the game range must be unbiased; modulo bias is prohibited unless negligible | intBelow(i, n): rejection sampling on 32-bit words, exactly uniform for any n ≤ 2^32; float = 53-bit uniform; shuffle = Fisher–Yates with intBelow. Legacy outcomeMod (uint256(r) % N) kept for byte-identity with on-chain verifiers, bias < N/2^256 (negligible under any standard) |
✅ |
| 3.7 | Independence / no correlation between draws or between players | Draw i and draw j are different PRF evaluations; different games under one r are domain-separated (`HMAC(r, "RAIN-RNG-v2.1 |
"+gameId)`); different players have different sessions, seeds and chains |
| 3.8 | RNG state / secrets protection — seeds and state must not be observable or modifiable by unauthorised parties | Unrevealed chain elements are the only secrets; each party holds only its own; B's are in the RAIN node (rng-node store, in memory + WAL/Postgres). No HSM integration yet |
⚠️ partial: operational controls (key storage, access) are the operator's deployment; the reference node is not hardened |
| 3.9 | Game outcome must not be altered after generation; no "near-miss"/outcome selection from multiple draws | r_k is fixed once hRev_k is revealed; the operator server derives it deterministically; a house cannot re-roll (one reveal per k, enforced by chain + cursor); the player can replay the exact draw sequence |
✅ for RAIN; the operator's engine must consume the cursor deterministically (lab checks the engine) |
| 3.10 | Persistence / recovery — after a failure the RNG must not repeat or replay outcomes | Chains cannot be rewound (k monotone); house persists the client commitment before revealing; rng-node replays the same hRev_k for a duplicate (k, decision, pRev) and refuses a different one (crash test in rng-node/test/crash.test.mjs) |
✅ design; operator must run a durable store |
| 3.11 | Documentation of the RNG for the lab — algorithm, seeding, scaling, source code | lab/RNG-DESCRIPTION.md (GLI-19 §3 order, §3.3.2 a/b/c, proofs), lab/SCALING-INVENTORY.md, lab/BUILD.md + lab/FINGERPRINTS.json; docs/RNG.md; source in packages/rng-core/src, packages/rng-py/rain_rng; KATs: NIST CAVP HMAC_DRBG (32), FIPS 180-4, RFC 4231, RFC 8439 — also executed at runtime by rng-node (startup, daily, /selftest; output inhibited on failure) |
✅ |
| 3.12 | Multiple implementations must be equivalent | TS and Python mirrors share generated vectors (drbg-vectors.json, 12 streams × 7 indices, intBelow, shuffle, ceremony); on-chain Solidity verifiers match the TS ceremony (npm run test:live) |
✅ |
| 3.13 | Hardware RNG requirements | Not applicable — software RNG; entropy for secrets from the OS CSPRNG (documented) | n/a |
| 3.14 | RNG for live/multi-player events (shared outcome) | Not covered by rng-session; the Live Crash design (per-round chains, interleaved ticks) exists in the channel protocol only |
➖ out of scope for v2.1 |
What the lab will actually test, and what we can give them
- Source review —
sha256.ts,drbg.ts,keccak.ts,rng.ts(TS),rain_rng/*.py. Zero dependencies, so there is nothing else to review. - Known-answer verification — run
npm test -w @rain/rng-coreandpython3 -m pytest packages/rng-py; add the lab's own CAVP files (the.rspparser used to embed ours is in the repo history ofscripts/). - Statistical suite —
node lab/tools/collect-raw.mjs --bits 32e9 --mechanism chacha|hmac --seed 0x… --workers 4 --out raw.bin(production ceremony +drbg(); deterministic by seed;--out -streams fordieharder -g 200/ TestU01) andnode lab/tools/collect-outcomes.mjs --game dice|roulette|coin|slot-reel|card-shuffle …for scaled data. Our own runs:lab/REPORT-STATISTICAL.md. - Scaling —
intBelowsource is 6 lines; the lab can verify the rejection bound. - Game-level — the operator's engine under
drbg(r, gameId).cursor(): RAIN does not certify game math, RTP, paytables, reel strips, or how many draws a feature consumes.examples/slot-spin-endpoint/paytable.mjsis a mock.
Known gaps (honest)
- No certification, no crypto audit, no pen-test. Statistical suites have been run by us (
lab/REPORT-STATISTICAL.md) but not by an independent lab. - Reference node not hardened (no HSM, no rate limiting beyond what a reverse proxy adds, secrets in process memory).
- Time-to-reveal is a liveness property, not a safety one: a stalled node cannot bias, but it can stall; the escrow protocol (
@rain/channels) turns stalls into faults,rng-sessiondoes not. - Same-entity A and B (operator runs both) removes the "two independent parties" argument unless commitments are published (
RngAnchor.sol/ transparency log). Say so in the submission. - Player-side verification depends on a client that verifies. A malicious or lazy client that trusts the server has no protection — this is inherent to any provably-fair scheme.
- 32-bit compat path exists (
seed32Compat, deprecated, warns). Labs should confirm it is not reachable in production builds.
← Back to the package index · Rendered 2026-09-14 09:34 UTC from the repository copy; the markdown in the zip / repo is the document of record.