30

开发必读! 手把手教你如何用SPOS解决EOS随机数漏洞

 5 years ago
source link: https://www.jinse.com/blockchain/346468.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

yUzIJnZ.jpg!web

作者 | 复杂美区块链

出品 | 区块链大本营(blockchain_camp)

经过2018一整年的发展,区块链的应用落地普遍增加,在公链领域中备受瞩目的链上应用DAPP开发也随着EOS主网的开源而白热化。

根据DappReview平台统计,EOS 2019年第一季度的DAPP交易额达$1.72B,活跃用户达274.93K,交易笔数达282.99M。

可伴随着这漂亮数据而来的却是EOS Dapp智能合约漏洞问题,其中大部分成功攻击的原因都和随机数漏洞有关,那如何优化这个问题呢?

在复杂美开源的Chain33区块链底层架构中,有一个共识模块叫作SPOS(save pos),它通过Ticket实现POS的挖矿逻辑。

在这篇文章中,我将详细讲解 SPOS模块的实现原理,以及其解决随机数漏洞的方式。

在Chain33的公链案例比特元中,用户使用钱包账户中BTY余额购票(挖矿权,目前10000个BTY可购买一票),一票对应一个唯一的TicketID,同时拥有一份挖矿权;一个区块只能由一票挖出,实际的挖矿几率各票均分(如全网有N张票,则一张票挖到矿的几率为1/N)。

Ticket挖矿流程如下所示:

  • 钱包 :定期检查账户中的BTY余额来购买票, 当满足购票条件后构造一条买票交易发往区块链。

  • 共识 :它会一直尝试使用本地持有的票去打包区块,一旦打包成功,是表示对应的Ticket持有人挖矿成功,并获得对应的区块奖励。

  • 智能合约 :智能合约会把地址对应的票信息写入到区块链数据库,每一张 Ticket 都对应有一个唯一的TicketID,也会有一条数据记录在数据库。

在区块链上为了体现公平性(针对游戏等应用场景),就需要一个不能被预测的随机数。

目前的区块链大体有如下实现方案:

1. 合约中调用外部中心化的随机数发生器获取随机数;

2. 使用区块hash中的某些值作为随机数。

但是这两种方案都有非常明显的弊端,原因在于:

1. 区块链多节点之间智能合约执行结果是要求强一致的,如果合约从外部读取数据,是很有可能获取到不同结果的(比如网络原因导致有的节点读取正常,有的返回错误)进而导致分叉。

2. 区块的哈希可以被控制,导致随机数被控制。比如EOS,没有提供很好的随机数算法,所以很多Dapp开发者会自己封装自认为完美的随机数算法导致随机数被预知。

例如以下两个例子: 

  1. Eosbet第一次随机数攻击 :这个游戏在开奖时使用了EOS中一个名为 ref_block_num 的随机数因子,但是在游戏开奖时合约中还是读取了老区块中的值,导致随机数被预知,进而被攻击。

  2. Eosbet第二次随机数攻击 :在修改了上一次的问题后,开发者再引入了一个新的参数:用户余额作为随机数因子。然而攻击者利用这一点,模拟完全一样的DApp代码,然后不停修改余额去尝试开奖逻辑,直到碰撞出开奖结果,进而又遭到攻击。

还有其它很多EOS上的游戏遭受了类似手段的攻击,造成大量的损失。

下面,我们就来着重讲讲如何实现在随机数上的优化。

首先,用户使用钱包账户中的BTY购买票(Ticket),10000BTY对应一票。 钱包同时生成一个randNum,哈希过后再结合钱包挖矿地址的私钥,票对应的index(一次可以买多张票)等元素再做两次哈希,得到一个公开哈希参数(pubHash):

pubHash = 

hash(hash(privateKey:index:hash(randNum)))

然后,新购买的票中包含这个pubHash以及randNum并存入区块链,这张票有12小时的成熟期,过了12小时才可以参与挖矿。 

接着共识算法从区块链中找到已经成熟的票(Ticket)开始打包,由于共识打包区块操作只在节点本地执行,所以它可以读取本地存储的私钥,算出一个私密哈希(privHash)并将这个参数放入到挖矿交易中:

privHash = 

hash(privateKey: index: hash(randNum))

最后,智能合约收到挖矿交易,对比 hash(privHash) pubHash 的值,两者一致挖矿交易成功,对应的节点获得挖矿奖励。否则挖矿交易执行失败。

最后总结一下,SPOS共识的实现结合了随机数,由于一般情况下是无法预测其它节点的共识信息,所以也无法获取到它的共识随机数。

并且系统设定私密哈希(privHash)不能提前泄露,就算有恶意矿工自己提前暴露,它对应的票也会被作废,同时本金会被冻结较长时间(2天以上)。

再加上系统设定票需要经过12小时的成熟期后才可以参与挖矿。 这些条件组合起来,系统的随机数几乎是无法被操控的 。这样当开发者实现的DApp中需要保证公平随机时,就可以直接使用系统提供的这个安全的随机数了。

*关于作者:

复杂美区块链(www.33.cn)成立于2008年,累计申请200多项区块链发明专利,全球排名前10。 拥有自主研发的区块链底层架构Chain33,从2018年11月开源至今,其首创的平行链架构被百度、阿里、360等机构认可与研究,并登录微软azure市场。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK