区块链学习笔记9——比特币分叉

九、比特币分叉

什么叫分叉?

原来是一条链,现在分成了两条链,这个叫做分叉。

分叉可能是多种原因造成的,比如之前讲到的,挖矿的时候,如果有两个节点差不多同一个时候,那么这个时候呢,两个节点都可以发布区块,这个时候就会出现一个临时性的分叉,管这样的分叉叫做state fork,由于对比特币当前的状态有了意见分歧而导致的分叉。

前面还讲过有分叉攻击的例子,forking attack 也属于state fork,也是对比特币当前的状态有了意见分歧而导致的分叉,只不过分叉攻击的例子这个意见分歧是故意造成的,是人为造成的,所以有时候管这个叫做deliberate fork,除了这个因意见分歧产生的呢,还有一种是比特币的协议发生了改变,要修改比特币协议,需要软件升级,在一个去中心化的系统里,升级软件的时候,没有办法都保证所有的节点都升级软件,假设大部分节点升级了软件,少数节点因为种种原因可能没有升级,有可能就是还没来得及升级,也可能是不同意对这个协议的修改,就你想把协议改成这个样子,社区当中,有些人可能是不支持的,那么这个时候也会出现分叉,叫做protocol fork,因为对比特币协议产生的分歧,用不同版本的协议造成的分叉。根据对协议修改的内容的不同,又可以进一步分成硬分叉(hard fork)和软分叉(soft fork)。

硬分叉

出现情况

如果对比特币协议增加一个新的特性,扩展一些新的功能,这个时候,那么没有升级软件的节点,这些旧的节点是不认可这些新特性的,认为这些特性是非法的,这就属于对比特币协议的内容产生了意见分歧,就会导致分叉

例子

block size limit,区块大小限制。

比特币规定哪个区块最多是一兆字节,有人认为一兆的限制太小了,也增加了交易的延迟,大家也可以算一下,1M = 1000000字节,一个交易可以认为是250字节,1000000字节/250字节=4000交易左右,就是一个区块,平均十分钟有这样一个区块,所以4000个交易要摊到10分钟,每分钟60秒,4000/(69x10)约等于7,算下来,大概是每秒钟7笔交易。这个是非常低的。

区块链学习笔记9——比特币分叉_第1张图片

像用信用卡买东西,信用卡公司能够处理的交易数目能够比这个要多好几个数量级,像大的信用卡公司,他每秒钟处理的交易数目跟这个完全不在一个数量级上,要差好几个数量级,很多电商网站,他每秒的交易量也是远远不止这些,所以有些人就认为这个区块太小了,限制了比特币的,同时也增加了延迟,因为区块里就能装这么多的交易,如果交易数目太多的话,可能有的交易就得等到下一个区块,才能被写进去,一等就是平均要等十分钟。

假设有人发布了一个软件更新,把block size limit从1M增加到4M,假设大多数节点更新了这个软件,把block size limit更新到4M,少数节点没有更新,这里说的大多数节点和少数节点不是按照账户数目来算的,不是说谁的账户多就占大多数,是按照算力来算的,就系统中拥有大多数哈希算力的节点都更新了软件。

区块链学习笔记9——比特币分叉_第2张图片

这时候,系统运行起来。

这是当前的区块链,然后软件更换新了,更新之后。

区块链学习笔记9——比特币分叉_第3张图片

有一个新节点挖出一个区块,这个区块比较大,这个区块旧节点是不会认可的,就旧节点是不会往下继续挖,他会沿着原来的区块链挖,挖这种小区快。这种小区块新节点是认可的。

区块链学习笔记9——比特币分叉_第4张图片

有个新节点挖出一个大区块,假设大多数节点更新了软件,所以大多数新节点是认可这个区块的,他会沿着这个继续挖,只有少数的旧节点不认可这个区块,会沿着下面的链往下挖,会出现这个情况。

区块链学习笔记9——比特币分叉_第5张图片

新节点认为上下两条链都是合法的,但上面这个是最长合法链,所以新节点会继续沿着上面那条链挖,而且算力因为足够多,会使这个链变得越来越长。旧节点认为下面的链才是合法的,上面这个链无论有多长都是没用的,因为对于旧节点来说,都是非法的链,他都会沿着下面那条链挖。当然上面那条链,有可能有一些小区块,就新节点也可能挖出大小不到1M的区块,这个区块是新旧节点都认可的,但是没有用,因为这条链上有对于旧节点非法的区块,就不会认,就这个分叉是永久性的,只要旧节点不更新软件,这个分叉就不会消失,这就是为什么管它叫硬分叉,比特币社区当中,有些人是比较保守的,像这种提高block size limit的事情,有些人是真的不同意,而且区块的大小也不是越大越好,因为比特币系统底层是P2P Overlay Network,传播主要采用flooding的方式,所以对带宽的消耗是很大的,带宽是瓶颈。

