我希望我的智能契约在调用契约时返回7或8个唯一的随机数,从1到100不等。怎样才能取得这样的结果呢?
发布于 2018-09-24 03:20:14
也许,如果您试图使用PRNG块链来构建轮盘赌、彩票和纸牌游戏,因为Ethereum区块链是确定性的,它会给那些选择编写自己的伪随机数生成器(PRNG)的人带来一定的困难。
当前使用的一些易受攻击的方法
如果您使用的是块变量,如block.coinbase、block.difficulty、block.timestamp等。作为熵的来源,所有这些块变量都可以被矿工操纵,因此由于矿工的激励,它们不能作为熵的来源。由于块变量显然是在同一个块中共享的,因此可以很容易地使用内部消息来产生相同的结果。
其他方法类似于使用当前块或过去块的块或过去块的块,或者结合私有种子的过去块块。在这些情况下使用了block.blockhash(block.number)函数。但是,在EVM中执行事务时,由于明显的原因,还不知道正在创建的块的块散列,而EVM总是会产生零。如果我们使用前一个块的块进行尝试,攻击者可以使用相同的代码进行攻击,以便通过内部消息调用目标协议。这两份合同的“随机”数字将是相同的。
即使我们将块与私有种子结合在一起,并且在本质上是透明的,块链也不能被用来存储明文中的秘密。从契约存储中提取私有变量指针的值并将其作为参数提供给漏洞攻击是非常简单的。
一些值得探索的领域
有了像Oraclize这样的外部预言,智能合同就可以从诸如货币汇率、天气预报和股票价格(如random.org)等网络API中请求数据。这种方法的主要缺点是它是集中的。Oraclize守护进程会篡改结果吗?我们能信任random.org吗?
我们也可以使用BTCRelay来代替Oraclize,它是连接Ethereum和比特币块链的桥梁。使用BTCRelay,Ethereum区块链中的智能契约可以请求未来的比特币块,并将其用作熵的来源。
西尼迪斯是一种基于密码签名的算法,可用于智能合同中的随机数生成,只涉及双方:玩家和房屋。该算法的工作原理如下:
提交-揭示方法由两个阶段组成:
提交显示方法的一个更好的实现是兰道。提交-显示可以与未来的封锁相结合,以使其更加安全。
这几乎涵盖了使用Ethereum生成随机数的所有方法。
发布于 2018-09-23 17:48:42
发布于 2020-05-22 07:16:55
使用链式VRF。
使用块散列或类似于随机播种的方法存在许多问题。如果攻击者在您的契约之前就知道了这个块,他们就可以利用该信息在您试图做的任何事情上获得恶意优势。一个先知在这里可以有所帮助,但他们是失败的中心来源,必须能够证明他们是随机的。
您需要一个oracle网络,该网络可以:
此时,下面的示例演示了如何解决#1。您可以通过从支持Chainlink VRF的节点中提取足够数量的节点来解决#2。
对于确切的实现,从类似的问题上看这个答案。
您需要向一个节点发出请求,该节点的函数接受您生成的种子:
function rollDice(uint256 userProvidedSeed) public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) > fee, "Not enough LINK - fill contract with faucet");
uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number)))); // Hash user seed and blockhash
bytes32 _requestId = requestRandomness(keyHash, fee, seed);
emit RequestRandomness(_requestId, keyHash, seed);
return _requestId;
}当这个值被返回时,你会把它修改为100并加1。如果你想要7或8个随机数,你需要调用它7或8次。
function fulfillRandomness(bytes32 requestId, uint256 randomness) external override {
uint256 d6Result = randomness.mod(100).add(1);
emit RequestRandomnessFulfilled(requestId, randomness);
}https://stackoverflow.com/questions/52467248
复制相似问题