随机数和区块链一直存在分歧。到目前为止,区块链上还没有可验证的随机函数。
问题源于以下事实:交易被挖掘时,需要由网络上的多个节点来确认。这意味着每个节点都必须得出相同的共识。因此如果函数确实是随机的,则每个节点将得出不同的共识,从而导致未能确认的事务。
chainlink介绍
区块链和智能合约非常适合根据一组不可变的规则执行计算。问题在于规则只能应用于系统内部的数据。从系统外部获取可验证的数据非常困难。
Chainlink的任务是通过提供分散的预言来解决此问题,使区块链能够访问其生态系统之外的数据。预言机实质上是区块链和外部世界之间的桥梁。
在最近的一篇文章中,Chainlink宣布发布了其新的可验证随机函数(VRF)。开发人员现在可以使用该功能将其集成到多个测试网上的DApp中,从而使智能合约能够检索可在链上验证的随机数。这意味着不再有漏洞,并保证了随机性。
那么该功能如何实现的?
如果您想在Javascript中生成一个随机数,代码非常简单:
Math.random();
在一行的单次执行中,检索一个随机数。这不是VRF的工作原理。与Javascript不同,VRF处理一些事务。
以下是事件的顺序:
1. 您的智能合约通过交易向VRF请求一个随机数。
2. VRF会生成该数字并进行验证。
3. VRF准备响应。
4. VRF通过另一笔交易将号码发送回您的智能合约。
为了使第4点成功,您的合同需要实现一个已知函数,以便VRF可以返回结果验证。但是如何在您的项目中实现呢?
如何实现随机性
让我们创建一个名为RandomGenerator的新智能合约,在这里我们将调用VRF并接收结果。
步骤1:创建消费者合约
我们将使用Chainlink提供的名为VRFConsumerBase的合约,这是一个抽象合约,它定义了消耗VRF所需的最少函数。让我们这样定义“ RandomGenerator.sol”文件的开头:
pragma solidity ^0.6.2;
import “https://raw.githubusercontent.com/smartcontractkit/
chainlink/develop/evm-contracts/src/v0.6/VRFConsumerBase.sol”;
contract RandomGenerator is VRFConsumerBase {
constructor(address _vrfCoordinator, address _link)
VRFConsumerBase(_vrfCoordinator, _link) public {
}
}
VRFConsumerBase仍在后期测试中,因此软件包尚为对外提供。这就是为什么我们使用Github的HTTP URL进行导入的原因。
基本合约采用两个参数,分别代表协调器(coordinator)和LINK ERC20令牌的地址。这些是每个网络上的固定地址(稍后会详细介绍)。
步骤2:重写函数
VRFConsumerBase附带了两个对VRF流程至关重要的函数。
第一个叫做requestRandomness,它已经实现了,我们不需要重写。这是对VRF进行初始调用的函数。
另一个叫做fulfillRandomness,这是VRF在生成数字时调用的函数。我们可以重写它,以便在调用随机数时对其执行操作。
我们的智能合约只是将生成的随机数存储在一个名为randomNumber的状态变量中,以便我们可以在完成时查询它。它看起来应该像这样:
pragma solidity ^0.6.2;
import “https://raw.githubusercontent.com/smartcontractkit/
chainlink/develop/evm-contracts/src/v0.6/VRFConsumerBase.sol”;
contract RandomGenerator is VRFConsumerBase {
bytes32 public reqId;
uint256 public randomNumber;
constructor(address _vrfCoordinator, address _link)
VRFConsumerBase(_vrfCoordinator, _link) public {
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) external override {
reqId = requestId;
randomNumber = randomness;
}
}
我们为fulfillRandomness函数添加了重写功能,并将状态变量reqId和randomNumber设置为等于该函数接收的值。
步骤3:生成随机数
正如我在步骤1前面提到的,函数调用需要传递一些地址和其他值作为参数。
部署智能合约并调用构造函数时,它需要VRF协调器(coordinator)地址和网络上LINK令牌的地址。在Ropsten测试网上:
· VRF coordinator: 0xf720CF1B963e0e7bE9F58fd471EFa67e7bF00cfb
· LINK address: 0x20fE562d797A42Dcb3399062AE9546cd06f63280
调用requestRandomness函数时,我们需要传递生成随机性的Key hash,生成随机数的fee(使用LINK令牌)和针对生成随机性的seed(这是我们提供的最后一个)。函数签名如下所示:
function requestRandomness(bytes32 _keyHash, uint256 _fee, uint256 _seed) public returns (bytes32 requestId)
在Ropsten上,参数值为:
· Key hash: 0xced103054e349b8dfb51352f0f8fa9b5d20dde3d06f9f43cb2b85bc64b238205
· Fee (1 LINK): 1000000000000000000
· Seed: [whatever_you_want_your_seed_to_be]
因此我们的调用代码将如下所示:
// set ropsten key hash
bytes32 keyHash = “0xced103054e349b8dfb51352f0f8fa9b5d20dde3d06f9f43cb2b85bc64b238205”;
// set ropsten LINK fee
fee = 1000000000000000000;
// set example seed
seed = 123456789;
// make call to request randomness
bytes32 reqId = rand.requestRandomness(keyHash, fee, seed);
当结果返回时,该值将存在并且可以通过调用以下方法进行检索:
rand.randomNumber;
本节将逐步介绍如何使用Remix IDE和Metamask从VRF获取随机数。在继续之前,请确保已在浏览器上安装了Metamask扩展。
· 前往Remix IDE。
· 如果您以前从未使用过Remix,请确保使用的是Solidity,如图3所示。
创建一个名为RandomGenerator的新文件,并粘贴图2中的代码。
使用左侧菜单,单击Solidity图标,然后选择0.6.2编译器版本,如图4所示。
然后单击下面的按钮,并在下拉列表中选择“Injected web3”,如图5所示。
这将提示您应接受的来自Metamask的连接请求。
确保您正在使用Metamask上的Ropsten测试网,如图6所示。
确保您的Metamask帐户中有一些Ropsten Ether。
回到Remix,在同一选项卡上,您应该看到橙色的“ Deploy”按钮,单击该按钮并接受来自Metamask的合约部署请求。
部署后,我们需要确保智能合约具有LINK令牌,以便它可以请求随机数。在Ropsten LINK龙头上,然后粘贴您的Metamask地址,以便您在Metamask中收到100 LINK。
Metamask不知道LINK令牌在Ropsten上的位置,因此我们需要添加它。在“ Metamask”中,在您的帐户名称左侧,单击burger符号,然后单击底部的“Add Token”。
在“Custom Token”下,添加地址:0x20fE562d797A42Dcb3399062AE9546cd06f63280。其余详细信息应自动填写。提交后,如果您要求LINK到正确的地址,那么您的帐户中应该会看到100 LINK。图7显示了一个具有70 LINK的帐户。
返回到Remix,单击图8中带圆圈的按钮,复制已部署合约的地址。
现在我们将向合约发送一些LINK。回到Metamask,然后单击100 LINK旁边的3个点。粘贴合约地址并发送10 LINK。确认交易后,请继续下一步。
在Remix中,我们现在可以请求随机性。在同一选项卡中,向下滚动您会发现更多代表公共功能的橙色按钮,如图9所示。单击requestRandomness右侧的箭头以展开参数。
按顺序将这些值粘贴到三个输入框中:0xced103054e349b8dfb51352f0f8fa9b5d20dde3d06f9f43cb2b85bc64b238205、10000000000000000000000、123456789(或您希望的seed是什么)。然后点击“Transact”!
这可能需要一些时间,因此您应该关注输出终端提供给您的Etherscan中的事务。
交易完成后,我们需要等待VRF生成随机数并将其发送回我们的合约。几分钟后,单击我们在Remix中发送交易的橙色按钮下方的蓝色“ randomNumber”按钮,检查您的合约是否收到了随机数,如图12所示。
如果一切顺利,您应该有一个像我这样的随机数,它是30207470459964961279215818016791723193587102244018403859363363849439350753829。
结 论
Chainlink证明,现在智能合约中可以使用可验证的随机数。我们已经解释了该机制的工作原理,如何将代码集成到智能合约中以及如何使用Remix IDE检索随机数的演示。