Bethropic

Um nonce, vários números: o que o cursor conta

winter_ledger700 visualizações
🌐 Originally written in English· AI translationView original

O quarto input

Toda explicação de jogo provably fair, incluindo a nossa, cita três inputs: uma server seed com a qual a casa se compromete previamente, uma client seed que você pode definir você mesmo, e um nonce que aumenta em um a cada aposta. Alimente-os em um hash com chave e sai a aleatoriedade da rodada. Essa descrição é completa para um coin flip. É incompleta para quase tudo mais, porque um hash produz um número e a maioria dos jogos precisa de vários.

O quarto input é o cursor. Neste site a mensagem que é hasheada não é “client seed-nonce”, mas “client seed-nonce-cursor”, e o cursor é um contador dentro da rodada: 0 para o primeiro número aleatório que o jogo precisa, 1 para o segundo, e assim por diante. Cada valor de cursor gera um digest de 256 bits novo, sem relação alguma com seus vizinhos de forma que você pudesse explorar, e o engine lê os primeiros oito bytes de cada digest como um número entre 0 e 1.

VERIFICADO PELO ENGINE_shared/demoLocal.ts: uAt(pair, cursor) retorna u64(HMAC-SHA256(serverSeed, `${clientSeed}-${nonce}-${cursor}`)), descrito como correspondente ao RandomUtils.generateHash(“clientSeed-nonce-cursor”) do servidor. _shared/rng.ts: u64 lê os primeiros oito bytes do digest como hi/2^32 + lo/2^64, “a mesma construção de arredondamento único” da conversão ULong→Double do servidor. O nonce é um stream único por par de seeds em todos os jogos: cada aposta consome o nonce atual e armazena nonce + 1.

Então uma rodada não é um único número aleatório, mas uma lista numerada deles, tão longa quanto o jogo precisar, e cada item da lista já está fixado no instante em que o par de seeds e o nonce são definidos. O jogo não sorteia conforme avança. Ele lê uma lista que já existe.

O que cada jogo lê

A parte interessante é que a lista é diferente para cada jogo, e cada módulo de derivação declara seu layout em seu cabeçalho. Aqui está o stream de cursores de cada original que se baseia no par de seeds, retirado do código-fonte do engine.

Uso de cursores por rodada, de cada módulo de derivação de jogo

JOGOCURSORES LIDOSNO QUE SE TORNAM
Limbo0Um número através da curva 0.99 ÷ (1 − u)
Roleta0O bolso: floor(u × 37)
Fukubukuro0O item, contra a tabela de pesos da sacola
Sic Bo0, 1, 2Os três dados
Chinchirolado × 9 + tentativa × 3 + dadoAté 18: banca depois jogador, até três lances de três dados cada; um lance que forma uma mão encerra o lado
Koban Flipum por viradaA virada i lê o cursor i; cada face da rodada é fixada quando a primeira moeda é comprada
Omikuji0, depois 1–3, depois 4 em dianteNível de sorte; as três células vencedoras em uma vitória; glifos de preenchimento para o restante
Pagodaum por andarA peça armadilha em cada andar: floor(u × peças)
Video Poker5, mais um por carta trocadaUma sequência sem reposição sobre 52 cartas; mantenha tudo e nenhum cursor adicional é lido
Casino Hold’ematé 9jogador 1, jogador 2, dealer 1, dealer 2, flop 1–3, turn, river; o turn e o river só são lidos em CALL
Blackjackum por cartaSapata infinita, carta = floor(u × 52), na ordem de distribuição: jogador, dealer visível, jogador, dealer oculto, depois cada nova compra
Andar Bahar0–4, depois um por carta disputadaDois buckets potencializados, suas magnitudes, o coringa, depois a disputa até a repetição do rank
Hanabi15 por giroCélula = rolo × 3 + linha; o giro grátis j lê a partir de 15 + 15j
Bingo0–24, depois 25–62A cartela, cinco sorteios por coluna; depois as 38 bolas

Keno e Crash são as exceções: suas rodadas demo usam uma cadeia de hash por bilhete, em vez do nonce do par de seeds, conforme descrito abaixo. Mines e Plinko são resolvidos pelo serviço da casa; a API do mines aponta que todo o layout sai de um único nonce.

