回目录 《区块链基础:解密挖矿与共识的误解》

引述我在百度词条的定义:

比特币共识机制/中本聪共识算法(Bitcoin Consesnsus/Nakamoto Consensus) 是由比特币的匿名创始人中本聪(Satoshi Nakamoto)为了在比特币点对点的分布式网络中让计算节点之间达成共识而基于工作量证明POW创建的的一套可以在比特币中解决拜占庭将军问题的规则。

作为一个“传统软件”开发者,在学习区块链开发的过程中感觉学习曲线还是比较陡的,比如经常错误理解一些看起来简单的概念,建议初学者少读类似本文这样的文章, 我也无法保证自己目前的理解是完全准确的,本文的目的是自己的笔记以及拿出来大家讨论。

初学者尽量先入为主读一些相关的经典材料:比如白皮书或者官方文档,相关协议文档,bip文档 (opens new window), 或者《Mastering Bitcoin》 (opens new window)这样的经典, 有能力的建议读source code以及release note,甚至可以去读开发者的一些email记录或者聊天日志,比如bitcoincore dev log (opens new window);

有了这些基础,再带着问题看看其他人的解读以及相关的一些论文,这样可以降低被错误观点误导的概率,在区块链的世界里误解基本概念会比较致命, 因为都是真金白银,太多的事故是因为几行代码引入致命漏洞,或者是基于没有完全理解的codebase或framework开发产品;

区块链技术引入了不少新词汇,比如POW POS,distributed consensus等,本文先讲下比较高频的POW/POS和共识算法,首先引用两段话:

# 1. POS/POW本身不是共识:

Consensus is a form of automated governance that populates and publishes ledger entries every x period. The “blockchain” is proof that this automated governance structure actually works as designed, providing near ABSOLUTE assurance over the integrity of the ledger data. -- https://blog.goodaudience.com/1-assurances-in-crypto-14c55a1fd616

Emin Gün Sirer:

Emin Gün Sirer

# 2.猜谜游戏-挖矿机制 solve the puzzle

POW POS是不同的挖矿机制,本质上他们是不同的猜谜游戏,规则类似,都是要构造出一个区块使其hash小于某个target目标值也就是所谓的动态调整的difficulty难度值;

POW是要在构造block的时候猜出一个nonce随机值,以满足上面的条件,当所有的nonce都无效时,可以调整block包含的transaction以及微调timestamp ,算力越多,机会越大,这是工作量证明;

POS是要找到一个UTXO用来构造coinstake transaction,满足kernel hash小于对应于该UTXO的权重难度值,当节点控制的

UTXO 越多时或者准确说stake越大时,找到的机会越大,这是权益证明;

可以看到所谓POW POS只是产出区块的不同要求,猜谜游戏是一轮一轮的,每一轮产生一个区块,每一轮产出区块之后广播发布到区块链网络上,所有的节点才会基于共识算法来选取这一轮的胜出区块并connect to the tip即连入当前的区块链,所以我把POW POS称为共识的门票或者说是成为候选者的门票。

POW小程序例子 (opens new window)

POSv3详解 (opens new window)

# 3. 投票程序-共识算法 trustless consensus

POW POS只是成为候选者的门票,最终哪个区块是这一轮的胜出者是由占多数的选民来决定的,他们的投票的规则才是共识算法本身,选民是网络中的节点,当然我这里说的是full node,投票的工作大概包括(这里没有展开详细的过程,完全是high-level概述):

# 1)validate and relay transaction:

对接收到的transaction进行验证并转播的过程,可以看作是投票的一个验证步骤之一,如果某个候选区块包含了某个不合法的transaction,那么这个候选区块也就失去了合法性;

# 2)full validate block and activate best chain:

对接收到的block进行更详细的验证(block级别和transaction级别验证)并找出最长的链,当然实际过程是动态的,当下最长的链未必是最终最长的链,

会不断出现soft fork,orphan block,甚至reorg,bitcoin一般是六个确认(一般情况下,只要这个世界上的网络没有出现大规模长时间的瘫痪,不太会出现所谓的deep reorg,除非是恶意的long range attack);

在区块链网络中,这里主要是说以Bitcoin为代表的公链,每个客户端,无论是普通手机钱包还是矿机节点都在这个网络中有各自的作用,对于普通手机钱包(热钱包),他的任务主要是广播以及转播交易信息,而矿机节点的目的是为了赚取coinbase奖励和手续费,所以矿工节点努力生成候选区块,这些矿工节点可能运行着不同的官方版本,有的是修改后的非官方版本,有的甚至是恶意的黑客节点,所以共识算法就是让这些好的坏的节点在互相不信任的情况下协作的基础,即达成所谓的trustless consensus;

共识本质是解决拜占庭将军问题,共识算法即拜占庭容错算法(此处是概指,不是特指BFT或PBFT),POW POS的目的是提高坏节点或叛徒节点的作恶的成本,实际上对于POW来说作恶成本确实挺高,尤其是针对比特币网络,但是对于POS来说存在很多低成本的作恶方式,后面3中会提到;

常见的共识算法有nakamoto consensus,即基于longest chain最长链原则的一系列consensus rules共识规则所组成的中本聪共识算法,具体参见:https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch10.asciidoc#decentralized-consensus

