Uso de um oráculo aleatório usando o exemplo da loteria

Certa manhã, me deparei com um artigo sobre um gerador de números aleatórios verificado na blockchain da Waves platform.

O quadro geral estava claro, mas o método de implementação específico não. Quais códigos, assinaturas, o que, para onde, por quê?

Após várias consultas com o autor do oráculo, consegui unir a lógica do sorteio (implementada em PHP) com o algoritmo de geração de números aleatórios.

  1. No início do torneio/rodada, pedimos ao oráculo a primeira parte do código (R-code).

    Nesse momento, não há informações sobre o número de jogadores, nem sobre a quantidade de prêmios, nem sobre o valor das recompensas e até mesmo sobre a existência da loteria. O oráculo emite um código aleatório pessoal através de uma transação, que poderá ser utilizado apenas uma vez e somente por quem o solicitou. A propósito, o R-code pode ser "adquirido" (entenda-se o custo da transação de solicitação + compensação ao oráculo pela transação de resposta, que soma cerca de $0.015 com a taxa atual, e o código em si é fornecido gratuitamente) com antecedência, em quantidades múltiplas, para não precisar esperar pela transação de resposta. Eu criei um pequeno buffer regularmente atualizado no banco de dados.

  2. O torneio normalmente dura 60 blocos na blockchain da Waves platform, o que atualmente equivale a aproximadamente 1 hora. O torneio é considerado realizado e fechado se, após 60 blocos, houver pelo menos dois ingressos, caso contrário, o tempo de atividade do torneio é estendido por mais 60 blocos.
  3. Imediatamente após o fechamento do torneio, formamos e enviamos a transação de dados (também pagamos uma taxa por isso, de aproximadamente $0.005), se necessário — várias transações, nas quais estão fixadas todas as condições do sorteio e uma lista ordenada de jogadores (ingressos) de onde precisamos selecionar os vencedores.
  4. Neste estágio, já temos a primeira parte do código (R-code) e o ID da transação de dados (TXID). Nós os enviamos para assinatura ao oráculo na forma de concatenação (R-code + TXID), novamente pagando a taxa e a compensação. O oráculo verifica os dados recebidos quanto à exclusividade e propriedade, e em resposta nos envia a segunda parte do código (S-code) no formato sha256, que se torna o ponto de partida para o gerador de números aleatórios.
  5. Para obter um número aleatório que indicará o número do bilhete vencedor, transformamos o S-code de dados binários sha256 em uma representação hexadecimal (HEX). Em seguida, a partir da string HEX resultante, obtemos um número. Calculamos o resto da divisão do número obtido pelo número de bilhetes (all_tickets) e adicionamos 1 ao resultado (para obter um número de 1 até all_tickets). No final, obtemos o número do vencedor.
  6. Se, de acordo com as condições do sorteio, houver vários vencedores, repetimos as operações anteriores na quantidade correspondente ao número de prêmios. Cada vez, removemos da lista o bilhete que já ganhou e diminuímos all_tickets em 1, enquanto substituímos o S-code pelo número anteriormente obtido.

Vamos analisar um exemplo real, torneio nº 119:

Um total de 7 bilhetes (all_tickets)
Custo do bilhete 50 moedas (Bet)
Taxa de jogo 10% (Fee)

De acordo com as regras da loteria, 30% vão para os prêmios, ou seja, neste caso, 2 bilhetes devem receber um prêmio, cujo valor é calculado pela fórmula (Bet*all_tickets-Fee)/2.

1. Recebemos o R-code: RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE

2. Após o fechamento do torneio, temos uma lista de bilhetes na forma de pares: número + endereço (endereço da carteira de onde foi feito o pagamento da participação no torneio). Note que os endereços podem se repetir, isso significa que um participante comprou vários bilhetes em um único torneio, o que não é proibido pelas regras.

Enviamos a data da transação: 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

3. Solicitamos o S-code: FTF3uRyaa4F2uAyD6z5a3CNbTXbQLc7fSR6CFNVjgZYV com o comentário (R-code + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

4. Recebemos o S-code: Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC

5. Determinamos os vencedores.

6. Enviamos os pagamentos

Como resultado, temos no blockchain um registro passo a passo do procedimento de sorteio de prêmios, com a possibilidade de verificá-lo a qualquer momento. Manipular os resultados por parte do organizador é praticamente impossível, ao menos que seja de forma imperceptível.

determinar o vencedor nº 1

Todos_ticket:
Índice: 1 Bilhete:139
Índice: 2 Bilhete:141
Índice: 3 Bilhete:143
Índice: 4 Bilhete:145
Índice: 5 Bilhete:147
Índice: 6 Bilhete:149
Índice: 7 Bilhete:151

1. bin -> hex (bin2hex(sha256(S-code))): Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC -> 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596

2. hex -> número gmp: 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 99037963059744689166154019807924045947962565922868104113173478160267437352342

3. gmp -> módulo (mod=7): 99037963059744689166154019807924045947962565922868104113173478160267437352342 -> 4

4. módulo -> bilhete: 4 -> 145

determinar o vencedor nº 2

Todos_ticket:

Índice: 1 Bilhete:139
Índice: 2 Bilhete:141
Índice: 3 Bilhete:143
Índice: 4 Bilhete:147
Índice: 5 Bilhete:149
Índice: 6 Bilhete:151

1. bin -> hex (bin2hex(sha256(hex anterior))): daf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0
2. hex -> número gmp: 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0 -> 67565829218838067182838043983962684143266386786567427968312120473742580659360
3. gmp -> módulo (mod=6): 67565829218838067182838043983962684143266386786567427968312120473742580659360 -> 1
4. módulo -> bilhete: 1 -> 139

Fim.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster