在⼀个去中⼼化的分布式系统中,随机数是⼀个⾮常重要的问题。除了密钥生成等传统安全场景,在共识机制、零知识证明等热门场景中也发挥着重要的作用,保护着区块链的安全。
随机数的不可预测,对于安全系统至关重要。
安全随机数
在⼀个中⼼化的系统中,⽐如我们的⼿机、电脑、平板、安全随机数可以通过获取系统内部的随机参数或者读取屏幕像素来作为种⼦⽣成。但是在区块链这样⼀个公开公正公平的系统中,在⼀个相信系统安全但是不信任任何⼀个单独节点的环境⾥,想要获取⼀个安全的随机数并不简单。
玩过智能合约的⼈应该对竞猜类的 dApp 不陌⽣,偶尔也会⻅到某某 dApp 被⿊客攻击被盗XX币的报道,比如 EOSDice。⽽这些报道⾥的⿊客攻击,很⼤⼀部分都是因为竞猜类 dApp ⾥的随机数⽣成函数被⿊客破解并加以利⽤。
⾸先区块链是个极度开放(数据公开,任何⼈可参与),⼜极度封闭(链上智能合约虚拟机执⾏)的系统。你的智能合约必须部署在区块链上,脚本肯定是要公开的,你的合约⼜必须在合约⾥执⾏,可调⽤接⼝能获取到的数据是很有限的。你想⽤能获取到的数据作为随机数种⼦,选择就那么多(nonce,区块⾼度,区块哈希,交易哈希等等),那⿊客会在清楚你的选择范围后迅速在交易提交之前就计算出可能的结果。
为了解决这个问题,有些区块链系统就直接给每个区块直接⽣成随机数种⼦,然后提供接⼝,这样在新的区块⽣成之前,⿊客就⽆法推断随机数,进⽽⽆法在 dApp 游戏⾥获取到⾮正常的优势。不过这个随机数的⽣成算法本⾝也有安全隐患。
问题就是,谁去⽣成这个随机数?⽐特币和以太坊⽤的是算⼒证明,⽣成区块的节点虽然跟算⼒相关,但也具有⼀定的随机性。但是我们能信任那个在算⼒证明中获胜节点⽣成的随机数吗?万⼀刚好那个节点就是⿊客呢?他岂不是刚好就可以⽣成⼀个最有利于⾃⼰的随机数然后赢取 dApp 中的奖励?
Neo 智能合约中的安全随机数
关于这个问题,针对不同的区块链系统有许多的解决⽅案,感兴趣的朋友可以去搜索⼀下,关键字【区块链中的随机数算法】。本⽂主要讨论 Neo 智能合约中的安全随机数问题。Neo 现在使⽤的是 dBFT 共识算法,每轮共识会有⼀个议⻓来⽣成新的区块议案,⼀堆议员举⼿表决,当有超过 2/3 的议员同意新区块议案时,新区块议案将被打包成区块并⼴播分发给 Neo ⽹络。我们依据这个共识算法来思考可能的随机数⽣成⽅案以及可能的结果。
最简单的随机数⽣成当然是让议⻓直接⽣成随机数,在他⽣成新区块议案的时候直接调⽤这个随机数,然后在共识过程中把随机数⼀并⼴播给议员以作验证。这是最简单⾼效的⽅案,对现有的共识协议⼏乎不会做什么更改。
但问题是,我们为什么要信任议⻓?
必须要明确的是,在 Neo ⽹络中,议⻓拥有的权限已经很⼤了,⼤到我感觉需要新的⼿段来进⾏制约,⽐如议⻓可以选择性打包交易;可以调整交易顺序;可以在所有节点知道交易执⾏结果之前知道结果。如果我们再给议⻓⽣成随机数的权⼒,那么如果议⻓在⽣成议案的时候发现某个合约执⾏到最后⼀步并且可以获取⾮常客观的收益,那是不是议⻓就可以临时⽣成⼀个最有利的交易来打包?这完全不违背 dBFT 共识算法,但是却有违公平。所以我们绝对不能让议⻓单独来⽣成随机数。
那是不是可以让所有的议员都⽣成⼀个随机数,然后同步给议⻓,让议⻓也依据 2/3 多数原则来⽤议员的随机数⽣成最终的随机数呢?这个⽅式⽐直接让议⻓⽣成随机数要安全的多,但还是有那个问题,最终的随机数还由议⻓来⽣成,他依然有最终决策权,⽐如他可以在已经计算了别的节点的随机数之后再⽣成⾃⼰的随机数,然后获取最有利于⾃⼰的结果,或者在总多收到的随机数的计算组合⾥选择最有利于⾃⼰的结果。这样议⻓依然可以在打包交易的时候获得优势,⽆⾮是多了些计算过程。
两权分立机制
接下来就到了呼应题⽬的时候。不过我们⾸先来考虑两权分⽴,就是把打包过程和⽣成随机数过程分开,让议⻓负责打包,让另⼀个议员负责⽣成随机数。这样议⻓就没办法在打包交易的时候获得优势(不考虑议⻓可以选择不打包某些交易)。但是问题⼜出现了,议员可以获得不公平的优势,虽然他不能确定最终哪些交易会被打包进新的区块议案,但是他依然可以利⽤⾃⼰⼿上的信息来⼴播对⾃⼰有利的交易,并利⽤已有的规则给⾃⼰创造最⼤的机会,⽐如⼿续费。
三权分立机制
于是现在就到了讨论三权分⽴的时候。打包还是由议⻓负责,但是随机数则由两位议员分别负责。过程描述是这样的:
● 在新⼀轮的共识周期⾥,所有的议员+议⻓⼴播⾃⼰⽣成的随机数。
● 两位随机数⽣成议员分别接收到超过 2/3 的随机数后计算出⼀个哈希结果,并把这个结果连同随机数都⼴播给议⻓。
● 议⻓在收到并验证通过两位议员的随机数数据包之后,依据两个数据包的哈希结果来最终计算出随机数种⼦。
在这个过程中,⽆论是议员还是议⻓,都⽆法在最终随机数种⼦⽣成之前知道随机数种⼦的结果。即便议⻓知道了安全随机数种⼦,也⽆法更改这个结果。
当然,这个⽅案只是保证了这个随机数的安全性,但还是没有办法避免议⻓在知道安全随机数种⼦后去临时⽣成新的交易。对于这个问题,我会在下一篇⽂章中进⾏分析。