乐趣区

关于区块链:Solidity中随机数的生成

Solidity 中无奈原生地实现随机数生成(RNG)。要在区块链上生成一个真正可验证的随机数,智能合约必须将种子发送到像预言机这样的链外资源,而预言机必须将随机数连同可验证的证实一起返回给智能合约,证实随机数是应用种子生成的。随着 Chainlink VRF 现已在 Ethereum 主网上线,开发者能够在 Solidity 中以安全可靠、可验证的形式轻松生成随机数。在这篇技术文章中,咱们将向您展现如何应用 Chainlink VRF 在 Solidity 中生成随机数。

在您的智能合约中生成平安随机数的例子能够在 Chainlink 文档中找到。这里有一个 Remix 上在 Kovan 测试网生成区块链随机数的例子,供当初想测试的人应用。只有记得依照申请和接管办法,用 LINK 转账到你的智能合约就能够了。

Chainlink VRF 的高级概述

Chainlink VRF(可验证随机函数)是一个为智能合约设计的偏心的可验证的随机性起源。Solidity 开发人员能够应用它作为防篡改的随机数生成器,为依赖不可预测后果的 Ethereum 利用构建安全可靠的智能合约。

在 Solidity 中应用 Chainlink VRF 生成随机数的第一步是确定一个种子。抉择一个难以被影响或预测的种子极为重要。如果有人可能影响或预测种子,实践上他们能够尝试与执行随机性申请的预言机节点串通,产生一个对本人无利的后果。正因为如此,倡议不要应用来自区块链状态的值,如区块高度或区块工夫戳。

而后,这个种子会以申请的形式发送到 Chainlink 预言机。而后,预言机会用给定的种子生成一个伪随机数,并将后果返回给智能合约,一起返回的还有一个加密证实,用来验证随机数是应用种子生成的。这种加密证实是通过公钥加密技术创立的,这是区块链技术中宽泛应用的技术。重要的是,后果能够被验证,防止矿工或预言机等参与者为了本人的利益而影响随机数的后果。

这是对 Chainlink VRF 工作形式的高级概述。对于底层技术实现的更多细节能够在咱们对 Chainlink VRF 的介绍中找到。然而,作为开发者,除了获取种子,而后向 Chainlink 预言机创立一个申请之外,你不须要放心任何事件。

创立消费者合约

如何在 Solidity 智能合约中取得一个随机数,咱们应该首先从 Chainlink VRFConsumerBase 合约中继承。消费者合约还应该蕴含存储随机数后果的变量,用于生成随机性的公钥哈希,以及为实现申请而付给预言机的费用。

import "https://raw.githubusercontent.com/smartcontractkit/chainlink/master/evm-contracts/src/v0.6/VRFConsumerBase.sol";

contract RandomNumberConsumer is VRFConsumerBase {
    
    bytes32 internal keyHash;
    uint256 internal fee;
    uint256 public randomResult;
    
}

接下来,在构造函数中,咱们应该初始化 Chainlink VRF 协调器。调用 VRFConsumerBase 函数,传入 VRF 协调器的地址和给定环境的 Chainlink token 的地址作为参数。还须要设置 keyHash 变量,这是生成随机性的公钥。这些的环境特定值能够在 Chainlink VRF 文档的合约地址局部取得。最初,咱们须要设置 LINK token 的领取金额。对于 Kovan 测试环境,它是 0.1 个 LINK。

constructor() 
    VRFConsumerBase(
        0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9, // VRF Coordinator
        0xa36085F69e2889c224210F603D836748e7dC0088  // LINK Token
    ) public
{
    keyHash = 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4;
    fee = 0.1 * 10 ** 18; // 0.1 LINK
}

接下来,咱们重写合同中的两个函数 getRandomNumberfulfillRandomnessgetRandomNumber函数应该把种子作为输出参数,并且调用 VRFConsumerBase 中的 requestRandomness 函数,传递 keyHash,费用金额和给定的种子作为参数。

  /** 
   * Requests randomness from a user-provided seed
   */
function getRandomNumber(uint256 userProvidedSeed) public returns (bytes32 requestId) {require(LINK.balanceOf(address(this)) > fee, "Not enough LINK - fill contract with faucet");
    return requestRandomness(keyHash, fee, userProvidedSeed);
}

执行时,这个函数将申请发送到给定的 VRF 协调器合约,而后建设一个最终种子,并将其发送到该 VRF 协调器的 Chainlink 预言机。最初的种子是用以下值的哈希值建设起来的。

  • 用户提供的种子
  • 满足申请的 Chainlink 预言机的公钥哈希值
  • 申请时的用户 nonce
  • 提出申请的合约地址
  • 以后区块号

应用这些额定的值的起因是为了避免合约应用雷同的种子不止一次地失去雷同的后果。nonce 有助于避免合约在同一区块内做多个申请,所以实践上,合约能够在同一区块内应用雷同的种子为申请多个随机数,而且他们依然会为每个申请失去惟一的可验证的随机数。

fulfillRandomness函数承受随机数响应参数为一个无符号整数,以及申请的 ID,而后将给定的随机数存储在合约中。当 VRFCoordinator 合约接管并验证一个随机数时,这个函数会被调用。对于这两个函数的更多信息能够在 Chainlink VRF 文档中找到。

/**
 * Callback function used by VRF Coordinator
 */
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {randomResult = randomness;}

当初,咱们在 Solidity 中领有了一个残缺且可行的随机数生成(RNG)示例,当初能够部署和测试该合约了。

测试随机数生成消费者合约

以上残缺的合约能够很不便地在 Remix 中关上、编译,并部署在 Kovan 网络上。部署好后,肯定要给合约转入一些 LINK。

一旦合约至多有 0.1 个 LINK 的资金,咱们就能够调用 getRandomNumber 函数,传入一个数字作为种子。这将把申请和种子一起发送给运行在 Chainlink oracle 上的 VRF 协调器。


事务被解决后,须要期待几秒钟,让 Chainlink 预言机实现对随机数的申请,而后调用咱们之前创立的 ’fulfillRandomness’ 函数,将随机数返回给咱们的消费者合约。

而后咱们能够调用randomResultgetter 函数来查看 Chainlink oracle 用给定种子生成的可验证随机数的后果。当初咱们有了一个可验证的随机数,它能够在咱们的消费者合约和任何其余利用中应用。

验证随机性

当初,咱们有一个随机数返回到咱们的合约,你可能会想晓得,咱们如何确定它是由执行申请的 Chainlink oracle 的给定种子和公钥哈希生成的。当应用 Chainlink VRF 时,答案是你不须要这样做。验证作为 VRFCoordinator 合约实现申请的一部分,会主动进行。

如果验证失败,那么随机数就不会返回到生产合约,交易也会被还原。因而,应用 Chainlink VRF 的区块链开发者能够释怀,他们通过 Chainlink VRF 取得的随机数是可验证的随机数。对于验证的底层技术细节,能够参考咱们对 Chainlink VRF 的技术演练。

总结

Chainlink VRF 帮忙 Solidity 开发者以平安、牢靠和通过验证的形式在智能合约中疾速、轻松地生成随机数。

如果您是一名智能合约开发者,并心愿利用 Chainlink VRF 性能,请拜访 Chainlink 开发者文档并退出 Discord 上的技术探讨。你能够通过拜访 Chainlink 网站和在 Twitter 和 Reddit 上关注 Chainlink 来理解更多对于 Chainlink 的信息。

退出移动版