链上随机数问题没有完美的解决方案。区块链上不仅没有真随机数,连传统的伪随机数也没有。
EOS官方示例中采用的随机数生成法类似于上文讨论的第二种方式——用不同参与者的私密数据的集合作为种子,生成难以被预测的伪随机数。
以Dice为例,玩家和庄家需要提前生成密钥,把公钥先传到链上,开奖的时候再提交各自的私钥,作为种子生成随机数,再由随机数判定开奖结果。这可能是目前最安全的伪随机数生成方式,但它给玩家增加了额外的且并不轻松的操作,提高了游戏门槛,在现实中并未被广泛的采用。
BM在EOS开发者群回答随机数安全问题时,提出了一个“信任区块生产者”的方案,也就是说用区块生产者在打包交易的某个特定时机获取的某些信息来生成伪随机数。虽然是在链上解决问题,但这种方法更接近于上文讨论的第一种方式——由一个中心化的第三方来提供随机数,虽然难以被破解,但提供者不一定值得信任。
屡败屡战的EOS上的DApp开发者通常选用上文中的第三种方式——智能合约获取链上数据作为种子,自己生成伪随机数。
在与黑客数次交锋之后,目前DApp最常用的开奖机制是“二次延时开奖+种子中不设置可控变量”。
实时开奖机制下,reference block是上一个区块,其中的种子数据在开奖前就可被黑客获取;而二次延时开奖,reference block是还未生成的区块,其中的种子数据难以预测,黑客也就无法提前算出开奖结果。种子中不设置可控变量则保证了黑客不能通过改变种子的数值来操控开奖结果。
不过,即便如此,“二次延时开奖+种子中不设置可控变量”也不能保证合约随机数的绝对安全,只能说在目前阶段这种方法还未被黑客攻破,相对安全。毕竟不管采用几次延时,开奖合约能获取的种子,攻击合约也一样能得到,链上的种子是“公平”、“透明”的。
如何在这种不完美的情况下尽量减少随机数攻击带来的破坏,慢雾团队给出了一些实用建议:
1.多用攻击者视角审查合约。
2.攻击者一般是通过恶意合约完成攻击,要思考合约能从什么角度攻击随机数。
3.随机数的安全与伪随机数生成算法相关,也与开奖机制相关,算法和机制要配合设计。
4. 伪随机数生成算法不要引入可预测种子和可控种子,避免结果被预测或被篡改。
5. 了解区块链上的随机数与传统随机数的差别。
6.做安全审计。在项目上线和开源前做安全审计,已知的漏洞能被查出,未知的漏洞也能通过风控机制把危害降到最低。