作者GameDemon ()
看板DigiCurrency
标题[Coin] Bitcoin Core 0.7ms 的代价
时间Sat Sep 29 12:32:54 2018
Bitcoin Core 0.7ms 的代价
细说 CVE-2018–17144的来龙去脉
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
图文好读 Medium 版 : https://tinyurl.com/y7l8gf53
前言
Bitcoin Core 在 2018/09/18 时紧急发布了新版本 0.16.3,并在其中提到:
We highly recommend users of all affected versions
immediately upgrade to 0.16.3.(Ref#1)
区块链圈无不掀起一波讨论,当然各式媒体也相继报导;最耸动的莫过於这句话:
康奈尔大学教授 EminGünSirer 表示,估计只需不到 8 万美元的成本
(12.5 枚比特币)就能瘫痪整条比特币区块链。(Ref#2)
事情真有这麽可怕?瘫痪整条链?只要八万美元?
秉持着工程师精神,追根究柢找了一些资料终於了解整件事情的前因後果,
就让我娓娓道来。
=============
前因
Bitcoin Core 身为元老级的 bitcoin 用户端
(Bitcoin 的其余分支也师承此 source code),算得上是 open source 界经典范例。
拥有五百个以上的全球贡献者时时都为 Bitcoin Core 上 pull request,
有的为了修正 bug,有的为了提升效能。
那现在我们就要回到 2016/11 的 pull request #9049 (Ref#3):
Benchmark results indicate this saves about
0.5–0.7ms during CheckBlock.
这个 PR 提高了 CheckBlock 的效能,主要是做了以下的 change:
// Check for duplicate inputs — note that this check is slow
so we skip it in CheckBlock
https://i.imgur.com/T2e1MtP.png
(Code Snippet for PR#9049)
简单来说,矿工们会无所不用其极地节省各式计算的时间,
以期在挖矿时确保能挖的比别人快。所以这个 PR 的用意在於,
想要在 CheckBlock 时略过检查於 transaction 中是否有两个相同的 input,
以节省时间。
(检查的方式算是蛮暴力的,利用 std::set::count 与 std::set::insert 来检查
是否有重复,时间复杂度为 O(n log n))
其实,有没有相同的 input 是一个非常重要的检查,
意义在於避免双花(double-spending);当初此 PR 作者群认为,
每个 transaction 在上到 mempool 的时候,就应该做过检查了,
所以当 block 上链後,照理说事後应不需多花这个计算时间重复检验。
=============
後果
But,就是这个 but ,在将近两年後的 2018/09/17 ,
这段 comment 被一位 Bitcoin Cash/Bitcoin Unlimited 的开发者 Awemany
於开发时无意发现(Ref#4),於是做了一些实验,
制造出具有相同的 input 的 transaction,
来测试 Bitcoin ABC (Bitcoin Cash 的 client),居然遇到了
assert(),
程式直接 crash ,当他转而测试 Bitcoin Core 也得到相同结果
(这并不意外,Bitcoin 子子孙孙的原始程式大多都从 Bitcoin Core fork 出来),
这时候 Awemany 就知道不太妙了,开始做後续通报的动作。
https://i.imgur.com/SOoc2XI.jpg
(bitcoin/src/validation.cpp code snippet)
Assertion failure point 在CheckBlock()之後的链结区块ConnectBlock()。
而其中之 UpdateCoin() 会检查 input 是否有被重复 spend,若有则 assert()。
Bitcoin Core 团队迅速的於24小时内提出修正并释出新版本(Ref#5)。
Fix 非常简单,就是把原本於CheckBlock() 的duplicate inputs重新打开…(#Ref6)
=============
这件事情为什麽是个区块链圈大新闻,这边归纳为以下几点:
1.
影响范围广大:许多区块链实作受到影响,尤其是从 Bitcoin 分叉出来的,
除了上述的 Bitcoin Cash、Bitcoin Unlimited 外,Litecoin 也受其影响。
2.
可能引发严重後果:普通程式异常关闭虽然是我们生活中的日常,
但在区块链的世界中却是一件大事。矿工利用程式挖矿,以建立共识并确认交易;
当程式异常关闭(而且是一直关闭),就不会有矿工可以帮交易做确认,
整条区块链可以算是瘫痪;
更严重的是,只要骇客成功算出一个包含有重复 input 的区块放到链上,
会成为一种阻断服务攻击(DoS),可以大大的降低整体算力,
使 51% 攻击更容易成功,进而修改区块链上的资料。
3.
修复是一个缓慢的过程:P2P 世界中,成千上万的节点需要被更新,
这不是像按一个按钮就可以完成的。截至 9/24 修正释出的一个礼拜後,
Bitcoin 全网仍有
87% 的节点受此CVE 影响(Ref#7)。(真的是87%….)
=============
反思
理解了来龙去脉,回到最前言的部分,
到现在为止我们已经知道了为什麽大家认为这是一个(目前)史上最严重的
Bitcoin bug,会使整条链瘫痪。
但让我再次引用 INSIDE 文章的某一段文字:
康奈尔大学教授 EminGünSirer 表示,
估计只需不到 8 万美元的成本(12.5 枚比特币)就能瘫痪整条比特币区块链。(Ref#2)
那个 8 万美元的成本(12.5 枚比特币)到底是怎麽算出来,
一直困扰着我。查阅了 Bitcoin Core 0.16.3 的 release note 後发现:
Such blocks are invalid, so they can only be created by a miner willing to
sacrifice their allowed income for creating a block of at least 12.5 BTC
(about $80,000 USD as of this writing)
原来国内外媒体一直引用的 8 万美元的成本(12.5 枚比特币)
就可以瘫痪 Bitcoin 的这句话是有一些误解的。
原意其实是指:攻击者先必须真正的算出合法的 hash,
才可将不合法的交易包入区块中,进而达成攻击。
反过来说,攻击者等於是放弃了这 12.5 枚比特币挖矿奖励
(时下汇率换算约八万美元),来达成攻击,
因为包含了不合法的交易之区块绝对不会被其他矿工承认。
所以真正要成功完成攻击,成本绝对是远高於所谓的 8 万美元。
(cryptoglobe 文章中提到,www.crypto51.app 已经成功预估出於
Bitcoin Private (BTCP) 网路上,只需 $122 美金即可达成 51% 攻击(Ref#8),
不过目前还找不到相关佐证文件)
=============
另一个反思则是,区块链世界强调去中心化,但吸引众多使用者的交易所、
共用的智能合约与区块链全网使用的相同程式,再再的打破去中心化的概念,
只要任何一点被攻破,都是重大的损失,这样还算是真正的去中心化吗?
=============
Note : 若有错误,欢迎指正;也欢迎讨论与指教,谢谢。
References :
1.
https://bitcoincore.org/en/2018/09/18/release-0.16.3/
2.
https://tinyurl.com/ycg2cmlm
3.
https://github.com/bitcoin/bitcoin/pull/9049
4.
https://medium.com/@awemany/600-microseconds-b70f87b0b2a6
5.
https://bitcoincore.org/en/2018/09/20/notice/
6.
https://github.com/bitcoin/bitcoin/pull/14247
7.
https://twitter.com/LukeDashjr/status/1044224230114627586
8.
https://tinyurl.com/ycq5gzjb
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.160.117.189
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/DigiCurrency/M.1538195587.A.998.html
1F:推 www10177: 写的还满清楚的,推 09/29 13:10
2F:推 DarkerDuck: 所以我向来都认为Bitcoin的金流protocol应该简单 09/29 13:24
3F:→ DarkerDuck: 甚至能有多个不同的node implementation 09/29 13:24
4F:→ DarkerDuck: 那就比较不会有单个implementation bug失效的问题 09/29 13:25
5F:→ DarkerDuck: 像这次的bug就是被Bitcoin Umlimited的开发者抓到 09/29 13:27
6F:推 kugwa: 推~ 09/29 13:59
7F:推 vvind: 认真推 09/29 14:11
8F:推 zhiping8: 推 09/29 14:18
9F:推 DarkerDuck: 真正的攻击成本当然是高於八万美金 09/29 14:19
10F:→ DarkerDuck: 除了12.5枚BTC还加上了算出区块的电费以及设备折旧 09/29 14:20
11F:→ DarkerDuck: 恐怖点在於BTC的挖矿节点几乎只有一种implmentation 09/29 14:21
12F:→ DarkerDuck: 攻击过後可能挖矿节点全死光,剩下自己爽爽挖51%攻击 09/29 14:21
13F:推 SecretAres: 好文章该推 09/29 14:23
16F:→ kugwa: 0.15.0之後 CheckTransaction()从validation.cpp被移到 09/29 14:51
17F:→ kugwa: consensus/tx_verify.cpp 09/29 14:51
18F:→ kugwa: 难怪刚刚找validation.cpp找无 09/29 14:52
19F:推 kugwa: 是说 点进去bitcoin的github的release页 09/29 14:54
21F:→ kugwa: 最近几个release 比较旧的反而在比较上面 09/29 14:55
22F:→ kugwa: 是否跟这个bug有关? 09/29 14:55
23F:→ tcn1john: 除了可以让程式crash, 能够凭空产生bitcoin才是重点吧 09/29 15:13
24F:→ kugwa: 应该没有允许多产生BTC UpdateCoins那里有检查 会挡下来 09/29 15:19
25F:→ kugwa: 只不过挡下来=直接让程式死掉 09/29 15:22
26F:→ DarkerDuck: 流通量不会增加,顶多可以让你double spend 09/29 15:22
27F:→ DarkerDuck: 但链要长的时候就会被reject掉 09/29 15:23
28F:→ DarkerDuck: 0.14x 的完整节点会直接死给你看,其他版本可能会拒绝 09/29 15:24
29F:→ kugwa: 不过我认为 就算有攻击者弄出一个区块 里面带有这种引用重 09/29 15:25
30F:→ kugwa: 复input的交易 09/29 15:25
31F:→ kugwa: 而且一时之间也成功进到区块链了 09/29 15:26
32F:→ tcn1john: 我是看到相关新闻@@ 像是发现bug的开发者说可以造成 in 09/29 15:26
34F:→ kugwa: 但之後当大家发现这个bug的时候 都能发现链上这个出问题的 09/29 15:27
35F:→ kugwa: 区块 09/29 15:27
36F:→ kugwa: 所以应该也能达成共识 一致把区块链转回那个区块之前 09/29 15:28
37F:→ DarkerDuck: 那篇文章只有说有这个可能,但实际上double spend的 09/29 15:30
38F:→ DarkerDuck: 检查依照节点实作的不同,会被检查不只一次 09/29 15:30
39F:→ DarkerDuck: 新加入的节点一定会检查double spend,所以inflation 09/29 15:31
40F:→ DarkerDuck: 不会产生,但是可能还是有少数的特定节点实作通过 09/29 15:32
41F:→ DarkerDuck: 那这样就会造成chain split 09/29 15:32
42F:→ DarkerDuck: Awemany就是在批评,避免双花这种核心的功能竟然可以 09/29 15:34
43F:推 whyever: 好文推 09/29 15:35
44F:→ DarkerDuck: 静悄悄地被省略拿掉,开启了inflation的可能性 09/29 15:36
45F:→ DarkerDuck: 想要攻击的人可以故意不公布,找到真正增加流通量方法 09/29 15:37
46F:→ kugwa: 请问现在的Bitcoin Core是谁在带头呀? 09/29 15:37
47F:推 tcn1john: 感谢解说@@ 09/29 15:38
50F:→ kugwa: 原来就是发release的人 09/29 15:52
51F:→ GameDemon: 谢谢各位强者的补充 还没机会回答问题 大家都解答完了 09/29 17:24
52F:推 john371911: 推。 09/29 18:49
53F:推 leftc: 技术文推 09/29 23:39
54F:推 aabb927: 推 09/30 00:15
55F:推 justben: 推~ 09/30 02:08
56F:推 camellala: 推专业文 09/30 02:14
57F:推 EthereumPTT: 以太好像没被波及到 09/30 12:28
58F:→ kugwa: 以太不是直接fork比特币ㄅ 09/30 16:32
59F:→ kugwa: 以太的客户端 最大宗的好像是用go写 而且也有不只一种实作 09/30 16:33
60F:→ kugwa: 用各种不同语言写 09/30 16:34
61F:→ DarkerDuck: 以太币自己重底层重刻的,金流只是EVM的一个功能罢了 09/30 17:08
62F:推 DarkerDuck: 从 09/30 17:09
63F:推 Binance: 推 谢谢分享 10/01 14:32
64F:推 Ayahuasca: 推认真解释 10/01 17:41
65F:推 ko88201: 专业给推 10/07 10:22