[北大肖臻-区块链技术与应用笔记]第八节课——BTC 分叉
state fork
如果两个节点差不多同时挖到一个区块,这两个区块都是挂在当前的区块上的,不同节点先收到的区块不同,就会各自沿着先收到的区块往下扩展,这种时候就会出现临时性的分叉,称为state fork
,即由于对区块链当前的状态有意见分歧而产生的分叉。
分叉攻击(forking attack)也属于state fork,只不过这种意见分歧是人为造成的,这种情况也称为deliberate fork
。
protocol fork
要修改比特币协议需要软件升级,在去中心化的系统中,没办法要求所有的结点都升级软件
假设大部分节点升级了软件,少部分节点没有升级(可能是没来得及升级,也可能是不同意协议的修改),这种分叉称为protocol fork,即对比特币协议产生了分歧,使用不同版本的协议而产生的分叉。
在protocol fork中,根据对协议修改的内容的不同,又可以分为硬分叉和软分叉。
硬分叉(hard fork)
如果对比特币协议增加一些新的特性,扩展一些新的功能,这时候没有升级协议的那些结点是不认可这些新特性的,认为它们是非法的。
block size limit
硬分叉的一个例子就是比特币中的区块大小限制。
比特币限制每个区块不超过1M,这样算下来大约最多能容纳4000个交易。而平均10分钟产生一个区块,算下来大约平均每秒只能写入7个交易。
有的人就认为区块太小了,限制了交易上链的速度。
假设软件更新了,将区块大小的限制从1M提高到4M,假设大多节点更新了软件以支持这个协议。节点的“多数”和“少数”不是按照账户数目来算的,而是根据算力来算的,上面那句话是假设系统中拥有大多哈希算力的节点都更新了软件。
当系统运行起来。假设新节点挖出一个区块,这个区块是比较大的,但旧节点是不认可这个区块的,不会沿着这个区块继续往下挖,而是继续沿着之前的区块往下挖下一个区块。
旧的节点不认可大的区块,小的区块新旧节点都认可。
假定大多节点都是新节点,即更新了软件支持新的协议,因为“大多数”即是其算力更强,新节点的新区块的分叉很快就比旧节点的分叉长了
对新节点而言,上下两条链都是合法链,但因为只会去扩展最长合法链,所以还是会沿着上面的链往下挖。因为只是约束了大小不到4M就可以,新节点也可能挖出一些大小不到1M的区块
这样的区块是新旧节点都承认的,但上面这条链上有旧节点认为不合法的区块,所以旧节点始终不会去扩展这条链,还是继续沿着下面这条链往下挖
这样的分叉是永久性的,只要这些旧节点不更新软件,这样的分叉就不会消失。比特币网络中,会有部分很保守的人,像这样的协议更新势必会有一些节点不同意,产生硬分叉。
出现硬分叉之后,出现了两条平行运行的链,两条链上的BTC也是不相干的,各挖各的矿。在某条链上的出块奖励,对于认可这条链为最长合法链的节点而言是有效的,对认可另一条链的则是无效的,而分裂之前产生的BTC则是在两条链上都认可的。从这个意义上来看,硬分叉可以认为是产生了新的一种加密货币。
在硬分叉后设置chain ID,来标识这两条链为两条独立的链
软分叉(soft fork)
如果对比特币协议加了一些限制,使得原本某些合法的交易或区块,在限制后的新协议中变得不合法,那么形成的分叉是软分叉。
假设对软件进行更新:使区块大小变小,从1M变为0.5M。假设大多节点是新节点,即已经更新了协议,区块限制为0.5M;少部分节点是旧节点,仍然认定区块限制为1M。
这时,新节点挖出的区块,旧节点会认为是合法的(因为在1M以内);但是旧节点挖出的区块,新节点很可能不认为是合法的(因为很可能不在0.5M内):
因为新节点占了大部分算力,所以很可能先挖到某个区块,出现上图的情况。这时旧节点观察到上面那条是最长合法链,就会放弃自己的分叉,接着上面的链继续挖。
某个时刻,旧节点先于新节点挖出一个区块,将其上链:
这个区块大于0.5M,新节点不认,会继续扩展上一个合法的区块。
所以在这种情况下,会持续出现软分叉,只要旧节点不更新协议,挖出的区块就一直无法上链。相比硬分叉,软分叉即是非永久存在的分叉,只会临时存在一段时间。
实际中情形
给某些目前协议中没有规定的域增加新的含义
这种情况下即是当前协议中未限制的一些域,被赋予了新的规则。一个例子就是铸币交易的CoinBase域,没人规定也没人检查。前面学习挖矿难度时,提到这个域可以作为extra nonce来使用,比如拿出前8个字节来和nonce一起调整,以增大挖矿的搜索空间。
CoinBase即便拿出了前8个字节,后面还是有很长的可调整空间。有人就提出将其作为UTXO(未花费的交易输出)的根哈希值,因为目前这个UTXO集合只是每个全节点自己在维护,目的就是快速查找,判断交易合法性,这个集合的内容没有写到区块链里。
Merkle proof可以证明某个交易存在于某个区块中,那么如何证明某个账户A中有多少钱?全节点可以在本地的UTXO集合里算一下,即找到UTXO中所有转账给A的交易的输出,加在一起。
但如果是轻节点呢?例如手机上的比特币钱包。轻节点要去请求全节点,全节点返回结果给它,如何证明全节点返回给轻节点的是正确的呢?轻节点自己没有维护一个UTXO集合,所以是证明不出来的。
因此有人提出将UTXO中的交易也组织成一个Merkle Tree,将其根哈希值写在铸币交易的CoinBase域里面,而铸币交易中的此内容也会随着影响交易的Merkle Tree的根哈希值,这在轻节点里是保存了的。所以在这种方式下就可以像Merkle proof的方式一样证明账户里有多少钱,需要提供UTXO的Merkle Tree对应位置的哈希。
增加新的功能
P2SH(Pay to Script Hash)形式的交易脚本,最开始的比特币系统中是没有的,是后来通过软分叉的方式加进去的。
总结
硬分叉特点:只要系统中半数以上(算力)的节点更新了软件,就不会出现永久性的分叉。这类分叉为软分叉
软分叉特点:必须系统中所有(算力)的节点都更新了软件,才不会出现永久性的分叉。文章来源:https://www.toymoban.com/news/detail-481830.html
参考资料
1、【区块链学习笔记】10:比特币系统中的分叉文章来源地址https://www.toymoban.com/news/detail-481830.html
到了这里,关于[北大肖臻-区块链技术与应用笔记]第八节课——BTC 分叉的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!