VERIFICADO PELO ENGINEComentários de cabeçalho em bingo/derive.ts (“Cursor stream: 0..24 — a cartela … 25..62 — as 38 bolas”), hanabi/engine.ts (“giro base = células 0..14 … giro grátis j = células 15+15j .. 29+15j”), blackjack/derive.ts (“carta i = floor(u × 52) no cursor i … Ordem de distribuição (cursor): player1, dealer-up, player2, dealer-hole”), vpoker/derive.ts (“as cinco primeiras são a distribuição, as substituições continuam a mesma sequência … Manter tudo e nenhum cursor adicional é lido”), holdem/derive.ts (“player1, player2, dealer1, dealer2, flop1, flop2, flop3, turn, river. Os cursores de turn/river só são consumidos em CALL”), andar/derive.ts (cursores 0–4 depois “5.. um cursor por carta disputada”), koban/derive.ts (“a virada i lê o cursor i”), sicbo/derive.ts (“cursores 0/1/2 são os três dados”), roulette/derive.ts (“o cursor 0 sozinho decide a casa: floor(u × 37)”), fuku/derive.ts (“o cursor 0 sozinho sorteia o item”), omikuji/derive.ts (cursor 0 nível, 1..3 células vencedoras, 4.. preenchimentos); demoLocal.ts rollSide (cursor de chinchiro = lado*9 + tentativa*3 + d), trapAt (pagoda: o número do andar é o cursor), demoLimboBet (uAt(p, 0)); mines/minesApi.ts (“todo o layout de minas sai deste único nonce”).

Três coisas se destacam nessa tabela. Primeiro, os jogos que distribuem cartas leem um cursor por carta em ordem fixa, e é por isso que uma mão de blackjack pode ser reproduzida a partir da sua lista de ações: sua decisão de pedir carta não cria uma carta, ela vira a próxima de uma lista que já estava completa antes da distribuição. Segundo, vários jogos param de ler antecipadamente. Uma mão de vídeo pôquer em que você mantém as cinco cartas nunca toca o cursor 5; um fold no Hold'em nunca lê o turn ou o river. Os números estavam lá; o jogo simplesmente não precisou deles. Terceiro, os dois buckets potencializados no Andar Bahar e o nível de sorte no Omikuji são sorteados antes das cartas e células, no início do stream, então os recursos especiais da rodada são fixados pelo mesmo compromisso que os elementos comuns.

Sorteio sem reposição

Um número uniforme entre 0 e 1 é fácil de transformar em uma casa da roleta: multiplique por 37 e arredonde para baixo. Um baralho é mais difícil, porque a segunda carta não pode ser a mesma que a primeira. O engine trata isso com o que seus comentários chamam de pool hop: manter uma lista das cartas ainda no pool, usar o número do cursor para escolher uma posição nela, e trocar a carta escolhida para o fim da lista, de modo que o próximo sorteio escolha entre uma carta a menos. Vídeo Pôquer, Casino Hold'em, Andar Bahar e a cartela do Bingo sorteiam dessa forma, então nenhuma carta ou número se repete dentro de uma rodada.

Blackjack é a exceção deliberada. Sua sapata é infinita: cada carta é floor(u × 52) a partir do seu próprio cursor, e a mesma carta pode aparecer duas vezes em uma mão. Essa é uma escolha de design com um custo publicado, discutido em o artigo sobre pagamento do blackjack, e é exatamente o tipo de coisa que o layout de cursores revela e que uma página de marketing não revelaria.

VERIFICADO PELO ENGINEvpoker/derive.ts: “As cartas vêm de UMA sequência sem reposição sobre o baralho de 52 cartas (pool-hop, cursor por sorteio)”. holdem/derive.ts: “UMA sequência de pool-hop sem reposição (cursor por sorteio)”. bingo/derive.ts: “cinco sorteios de pool-hop por coluna” e “as 38 bolas, pool-hops sobre 1..75”. blackjack/derive.ts: “Sapata infinita: carta i = floor(u × 52) no cursor i”.

As duas exceções

Keno e Crash não leem o nonce do par de seeds em nenhum momento no motor de demonstração. O Keno usa um esquema por bilhete: o bilhete recebe seu próprio hash aleatório e um salt, e cada uma das dez bolas é sorteada aplicando hash novamente sobre o hash anterior, pegando os bits iniciais como um número e escolhendo do pool decrescente de quarenta. O painel de fairness verifica um bilhete de keno a partir dessas duas strings, e não a partir do par de seeds. O Crash segue a convenção do bustabit, uma cadeia de hashes em que o ponto de crash de cada rodada é calculado a partir do seu próprio elo com aritmética de inteiros exata.

