BitcoinCash Classic(BCC) Make BCH decentralized again!

BCH原链的51%算力攻击实验


前言

我们大概听说过很多关于黑客进行区块链51%攻击的报道,比如ETC、BTG在2018年前后,都遭受过51%攻击,其中BTG据说被干掉了38万枚交易记录。但是,我们很少能看到攻击的详细操作细节披露,本实验以BCH原链为基础,在真实的全球网络环境下,完全实战了一次51%攻击,本文将会讲解这次实验完整的操作步骤和细节,并且就攻击的博弈和经济学意义做一些分析。

攻击效果截图:

2018年12月的762048区块

2019年6月的762048区块

攻击发生前的最后一个区块截图记录(已经消失):

814652区块

一、实验环境准备

1、物理环境

  • 最少需要2个节点主机,本实验采用2个虚拟机系统,Vmware装Ubuntu 18.04 LTS Server(64bit),各500GB硬盘

  • 可以设置访问控制列表的网关,Ubuntu本身可以设置防火墙,但是我的网络接入设备是Cisco交换机,访问列表是在这上面做的,用于分隔攻击链和诚实链

  • 矿机若干,详细需求见算力测算部分

2、软件环境

  • 2个节点主机均同步到最新的区块高度

  • 2个节点主机放在一个独立的VLAN内,网关设置访问列表,只允许与特定主机IP通讯,比如矿机IP、SSH登陆主机IP,其它的访问一律禁止,只样是为了将2个节点主机隔离开。允许通讯的特定主机,均不能运行节点(否则导致隔离失败)。

  • 在2个节点主机中的一台安装CKPOOL矿池服务,用于出块(攻击链),不安装矿池采用Solo挖矿也可以。

3、所需算力测算

  • 算力测算主要用chainwork计算进行,具体计算办法,[最新区块的chainwork删掉最后8位]-[攻击回滚目标的chainwork删掉最后8位],得出一个数值(先把16进制转10进制),该数值即累计难度差。

  • 本实验的攻击前的区块高度是814652,攻击的目标是“删除”762048之后的全部区块,这两个区块之间的累积难度差很低,只有400多万。

  • 有一个简便的算法,难度10000对应的算力大概是75G/10分钟,400万难度差需要调用的算力是75G*400=30T,也就是有30T算力,只需要10分钟时间,就可以追上这个难度差。这个算法是简便的,实际中还需要考虑上诚实链的也在出块增加难度差。

  • 比特币最长链条判定机制说明

二、51%攻击的启动

1、隔离私链(攻击链)

在网关路由器上,关闭2个节点的对外通讯,这里用的Cisco路由器配置,也可以用其它的方式实现网络控制:

!
interface Vlan11
 ip address 10.1.102.1 255.255.255.0
 ip access-group vlan11-in in
!

Extended IP access list vlan11-in
    30 permit ip any host 10.1.101.110
    40 permit ip any host 10.1.101.11
    50 deny ip any any

控制这两个节点只能与矿机或指定IP通讯,限制其访问任何外网节点。矿机由多台,则依次添加允许IP。

2、私链的区块回滚

比特币的节点自带隐藏的区块操作命令,invalidateblock,用这条命令指定具体的区块为无效,比如指定区块100为无效,那么100之后的全部区块就会全部无效。我们的目标是期望762048区块及之后区块均重新挖矿,因此查询该区块的hash值为:

000000002b7ad68e8528c20ec8bc8366cdd9a8c2db2b4050e0c9f2c9e39603b0

在两台节点均输入以下命令:

./bitcoin-cli invalidateblock 000000002b7ad68e8528c20ec8bc8366cdd9a8c2db2b4050e0c9f2c9e39603b0

这条命令没有输出,等其运行完毕,运行getinfo查看,确认区块已经回滚:

./bitcoin-cli getinfo
{
  "version": 150100,
  "protocolversion": 70015,
  "walletversion": 130000,
  "balance": 0.00000000,
  "blocks": 762047,
  "timeoffset": 0,
  "connections": 0,
  "proxy": "",
  "difficulty": 1,
  "testnet": false,
  "keypoololdest": 1559171551,
  "keypoolsize": 100,
  "paytxfee": 0.00000000,
  "relayfee": 0.00001000,
  "errors": ""
}

两台主机节点均回滚到了762047区块高度。回滚不要重启进程,否则有可能又需要重新指定无效区块。

这个时候,你会发现它们的connections数为零,因为外网已经隔离。但是连接数位零,是无法挖矿的,用getblocktemplate命令会提示“bitcoin is not connected!”,这是一个节点的常规限制,这也就是为什么我们要设置私链的节点数为2个。用addnode “10.1.102.33:8333” add命令让两个节点建立连接。

