RSA aleatório no blockchain

Há um problema - é difícil gerar um número aleatório em uma rede descentralizada. Quase todos os blockchains já encontraram isso. Na verdade, em redes onde não há confiança entre os utilizadores, criar um número aleatório inegável resolve muitos problemas.

Neste artigo contamos como conseguimos resolver o problema usando os jogos como exemplo. O primeiro deles foi Árvore de Natal Ondas. Para o desenvolvimento, precisávamos de um gerador de números aleatórios.

RSA aleatório no blockchain

Inicialmente, planejamos gerar um número com base nas informações do blockchain. Porém, ficou claro: o número pode ser manipulado, o que significa que a solução não é adequada.

Criamos uma solução alternativa: use o esquema commit-expand. O servidor adivinhou um número de 1 a 5, adicionou um sal a ele e, em seguida, fez o hash do resultado usando Funções Keccak. O servidor implantou antecipadamente o contrato inteligente com o número já salvo. Acontece que o jogo se resume ao usuário adivinhar o número escondido pelo hash.

O jogador fez uma aposta e o servidor enviou o número oculto e o “sal” para o contrato inteligente. Em termos simples, ele revelou as cartas. Depois disso, o servidor verificou os números e decidiu se o usuário ganhou ou perdeu.

Caso o servidor não enviasse um número ou “sal” para verificação, o usuário ganhava. Nesse caso, para cada jogo foi necessário implantar antecipadamente um contrato inteligente e incluir nele ganhos potenciais. Acabou sendo inconveniente, demorado e caro. Naquela época não havia outra solução segura.

Recentemente, a equipe Tradisys propôs adicionar uma função ao protocolo Waves rsaVerificar(). Verifica a validade da assinatura RSA com base na chave pública e privada. Como resultado, o recurso foi adicionado.

Desenvolvemos três jogos: Rolo diz, Coin Flip и Passeio nas ondas. Cada um implementa tecnologia de números aleatórios. Vamos descobrir como isso funciona.

RSA aleatório no blockchain

Vejamos como gerar um número aleatório usando Ride on Waves como exemplo. O contrato inteligente pode ser encontrado aqui.

Vá para a guia Script e selecione descompilado. Você verá o código do contrato inteligente (também conhecido como script).

RSA aleatório no blockchain

O código do contrato inteligente contém um conjunto de funções. Aqueles marcados como @Callable podem ser iniciados usando Transações de invocação. Estamos interessados ​​em duas funções: aposta и retirar:

  • aposta func (playerChoice)
  • func retirar(gameId,rsaSign)

1. O usuário seleciona a duração do segmento e o tamanho da aposta.

RSA aleatório no blockchain

2. O cliente cria uma função de aposta. Para a imagem acima seria aposta("50").

3. O cliente envia uma transação de Invocação para o endereço do contrato inteligente (broadcast InvocationTx). A transação contém a função bet como parâmetro de chamada. Isso significa que a transação de Invocação aciona a execução da função de aposta (escolha: String) no contrato inteligente.

RSA aleatório no blockchain

4. Considere a função de aposta:

@Callable(i)
func bet (playerChoice) = {
    let newGameNum = IncrementGameNum()
    let gameId = toBase58String(i.transactionId)
    let pmt = extract(i.payment)
    let betNotInWaves = isDefined(pmt.assetId)
    let feeNotInWaves = isDefined(pmt.assetId)
    let winAmt = ValidateBetAndDefineWinAmt(pmt.amount, playerChoice)
    let txIdUsed = isDefined(getString(this, gameId))
    if (betNotInWaves)
        then throw ("Bet amount must be in Waves")
        else if (feeNotInWaves)
            then throw ("Transaction's fee must be in Waves")
            else if (txIdUsed)
                then throw ("Passed txId had been used before. Game aborted.")
                else {
                    let playerPubKey58 = toBase58String(i.callerPublicKey)
                    let gameDataStr = FormatGameDataStr(STATESUBMITTED, playerChoice, playerPubKey58, height, winAmt, "")
                    ScriptResult(WriteSet(cons(DataEntry(RESERVATIONKEY, ValidateAndIncreaseReservedAmt(winAmt)), cons(DataEntry(GAMESCOUNTERKEY, newGameNum), cons(DataEntry(gameId, gameDataStr), nil)))), TransferSet(cons(ScriptTransfer(SERVER, COMMISSION, unit), nil)))
                    }
    }

A função grava um novo jogo no estado do contrato inteligente. Nomeadamente:

  • Identificador exclusivo para um novo jogo (ID do jogo)
  • Estado do jogo = ENVIADO
  • Escolha do jogador (comprimento do segmento 50)
  • Chave pública
  • Ganhos potenciais (dependendo da aposta do jogador)

RSA aleatório no blockchain

Esta é a aparência de um registro de dados no blockchain (valor-chave):

{
    "type": "string",
    "value": "03WON_0283_448t8Jn9P3717UnXFEVD5VWjfeGE5gBNeWg58H2aJeQEgJ_06574069_09116020000_0229",
    "key": "2GKTX6NLTgUrE4iy9HtpSSHpZ3G8W4cMfdjyvvnc21dx"
  }

"Chave" (chave) – ID do jogo novo jogo. Os dados restantes estão contidos na linha do campo “valor”. Essas entradas são armazenadas na guia Data contrato inteligente:

RSA aleatório no blockchain

RSA aleatório no blockchain

5. O servidor “olha” o contrato inteligente e encontra a transação enviada (novo jogo) usando a API blockchain. O ID do novo jogo já está registrado no blockchain, o que significa que não pode mais ser alterado ou influenciado

6. O servidor gera uma função de retirada (gameId, rsaSign). Por exemplo, assim:

withdraw ("FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq", "base64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5/qO8COA+QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL/TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk/GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY/0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr/ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa/QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr/q0x6Bg==")

7. O servidor envia uma transação de Invocação para o contrato inteligente (broadcast InvocationTx). A transação contém uma chamada para a função de retirada formada (gameId, rsaSign):

RSA aleatório no blockchain

A função contém ID do jogo novo jogo e o resultado da assinatura RSA de um identificador exclusivo com uma chave privada. O resultado da assinatura permanece inalterado.

O que isso significa?

Pegamos o mesmo valor (ID do jogo) e aplicamos o método de assinatura RSA a ele. Sempre obteremos o mesmo resultado. É assim que funciona o algoritmo RSA. O número final não pode ser manipulado, pois o id do jogo e o resultado da aplicação do RSA não são conhecidos. Escolher um número também é inútil.

8. Blockchain aceita a transação. Ele executa a função de retirada (gameId, rsaSign)

9. Dentro da função de saque, ocorre o saque Funções GenerateRandInt (gameId, rsaSign). Este é um gerador de números aleatórios

# @return 1 ... 100
func GenerateRandInt (gameId,rsaSign) = {
   	# verify RSA signature to proof random
    let rsaSigValid = rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)
    if (rsaSigValid)
        then {
            let rand = (toInt(sha256(rsaSign)) % 100)
            if ((0 > rand))
                then ((-1 * rand) + 1)
                else (rand + 1)
            }
        else throw ("Invalid RSA signature")
    }

rand - e há um número aleatório.

Primeiro, é obtida a string, que é o resultado da assinatura RSA ID do jogo chave privada (rsaSign). Em seguida, hash com SHA-256 (sha256(rsaSign)).

Não podemos prever o resultado da assinatura e do hash subsequente. Portanto, é impossível influenciar a geração de um número aleatório. Para obter um número em um determinado intervalo (por exemplo, de 1 a 100), use a função de conversão toInt e %100 (semelhante a mod).

No início do artigo mencionamos a função rsaVerificar(), que permite verificar a validade de uma assinatura RSA usando uma chave privada em relação a uma pública. Aqui está a parte GenerateRandInt(gameId,rsaSign):

rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)

A chave pública RSAPUBLIC e a sequência rsaSign são passadas para a entrada. A assinatura é verificada quanto à validade. O número é gerado se a verificação for bem-sucedida. Caso contrário, o sistema considera que a assinatura não é válida (Assinatura RSA inválida).

O servidor deve assinar o ID do jogo com uma chave privada e enviar uma assinatura Rsa válida em 2880 blocos. O parâmetro é configurado ao implantar o contrato inteligente. Se nada acontecer dentro do tempo estipulado, o usuário ganha. Neste caso, o prêmio deverá ser enviado você mesmo para o seu endereço. Acontece que “não é lucrativo para o servidor trapacear”, porque isso leva a perdas. Abaixo está um exemplo.

RSA aleatório no blockchain

O usuário está jogando Rolo diz. Escolhi 2 dos 6 lados do cubo, a aposta é 14 ONDAS. Se o servidor não enviar uma assinatura RSA válida para o contrato inteligente dentro do tempo especificado (2880 blocos), o usuário receberá 34.44 WAVES.

Para gerar números em jogos, usamos um oráculo – um sistema externo e não blockchain. O servidor executa uma assinatura RSA do ID do jogo. O contrato inteligente verifica a validade da assinatura e determina o vencedor. Se o servidor não enviar nada, o usuário ganha automaticamente.

Este é um método de geração honesto, porque a manipulação é tecnicamente impossível. Todos os jogos Tradisys funcionam com base no algoritmo descrito. É assim que funcionam os jogos blockchain. Tudo é transparente e verificável. Não existem análogos de tal sistema em qualquer outro blockchain. Isso é bastante aleatório.

Fonte: habr.com

Adicionar um comentário