首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我们如何在ethereum中生成多个随机数?

我们如何在ethereum中生成多个随机数?
EN

Stack Overflow用户
提问于 2018-09-23 14:46:55
回答 4查看 3.1K关注 0票数 9

我希望我的智能契约在调用契约时返回7或8个唯一的随机数,从1到100不等。怎样才能取得这样的结果呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 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生成随机数的所有方法。

票数 12
EN

Stack Overflow用户

发布于 2018-09-23 17:48:42

就像Raghav说的,区块链上的随机数很难。由于网络的公共性,很难生成一个无法预先计算的数字。

尽管如此,最好的解决方案之一是使用从外部(读:非块链)源获取随机数的oracle。看一看指南。Ethtroll就是一个很好的例子,所以请看一下代码这里。他们使用Oraclize从Random.org获得一个随机数。

使用甲骨文的一个问题是集中化因素。如果您按照我前面描述的方式设置Dapp,那么您将在两种不同的集中服务-Oraclize和Random.org --中任由胭脂雇员支配。虽然不太可能有人操纵这两个来源,但人们会为了潜在的经济利益而进行非理性行为。

票数 4
EN

Stack Overflow用户

发布于 2020-05-22 07:16:55

使用链式VRF

使用块散列或类似于随机播种的方法存在许多问题。如果攻击者在您的契约之前就知道了这个块,他们就可以利用该信息在您试图做的任何事情上获得恶意优势。一个先知在这里可以有所帮助,但他们是失败的中心来源,必须能够证明他们是随机的。

您需要一个oracle网络,该网络可以:

  1. 证明了生成的数是随机的。
  2. 拥有足够多的预言/节点,即使其中一个失败/损坏,您的智能契约也将持续。

此时,下面的示例演示了如何解决#1。您可以通过从支持Chainlink VRF的节点中提取足够数量的节点来解决#2。

对于确切的实现,从类似的问题上看这个答案。

您需要向一个节点发出请求,该节点的函数接受您生成的种子:

代码语言:javascript
复制
 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次。

代码语言:javascript
复制
function fulfillRandomness(bytes32 requestId, uint256 randomness) external override {
        uint256 d6Result = randomness.mod(100).add(1);
        emit RequestRandomnessFulfilled(requestId, randomness);
    }
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52467248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档