上节课我们提到了重入攻击,那么这种攻击真的可能存在么?我们这节会介绍一个真实的案例,这个案例造成了以太坊的分裂,他就是一个众筹智能合约The DAO。

我们说以太币实现了去中心化的货币,以太坊实现了去中心化的合约。那么为什么不把一切都去中心化,DAO这个概念就是这时候产生的,

DAO

Decentralized Autonomous Organization,去中心化的自治组织。传统社会中,组织是建立在某种法律文件上的,比如一个书面的章程来规范组织的行为,有时候还需要到政府部门去注册(比如一个公司)。在区块链中,DAO这个组织就是建立在代码基础上,组织的规章制度写在代码里,通过区块链的共识协议来维护规章制度的正常执行。比如以太坊的智能合约就可以作为一个DAO的规章制度。

The DAO

在2016年5月,出现了一个致力于众筹投资的DAO:The DAO。它的工作原理类似一个众筹的投资基金,用于投资项目,只不过钱的来源是通过区块链上大家众筹的方法得到的。本质上是运行在以太坊上的一个智能合约

如果你想参与The DAO,那么你可以把以太币转给这个智能合约,换回The DAO的代币,需要决定投资那个项目的时候,大家投票决定,每个人的投票权中跟代币数量有关。最终有了收益,也是按照智能合约里的规章制度分配收益。所以他的工作形式类似于DAC(Decentralized Autonomous Corporation)去中心化的自治公司。DAO和DAC的区别是前者更多的是为了公益,后者更多是为了盈利。虽然DAC叫公司,但并没有现实中公司的法律地位,一般也不会有公司的组织形式。

The DAO在2016年5月开始众筹的时候,引发了很大的关注度,因为之前从未有过如此民主的投资基金(只要你投入以太币,就有权决定投资那个项目)。在当时被称为一种伟大的尝试,一个月的时间就筹集到了价值1.5亿美元的以太币,这种速度和规模是很罕见的,大伙议论纷纷,并觉得The DAO的前景一片光明,甚至说3-5年之后,The DAO的影响甚至可能超过以太坊本身。遗憾的是The DAO只存活了三个月。

问题出在取回资金上。我们提到加入众筹只需要投入以太币,换取The DAO的代币,那么我怎么取回我投入的以太币?实际上,The DAO采用账户拆分的方法来实现。

split DAO

账户拆分。不仅仅用来取出收益,也是一种建立子基金的方法。

拆分完得到一个child DAO。我们提到之前投资是用以太币换代币,代币作为票数投票投资,那么如果有一小部分人的投资理念与其他人不一样,他们想独自投资,就可以用到split DAO的方法,从The DAO里独立出来,成立一个child DAO,拆分时,用户手中的代币要被收回,换成相应数量的以太币打入子基金里,就能独立投资了。

拆分的一个极端例子就是child DAO里只有他自己,这时候就能把所有的钱投给自己。这是投资者取回投资和收益的唯一途径。

拆分之前,有七天的辩论期,大家可以讨论拆分的是否合理,也可以选择加入拆分。拆分之后有28天的锁定期,就是打入子基金的以太币要锁定28天,28天之后才能进行交易。我们后面可以看到,就是这28天的锁定期给了以太坊的补救时间。

拆分制度的理念并没有错,而且可以说是民主制度的进一步体现,民主制度并不是少数服从多数,而是也要尊重少数人选择的权利

split DAO的代码实现

下图为具体代码实现 很容易发现问题。

image-20230119181445217

问题就出在框起来的转账操作,他这样的实现完美符合了上节提到的重入攻击的条件。所以黑客就通过重入攻击从里面转出了5000万美元的以太币,差不多占The DAO的1/3。这在现实社会引起了很大的恐慌,大家本来认为前途无量的The DAO,去中心化这样完美的理念,在现实中被证明是不堪一击的。这也引起了以太币的价格大缩水

大家的观点

以太坊社区对此进行了激烈的讨论,分为两派人

  • 一部分人认为要回滚交易。我们提到有28天的锁定期,也就是还有时间采取补救措施,不能让黑客得逞
  • 另一部分人认为不需要采取回滚。因为黑客做法并没有违法,我们说过’code is law’,代码中的漏洞也是规则的一部分。

这个事件发生后,网上流传着据说是黑客写给以太坊社区的公开信,公开信里说:我没有做错任何事情,我只是运用了你代码里的一个feature。因此以太坊社区一部分人认为不应该采取补救措施,尤其不应该回滚,因为区块链最重要的特性就是不可篡改性,如果出了问题就会滚,那怎么能叫不可篡改性呢。而且这次出问题的只是以太坊的一个应用,也就是众多智能合约的一个,要是智能合约出了问题就会滚,那就不能称为不可篡改的去中心化账本