出现了硬分叉之后,就变成了两条平行运行的链,平行运行的链彼此之间有各自的加密货币,就下面这条链的挖矿奖励在这条链是认的,就变成了社区分裂,社区中有一部分人认为下面才是正统的,没有经过篡改的,根正苗红的,上面的是非法的,这是真实发生过的例子,就社区两个人打架,对于比特币协议的修改互相之间有一点分歧,最后就分家了,你按你的规则,我按我的规则。这个币在旧链上是认的,在新链上有新的币,那么原来分叉之前的币按道理来说应该变成上下两条链都认可,就他一个币是拆成两个币的,后面讲以太坊的时候有一个经典的例子,以太坊叫做ETH,现在看到的ETH实际上是分叉的,是ETC(以太经典),这个才是真正原来的协议,这个ETH是经过“回滚”的协议,就是有人攻击ETH上的一个智能合约叫TheDAO,TheDAO是一个众筹的,然后进行投资基金那种东西,他收到攻击之后,以太坊社区,包括当初的开发者,决定用硬分叉的方法重新记账,把这个黑客偷到的钱,其实整个TheDAO的钱都重新分到另外一个智能合约,然后退回给当初的投资者,就是有人不同意这样做,觉得这个是胡闹。所以ETH实际上是没有改协议的旧链,分裂完,就是出现,一个的以太币,分裂完之后实际上是变成两个了,ETC也是一个在交易所交易的加密货币,而且还不算小众,他没有ETH这么流行,但他也算是比较主要的加密货币,也照样有人用,就变成各挖各的。

假如在分叉之前转了一笔账A->B,然后B拿到钱,分叉之后,两个都可以花,基本上是可以的,但是如果不采取措施的话,这两条链会有影响,就举个例子,就ETH和ETC分叉完之后,因为原来是一条链,账户,私钥都是一样的,如果分裂完之后,不采取任何措施的话,两条链上,别的都一样,就是运行的协议不一样。如果在上面那条链有一笔转账交易,比如说B->C,下面链也出现了B→C,因为账户,私钥都是一样的。本来是上面那条链要把B的以太币转给C,变成下面那条链,B的ETC的币也转给C了。还有人采取更激进的措施,比如说上面那条链C希望有一个认转给他钱,然后下面那条链回放,想收到上下两条链的转账,那如果说没有人转给C钱怎么办。

B去购物,交一笔钱发给C,后来要取消这个交易,有的网站允许取消,C又把钱转给了B,有了这个转账交易之后,在下面那条链回放,然后,B在底下又赚了一笔钱。B这么干好像有风险。

一开始B->C,然后C->B,然后C->B在底下回放。那B->C的时候,C会不会把B->C在底下回放呢,好像也是有风险的,因为B这个账户有可能在下面,他没有钱,有可能在底下先把这个钱花了,然后在上面搞B->C,这样的话,C转给B是可以的,C在底下有钱,B在底下没有钱。这都是以前发生过的案例。

所以后来就加一个措施这两条链各带一个chain ID把他给分开了,所以现在以太坊的分裂的这个链已经没有问题了,就是两条独立运行的链了。

软分叉

出现情况

如果对比特币协议加一些限制,加了之后,原来合法的交易或者是区块,在新的协议当中有可能变得不是合法了,就引起了软分叉。

例子

假设有人发布软件更新,把区块大小变小了,1M——>0.5M,不了解的人可能觉得调整区块的大小就是改一个参数就行了,其实不是的,一个去中心化的系统,改一个参数就可能导致分叉,而且取决于这个参数是怎么改的,有可能是硬分叉,有可能是软分叉,这里的例子只是为了解释一下软分叉的概念。实际当中不会这样做的,因为1M本来就比较小了,不会真的再把他改成0.5M。假设有新节点和旧节点,大部分是新节点,新节点认为是0.5M,旧节点认为是1M,这时候会出现什么情况?

下图是当前的区块链

区块链学习笔记9——比特币分叉_第6张图片

现在,分叉了,分叉完之后,新节点开始挖不超过0.5M的小区块,旧节点认这个小区块。然后旧节点挖出的可能是大区块,这个大区块新节点是不认的,认为挖了一个不合法的区块出来

区块链学习笔记9——比特币分叉_第7张图片

按照比特币协议扩展的应该是最长合法链,新节点就会沿着上面的链挖,这个时候会出现什么情况。

出现的情况:
下面那个链是旧节点挖出来的,旧节点也认上面那条链,所以看到上面那条链变成最长合法链之后,会放弃当前所在的分叉,切换到上面那条链挖,为什么叫做软分叉,因为这个分叉是临时性的,如果旧节点不更新软件的话,他们挖出的区块可能就白挖了,像下面那条链的区块就白挖了,他自己都放弃了

区块链学习笔记9——比特币分叉_第8张图片

