ETH-23TheDAO

内容整理自 北京大学肖臻老师《区块链技术与应用》公开课 ETH-23-TheDAO

2016年一个真实案例,该案例在以太坊历史上造成了以太坊的分裂,可以说改写了以太坊的历史。

比特币实现了去中心化的货币,以太坊实现了去中心化的合约,所以有人提出把所有的都改成去中心化,DAO(Decentrallized Autonomous Organization,去中心化自治组织)这个概念就是在这个背景下产生的。DAO这个组织是建立在代码基础上,组织的规章制度是写在代码里的,通过区块链的共识协议来维护这种规章制度的正常执行。

2016年5月,出现了一个致力于众筹投资的DAO,名字叫做The DAO。工作原理类似于众筹的投资基金,用来投资项目的,只不过资金来源是通过在区块链上众筹的方法得到的,本质是运行在以太坊上的智能合约。如果想参与The DAO,就把以太币发给智能合约,然后换回The DAO的代币,需要决定投资哪个项目是投票决定的,手里的代币越多,投票的权力越大。如果有了收益也是按照智能合约中制订的规章制度来进行收益分配。

开始众筹的时候受到了很大的关注度,因为以前没有这样民主的投资基金,一个月的时间筹集到1.5亿美元的以太币。不过遗憾的是The DAO只存活了3个月。如果想要把投资的以太币换回来,通过拆分的方法来实现(split DAO)。拆分的方法不是仅用来取回收益,也是一种建立子基金的方法(child DAO)。设计的理念是投资项目是靠大家手中的代币去投票,如果有一小部分人的投资理念跟其他人不一样,这种情况下这小部分人可以通过拆分的方法独立出来,成立一个自己的子基金(child DAO),拆分的时候手中的代币是要被收回的,换成相应数量的以太币,把相应数量的以太币打到子基金里,然后就可以投想投的项目,这就是拆分的过程。拆分极端的例子就是单个投资者成立子基金,在子基金里可以把所有的钱投给自己,这是投资者取回投资和收益的唯一途径。拆分前有7天的讨论期,拆分后有28天的锁定期,就是这28天的锁定期,给了以太坊社区采用补救措施的时间。

拆分的理念没有错,问题在于split DAO的实现上,代码如下:

注意withdrawRewardFor方法,首先把钱还给调用函数的人,然后把The DAO中的总金额减少相应的数量,再把调用者的账户清零。这就是问题所在,正确的顺序是先把账户清零然后再转账,黑客就是利用这个漏洞进行重入攻击。The DAO从5月开始众筹,一个月的时间筹集到1.5亿美元的以太币,然后黑客利用重入攻击从里面转走了5000万美元的以太币,接近1/3。这在当时引起很大的恐慌,也引起以太币价格的下降。

以太坊社区对此意见分为两派:一派认为要回滚交易,因为28天锁定期黑客暂时无法把钱取走,通过回滚交易不让黑客得逞;另一派认为不需要采取补救措施,因为黑客的行为并不违法,代码中的漏洞也是规则的一部分,所以不该采取补救措施,尤其不该回滚交易,因为区块链最重要的特性是不可篡改性,如果出了问题就回滚,不能说是不可篡改,而且出问题的只是以太坊上运行的一个应用,以太坊本身的代码没有问题,只是上面的一个智能合约有一个漏洞,以太坊有那么多智能合约,如果每个出问题都回滚就会乱套,更不能称之为不可篡改的去中心化的账本。

以太坊开发团队是支持采取补救措施的,因为事情影响大,The DAO筹集的以太币数目占到当时以太币总流通量的很大一部分,大概是10%以上,如果不管那么这些以太币中大概1/3要落到黑客手中,以太坊社区认为The DAO这个组织是too big to fail(美国金融危机时期的说法),所以要救。 

如何补救:比如从发生之前的那个区块开始分叉,这样造成的问题是不光是黑客攻击的交易回滚了,其他合法交易也回滚了。要回滚的话必须是只针对黑客攻击的那些交易,其他正常交易不能受到影响,这是补救措施的一个原则。以太坊团队制定两步走的方案,第一步首先锁定黑客账户,第二步再设法把盗取的以太币退回去。

第一步:以太坊团队发布软件升级,升级的软件里增加一条规则,凡是与The DAO基金上的账户相关的,不允许做任何交易。大部分以太坊矿工都升级了该软件,这个是属于软分叉。但是升级之后的软件有一个bug,与gas fee相关,当收到一个交易判断是不是与The DAO账户相关,如果相关认定非法不予执行,这个时候还要不要收取gas fee?如果不收取可能会有攻击者不断发放非法交易浪费矿工资源,攻击成本低。以太坊社区发布的软件升级没有收取gas fee, 结果有大量的恶意攻击。矿工升级软件后长期收到这样的交易,便回滚了软件升级,于是软分叉的方案失败了。

软分叉方案失败后剩下的时间就不多了,团队设计一个硬分叉方案,通过软件升级方法,把The DAO账户上所有资金强行转到另外一个新的智能合约上去,新的智能合约只有一个功能就是退钱,把代币退回成以太币。这种做法的本质是用软件升级的方法强行重新记账,类似法院强制执行。升级软件里规定强制执行的日期就是挖到第192万个区块的时候,自动执行转账交易,不需要合法签名。旧矿工是不认可这个区块的,因为没有合法签名,是非法交易,所以是硬分叉。

支持硬分叉和反对硬分叉的两派最后决定用智能合约投票,可以把手里的以太币放到智能合约中进行投票,最后投票结果是大部分人支持硬分叉,也升级了软件,等着挖出第192万个区块,最后硬分叉成功了,黑客盗取以太币的行为没有获利。

但是当初反对硬分叉的人并没有因为投票结果而改变立场,首先投票参与的人不是很多,因为投票是有两个智能合约,支持硬分叉把以太币发到一个智能合约里,反对硬分叉发到另一个智能合约里, 然后用锁的智能合约等到投票结束后再退回来,很多以太币没有参加投票。 第二点是投票不能解决问题,大多数人的意见也不一定是对的。硬分叉之后旧的链并没有消亡,还是有些矿工继续挖,只是算力大幅度下降,同时挖矿难度也大幅度下调了,没有那么激烈的竞争。分叉之后新的那条链继承了ETH的符号,旧的链挖出的以太币叫做ETC(Ethereum Classic)。至今以太坊依然是两条链并存。

开始分叉的时候两条链带来有些问题,因为两条链的代码基本相同,除了硬分叉相关规则不一样,而且硬分叉之前用的也是同一套历史账本,用的同一套账户,私钥都是一样的,这样会带来重放攻击,新链上的交易放到旧链上依旧是合法的, 反过来旧链上的合法交易放到新链上也是可以执行,带来管理上的混乱。后来给两条链增加了一个chainID,给两条链区分开,现在是两条分开的链,现在交易所上还是有两种不同的以太币,而且旧链上的算力比刚刚硬分叉的时候提高了很多倍。

无论是硬分叉还是软分叉的解决方案,目标都是为了锁定黑客的账户,但是解决方案中都是把The DAO的所有账户作为目标,之所以不能只针对黑客的那些账户,是因为如果只冻结黑客账户,那么其他账户依旧可以发动攻击,如果智能合约有bug,那么发到区块链上之后就不能再更改了。如果剩下其他账户继续运行,那么任何人都可以成为黑客偷以太币,因为智能合约修改不了。硬分叉之后,The DAO就随之解体了。