0%

ETH十---The DAO

TheDAO

​ 冲入攻击在现实中真的会发生吗?本文章讲解一下2015年发生过的一次真实的案例。这个案例在以太坊的历史上赫赫有名,造成了以太坊的分裂,可以说以太坊的历史都被他改写了。

​ 我们说比特币实现了去中心化的货币,以太坊实现了去中心化的合约,那么去中心化这么好,那为什么不把所有的都改成去中心化的?所以有的人就提议:DAO(Decentralized Autonomous Organization),去中心化的自治组织。

​ 传统社会上,组织是建立在某种法律文件上的,规范组织的行为,有时候还可能需要到政府登陆注册,在区块链上,DAO这个组织就是建立在代码之上的,组织上的规章制度,是写在代码里的,通过区块链的共识协议来维护规章制度的正确执行,这就是DAO。

​ 在2016年5月的时候,出现了一个致力于众筹投资的DAO,他的名字叫做The DAO(是指这个DAO叫做The DAO),它的工作原理,有点像众筹的一个投资基金,只不过投资的钱的来源,是通过在区块链上众筹的方法得到的,本质上是运行在以太坊上的一个智能合约,如果你想参与这个The DAO,那么你可以把以太币发给这个智能合约,然后可以换回The DAO的代币,需要决定投资哪个项目是大家投票决定的,你手里的代币越多,投票的权重越大,那么最后如果有了收益,也是按照智能合约中规定的制度来进行收益分配的,就是The DAO的工作原理。工作方法实际上有点像DAC(Decentralized Autonomous Corporation,去中心化的自治公司)的模式,一般来说DAC是出于盈利目的的,是为了经营赚钱,DAO可以是出于非营利性目的,DAC虽然叫做公司,但是不具有社会上公司的法人地位,一般来说,也没有董事长、CEO之类的职务。

​ The DAO在当时收到了很高的关注度,因为以前从来没有这样民主的投资基金,在当时被称为一种“伟大的尝试”,引起了互联网社区里很大的兴奋,从2016年5月份开始众筹,一个月的时间就筹集了价值1.5亿美元的以太币,当时的以太币价格还是比较便宜的,这些以太币放在现在的话,大概是价值几十亿美元,众筹的速度和规模在历史上是非常罕见的,比很多众筹网站要快得多,这也反映出了区块链技术的强大生命力,遗憾的是,The DAO只存活了三个月,问题出在哪里?比如你是一个投资者,你怎么取回The DAO的收益?这个在The DAO的基金里是通过“拆分”的方法实现的,叫做Split DAO,拆分的方法不是单纯的用来取回你的收益,也是一种建立子基金的方法,叫child DAO(拆分完之后叫做child DAO),设计理念是:

​ 我们说这个The DAO投资项目是靠大家一起用手中的代币去投票,那么如果有一小部分人投资理念和其他人不太一样,怎么办?比如说有一个小众的项目,少数人觉得很好,值得投,得不到大多数人的认可,这种情况下,这一小部分人可以用拆分的方法,从The DAO里面独立出来,成立自己的一个子基金,就是child DAO,然后拆分的时候,手中的代币,是要被收回去的,然后换成相应数量的以太币,就是把相应数量的以太币打到他们这个子基金里,然后他们就可以投他们想投的项目了。

​ 拆分的一个极端的例子,就是单独的一个投资者成立一个子基金,这个child DAO里就是他一个人,这样就可以把所有的钱投给自己,这是投资者取回投资和收益的唯一途径,它没有像上一篇文章所说的那种withdraw函数,拆分之前有7天的辩论期(决定要不要加入这个拆分,或者评价),拆分之后有28天的锁定期(成立一个子基金之后,需要28天之后才能把以太币取出来),我们后面会看到这28天的锁定期给了以太坊社区采用补救措施的时间,拆分的理念并没有错,而且可以说是民主制度的体现,民主制度并不是绝对的,少数的服从多数,而是说,也要尊重少数人选择的权力,既然这个拆分的理念没有错,那么问题出在哪里了?问题就出现在了split DAO的实现上。

相关代码:

withdrawRewardFor把钱还给调用这个函数的人,之后把The DAO中的金额减少相应的数量,再把调用者的账户清零,这里就有问题了,按照上一篇文章所说的,应该先把账户清零,然后再转账,黑客就是利用这个漏洞进行的重入攻击。