3、启动挖矿

开启矿机,将矿机设置指向私链节点中的一个(前提是装好了ckpool矿池,用其它挖矿代理也是一样的),总而言之,矿机算力显示正常即可。

4、出块检查

使用getinfo检查出块情况,一旦发现区块高度正常增加,且该高度在外网浏览器查询不存在,则证明新的链条已经生成。

三、51%攻击目标的达成

1、chainwork的检查

在私链节点上面检查chainwork累积情况:

 ./bitcoin-cli getblockchaininfo
{
  "chain": "main",
  "blocks": 775350,
  "headers": 775350,
  "bestblockhash": "00000000000908a11cbbcfa13f819a82511476d4d02da0315d91e70b0d906188",
  "difficulty": 4096,
  "mediantime": 1559563362,
  "verificationprogress": 0.9999995967199629,
  "chainwork": "0000000000000000000000000000000000000000007cb5f9cb5791e6eb380892",
  "pruned": false,
  "softforks": [
    {
      "id": "bip34",
      "version": 2,
      "reject": {
        "status": true
      }
    }, 
    {
      "id": "bip66",
      "version": 3,
      "reject": {
        "status": true
      }
    }, 
    {
      "id": "bip65",
      "version": 4,
      "reject": {
        "status": true
      }
    }
  ],
  "bip9_softforks": {
    "csv": {
      "status": "active",
      "startTime": 1462060800,
      "timeout": 1493596800,
      "since": 419328
    }
  }

chainwork数值超过诚实链就代表攻击目标达成,为了稳妥起见,可以等该数值拉开一定距离再进行全网广播。

2、全网广播

删除掉网关隔离对外通讯的访问列表限制,两个私链节点就会自动向全网进行广播,因为它们是最长链条,所以会成为新的诚实链。为了加速广播速度,可以手动使用addnode指令,对没有被同步的节点进行握手,如此一来,一传十,十传百,只要短期内没有更强的算力扭转,所有的算力都会自动加入到私链,而私链就自然而然成为了公链。

在节点上面查看原来的区块信息,仍然能够看到原来高度762048及之后的老区块,但是已经成为了孤儿块,确认数为-1:

getblock 000000002b7ad68e8528c20ec8bc8366cdd9a8c2db2b4050e0c9f2c9e39603b0

{
  "hash": "000000002b7ad68e8528c20ec8bc8366cdd9a8c2db2b4050e0c9f2c9e39603b0",
  "confirmations": -1,
  "size": 201,
  "height": 762048,
  "version": 536870912,
  "versionHex": "20000000",
  "merkleroot": "9d456740607533c1982b622fdfbca150c4f457de57d539c40b585d63359e3304",
  "tx": [
    "9d456740607533c1982b622fdfbca150c4f457de57d539c40b585d63359e3304"
  ],
  "time": 1545892389,
  "mediantime": 1545892385,
  "nonce": 3763299100,
  "bits": "1d00ffff",
  "difficulty": 1,
  "chainwork": "0000000000000000000000000000000000000000007cb5f9cae224127d639b33",
  "previousblockhash": "00000000b6cde760c076bc5c5731f70ab17c68ce2676b01a810696992269b169"
}

3、确认全网同步区块数据

因为BCH原链节点数不多,节点的同步时间从数分钟到数小时不等。手动addnode进行“握手”,让没有同步的节点尽快同步。 图片描述

四、关于博弈和经济学意义

1、区块链=治理

在详细了解51%的攻击之前,重要的是要了解区块链协议基本上是一种治理形式。区块链管理数据的分类帐,例如交易数据。由于区块链协议可以为我们管理,我们不再需要第三方来执行此操作,例如政府或银行。这就是(大多数)区块链去中心化的原因。比特币区块链的协议基于民主自治制度,这意味着网络上的大多数参与者(矿工)将决定哪种版本的区块链代表真相。

去中心化的民主是什么?这就是一个具体的例子,由数学决定一切,没有任何中间人。传统的民主代议制度,不是基于数学的,而是用选举、代理人、议会、行政、司法分权等各种系统和制度来运行,中间有大量的人为因素。而比特币的治理模式非常简单,只有一条最基本的原则,即数学至上,没有任何其它的人为规则,而这也就杜绝了一切的作弊可能性。从比特币的角度,是不存在所谓诚实链和攻击链的,这是我们人为的主观定义,它很简单,算力最强的链条是数学上证明安全级别最强的,代码会自动选择它,不需要说明。

所谓的51%攻击,也只是我们人为的定义,比特币并不需要防范这种情况,它是符合比特币追随最强者的顶层原则的,这种制度恰恰构成了比特币的核心价值,是非常理性的。

好的制度是追求优胜劣汰,而不是反向的劣币驱逐优币,现实的复杂的制度往往存在这种情况,是逆进化论的。比特币的基于数学的治理.没有九九八十一条人为的法律、法规,可谓简单而粗暴,但却是绝对的有效。

2、挖矿经济学

挖矿是用算力去挖“币”,本质上,等同于矿工付出了电费、设备成本去兑换了挖出来的币。假设矿工花了1块钱去挖了1个币,也就是矿工认可用1块钱去买一个币的市场价格,而当一个币在市场上的价格为2元时,矿工是不大可能花一块钱就能挖到1个币的,因为那个时候,会有人投资挖矿,然后把这个币卖出去赚钱,直到挖矿的成本和市场的价格相当接近。因为挖矿是一种纯粹的数学,没有门槛,也没有限制任何人参与,是完全市场化的。所以,挖矿的成本等于币的市场价。

从矿工的角度,虽然期望越低的成本挖到越多的币,但是在公开竞争的情况下,他买不到跟市场价差别太大的币。比特币最早几分钱一个,用电脑就能挖,最早挖矿的成本是比特币启动的市场定价,越容易挖,则卖出的价格越低,卖出去的价格越低则越容易挖,反之亦然。

51%攻击实践揭示了一点,没收其他人的币,成本会高于其他人挖矿的成本,比特币没有情感,谁给的钱多,它就属于谁,这个规则是公开公平的,对中本聪也没有例外。

3、矿工博弈

从以上51%攻击我们可以看到,矿工付出成本去“买”币,其实有两种选择,其一,挖私链,并让其成为公链;其二,挖公链。第一种情况,是矿工要占有100%的挖矿产出,而第二种情况,则是与其它矿工合作,联合起来强化链条的安全门槛。挖矿是一种自私的行为,矿工基于利益最大化进行选择,100%的矿工其实都有动机进行51%挖矿(私链),因为100%的矿工有这种动机,且挖矿算法是公开的情况下,矿工会意识到自身无法保证自身挖出来的币的安全,矿工反倒有可能倾向于合作,合作的动机与其占有全网算力的比率成正比,也就是其占有99%的算力,那么挖私链的动机就会上升到99%,代表受到惩罚的风险越低。而其算力比率较低,则会因为挖私链失败导致颗粒无收,相当受到了处罚(浪费了成本)。总结来说,矿工是挖矿算法的人格化,其行为完全可以预测及精确计算出来。

在有少量矿工的情况下,假设有一个矿工用很低的算力(成本)挖了一些币,那么覆盖掉这些币的成本也很低,所以,矿工选择用多少成本去挖矿,其实等于给自己的币加上多少安全外壳,当他用一分钱去挖矿的时候,他即使获得了一万个币,但是这一万个币,会被别人用2分钱给干掉的概率很高。犹如本实验干掉了30万个币。

回滚区块的成本完全是可以预测的,因为公开竞争,只要成本可以被覆盖,那么就会发生区块回滚。BCH原链如此,BCH如此,比特币也是如此。如果回滚一个币的成本是一块钱,并获得一个币,那么矿工就给出了一个市场定价为1块钱,当成本超过其所愿意支付的市场定价时,他自然会停止这种挖矿行为。

所以,最后我们要记住一点,在大部分时候花一块钱挖一万个币,跟花一百块钱挖一个币,所得跟币数关系不大,而跟成本有关,今天花五万块钱去挖一个比特币,跟花五万块钱去挖20个BCH,矿工不会有一种错觉,认为后者所得更多。有很多类似的逻辑漏洞,不知道如何区分必要和充分条件,比如一些分叉币发行量只有几千个,然后就敢号称稀缺性导致市场价值更高。有一个比特币矿工花了2万个比特币去购买了两块披萨饼,其实他在干一件让比特币值钱的事情,而不是比特币自己会值钱。如果他不这么干的话,就像今天在这个世界的各个角落,拥有数万个BCH原链币的持有者一样,连2个披萨饼都买不起。写到这,我笑了。

4、51%攻击对BCH原链的实际作用

  • 算力竞争会导致算力工作量累积越来越高,每次攻击都抬高了chainwork(否则无法成功),安全壁垒不断上升。
  • 每一次攻击等于花费了成本投入了,一个原来一分钱的东西,有人愿意花两分钱去获得,提高了市场定价。
  • 这是论证BCH原链可以覆盖BCH新链的第一步
  • 证明大资本的批量采购在技术上是可行,这提供了一种可能性
  • 矿工的竞争本质还是算力竞争,完全自由的市场竞争有利于去中心化

Similar Posts

Comments