Solidity - 生成不依赖于输入的不可预测的随机数

Solidity - Generate unpredictable random number that does not depend on input

我知道solidity中的"how to generate random number"是一个很常见的问题。但是,在阅读了绝大多数答案后,我没有找到适合我的情况。

我想要做的事情的简短描述是:我有一个对象列表,每个对象都有一个唯一的 ID,一个数字。我需要生成一个包含这些对象的 25% 的列表, 每次调用函数时随机选择 。不能依赖调用该函数的人提供会以某种方式对结果列表产生可预测影响的输入。

我发现唯一给出安全随机数的答案是 Here。但是,这取决于参与者的输入,并且旨在解决赌博场景。我不能在我的实现中使用它。

所有其他案例都提到生成的数字将是可预测的,甚至其中一些依赖于奇异输入来生成单个随机数。再一次,对我没有帮助。

总而言之,我需要一个能给我 多个不可预测的随机数的函数。

感谢您的帮助。

智能合约是确定性的,因此,基本上每个函数都是可预测的——如果我们知道输入,我们就会知道输出。而且你不能在没有任何输入的情况下获得随机数 - 几乎每种语言都会使用时钟生成 "pseudo random number"。这意味着,您不会使用简单的方法在区块链中获得随机数。

有许多有趣的方法可以使用智能合约生成随机数 - 使用 DAO、Oracle 等 - 但它们都有一些权衡取舍。

总之,没有您要找的方法。你需要牺牲一些东西。

:(

100% 的随机性在以太坊上是绝对不可能的。这样做的原因是,当分布式节点从头开始构建区块链时,它们将通过 运行 在区块链上创建的每笔交易来构建状态,并且所有这些节点都必须达到完全相同的最终状态。为了做到这一点,以太坊虚拟机完全禁止随机性,否则每次执行完全相同的代码都可能产生不同的结果,这将不可能在网络的所有参与者之间达到共同的最终状态。

也就是说,有像 RanDAO 这样的项目假装在区块链上创建可信赖的伪随机性。

无论如何,有一些方法可以实现伪随机性,这是最重要的两种方法,即提交-显示技术和使用 oracle(或两者的组合)。

作为我刚刚想到的一个例子:您可以使用 Oraclize 不时调用一个可信的外部 JSON API returns 伪随机数并在合约上验证调用是否真实执行。

当然,这些方法的缺点是您 and/or 您的用户将不得不花费更多的 gas 来执行智能合约,但在我看来,对于安全方面的巨大好处来说,这是一个公平的价格。

这里有一个选项:

function rand()
    public
    view
    returns(uint256)
{
    uint256 seed = uint256(keccak256(abi.encodePacked(
        block.timestamp + block.difficulty +
        ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)) +
        block.gaslimit + 
        ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)) +
        block.number
    )));

    return (seed - ((seed / 1000) * 1000));
}

它生成一个0-999之间的随机数,基本上无法预测(它已经被一些著名的Dapps使用,如Fomo3D)。