VERIFICADO PELO MOTORdemoLocal.ts kenoDraws: “cadeia randomHash por aposta + salt (verificável por bilhete via o modal de fairness) … Não toca o nonce do par de seeds”; o loop aplica HMAC-SHA256(salt, hash anterior) dez vezes, lê os 52 bits iniciais e escolhe o índice floor(norm × restante) de um pool de 40 números com uma troca para o final. rng.ts h52 e o comentário do crash: “ponto de crash do bustabit em centésimos: floor((n·e − h)/(e − h)), e = 2^52, n = 100 … Matemática exata com BigInt para bater com o servidor”.

Nenhuma das exceções é mais fraca que o esquema do cursor; ambas são mais antigas e mais conhecidas. O que importa para o jogador é apenas que o painel mostre qual esquema uma rodada usou, e que cada um possa ser recalculado a partir das strings que exibe.

O que isso significa na mesa

  • A rodada já existe antes de você agir. Cada carta, bola e símbolo de rolo de uma rodada é uma função do par de seeds, do nonce e da posição do cursor. Pedir carta, chamar ou manter escolhe quais entradas serão lidas, não o que elas contêm.
  • Suas escolhas não podem mudar a lista, e a casa também não. Uma vez que a seed do servidor está comprometida e o nonce está fixado, ninguém de nenhum dos lados pode alterar a entrada 7 sem alterar a seed, o que quebraria a fingerprint que foi mostrada a você.
  • Um verificador precisa ler a mesma lista da mesma forma. Recalcular uma rodada de bingo significa derivar todos os 63 cursores na ordem publicada; recalcular um fold de Hold'em significa derivar 7. O painel de seed faz isso no seu navegador, e os layouts na tabela acima são o que ele segue.
  • Uma sequência é uma lista, não um estado de espírito. Duas rodadas não compartilham nada além do par de seeds; seus nonces diferem e, portanto, cada digest difere. Esse é o mesmo ponto que o artigo sobre a mão quente faz a partir do outro ângulo.
Três entradas decidem a rodada. A quarta decide quanto tempo dura a rodada. o cursor, em uma linha

Os layouts de cursor acima são lidos dos módulos de derivação do lado cliente que o verificador do navegador e o motor de demonstração compartilham. O serviço da casa é a autoridade pagante; onde um comentário no código-fonte diz que um módulo espelha o servidor, isso é citado como está escrito, não certificado por nós.

Perguntas frequentes

O que é o cursor em uma rodada provably fair?

Um contador dentro da rodada. A mensagem hasheada com a seed do servidor é “client seed-nonce-cursor”; o cursor 0 dá o primeiro número aleatório que o jogo precisa, o cursor 1 o segundo, e assim por diante. Um jogo que precisa de apenas um número lê somente o cursor 0.

Como o cursor é diferente do nonce?

O nonce conta as rodadas e aumenta em um a cada aposta em cada original. O cursor conta os sorteios dentro de uma rodada e reinicia em 0 a cada rodada. Junto com o par de seeds, eles identificam cada número aleatório que o site já produziu.

Quantos números aleatórios uma rodada de bingo usa?

Sessenta e três: os cursores 0 a 24 organizam as 25 células da cartela e os cursores 25 a 62 sorteiam as 38 bolas, tudo sem reposição dentro de seus pools.

Pedir carta no blackjack muda a próxima carta?

Não. Cada carta é derivada do seu próprio cursor na ordem de distribuição, e a lista inteira já existe assim que o par de seeds e o nonce estão fixados. Pedir carta lê a próxima entrada; manter deixa ela não lida.

Todos os jogos usam o esquema de cursor?

Keno e Crash usam cadeias de hash em vez disso: o keno faz hash de um hash aleatório por bilhete e salt dez vezes, e o crash segue a cadeia bustabit com aritmética de inteiros exata. O painel de fairness verifica cada um a partir das strings que exibe.

FONTES & REFERÊNCIAS

  • Código-fonte do engine Betkyo: _shared/demoLocal.ts (uAt, rollSide, trapAt, kenoDraws), _shared/rng.ts (u64, h52, crash point), e os módulos de derivação para bingo, hanabi, blackjack, vpoker, holdem, andar, koban, sicbo, roulette, fuku e omikuji
  • RFC 2104 — HMAC: Keyed-Hashing for Message Authentication
  • Esquema provably fair do Bustabit (a construção do crash-point que o engine espelha)

OS JOGOS DESTE ARTIGO

Blackjack — regras e jogo grátis →Bingo — regras e jogo grátis →Sic Bo — regras e jogo grátis →

Um nonce, vários números: o que o cursor conta

Comentários (1)

  • winter_anchor36

    So the cursor is basically just tracking which random number you're on within a single round? That makes sense for games that need multiple values per bet.