​ The DAO是从2016年五月开始众筹的,差不多一个月的时间,筹集了价值1.5亿美元的以太币,然后黑客就利用这个重入攻击,从里面转走了5000万美元的以太币,差不多1/3,这件事情当前在以太坊社区引起了很大的恐慌。这个时间也引起了以太币价格的大跳水,那么以太坊社区对此进行了激烈的讨论,社区的意见分裂为两派,一派认为要回滚交易(成立的子基金有28天的锁定期,所以黑客暂时还没有办法把钱取走,还有时间可以采取补救措施),通过回滚交易就不能让黑客得逞,这样能保障广大投资者的正当利益,另一派认为,不需要采取补救措施,因为黑客的行为并没有违法,既然我们说code is law,规则是由代码决定的,那么代码中的漏洞,也是规则的一部分,发生这个事情之后,网上流传了一封据说是黑客也给以太坊社区的公开信,公开信里黑客说,我没有做错任何事情,我只是利用了你代码中的一个feature。所以以太坊有一部分人认为是不应该采取补救措施,尤其是回滚交易,因为区块链最重要的特性是不可篡改性,如果出了问题就回滚,那么怎么能叫做不可篡改呢?而且这次出问题的只是以太坊运行的一个应用而已,The DAO是以太坊上的一个智能合约,以太坊本身的代码没有问题,如果每个智能合约出了问题都回滚的话,那不乱套了?

​ 以太坊的开发团队是支持补救措施的,主要是这个事情的影响太大了,The DAO筹集的以太币的数目已经占到了当时流通量的很大一部分,大概是百分之十几。如果放纵不管,这些以太币的1/3要落入黑客的手里,我们真的希望这么多的以太币都集中在黑客的手里吗?而且投资者的利益怎么办?(too big to fail 出自2008年美国金融危机),以太坊社区有人认为The DAO的危机也是属于too big to fail,如果只是个小的智能合约出了问题,以太坊社区是不管的,开发团队也是不管的。

​ 假设要采取补救措施,怎么补救?

比如我们就从开始攻击的那个区块开始分叉,这样行不行?从攻击的链的上一个区块分叉,让下面的一条链,比上一条链要长(常见的分叉攻击的方法)

​ 上图所说的方法行不行?

这个问题不是所有人都要统一,假设所有人都往下挖,这样会有什么后果?

不光是黑客攻击的交易回滚,上面这条链上攻击之后的所有交易都回滚了。上面有很多合法的交易,The DAO只是以太坊中运行的一个智能合约,另外还有很多智能合约在运行,还有一些正常的网上支付的交易,那就乱套了。要回滚的话,只能是精确定位,只能是针对黑客盗取以太币的那些交易,其他发生的正常交易不能发生影响,这是采取补救措施的一个原则。

​ 以太坊团队制定了两步走的方案,第一步,首先要锁定黑客的账户,第二步再设法把盗取的以太币退回去,清退The DAO基金上的这些钱。

第一步:以太坊团队发布了一个软件升级,在升级的软件里增加了一条规则,凡是跟The DAO这个基金上的账户相关的,不允许做任何交易,发布之后,大多数以太坊的矿工都升级了这个软件。这个是属于软分叉,软件升级只是增加了一个判断规则,当一个节点收到一个交易的时候,判断这个交易是否合法,增加一个判断规则,The DAO相关的账户不允许任何交易,如果这个交易和The DAO账户相关的,就认为这个交易非法,增加这个规则之后,新矿工挖出的这个区块,旧矿工是认可的,因为旧矿工不知道这个新规则,他也不会去查这个,但是旧矿工挖出的区块,新矿工有可能不认可,如果这个区块里包含了The DAO这个账户的交易,就不认可,所以是软分叉。软件升级的想法是挺好的,也得到了大多数矿工的支持,遗憾的是,升级之后的软件,有一个bug,这个bug不是功能上的bug,也不是安全漏洞,而是和汽油费相关的,我们说你增加一个规则,收到一个交易,判断一下这个交易是不是和The DAO账户相关的,如果是的话,认定是非法交易,不予执行,这个时候还要不要收取汽油费?汽油费的机制很大的一方面是为了防范恶意的攻击者不断地去发放非法交易,浪费矿工的资源,反正对他来说成本很低,以太坊发布的软件升级,在这种情况下,恰恰是没有收汽油费,结果网上有大量的非法的交易,本来是大多数矿工都升级了软件的,但是升级之后不停地收到这种攻击,过不了多久,矿工就受不了了,于是回滚了软件升级,又改回了原来的版本,于是软分叉的方案就失败了,这个时候,形势就比较严峻了。

​ 子基金成立之后,有28天的锁定期,然后黑客就可以把钱取走了,软分叉的方案失败之后剩下的时间就不多了,既然软的不行,就来硬的。

​ 以太坊团队设计了一个硬分叉的方案,通过软件升级的方法,把The DAO账户上的所有资金强行转到另外一个新的合约上去,这个新的智能合约只有一个功能,就是退钱,当初用以太币买的The DAO的代币,现在可以把这个代币退回成以太币,就这一个功能,为什么是硬分叉?

