本节介绍比特币系统中的分叉(fork)

分叉指的是,原来的系统中为一条链,但分成了两条链。分叉形成的原因可能有多种,例如:挖矿时两个节点差不多同时挖出矿,都会发布区块(对比特币系统当前状态产生分歧导致的分叉——state fork);分叉攻击,同样也会导致分叉(forking attack,人为故意造成);比特币协议改变,在分布式系统中不能保证所有节点同时升级软件,假设存在少数节点未升级,导致出现分叉(protocal fork);

根据对比特币协议修改的不同,可以将分叉分为硬分叉和软分叉。本篇便专门介绍比特币系统中的分叉。

硬分叉(hard fork)

什么情况会出现硬分叉?
对比特币协议增加新协议,扩展新功能,只是拓展,未更新的节点认为更新了之后节点发布的区块为非法区块。未升级软件的旧节点会不认可这些修改,会认为这些特性是非法的。这也就是对比特币协议内容产生分歧,从而导致分叉。硬分叉的一个典型例子,就是对比特币区块大小的修改(之前有提到过,BTC区块大小限制1MB,但是否合适存在争议)。

在BTC系统中,区块大小最大为1MB,可以包含的交易最大数量为4000笔左右(每个交易大概250字节)。而一个区块产生大概需要10min左右,也就是说,整个比特币系统,平均每10分钟最多只能处理4000笔交易(平均每秒7笔交易),相比目前银行等金融机构每秒数十万数百万的交易量来说,根本不在一个数量级上,严重影响吞吐率和交易处理(即上链)时间(因为交易太多,无法写入只能等待下一个区块)。
所以,有人便认为可以增大区块大小,使得一个区块中可以包含的交易数量增多,在此,我们假设将区块大小从1MB增大至4MB

假设系统中大多数节点更新了软件,少数节点仍然遵从1MB限制的协议(注意,这里大多数和少数是按照算力来区分的,和账户数量无关)。即:新节点认为区块大小最大4MB,旧节点认为区块大小最大1MB,且新节点占据大多数。

image-20230107154534913

我们看图,大部分更新了软件的节点认为上面分叉的大区块是合法的,而没有更新软件的旧节点认为上面链是非法的,会自己沿着下面一条链挖。这时虽然新节点认为也是合法的,但是由于大部分算力更新了软件,上面的链更容易成为最长合法链。这时候就会产生硬分叉,分叉是永久存在的,只要旧节点不更新软件,分叉就一直存在,形势变成两边人各挖各的。

1.BTC社区中有些人很保守,不愿意加大区块大小 2.区块大小并非越大越好,在网络篇中提到,比特币网络传输为”尽力而为”,区块加大会造成传输变慢等问题。 3.单纯增加区块大小,对交易数量的增加远不能达到数量级的提升。

出现hard fork后,变成了两条平行的链,也就造成了社区分裂。社区中有一部分人,会认为下面的链才是”正统“,各个链上的货币独立。

实际上,这个事情真正出现过。后续会介绍以太坊,以太坊历史上的一件大事就是硬分叉事件。以太坊称为ETH,但目前看到的ETH已经不是最初的ETH了,以太坊在历史上发生过硬分叉,另一个链称为ETC。实际上,ETC才是以太坊设计原本的协议,而ETH是黑客攻击ETH上一个智能合约THE DAO后进行回滚的协议链(将黑客攻击偷取的以太币采用硬分叉方式回滚回到另一智能合约,然后退还给真正拥有者)。
但是这次硬分叉的后果,由于有人不愿意这么做,造成了以太坊社区的分裂。实际上,虽然ETC不如ETH又名,但实际它也是目前一种主流货币。

硬分叉后其实会发生一个币变成两个币这种情况,因为上下两个链都认为之前的交易是合法的,分叉之前的一个币在分叉中都可以使用,就导致了一个币变成两个币使用。分叉之初,由于两个链分叉造成了互相影响,产生了很多麻烦。比如:在ETH链上有一笔转账B->C,有人便在ETC链上回放(就是把ETH订单的输入输出复制一份,在ETC上重现),将ETC链上的货币页转给了C(C收到两笔钱)。后来,对两条链各添加了一个chainID,将两个链区分开,才使得这两条链真正分开。

软分叉(soft fork)

如果对BTC协议添加限制,使得原本合法交易在新交易中不合法,便会形成软分叉。

同样,有人想将区块大小调大,也就会有人思考调小的好处。在这里,我们假设将区块大小从1MB减小至0.5MB(实际中,1MB已经足够小,不会调小了).

注意:区块链中区块大小调整并非简单修改一个参数,调改大小便很有可能会引发分叉,由于参数修改方式不同,有可能会是硬分叉,也有可能是软分叉。

假设系统中大多数节点更新了软件,少数节点仍然遵从1MB限制的协议(注意,这里大多数和少数是按照算力来区分的,和账户数量无关)。即:新节点认为区块大小最大0.5MB,旧节点认为区块大小最大1MB,且新节点占据大多数。

image-20230107155951466

这样新节点不认下方的大区块,都会按照上方挖,而旧节点认为两个都合法,导致出现一个新的区块,如果他没有挖出矿,他会放弃当前进度,跟着新节点挖(下方分叉);甚至可能他是最先挖出来的节点,但是由于新节点认为他挖的区块是非法的(右上角),这样他永远不会有出块奖励,除非他更新软件。

软分叉不会导致系统出现永久性分叉,软分叉只会是临时性的

系统中可能出现软分叉的情况

给某些目前协议中未规定的域赋予新的含义或规则。

最经典的就是,铸币交易中CoinBase域。在CoinBase域中写入任何内容都可以,没有任何规定。之前,在介绍挖矿时,提到挖矿本质是调整block header中的nonce,但其本身只有4个字节,搜索空间太小。所以实际使用中,将CoinBase域前8个自己作为另一个extra nonce,此时搜索空间从原本2^32 增长到2^96,对于目前挖矿难度来说已经足够。

但CoinBase中并不是只有8个字节,还剩下很多空间。有人便提出将其作为UTXO(当前还没花掉的交易结合,)集合的根哈希值。目前UTXO是全节点自己在本地为了方便查询自行维护的,但UTXO内容并未写入区块链(还记得Merkle proof吗?Merkle proof用于验证某个交易是否在区块中,Merkle proof的交易信息是写入区块链的。)

由于UTXO存在本地,如果查询某账户余额,轻节点便需要询问全节点,全节点根据UTXO中信息可以计算得到账户余额,但如何确保全节点给的数据可信?由于直接修改block header会造成硬分叉,有人便提出了以上的方案(该域刚好无人用)。

可以看到,旧节点认可新节点的区块,但新节点对于旧节点CoinBase域检查时候,发行并没有这个UTXO的根哈希值,不会认可其发布的区块,所以这是软分叉。

P2SH

最初比特币版本中没有该功能,后来通过软分叉方法加入了进去。

总结

  • soft fork
    特点:只要系统中拥有半数以上算力节点更新软件,系统就不会产生永久性分叉

  • hard fork
    特点:必须系统中所有节点更新软件,系统才不会产生永久性分叉