De vierde input
Elke uitleg van provably fair gaming, inclusief de onze, noemt drie inputs: een server seed waartoe het huis zich vooraf verplicht, een client seed die je zelf kunt instellen, en een nonce die met elke inzet met één omhoog gaat. Voer ze in een keyed hash in en daar komt de willekeur van de ronde uit. Die beschrijving is compleet voor een coinflip. Ze is onvolledig voor bijna al het andere, omdat een hash één getal produceert en de meeste games er meerdere nodig hebben.
De vierde input is de cursor. Op deze site is het bericht dat gehasht wordt niet “client seed-nonce” maar “client seed-nonce-cursor”, en de cursor is een teller binnen de ronde: 0 voor het eerste willekeurige getal dat het spel nodig heeft, 1 voor het tweede, enzovoort. Elke cursorwaarde levert een nieuwe 256-bit digest op, op geen enkele manier te exploiteren gerelateerd aan zijn buren, en de engine leest de eerste acht bytes van elke digest als een getal tussen 0 en 1.
ENGINE-GEVERIFIEERD_shared/demoLocal.ts: uAt(pair, cursor) retourneert u64(HMAC-SHA256(serverSeed, `${clientSeed}-${nonce}-${cursor}`)), beschreven als overeenkomend met de RandomUtils.generateHash(“clientSeed-nonce-cursor”) van de server. _shared/rng.ts: u64 leest de eerste acht bytes van de digest als hi/2^32 + lo/2^64, “dezelfde single-rounding constructie” als de ULong→Double-conversie van de server. De nonce is één stream per seed-paar over alle games heen: elke inzet verbruikt de huidige nonce en slaat nonce + 1 op.
Een ronde is dus niet één willekeurig getal maar een genummerde lijst ervan, zo lang als het spel nodig heeft, en elk item op de lijst ligt vast zodra het seed-paar en de nonce vaststaan. Het spel trekt niet gaandeweg. Het leest een lijst af die al bestaat.
Wat elk spel leest
Het interessante deel is dat de lijst voor elk spel anders is, en elke derivatiemodule vermeldt zijn indeling in de header. Hier is de cursorstream van elk origineel dat put uit het seed-paar, afkomstig uit de engine-broncode.
| SPEL | GELEZEN CURSORS | WAT ZE WORDEN |
|---|---|---|
| Limbo | 0 | Eén getal door de 0.99 ÷ (1 − u) curve |
| Roulette | 0 | De pocket: floor(u × 37) |
| Fukubukuro | 0 | Het item, afgezet tegen de gewichtstabel van de tas |
| Sic Bo | 0, 1, 2 | De drie dobbelstenen |
| Chinchiro | kant × 9 + poging × 3 + dobbelsteen | Tot 18: eerst de dealer, dan de speler, tot drie worpen van elk drie dobbelstenen; een worp die een hand vormt beëindigt de kant |
| Koban Flip | één per flip | Flip i leest cursor i; elk vlak van de rit ligt vast zodra de eerste munt is gekocht |
| Omikuji | 0, dan 1–3, dan 4 en verder | Fortuinniveau; de drie winnende vakjes bij een winst; vulsymbolen voor de rest |
| Pagode | één per verdieping | De valstriktegel op elke verdieping: floor(u × tegels) |
| Video Poker | 5, plus één per ingewisselde kaart | Eén reeks zonder terugleggen over 52 kaarten; alles vasthouden betekent dat er geen verdere cursor wordt gelezen |
| Casino Hold’em | tot 9 | speler 1, speler 2, dealer 1, dealer 2, flop 1–3, turn, river; de turn en river worden alleen gelezen bij CALL |
| Blackjack | één per kaart | Oneindige shoe, kaart = floor(u × 52), in deelvolgorde: speler, dealer open, speler, dealer verdekt, daarna elke volgende trekking |
| Andar Bahar | 0–4, daarna één per gespeelde kaart | Twee versterkte buckets, hun waarden, de joker, daarna de race totdat de rang zich herhaalt |
| Hanabi | 15 per spin | Cel = rol × 3 + rij; free spin j leest vanaf 15 + 15j |
| Bingo | 0–24, daarna 25–62 | De kaart, vijf trekkingen per kolom; daarna de 38 ballen |
Keno en Crash zijn de uitzonderingen: hun demoronden gebruiken een per-ticket hash-keten in plaats van het seed-paar nonce, hieronder beschreven. Mines en Plinko worden afgehandeld door de house service; de mines API vermeldt dat de hele lay-out uit één nonce komt.
ENGINE-GEVERIFIEERDHeadercommentaren in bingo/derive.ts (“Cursor stream: 0..24 — de kaart … 25..62 — de 38 ballen”), hanabi/engine.ts (“basis spin = cellen 0..14 … free spin j = cellen 15+15j .. 29+15j”), blackjack/derive.ts (“kaart i = floor(u × 52) bij cursor i … Deelvolgorde (cursor): speler1, dealer-open, speler2, dealer-verdekt”), vpoker/derive.ts (“de eerste vijf zijn de deal, vervangingen zetten dezelfde reeks voort … Hold everything betekent geen verdere cursor wordt gelezen”), holdem/derive.ts (“speler1, speler2, dealer1, dealer2, flop1, flop2, flop3, turn, river. De turn/river cursors worden alleen verbruikt bij CALL”), andar/derive.ts (cursors 0–4 daarna “5.. één cursor per gespeelde kaart”), koban/derive.ts (“flip i leest cursor i”), sicbo/derive.ts (“cursors 0/1/2 zijn de drie dobbelstenen”), roulette/derive.ts (“cursor 0 alleen bepaalt de pocket: floor(u × 37)”), fuku/derive.ts (“cursor 0 alleen trekt het item”), omikuji/derive.ts (cursor 0 tier, 1..3 winnende cellen, 4.. opvulling); demoLocal.ts rollSide (chinchiro cursor = side*9 + attempt*3 + d), trapAt (pagode: het verdiepingsnummer is de cursor), demoLimboBet (uAt(p, 0)); mines/minesApi.ts (“de hele mijnenlay-out komt uit deze ene nonce”).
Drie dingen vallen op in die tabel. Ten eerste lezen de spellen die kaarten delen één cursor per kaart in een vaste volgorde, waardoor een blackjackhand kan worden nagespeeld vanuit zijn actielijst: je beslissing om te hitten creëert geen kaart, het draait de volgende om op een lijst die al compleet was voordat de deal begon. Ten tweede stoppen sommige spellen vroeg met lezen. Een video poker-hand waarbij je alle vijf kaarten houdt, raakt cursor 5 nooit aan; een Hold'em-fold leest nooit de turn of river. De getallen waren er, het spel had ze gewoon niet nodig. Ten derde worden de twee versterkte buckets in Andar Bahar en de fortune tier in Omikuji getrokken vóór de kaarten en cellen, aan het begin van de stream, zodat de speciale functies van de ronde door dezelfde commitment worden vastgelegd als de gewone.
Trekken zonder teruglegging
Een uniform getal tussen 0 en 1 is makkelijk om te zetten in een roulette pocket: vermenigvuldig met 37 en rond naar beneden af. Een kaartspel is lastiger, omdat de tweede kaart niet opnieuw de eerste kaart mag zijn. De engine regelt dit met wat de commentaren een pool hop noemen: houd een lijst bij van de kaarten die nog in de pool zitten, gebruik het cursorgetal om een positie erin te kiezen, en wissel de gekozen kaart naar het einde van de lijst zodat de volgende trekking uit één minder kiest. Video Poker, Casino Hold'em, Andar Bahar en de Bingo-kaart trekken allemaal op deze manier, zodat geen kaart of getal binnen een ronde herhaalt.
Blackjack is de bewuste uitzondering. Zijn shoe is oneindig: elke kaart is floor(u × 52) van zijn eigen cursor, en dezelfde kaart kan twee keer voorkomen in een hand. Dat is een ontwerpkeuze met een gepubliceerde kostprijs, besproken in het blackjack-uitbetalingsartikel, en het is precies het soort ding dat de cursorlay-out je vertelt dat een marketingpagina niet zou vertellen.
ENGINE-GEVERIFIEERDvpoker/derive.ts: “Kaarten komen uit ÉÉN zonder-teruglegging-reeks over het kaartspel van 52 kaarten (pool-hop, cursor per trekking)”. holdem/derive.ts: “ÉÉN zonder-teruglegging pool-hop reeks (cursor per trekking)”. bingo/derive.ts: “vijf pool-hop trekkingen per kolom” en “de 38 ballen, pool-hops over 1..75”. blackjack/derive.ts: “Oneindige shoe: kaart i = floor(u × 52) bij cursor i”.
De twee uitzonderingen
Keno en Crash lezen de seed-pair nonce helemaal niet in de demo-engine. Keno gebruikt een per-ticket schema: het ticket krijgt zijn eigen willekeurige hash en een salt, en elk van de tien ballen wordt getrokken door de vorige hash opnieuw te hashen, de eerste bits als getal te nemen en te kiezen uit de krimpende pool van veertig. Het fairness-paneel verifieert een keno-ticket op basis van die twee strings in plaats van het seed-paar. Crash volgt de bustabit-conventie, een keten van hashes waarbij het crashpunt van elke ronde wordt berekend uit zijn eigen schakel met exacte integer-rekenkunde.
ENGINE-GEVERIFIEERDdemoLocal.ts kenoDraws: “per-bet randomHash-keten + salt (per ticket verifieerbaar via de fairness-modal) … Raakt de seed-pair nonce niet aan”; de loop hasht HMAC-SHA256(salt, vorige hash) tien keer, leest de eerste 52 bits en kiest index floor(norm × resterend) uit een pool van 40 getallen met een swap naar het einde. rng.ts h52 en het crash-commentaar: “bustabit crashpunt in honderdsten: floor((n·e − h)/(e − h)), e = 2^52, n = 100 … Exacte BigInt-rekenkunde om overeen te komen met de server”.
Geen van beide uitzonderingen is zwakker dan het cursorschema; beide zijn ouder en beter bekend. Wat voor een speler telt, is alleen dat het paneel toont welk schema een ronde gebruikte, en dat elk kan worden herberekend op basis van de strings die het toont.
Wat het aan de tafel betekent
- De ronde bestaat al voordat je handelt. Elke kaart, bal en reel-symbool van een ronde is een functie van het seed-paar, de nonce en zijn cursorpositie. Hitten, callen of houden bepaalt welke items worden gelezen, niet wat ze bevatten.
- Jouw keuzes kunnen de lijst niet veranderen, en het huis ook niet. Zodra de server seed is vastgelegd en de nonce is vastgesteld, kan niemand aan beide kanten item 7 wijzigen zonder de seed te wijzigen, wat de vingerafdruk die je te zien kreeg zou breken.
- Een verificateur moet dezelfde lijst op dezelfde manier lezen. Het herberekenen van een bingoronde betekent het afleiden van alle 63 cursors in de gepubliceerde volgorde; het herberekenen van een Hold'em fold betekent het afleiden van 7. Het seed-paneel doet dit in je browser, en de indelingen in de tabel hierboven zijn wat het volgt.
- Een reeks is een lijst, geen stemming. Twee rondes delen niets behalve het seed-paar; hun nonces verschillen en dus verschilt elke digest. Dit is hetzelfde punt dat het artikel over de hot hand vanuit de andere richting maakt.
Drie inputs bepalen de ronde. De vierde bepaalt hoe lang de ronde is.de cursor, in één regel
De cursorindelingen hierboven zijn afgelezen uit de client-side afleidingsmodules die de browser-verificateur en de demo-engine delen. De huisdienst is de betalende autoriteit; waar een commentaar in de broncode zegt dat een module de server weerspiegelt, wordt dat geciteerd zoals geschreven, niet door ons gecertificeerd.
Veelgestelde vragen
Wat is de cursor in een provably fair ronde?
Een teller binnen de ronde. Het bericht dat wordt gehasht met de server seed is “client seed-nonce-cursor”; cursor 0 geeft het eerste willekeurige getal dat het spel nodig heeft, cursor 1 het tweede, enzovoort. Een spel dat één getal nodig heeft, leest alleen cursor 0.
Hoe verschilt de cursor van de nonce?
De nonce telt rondes en gaat met elke inzet bij elk origineel met één omhoog. De cursor telt trekkingen binnen één ronde en begint elke ronde weer bij 0. Samen met het seed-paar identificeren ze elk willekeurig getal dat de site ooit produceert.
Hoeveel willekeurige getallen gebruikt een bingoronde?
Drieënzestig: cursors 0 tot 24 leggen de 25 vakjes van de kaart vast en cursors 25 tot 62 trekken de 38 ballen, allemaal zonder teruglegging binnen hun pools.
Verandert hitten bij blackjack de volgende kaart?
Nee. Elke kaart wordt afgeleid van zijn eigen cursor in deelvolgorde, en de hele lijst bestaat al zodra het seed-paar en de nonce zijn vastgesteld. Hitten leest het volgende item; passen laat het ongelezen.
Gebruiken alle games hetzelfde cursorschema?
Keno en Crash gebruiken in plaats daarvan hashketens: keno hasht een random hash en salt per ticket tien keer, en crash volgt de bustabit-keten met exacte integer-rekenkunde. Het fairness-paneel verifieert elk resultaat aan de hand van de getoonde strings.
BRONNEN & REFERENTIES
- Betkyo engine-broncode: _shared/demoLocal.ts (uAt, rollSide, trapAt, kenoDraws), _shared/rng.ts (u64, h52, crash point), en de afleidingsmodules voor bingo, hanabi, blackjack, vpoker, holdem, andar, koban, sicbo, roulette, fuku en omikuji
- RFC 2104 — HMAC: Keyed-Hashing for Message Authentication
- Bustabit provably fair-schema (de crash-point-constructie die de engine weerspiegelt)
DE GAMES IN DIT ARTIKEL
Blackjack — regels & gratis spelen →Bingo — regels & gratis spelen →Sic Bo — regels & gratis spelen →