![](/web-v2/img/index/iconfen.png)
原文标题:《以太坊升级的拖油瓶,竟只是这几行代码》
原本,马上就到了以太坊原定的君士坦丁堡大升级的时间。但是,一天前的一条 bug 改变了一切:
北京时间 1 月 15 日傍晚 7:09,ChainSecurity 通过以太坊基金会的 bug 悬赏计划披露了本次升级中 EIP 1283 所存在的一个漏洞。
今天凌晨 0:09,以太坊基金会请求 ChainSecurity 公开该漏洞相关的具体信息。2 分钟后,ChainSecurity 关于漏洞报告的文章公开发布。
凌晨 0:52,以太坊基金会安全主管 Martin Holst Swende 在 Gitter 的 ethsecurity 和 AllCoreDevs 频道向相关相关开发者通报漏洞情况:
「请大家都看看这篇文章:https://medium.com/chainsecurity/constantinople-enables-new-reentrancy-attack-ace4088297d9。并 @ 所有人 我们需要迅速确定其潜在后果并定下来如何推进。我们离分叉只剩下 37 小时时间了。」
凌晨 0:52 — 2:15,以太坊基金会通过多种渠道讨论了相关的潜在风险、链上分析以及需要采取的应对措施。
凌晨 2:15 — 4:40,关键的利益相关者也通过 Zoom 音频通话进行了讨论,同时 Gitter 和其它渠道上的讨论还在继续进行。
北京时间今天凌晨 4:08,以太坊基金会决定推迟君士坦丁堡升级。
凌晨 5:30,以太坊基金会通过多种渠道和社交媒体公布了这一决定。
链接:https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/
一只虫子瞬间毁了一锅汤:
那么,这究竟是一只怎样的虫子呢?
废话不说,在 ChainSecurity 的文章里面,存在漏洞的代码是这样的:
翻译成普通话就是,在智能合约中使用这里的代码,可以让双方两方共同接收资金,共同决定如何分割资金,然后启动这些资金的支付。
看上去很美好,但如果攻击者使用下图中的代码进行攻击,就可以多次「重新进入」同一个函数,却又无需更新用户的事务状态,从而可以「重复撤回资金」。
这就是重入式攻击(re-entrancy attack),特别是那些在 transfer() 或 send() 函数后附加改变状态操作的合约,更容易受到攻击。
发生这种情况时,通过 1 ETH 的成本投入,攻击者轻易就能换回成千上万以太币的收益。
这不得不让人回想起 2016 年 The DAO 事件中的漏洞:
当年的 6 月 17 日,黑客利用 The DAO 代码内的一个递归调用漏洞,不停地从 The DAO 资金池里面分离资产;而后又利用 The DAO 另外一个漏洞来避免分离后的资产被销毁,数小时内执行攻击 200 多次,所盗取的以太币共计超过 360 万,当时价值 7000 多万美元,按今天的价格则高达 4.4 亿美元。
The DAO 项目随之分崩离析,并引来美国证券交易委员会的严格调查。而以太坊基金会为了避免损失,不得不实行硬分叉,一时间争议极大,以太币价格径直暴跌 30%。
而对于这一次的漏洞,ChainSecurity 的总结非常简短:
- EIP-1283 为 SSTORE 操作带来了更便宜的 Gas 成本;
- 一些(已经在链上的)智能合约的代码模式,可能使它们在君士坦丁堡升级发生后容易受到重入式攻击(re-entrancy attack);
- 在君士坦丁堡升级之前,这些智能合约不会受到影响。
具体代码研究的 GitHub 项目在这里:https://github.com/ChainSecurity/constantinople-reentrancy
可能是 The DAO 事件的教训太过深刻,对于这次 EIP 1283 所曝出来的漏洞,以太坊社区的行动极其迅速,从漏洞披露到应对决策,短短 9 个小时,利益相关的各方便能就漏洞的解决方案达成一致。
对此,以太坊基金会的 Hudson Jameson 给出了极高的评价,在它看来,几经风雨的以太坊社区确实成熟了许多:
反差之下,营长瞬间记起了 EOS 主网上线前的缓冲区越界写入漏洞,去年 5 月底那场发生在 BM 与 360 之间长达数天的撕逼……
说点正事,这个漏洞会影响到我吗?
一般用户:吃瓜就好,无需任何操作。
矿工或节点运行者:请更新你的以太坊客户端——Geth 和 Parity
Geth
- 升级到 1.8.21
https://github.com/ethereum/go-ethereum/releases/tag/v1.8.21 - 或降级至 Geth 1.8.19
https://github.com/ethereum/go-ethereum/releases/tag/v1.8.19 - 保持在 1.8.20,使用开关 '-override.constantinople = 9999999' 无限期推迟君士坦丁堡分叉。
Parity
- 升级到 Parity Ethereum 2.2.7-stable (推荐)
https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.7 - 升级到 Parity Ethereum 2.3.0-beta
https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.0 - 降级至 Parity Ethereum 2.2.4-beta (不推荐)
https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.4
究竟君士坦丁堡何时能上线?
不过,以太坊的君士坦丁堡推迟后,大家更关心的可能还是它真正上线的时候问题。
根据紧盯以太坊动态的 Evan Van Ness 的说法,新的升级时间需要等到本周五以太坊核心开发者的电话会议。
Evan Van Ness 是每周以太坊动态「Week in Ethereum News」的作者。
补充一下,何谓君士坦丁堡?
君士坦丁堡是以太坊网络更新的代号。此次更新是无争议的,并且预计每个人都同意在这条新路径上采用以太坊区块链。就像 2016 年的「家园」和 2017 年的「拜占庭」,此次硬分叉将导致两个链条,但旧链几乎立刻会死亡。
这次以太坊更新包括以下 5 个新的以太坊改进提案(EIP):
EIP145:出自以太坊开发人员 Alex Beregszaszi 和 Pawel Bylica;主要引进了一种叫做「按位移动」(bitwise shifting)的运算符。以太坊虚拟机(EVM)之前缺少这种运算符,只支持其他逻辑和算数运算符,「按位移动」运算符只能通过逻辑和算数运算符实现,现在通过原生支持「按位移动」运算符,能大大优化 DApp 开发者智能合约的 Gas 消耗。
EIP1014:由以 V 神亲自提出,增了一个合约创建函数 CREATE2,提供了一种可以提前预测合约地址的合约创建方法,该升级能更好的支持基于状态通道或者链下交易的扩容解决方案,即现在主流的 Layer 2 方案。
EIP1052:出自以太坊核心开发人员 Nick Johnson 和 Pawel Bylica;引入了一个新的操作码,允许直接返回合约字节码的
keccak256 哈希值,该升级能有效减少以太坊网络对于大型智能合约的运算量,尤其是只需要智能合约的哈希值的时候。
EIP1234:该升级主要是将现有的区块奖励由 3 ETH 减少到 2 ETH,减产 33%,同时将难度炸弹(difficulty bomb)推迟 12 个月。
EIP1283:该升级通过更改 SSTORE 操作码优化智能合约网络存储的定价(Gas),减少和智能合约运行量不匹配的 Gas 消耗。
早前报道普遍猜测,本次升级中以太坊的共识算法将会进入 PoW/PoS 的混合模式,即每 100 区块中,前 99 个区块使用 PoW 共识,而最后一块使用 PoS 共识。基于此,以太坊将可以在公网环境以一个安全系数较低的方式检验基于 PoS 的 Casper 算法,而且可以依赖最后一块的 PoS 共识来有效抵御 51% 攻击。
而事实上,在君士坦丁堡版本中,共识模块只包含主网使用的 PoW 算法 Ethash,以及测试网 Ropsten 采用的 PoA 算法 Clique,并没有 PoW/PoS 混合共识的支持。而且,本次硬分叉也不会分叉处新的资产。
2019,为以太坊 2.0 铺路
尽管难产,君士坦丁堡却是以太坊 2019 年最重要的一个起点:
以太坊接下来的升级,还将引入 Casper、Beacon chain、Sharding、eWASM、Plasma 等以太坊 2.0 的理念,为最终的「宁静」阶段铺路。
其中,Casper 协议,将以太坊从 PoW (工作量证明)过渡到 PoS (权益证明)。虽然 PoS 不会立即取代 PoW,但是我们将看到一个同时运行的混合系统。由于「难度炸弹」协议的延迟,矿工将有充分的时间从 PoW 转到 PoS。一旦被激活,以太坊中的 PoW 挖矿将变得更加困难,以便将激励转向 PoS。
以太坊开发人员随后将转向使用「Beacon chain」概念验证。Beacon Chain 将是一个融合现有主网络和网络新功能的协调层,但是目前还没有开始构建。它将把 PoS 区块链作为新的共识协议带入到以太坊网络中。Beacon chain 的一个主要功能是管理以太坊扩展的新特性,即:「分片」(sharding)。
分片将把网络切分为独立的节点组——shards。这将分割网络负载,使主网络不必承担所有交易的负载。相反,分片将重新分配以太坊网络的计算负载,以便其实现扩展。然而,这样做的缺点是对网络安全的影响,因为这可能导致每个分片受到攻击。这就是为什么实现非常重要的原因,因为必须在安全 , 去中心化和可扩展性之间的维持平衡。保持分片协调也很重要,以便保持区块链的一致性状态,这也正是 Beacon chain 的功能。
此外,EIP 145 和 1052 还详细规定了优化 EVM (以太坊智能合约虚拟机)的代码。该优化引入了按位移动(bitwise shifting),提高了网络效率。逐位移动就像字节码中的快捷方式,不依赖于复杂的算术运算,这使得网络可以更快地处理去中心化应用。正如我们过去所看到的,当以太坊网络的在线用户过多时,网络速度很容易变得慢的不像话。代码的优化将使网络能更有效地使用计算资源。反过来,开发人员和用户在以太坊网络上的计算成本也得到了节省。
用 eWASM (Ethereum Flavored WebAssembly)替换 EVM 也是该计划的一部分。这样做的优点之一是:智能合约的代码执行速度更快。EVM 使用 256 字节的字大小,这在实际应用程序中效率并不高。WASM 也被用于其他加密货币项目,如 EOS 和 Cardano。
gas 收费结构的调整很受开发者欢迎。EIP 1283 将为智能合同带来更好的成本优化。具体方法是分解写在以太坊内存存储中的合约更改。由于这样做不会影响区块链上的任何状态更改,不会消耗 gas,从而降低了开发人员的成本。
此次计划还有一些扩展以太坊网络的建议,名为:第 2 层(Layer 2)或「链下」解决方案。Plasma,是一个基于在子链上实现的智能合约的第二层解决方案。Raiden,相当于以太坊的闪电网络。这些解决方案与以太坊框架完全适配。如果事实证明这些解决方案可行,那么对投资者来说也将是件好事。
工作量证明为区块链提供了安全保障。有了「链下」解决方案,用户将承担更多的责任,因为他们不再拥有主网络提供的共识机制。由于是由工作量证明向权益证明转换,这将要求区块验证者维持良好的信誉,他们必须质押一定数量的 ETH (他们的权益)。如果区块验证者有不良企图,他们质押的 ETH 将会被没收,这就像是在一个去信任系统中将他们的信誉作为保证金。
在其他相关新闻中,也有关于以太坊期货合约的讨论。机构投资者致力于推动以太坊生态系统的构建,但监管机构在评估 ETH 等数字资产与比特币的不同之处。问题是这些资产是一种证券还是一种商品。一旦确定了这一点,答案就很明了了。
如果以太坊项目成功实现了这些升级特性,那么接下来就是「宁静(Serenity)」阶段。宁静是以太坊下一个版本的名称,它将在纯粹的 PoS 共识协议上运行。这将使以太坊成为一个更快的去中心化计算平台。实现这一点是重要的一步。
从以太坊社区的表现上看,本次漏洞应该不会发展成「君士坦丁堡的沦陷」。不过,即便君士坦丁堡成功升级,以太坊发展到宁静阶段仍然需要一条相当漫长的路。
参考链接:
- https://eips.ethereum.org/EIPS/eip-1283
- https://github.com/ChainSecurity/constantinople-reentrancy
- https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/
- https://medium.com/chainsecurity/constantinople-enables-new-reentrancy-attack-ace4088297d9
- https://hackernoon.com/ethereum-2-0-the-road-to-constantinople-and-beyond-44f8876ef748
- https://blog.ethereum.org/2019/01/11/ethereum-constantinople-upgrade-announcement/
- https://medium.com/futuresin/ethereums-constantinople-is-here-f3d5353cfce3
- https://media.consensys.net/the-constantinople-hard-fork-what-you-need-to-know-d438a91dec3f
- https://pages.consensys.net/constantinople
![](/web-v2/img/index/right-outlined.png)
![](/web-v2/img/index/right-outlined.png)
![](/web-v2/img/index/right-outlined.png)