随机数
Solidity 中最好的随机数生成器是 keccak256
哈希函数.
// 生成一个0到100的随机数:
uint randNonce = 0;
uint random = uint(keccak256(now, msg.sender, randNonce)) % 100;
randNonce++;
uint random2 = uint(keccak256(now, msg.sender, randNonce)) % 100;
这个方法很容易被不诚实的节点攻击
在以太坊上, 当你在和一个合约上调用函数的时候, 你会把它广播给一个节点或者在网络上的 transaction
节点们。 网络上的节点将收集很多事务, 试着成为第一个解决计算密集型数学问题的人,作为“工作证明”,然后将“工作证明”(Proof of Work, PoW)
和事务
一起作为一个 block
发布在网络上。
一旦一个节点解决了一个PoW
, 其他节点就会停止尝试解决这个 PoW
, 并验证其他节点的事务列表是有效的,然后接受这个节点转而尝试解决下一个节点。
这就让我们的随机数函数变得可利用了
我们假设我们有一个硬币翻转合约——正面你赢双倍钱,反面你输掉所有的钱。假如它使用上面的方法来决定是正面还是反面 (random >= 50 算正面, random < 50 算反面)。
如果我正运行一个节点,我可以 只对我自己的节点 发布一个事务,且不分享它。 我可以运行硬币翻转方法来偷窥我的输赢 — 如果我输了,我就不把这个事务包含进我要解决的下一个区块中去。我可以一直运行这个方法,直到我赢得了硬币翻转并解决了下一个区块,然后获利。
所以我们该如何在以太坊上安全地生成随机数呢?
因为区块链的全部内容对所有参与者来说是透明的, 这就让这个问题变得很难,目前没有标准答案。
尽管这个方法在以太坊上不安全,在实际中,除非我们的随机函数有一大笔钱在上面,你游戏的用户一般是没有足够的资源去攻击的。