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}
接下来,咱们重写合同中的两个函数getRandomNumber
和fulfillRandomness
。 getRandomNumber
函数应该把种子作为输出参数,并且调用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'函数,将随机数返回给咱们的消费者合约。
而后咱们能够调用randomResult
getter函数来查看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的信息。