而且他切换到上面那条链的时候,问题还会再出现,可能又挖出一个大区块来,然后新节点又不认,新节点又变成了沿着下图的情况挖,然后,上面那条链挖的大区块又白挖了,如果旧节点如果不更新软件的话,可能会生活的比较抑郁,因为不停的挖,但是又白挖了,但是系统不会有永久性的分叉,这就是软分叉。

区块链学习笔记9——比特币分叉_第9张图片

实际当中可能出现软分叉的情况

给某些目前协议中没有规定的域增加一些新的含义,赋予他们一些新的规则。

比如,coinbase域,每个发布的区块里可以有一个铸币交易coinbase tx,coinbase tx里面有一个域,叫做coinbase,这个域用来干什么,没人规定,也没人检查,之前讲过他的一个用途,挖矿难度的时候,可以把他作为extra nonce,挖矿的时候不是要调block header里面的nonce吗,但是block header里的nonce只有四个字节,调啊调,最多是2的32次方可能性,搜索空间不够大,所以可以用coinbase的前八个字节用来做extra nonce,两个合在一起就变成了2的96次方,作为目前的挖矿难度是足够的。但是coinbase域不止八个字节,后面还有好多呢。

后面的干嘛用呢,用人就提出把它作为UTXO的根哈希值。

UTXO:当前还没有花掉的交易的输出。

目前这个集合只是每个全节点自己在内存中去维护这样一个集合,主要是为了快速查找,能不能判断这个交易是不是double spending,但是这个集合的内容并没有写到区块链里,这跟前面说的Merkcle proof(能证明某个交易是不是在给定的区块里),比如说,一个轻节点,没有维护整个区块链的内容,只是知道block header,就问全节点,这个交易是不是在这个区块里,全节点可以返回一个Merkcle proof作为证明,轻节点就可以验证出来,这个是不是真的是这个情况,可以验证全节点回复结果的正确性

但是如果是另外一个场景,要证明某个账户上有多少钱,这个目前在比特币系统种,是证不出来的,如果是全节点的话,怎么知道账户上有多少钱,A这个账户上有多少钱,就看一下,A在这个UTXO里对应的输出,上面一共收到多少个币,账户上就有多少钱,如果是全节点是可以算出来的,但是有很多区块链钱包,比如手机上的比特币钱包,他不可能在手机上维护一个完整的区块链,他实际上是一个轻节点,要知道账户的余额,要询问其他全节点,全节点返回一个结果,怎么知道这个结果是不是对的,现在是证不出来的,自己如果不维护一个UTXO集合,没有办法用Merkcle proof 证出来。

有人就提议,把UTXO集合当中的内容也组织成一个Merkcle tree,这个Merkcle tree 有一个根哈希值,这个根哈希值写在coinbase域里面,因为block header没法再改了,改block header动静太大了,这个coinbase域正好是没人用的,就写一个UTXO的根哈希值,这个域当中的内容最终往上传递的时候,会传到block header的根哈希值里,改这个域的内容,根哈希值会跟着改。

所以这个提案就是说把UTXO集合的内容组织成Merkcle tree,算出一个根哈希值出来写在coinbase域里面某个位置,然后coinbase 域的内容本身也会算哈希,算到block header的根哈希值去,这样的话,就可以用Merkcle proof证出来了。假设有人发布一个软件更新,规定coinbase域要按照这个要求来填写,大多数节点都升级了软甲,少数节点没有更新,这是软分叉,因为新的节点发布的区块旧节点认为是合法的,因为旧节点不管你写什么内容都没有关系,但旧节点发布的区块,新节点可能是不认的,因为coinbase域如果不按要求写的话,他是不认的,这就是一个软分叉。

比特币历史上,一个比较著名的软分叉的例子是P2SH

P2SH:Pay to Script Hash

这个功能在最初的比特币版本里是没有的,这是后来通过软分叉的方法给加进去的。

意思:支付的时候不是付给一个Public Key Hash,而是付给一个赎回脚本(redeem Script)的哈希。

花钱的时候要把这个交易的输入脚本,跟前面那个币的来源的输出脚本拼接一起执行,执行的时候验证分为两步,第一步是要验证输入脚本给的redeem Script跟前面那个输出脚本给出的Scirpt的哈希值是对得上的,证明输入脚本提供的redeem Script是正确的。第二步,再去验证,执行这个redeem Script来验证输入脚本里给出的签名是合法的。对于旧节点来说,他不知道P2SH的特性,只会做第一步的验证,旧节点没有更新软件。新节点才会做第二阶段的验证,所以呢,旧节点认为合法的交易,新节点可能认为是非法的,如果第二阶段的验证通不过的话,而新节点认为合法的交易呢,就节点肯定认为是合法的。

总结:

软分叉特点:只要系统中有半数以上的节点更新软件,那么系统就不会出现永久性的分叉,可能有临时性的分叉。

硬分叉特点:必须是所有节点都更新软件,系统才不会出现永久性的分叉,如果有小部分节点不愿意更新,那么系统种就会出现两条链。

你可能感兴趣的:(区块链,区块链,比特币)