以太坊的开发人员认为应该会滚,主要是因为这次事件的影响太大了,The DAO这个智能合约中的以太币数目已经占到了当时总量的10%左右,如果我们放任不管,那么这10%的以太币都会受到影响。套用美国金融危机的一个说法:’too big to fail’。2008年美国金融危机时有两个房地产公司,美国有一半的房子属于这两家公司,当时两家公司勉励破产,美国政府出面拯救了这两家公司,原因就是这两家公司太大了,如果垮掉会对美国经济产生极大的影响。所以开发人员决定补救也只是因为他的影响太大了,影响小的交易是不会被补救的。

补救措施

首先,能不能如下图从黑客攻击的区块开始,在前一个区块建立一个分叉

image-20230119185743370

答案是否定的,因为The DAO只是以太坊众多智能合约的一个,其他的不涉及到这个给智能合约的交易是合法的,整体回滚会让系统乱套,所以不行,要回滚必须精确定位,其他的正常交易不能受到影响,这是采取补救措施的原则

所以以太坊开发团队设计了两步走的方案,首先锁定黑客的账户,然后再设法清退The DAO基金上的钱

首先怎么锁定黑客账户?

以太坊团队发布了一个软件升级,增加了一个规则,凡是和The DAO基金相关的账户不能进行交易。

这个升级发布之后,大部分矿工升级了软件。这次升级为软分叉。(新节点认为旧节点非法,旧节点认为新节点合法)

这个软件升级的想法是很好的,也得到了大多数矿工的支持,遗憾的是升级之后的软件有一个bug,这个bug是跟汽油费相关的。我们说一个全节点收到一个交易,判断这个交易是否和The DAO相关,如果是非法交易不予执行,那么要不要收取汽油费?

社区发布的软件升级恰恰没有收取汽油费,结果网上攻击者发布大量的非法交易,大部分矿工都升级了,但是升级了就会频繁收到这样的非法交易,没多长时间矿工就受不了了,于是纷纷回滚软件升级,这个软分叉的方案就失败了。

这时候形势就比较严峻了,因为只能锁28天,采取软分叉失败之后,留给开发团队的时间已经不多了,那该怎么办呢?

既然软的不行,那就来硬的。开发团队通过软件升级的方法把The DAO账户上的所有资金强行转到一个新的智能合约上,这个智能合约只有一个功能:退钱。这是硬分叉,因为本来转账要有合法的签名,我从你账户上转走钱,要你的签名,而这时是非常时期,凡是The DAO账户上的资金,不管同意与否,都强制转到一个新的合约账户里。升级的软件里规定了强制执行的具体日期:挖到第192万个区块的时候。也就是升级软件的矿工挖到第192万个区块的时候,自动执行转账交易,不用管是否有合法的签名。(旧的认为新的非法)

这个解决方案一出,引起了激烈的讨论。之前本来就有反对回滚的人,现在又要强行转走账户的钱,他们认为这是,开发团队发布一个软件升级就能把别人账户上的钱转走,这怎么能叫去中心化的不可篡改的账本,这跟中心化的组织没有区别,甚至比中心化的组织更差,因为现实中中心化的组织做这种决定还得走法律流程,这里发布个升级就完事了。

为了解决争议,开发人员发布了投票,设计了一个用于投票的智能合约,账户可以用手里的以太币作为筹码投支持或反对,结果是绝大部分矿工支持硬分叉。大家就平心静气的等待挖出第192W个区块的时刻,这时候,没有出现意外,硬分叉成功了。黑客最终没有获利。

有一个细节问题,提到的硬分叉和软分叉的解决方案,我们锁定的并不是只有黑客的账户,而是锁定所有的和The DAO相关的账户,这是为什么?能不能只锁定黑客账户?

答案是必须全部锁定,我们上节提到,如果智能合约写的有bug,你发布到区块链上,这个bug是无法修改的,不能默认除了黑客以外的账户都是好的,你冻结黑客的账户,那么还可能冒出来第二个黑客。所以智能合约出现这种致命的bug就作废了,事实上最后The DAO也是只能作废。

后续

我们听到这里感觉故事已经结束了,但你先别急,当初那些反对硬分叉的人并没有因为投票结果而改变立场,因为首先投票的形式是两个合约,一个代表支持,一个代表反对,需要把以太币投进去,他们认为投票的人不是很多,其次,也是更重要的一点,投票能说明问题么?大多数人的意见一定是对的么?

硬分叉结束后,旧链并没有消亡,还是有人沿着那条链挖,但是算力大幅度降低,大概到原来的1/10,但这也有一个好处:挖矿难度大幅度降低,竞争变小。

过一段时间,一些交易所开始上市交易旧链的以太币。这时候新的链的币继承了ETH,旧的链挖出的以太币叫ETC(Ethereum Classic)。在旧链上挖的矿工有一部分是为了投机,因为挖矿难度小,还有一部分人是出于信仰,这些人认为旧链才是正宗的以太坊,那些搞硬分叉的是在搞修正主义。

ETC刚上市,大家对ETC的前途表示怀疑,并且刚刚硬分叉出现了很多问题,比如我们之前提到的重放攻击。

一直到现在ETC还活着,只是一直被ETH压一头,除非ETH2.0出现。