No mundo dos aplicativos descentralizados, obter aleatoriedade é um aspecto crucial para vários casos de uso, como jogos, loterias e operações criptográficas. No entanto, a geração de números realmente aleatórios de forma determinística e transparente impõe desafios únicos. Neste artigo, explorarei diferentes técnicas e melhores práticas para obter aleatoriedade no Solidity.
Pseudoaleatoriedade vs. Aleatoriedade real
Antes de nos aprofundarmos nas técnicas para obter aleatoriedade, é importante entender a distinção entre pseudoaleatoriedade e aleatoriedade real. Os números pseudoaleatórios são gerados por meio de algoritmos determinísticos, a partir de um valor semente. Dada a mesma semente, a sequência de números gerados será sempre a mesma. Por outro lado, a verdadeira aleatoriedade depende de fontes de entropia imprevisíveis e não tendenciosas, garantindo que os números gerados sejam realmente aleatórios e independentes de quaisquer estados anteriores.
Desafios para Obter Aleatoriedade
Solidity é uma linguagem de programação determinística, o que significa que a execução de um contrato inteligente deve sempre produzir o mesmo resultado a partir da mesma entrada. Alcançar a aleatoriedade nesse ambiente determinístico é um desafio devido à falta de acesso a dados externos, à incapacidade de confiar em registros de data e hora (timestamp) e à necessidade de transparência e auditabilidade.
Geração de Aleatoriedade com o Blockhash
Uma das maneiras mais simples de introduzir a aleatoriedade no Solidity é utilizar a função blockhash
. A função blockhash
retorna o hash de um bloco específico na Ethereum. No entanto, há limitações em seu uso. Ele só pode acessar o hash dos 256 blocos mais recentes. Além disso, os mineradores podem manipular o registro de data e hora do bloco dentro de um determinado intervalo, o que pode afetar o número aleatório gerado. Portanto, confiar somente no blockhash
para aplicativos críticos não é recomendado.
Para gerar um número aleatório usando o blockhash
, pode-se implementar uma função como esta:
function generateRandomNumber(uint256 seed) public view returns (uint256) {
uint256 blockNumber = block.number - 1; // Use o hash do bloco anterior
bytes32 blockHash = blockhash(blockNumber);
return uint256(blockHash) % seed;
}
Utilização do VRF (função aleatória verificável) da Chainlink
Para superar as limitações do blockhash
, os serviços de oráculo externo podem ser aproveitados para obter a verdadeira aleatoriedade. O VRF da Chainlink é uma solução amplamente utilizada que fornece números comprovadamente aleatórios gerados por oráculos.
A integração do VRF da Chainlink em seu contrato inteligente envolve as seguintes etapas:
- Importar a biblioteca VRF da Chainlink do Solidity para o seu contrato inteligente. Certifique-se de que você tenha as interfaces de contrato e as variáveis de contrato necessárias.
- Solicitar Aleatoriedade: Chame a função
requestRandomness
fornecida pelo VRF da Chainlink para solicitar um número aleatório. Essa função requer uma quantidade de tokens LINK como pagamento pelo serviço do oráculo. Ela também recebe um valor semente e uma função callback que será chamada quando a resposta de aleatoriedade for recebida. - Receber aleatoriedade: A função callback especificada na solicitação é acionada quando a resposta de aleatoriedade é recebida. Essa função deve tratar o valor de aleatoriedade recebido adequadamente de acordo com a lógica do seu aplicativo.
- Verificar a Aleatoriedade: Para garantir que a aleatoriedade gerada pelo VRF da Chainlink seja legítima, inclua uma etapa de verificação. A Chainlink fornece uma função
fulfillRandomness
que verifica a autenticidade do número aleatório recebido, comparando-o com o valor semente.
Para obter mais informações: https://docs.chain.link/getting-started/intermediates-tutorial
Aleatoriedade de Oráculo Externo
Além do VRF da Chainlink, outros serviços de oráculo externo também podem ser usados para obter aleatoriedade. Esses serviços fornecem APIs ou interfaces de contrato inteligente que expõem recursos de geração de números aleatórios.
Esquemas de Compromisso-Revelação
Os esquemas de compromisso-revelação são outra abordagem para obter aleatoriedade no Solidity. O processo envolve duas fases: compromisso e revelação.
Na fase de compromisso, os participantes enviam versões com hash de suas escolhas aleatórias. Eles mantêm os números aleatórios originais ocultos até a fase de revelação. O compromisso pode ser obtido usando o algoritmo de hash keccak256
.
function commit(uint256 randomNumber) public {
bytes32 commitment = keccak256(abi.encodePacked(randomNumber));
// Armazenar o compromisso para futura verificação
// ...
}
Na fase de revelação, os participantes revelam seus números aleatórios originais, que são então combinados ou processados para obter uma saída final aleatória. Os participantes podem enviar seus valores revelados usando uma função reveal
:
function reveal(uint256 randomNumber) public {
// Recuperar o compromisso e verificar o valor revelado
bytes32 commitment = getCommitment(msg.sender);
require(keccak256(abi.encodePacked(randomNumber)) == commitment, "Invalid commitment");
// Processar os números revelados para obter o resultado aleatório final
// ...
}
Os esquemas de compromisso-revelação proporcionam imparcialidade e impedem que os participantes influenciem o resultado com base em valores revelados. No entanto, a eficácia do esquema depende da coordenação e do comportamento dos participantes.
Aleatoriedade de Contratos Externos
Outro método para obter aleatoriedade envolve a utilização de contratos externos projetados especificamente para gerar números aleatórios. Esses contratos aproveitam várias técnicas, como oráculos, operações criptográficas e fontes de dados externas verificáveis para gerar números aleatórios.
Por exemplo: https://github.com/axiomzen/eth-random or https://fravoll.github.io/solidity-patterns/randomness.html
Palavras Finais
Neste guia, explorei diferentes técnicas para obter aleatoriedade, incluindo a utilização do blockhash
, a integração da VRF da Chainlink, dependência de oráculos externos, implementação de esquemas de confirmação-revelação e interface com contratos externos. Cada técnica tem suas próprias vantagens e considerações, por isso é importante escolher a abordagem que melhor se adapte ao seu caso de uso específico, considerando fatores como segurança, confiabilidade, transparência e descentralização.
Lembre-se de que alcançar a aleatoriedade em um ambiente determinístico é uma tarefa complexa, e são necessárias pesquisas, testes e auditorias contínuas. É muito trabalhoso. Portanto, talvez você deva reconsiderar seu projeto de jogos….
Se você achou este artigo informativo e útil, considere a possibilidade de me seguir para obter mais conteúdo relacionado à blockchain e criptomoeda. Você também pode se inscrever em minha lista de e-mails para receber atualizações sobre meus artigos e projetos mais recentes.
Esse artigo foi escrito por Kaan Kaçar e traduzido por Fátima Lima. O original pode ser lido aqui.
Top comments (0)