Įrodomai sąžininga
Patikrinkite patys kiekvieną išdalijimą, kiekvieną metimą ir kiekvieną vietų paskirstymą.
Mūsų stalo žaidimai yra įgūdžių žaidimai: sėkla nulemia tik maišymą, kauliukus ir tai, kas kur sėdi. Kiekvienas tolesnis ėjimas – jūsų. Prieš ką nors išdalijant, serveris įsipareigoja slaptai sėklai, paskelbdamas jos SHA-256 maišos reikšmę. Jūsų paties kliento sėkla įmaišoma, todėl serveris negali pasirinkti išdalijimo ją pamatęs. Kai sėkla atskleidžiama, bet kas gali perskaičiuoti kiekvieną kortą, kiekvieną kauliuką ir kiekvieną plytelę.
Jūsų žaidimai ir kliento sėkla
Kaip tai veikia
- Įsipareigojimas: serveris pasirenka slaptą sėklą (32 atsitiktinius baitus) ir parodo jums jos SHA-256 maišos reikšmę prieš pirmą kortą ar pirmą metimą.
- Jūsų sėkla: jūsų naršyklė prideda kliento sėklą (atsitiktinę arba jūsų išsaugotą). Ji išsiunčiama tik parodžius maišos reikšmę.
- Skaičiai: kiekvienas atsitiktinis skaičius yra HMAC-SHA256(serverio sėkla, pranešimas su visomis klientų sėklomis ir skaitikliu). Pirmieji jo 52 bitai sudaro vieną skaičių.
- Atskleidimas: po žaidimo serverio sėkla paskelbiama. Jos SHA-256 maišos reikšmė turi sutapti su įsipareigojimu, o perskaičiavimas turi duoti būtent tuos išdalijimus, kurie buvo sužaisti.
Nuo skaičių iki kortų, kauliukų ir vietų
52 bitų skaičius atmetimo imtimi paverčiamas sveikuoju skaičiumi, mažesniu už n: skaičius, patekęs į viršutinį nepilną intervalo 2^52 bloką, praleidžiamas ir naudojamas kitas skaitiklis, todėl kiekvienas rezultatas yra lygiai vienodai tikėtinas. Maišymas yra Fisher–Yates iš viršaus: kiekvienam i nuo paskutinės pozicijos žemyn iki 1 parenkamas j, mažesnis už i + 1, ir jie sukeičiami vietomis.
Žaidimas po žaidimo
- Nardai: pradinis metimas ir abu kiekvieno ėjimo kauliukai yra int(6) + 1, ėjimų tvarka.
- Šaškės ir Xiangqi: nei kauliukų, nei kortų. Sėkla nustato, kas pradeda (vietų tvarka).
- Tarneeb, Trix ir Bridžas: vienas 52 kortų kaladės Fisher–Yates maišymas per išdalijimą; vieta i gauna kortas nuo 13i iki 13i + 12.
- Baloot: vienas 32 kortų kaladės maišymas per partiją; likusi kaladės dalis antram išdalijimui sumaišoma iš naujo.
- Madžongas: kiekviena paimta plytelė yra int(likusios plytelės) iš sienos jos nustatyta tvarka – maišymas po vieną plytelę.
- Pokeris: kiekvienas stalas veikia sėklos sesijoje. Prieš kiekvieną išdalijimą stalas įsipareigoja kaladei: Merkle šaknis per jos 52 pozicijas, kur kiekviena pozicija yra korta ir jos pačios druska. Palikę stalą gaunate savo kortas, bendrąsias kortas ir jų Merkle įrodymus, kad galėtumėte jas patikrinti pagal šį įsipareigojimą; kitų žaidėjų kortos neatskleidžiamos. Visa kaladė ir sėkla paskelbiamos, kai sesija pasikeičia: kas 24 valandas, po 500 rankų, kai stalas ištuštėja arba kai serveris paleidžiamas iš naujo.
- Šachmatai: jūsų ryšys turi įsipareigotą sėklą dar prieš jums ieškant žaidimo, metant iššūkį ar pradedant žaidimą prieš botą. Spalvos nustatomos iš abiejų žaidėjų sėklų ir klientų sėklų.
Mačai, sužaisti prieš šią schemą (match_seed_v1), lieka patikrinami: tikrintuvas parenka schemą pagal įrašą.
Tikrinti
Įklijuokite mačo įrašą (jį užpildo jūsų žaidimų mygtukas Tikrinti). Kiekvienas išdalijimas ir metimas atkuriamas pagal paties žaidimo taisykles ir palyginamas su tuo, kas buvo sužaista.
Įveskite mačo sėklas, kad pamatytumėte, ką jos išdalija pradžioje.
Įveskite rankos sėklas, kad perskaičiuotumėte visą jos kaladę, arba įklijuokite kortų įrodymus, gautus palikus stalą, kad patikrintumėte savo kortas ir bendrąsias kortas.
Įveskite abiejų pusių sėklas, kad perskaičiuotumėte, kas žaidžia baltaisiais.
Pusė A (paieškos ar iššūkio autorius)
Pusė B
Patikrinkite patys
// Node.js 18+ — check a table-game match yourself (scheme match_seed_v2)
const { createHash, createHmac } = require('crypto');
const sha256 = (s) => createHash('sha256').update(s).digest('hex');
const word = (key, msg) => BigInt('0x' + createHmac('sha256', key).update(msg).digest('hex').slice(0, 13));
console.log(sha256(serverSeed) === commitment); // 1. the reveal matches the commitment
let k = 0; // 2. the draw stream: one counter per match
const seeds = clientSeeds.map((s, i) => i + '=' + s).join(',');
const next = () => word(serverSeed, 'pf2:' + game + ':' + matchId + ':' + seeds + ':' + (k++));
const SPAN = 1n << 52n;
function int(n) { // 3. whole number below n, no modulo bias
const N = BigInt(n), limit = SPAN - (SPAN % N);
for (;;) { const w = next(); if (w < limit) return Number(w % N); }
}
const die = () => int(6) + 1;
function shuffle(a) { // 4. Fisher–Yates from the top
a = a.slice();
for (let i = a.length - 1; i > 0; i--) { const j = int(i + 1); [a[i], a[j]] = [a[j], a[i]]; }
return a;
}
// seat order (pairings): shuffle([0, 1]) first, then the game's opening deal / roll
// Poker (scheme poker_hmac_v1): hand n of seed session S at table T
const handValue = createHmac('sha256', serverSeed).update('pk1:hand:' + T + ':' + S + ':' + n).digest('hex');
console.log(sha256(handValue) === handCommitment); // stored before the deal
// deck = shuffle([0..51]); key = handValue; message = pk1:T:S:n:{seat}={seed},…:{k}; seats ↑
// rank = id % 13 → 23456789TJQKA; suit = Math.floor(id / 13) → c d h s
// deck commitment (before the deal): salt_i = HMAC(handValue, 'pk1:salt:' + i); leaf_i = sha256('pk1:leaf:' + i + ':' + card_i + ':' + salt_i)
// 64 leaves (52..63 = sha256('pk1:pad')), parent = sha256('pk1:node:' + left + right) → root; on leave you get your leaves + paths
// Chess colour (scheme chess_colour_v1): A = owner of the seek / challenge, B = the other side (a bot adds no seed)
const m = (k) => 'cc1:' + commitA + ':' + (commitB || '-') + ':0=' + clientA + ',1=' + clientB + ':' + k;
// w = word(seedA, m(k)) XOR word(seedB, m(k)); int(2) over w as above → 0 means A plays White
Šio puslapio tikrintuvas veikia jūsų naršyklėje ir nesikreipia į serverį. Atsisiųskite jį, kad paleistumėte neprisijungę: verifier.js