用软件升级的办法强行重新记账,本来要转账得有合法的签名,比如说我要把你账上的钱转走,那得经过你的同意,有你的签名才行,这个时候就不管这些了,这是非常时期,凡是The DAO上面的资金,不管本人同意不同意,都要强行转到一个新的智能合约上去,就有点像法院的强制执行,那么升级的软件里规定了强制执行的具体日期:挖到第192万个区块的时候。所有升级软件的矿工,挖到第192万个区块的时候,自动执行这个转账交易,不用合法的签名,这是在升级的软件里写死的一条规则,旧矿工是不会认可这个区块的,因为没有合法的签名,认为是非法交易,所以是硬分叉。

​ 硬分叉的方案一提出来,在以太坊社区引起了非常激烈的辩论,我们前面说过,社区本来就分成了两派,有一派是认为不应该采取补救措施,这些人认为这种强行重新记账的办法是没办法接受的,这不是“耍流氓”吗?其实比中心化的组织还要差,法院强制执行都要走法律程序,被告还能聘请律师辩护呢。支持硬分叉和反对硬分叉的两派,争论地非常激烈,之后就投票,以太坊团队实现了一个用智能合约投票的功能,你可以把手里的以太币发到合约里进行投票,最后投票的结果是大部分人支持硬分叉,于是绝大多数矿工也升级了硬分叉的版本,大家就等着挖出第192万个区块的历史性时刻,这一次没有出现意外,硬分叉成功了,黑客盗取以太币的行为最终还是没有能够获利。故事到这也就结束了。

​ 当初那些反对硬分叉的人,并没有因为投票结果而改变立场,他们认为,首先这次投票参与的人不是很多,投票是由两个智能合约,如果支持硬分叉,就把以太币投到一个合约里,如果反对硬分叉,发到另外一个合约里,然后锁到这个合约里,等投票之后再退回来,有很多以太币根本没有参加投票,这是第一点。第二点,也是最重要的一点,投票能说明问题吗?大多数人的意见一定是对的吗?你这样做是不是真的公平?硬分叉之后,旧的那条链并没有消亡,还有一些矿工留在上面继续挖,只不过算力大幅度下降,不到原来的1/10,但是这样做也有一定的好处,挖矿的难度大幅度的下调了,因为竞争没有这么激烈了,所以还是有些矿工愿意留在旧链上继续挖,过一段时间,有一些交易所开始上市交易旧链上的以太币(ETC:Ethereum Classic)。在旧链上挖的那些矿工有一些是出于投机目的,因为旧链上挖矿难度小,容易挖到币,而且上到交易所之后,盈利就有了途径,也有一些人在旧链上挖是出于信仰,出于坚持,纯而又纯的去中心化的理念,认为旧链中的以太坊根正苗红,这个ETC刚开始上交易所的时候,有很多人认为它的前途有非常大的不确定性,因为以太坊的核心开发团队都是支持硬分叉的,都是转到新链上开发的,那么旧链还能存活多久,这是大家的一个疑问,结果一直存活到了现在。

​ 在刚开始的时候,两条链并存实际上带来了很多问题,因为这两条链的代码基本上是一样的,除了硬分叉相关的规则不一样之外,其他大部分代码都是一样的,而且硬分叉之前,用的也是同一套历史账本,用的同一套账户,私钥都一样,这样会带来一个什么问题?重放攻击,在新链上一个合法的交易,放在旧链上去,同样是合法的,重放之后仍然是可以执行的,同样,反过来也是一样,带来了很多管理上的混乱,后来给两条链增加了一个chain ID。旧链上的算力,已经比刚硬分叉的时候提高了很多倍了,到这里,这个故事才真正讲完了。

​ 不论是软分叉的解决方案,还是硬分叉的解决方案,目标都是为了锁定黑客盗币的那些账户,但是我们讲解决方案的时候,都是把The DAO的所有账户都作为目标,比如软分叉的时候,The DAO的所有账户都不准交易,硬分叉的时候,The DAO的所有交易都必须转账,为什么不能只针对黑客的那些账户?

我把黑客的钱没收了,然后按照发生攻击之前,每个人的账户余额去退,实际上最后也是这么操作的,智能合约的内容是公开的,包括智能合约所有的变量,存储什么的,函数定义成public,是大家都可以调用,但是不定义成public,函数的内容还是可以看得见的,就区块链上的代码都是开源的。

如果我们只冻结黑客的账户,The DAO的其他账户该怎么处理?其他账户是好人的所以不用管?如果你的智能合约写的有bug,你发布到区块链上之后,就改不了了,The DAO这个智能合约是有bug的,这个bug黑客这次用了,下次别人也可以用,光是把黑客的账户冻结了 ,剩下的账户继续运行,那任何人都可以成为黑客,在用同样的方法盗取以太币,这个bug你修不了,所以智能合约出现这种致命的bug,就作废了,事实上最后他也作废了,为什么他只存活了三个月,硬分叉之后,这个风靡一时的投资基金,The DAO就随之解体了,所有的账户都不安全了。