其他的共识算法有PBFT(ripple stellar hyperledger都在采用),查看详细解释 (opens new window)

PBFT

简单来说就是当客户端发来transaction请求,primary节点(类比选民代表)向其他节点发出pre-prepare信息,收到信息的节点响应prepare信息,当每个节点都收到了其他节点的ack之后,全部节点发出commit信息,当收到足够多的commit信息后,回复给client端;

然后这里还要提一下所谓的DPOS算法

The DPOS algorithm is divided into two parts: electing a group of block producers and scheduling production. The election process makes sure that stakeholders are ultimately in control because stakeholders lose the most when the network does not operate smoothly. --https://steemit.com/dpos/@dantheman/dpos-consensus-algorithm-this-missing-white-paper

就像上面说的,DPOS算法有两个部分,'D': 选出区块生产者, 'POS': 生成区块,所以DPOS本身并不是一种共识,因为共识是在生成区块之后才在这些block producers之间发生的; 个人观点DPOS跟POS主要的区别是,POS是多数人参与到共识的门票,DPOS是一小撮被选出的人参与到共识的门票,所以对于EOS来说依然是要基于longest chain最长链原则达成共识, 这里潜在的问题是个别拥有大量coin的富人节点也许会为所欲为,所以EOS提出引入BFT共识模型,有兴趣的可以看这篇文章 《DPOS BFT— Pipelined Byzantine Fault Tolerance》 (opens new window)

如果你想问如果有些节点不遵守共识或修改共识会如何,答案是会发生分叉,只不过如果没有足够的节点支持和加入你的这个新共识,你的这条分叉链也就没有什么意义了,所以共识是多数人的共识,少数人的共识只有在基于DPOS的公链或者一些联盟链上才有意义。

# 4. 攻击向量 attack vector

理解了这些,就会对一些完全问题或者安全事故有相对更清晰的理解,比如

1)某些攻击手法对于很多POS公链来说是经济上可行的,但是对于比特币这样的POW公链是经济上不可行的

比如long range attack (opens new window)noting at stake attack (opens new window), 主要原因是在POW上出一个区块的代价都很大,更不要说故意选择错误的分支,代价是更大的,而POS没有这个问题,出块没有什么成本,只要有一定的stake即可,甚至有时候可以买入stake,然后构造攻击transaction,然后卖出stake,成本只是手续费而已,nothing at stake attack不要理解错以为是不需要stake,他的意思是miner或者应该说是forger会同时在多条分支上挖矿,因为出块成本低,在多条分支可以增大获取奖励的机会,nothing at stake 最后也会引出双花攻击;

解决方法是在共识算法上做改进,比如设置checkpoints(bitcoin也已经采用),penalize equivocation nodes惩罚模棱两可的节点, 具体有Slasher算法 (opens new window),感兴趣的可以进一步看下以太坊的Casper (opens new window)

2)同样的codebase,同样的header-first节点同步,POS上面会发生resource exhausted attack(即耗尽内存和磁盘空间的攻击方法),而POW可以规避这个问题

这种攻击方式简单来说是利用了节点在同步分叉分支区块的时候,如果没有发生reorg,即分支节点不是最长节点,则不会进行full validation(对双花和签名等做完全验证),以此消耗内存(发送header)或磁盘(发送block)

resource exhausted attack

具体解释:Resource Exhaustion Attacks on PoS (opens new window)

可以看下qtum对于这个研究的回应:

Re: “Fake Stake” attacks on chain-based Proof-of-Stake cryptocurrencies (opens new window)

从上面的两个例子可以看出,共识算法的任何小改动小漏洞都可能会引入多个攻击向量,我们从中可以学到很多思考方式,下面给出比特币历史上发生的漏洞链接:

https://en.bitcoin.it/wiki/Common_Vulnerabilities_and_Exposures

https://en.bitcoin.it/wiki/Weaknesses

可以学习下分析报告一行代码引起的两个漏洞DOS和double spend

BitcoinCore CVE-2018-17144 漏洞研究与分析 (opens new window)

  1. 更多思考 虽然我只是个区块链技术爱好者,也没有参与公链开发的机会,但是不断深入的理解也是对自己的开发能力有帮助的,培养去中心化的全局思维是挺有挑战的, 可能熟悉分布式开发或者多线程开发的同行们会比我容易入门,当然除了技术上的思考,很多地方也是要结合经济学的激励机制,比如这篇论文就提出了关于矿工节点的验证困境:

如果做一个完全验证(包含script执行验证)会花费一定的时间,好处是排除掉不合法的交易,如果跳过验证,会争取到比别的矿工更多的时间,但是危险是可能会包含不合法的交易, 从而浪费算力付出代价,这个论文挺有意思的,感觉有点像把我前面的1挖矿机制和2共识算法两者的矛盾点展示出来了,在挖矿的利益驱使下是完全遵守共识规则还是选择性的遵守, 有兴趣可以了解下作者提出的解决方案《THE VERIFIER’S DILEMMA》 (opens new window)

本文发布在 巴比特专栏 (opens new window)

# 如何获得

推荐coinhako,目前有赠送活动 (opens new window)