区块链的帐本要如何维持一致性是相当重要的问题,所谓的分叉,是指纪录区块链帐本的节点,对帐本的共识出现分歧,简单来说,又是全网出现两种或多种版本的帐本,这时就必须依赖所谓的「链分叉选择规则(fork choice rule)」,透过规则的设计,促使矿工们达成共识,在不同帐本中选择一份作为该区块链的权威帐本。而区块链分叉又分为自然产生的「临时性分叉」,以及区块链版本升级时所导致的「硬分叉」,本文将着重探讨「临时性分叉」的原因与解决方式。

区块链临时性分叉的原因

在PoW的共识机制中,矿工会互相竞争,解出一道题目,谁先解出来,谁就有下一个区块的记帐权。问题来了,有没有有两个矿工同时解出题目,同时产生新区块呢

答案是,有可能。因为这道题目是随机的,而且网络是异步的,势必会有矿工因为同时解出题目,因而同时产出新区块,此时双方便会各自广播自己挖到的新区块到网络上给其他节点验证,节点验证过后,便会认可该区块为新区块。

以上图为例,甲节点(图上可能要标记)挖出了C区块,乙节点(图上可能要标记)挖出D区块,同时广播到网络中验证,我们说过,网络的信息在传递上不会同步,会有延迟的可能,因此网络中的状态就会变成:

C队→先接收到C区块的节点会认可C为新区块(否定D区块,并将其放在孤块池中)

D队→先接收到D区块的节点会认可D为新区块(否定C区块,并将其放在孤块池中)

分叉-最长链共识

此时矿工之间就会产生分歧,区块链状态就会长这样

以上图为例,A是B的前一个区块,又称为「父区块」,现在出现一个情况,C跟D区块都同时以B作为父区块被广播到全网,问题来了,接下来的矿工应该要以哪一个区块做为父区块,继续往下延伸呢就是所谓的区块链临时分叉,在比特币PoW算法网络中的共识规则是这样的:

如果分叉情况出现,那么网络上的人们继续保持两个分支,一但其中一个分支累积的工作量超越另一个分支,任何情况下,节点只在累计工作量多的那条链上工作。

简单来说C队以C区块为父区块继续挖矿,D队以D区块继续挖矿,哪一队先挖出第二个区块,全网便认定其为主链,这就是所谓的「最长链共识」。

以上图为例,假设D队率先挖出E区块,并广播至全网给其他节点验证,C队接收到E区块后,便会将D区块从孤块池中取出,并以D分支作为主链(因为C分支已经不是最长链),C区块便成为孤块。

你可能会好奇,为什么C队的矿工要乖乖遵守最长链共识,因为在正常状况下,大多数矿工都会选择按照共识规则工作,如果有矿工选择在较短的那条分支挖矿,即便挖出新区块,也不会被大多数矿工认可,自然也拿不到奖励,因此在正常情况下,理性矿工都会选择遵循「最长链共识」。

分叉对交易的影响

遇到分叉时,短链区块内验证的交易若尚未被长链验证,那会发生什么事我们来看看中本聪本人的解释

(图片来源)

如果短链的交易不在长链里,会重新被放进交易池(内存池),等待矿工打包进入后面的区块,该笔交易的确认数也会重新计算。这就是为什么比特币需要等待六个区块,才能完全确认交易,因为一般来说,用户不会知道区块链是不是处于分叉状态,如果包含交易A的区块在下一个区块后,成为孤块,交易A除了可能需要重新验证之外,还会有面临双花攻击的风险。

至于为什么是六个区块,这其实并不是硬性规定,有些交易所只要有两个确认或三个确认就能够成功入帐了,六个确认所代表的是该交易在全网共识中处于安全状态。当然六这个数字也是经过计算得来的,详情请见比特币白皮书。

硬分叉不适用「最长链共识」

以上介绍的,是区块链在自然情况下产生的临时性分叉。若区块链因为版本更新,抑或是社群共识分裂而产生「硬分叉」时,由于硬分叉本身不是在自然情况下发生且过程中涉及矿工的意识选择,因此无法单纯透过「最常链共识」解决分叉问题,详情请见下一篇文章「硬分叉与软分叉」。