Jinghui Liao

A computer security PhD student who prefers blockchain and 6am sunlight and misses his family.

三权分立的随机数生成算法

October 29, 2020

在一个去中心化的分布式系统中,随机数是一个非常重要的问题。特别是在大家都非常熟悉的区块链系统里,一个安全的随机数算法不仅关乎到共识算法的安全性,同时也与很多的智能合约息息相关。但同时,安全随机数又是一个老大难的问题,在一个中心化的系统中,比如我们的手机,电脑,平板,安全随机数可以通过获取系统内部的随机参数或者读取屏幕像素来作为种子生成。但是在区块链这样一个公开公正公平的系统中,在一个相信系统安全但是不信任任何一个单独节点的环境里,想要获取一个安全的随机数则没有那么简单。

玩过智能合约的人应该对竞猜类的Dapp不陌生,这种Dapp一度火爆到把各大公链挤爆,但同时留意区块链新闻的人也不难见到某某Dapp被黑客攻击被盗XX币的报道。而这些报道里的黑客攻击,很大一部分都是因为竞猜类的Dapp里的随机数生成函数被黑客破解并利用,举个例子EOSDice. 这也不难理解,首先区块链是个即极度开放(数据公开,任何人可参与),又极度封闭(链上智能合约虚拟机执行)的系统,你的智能合约必须部署在区块链上,脚本肯定是要公开的,你的合约又必须在合约里执行,能调用的接口获取到的数据是很有限的。你想用能获取到的数据作为随机数种子,选择就那么多(nonce,区块高度,区块哈希,交易哈希等等),黑客也知道你都能怎么选然后迅速在交易提交之前就计算出可能的结果。

为了解决这个问题,有些区块链系统就直接给每个区块直接生成随机数种子,然后提供接口,这样在新的区块生成之前,黑客就无法推断随机数,进而无法在Dapp游戏里获取到非正常的优势。不过这个随机数的生成算法本身也有安全隐患。

问题就是,谁去生成这个随机数?比特币和以太坊用的是算力证明,生成区块的节点虽然跟算力相关,但也具有一定的随机性。但是我们能信任那个在算力证明中获胜的节点生成的随机数么?万一刚好那个节点就是黑客呢?他岂不是刚好就可以生成一个最有利于自己的随机数然后赢取Dapp中的奖励?关于这个问题有很多的针对不同区块链系统的解决方案,感兴趣的朋友可以去搜索一下,关键字【区块链中的随机数算法】本文主要讨论neo智能合约中的安全随机数问题。

neo现在使用的是dBFT共识算法,每轮共识会有一个议长来生成新的区块议案,一堆议员举手表决,当有超过2/3的议员同意新区块议案时,新区块议案将被打包成区块并广播分发给neo网络。我们依据这个共识算法来思考可能的随机数生成方案以及可能的结果。

最简单的随机数生成当然是让议长直接生成随机数,在他生成新区块议案的时候直接调用这个随机数,然后在共识过程中把随机数一并广播给议员以作验证。这是最简单高效的方案,对现有的共识协议几乎不会做什么更改,但是问题是,我们为什么要信任议长。必须要明确的是,在neo网络中,议长拥有的权限已经很大了,大到我感觉需要新的手段来进行制约,比如议长可以选择性打包交易,议长可以调整交易顺序,议长可以在所有节点知道交易执行结果之前知道结果,如果我们再给议长生成随机数的权力,那么如果议长在生成议案的时候发现某个合约执行到最后一步并且可以获取非常客观的收益,那是不是议长就可以临时生成一个最有利的交易来打包?这完全不违背dBFT共识算法,但是却有违公平。所以我们绝对不能让议长单独来生成随机数。

那是不是可以让所有的议员都生成一个随机数,然后同步给议长,让议长也依据2/3多数原则来用议员的随机数生成最终的随机数呢?这个方式比直接让议长生成随机数要安全的多,但是还是有那个问题,最终的随机数还是由议长来生成的,议长依然有最终决策权,比如他可以在已经计算了别的节点的随机数之后再生成自己的随机数,然后获取最有利于自己的结果,或者在总多收到的随机数的计算组合里选择最有利于自己的结果。这样议长依然可以在打包交易的时候获得优势,无非是多了些计算过程。

接下来就到了呼应题目的时候。不过我们首先来考虑二权分立,就是把打包过程和生成随机数过程分开,让议长负责打包,让另一个议员负责生成随机数。这样议长就没办法在打包交易的时候获得优势(不考虑议长可以选择不打包某些交易)。但是问题又冒出来了,议员可以获得不公平的优势,虽然他不能确定最终哪些交易会被打包进新的区块议案,但是他依然可以利用自己手上的信息来广播对自己有力的交易,并利用已有的规则给自己创造最大的机会,比如手续费。

于是现在就到了讨论三权分立的时候。打包还是由议长负责,但是随机数则由两位议员分别负责。过程描述是这样的:

  1. 在新一轮的共识周期里,所有的议员+议长广播自己生成的随机数。
  2. 两位随机数生成议员分别接收到超过2/3的随机数后计算出一个哈希结果,并把这个结果连同随机数都广播给议长。
  3. 议长在收到并验证通过两位议员的随机数数据包之后,依据两个数据包的哈希结果来最终计算出随机数种子。

在这个过程中,无论是议员也好,议长也好,都无法在最终随机数种子生成之前知道随机数种子的结果。而议长即便是在知道了安全随机数种子,他也无法更改这个结果。

当然,这个方案只是保证了这个随机数的安全可靠,但是没有办法避免议长在知道了安全随机数种子之后去临时生成新的交易。对于这个问题,我会在别的文章中进行分析。

Share This Post