兼容性与分叉

区块链的一大特点就是永不停机。这对应用来说可能是件好事,对区块链平台的兼容性设计却是一个很大的挑战。区块链平台不可能是一蹴而就的,不可避免要开发新的特性,或者旧版本有严重的问题需要修复,都可能会引入一些不兼容的修改。对于区块链这种复杂的分布式系统进行在线升级,难度不亚于给急速奔跑中的赛车更换轮胎。

软件兼容性

兼容性(compatibility)是指硬件之间、软件之间或是软硬件组合系统之间的相互协调工作的程度。

因为热力学第二定律,封闭系统将不可避免的走向混乱。要维护一个良好的秩序,需要投入大量的精力。目前也只有Intel和微软分别在硬件和软件领域做到了很好的兼容性。

兼容性可以分为:

  • 向后兼容(Backward Compatibility):指新版本在功能或者数据格式等方面可以兼容老版本。比如win 10可以运行为win xp开发的程序,反之则不行。还有Intel的x86指令集的CPU,新款CPU依然可以运行老版本的软件。
  • 向前兼容(Forward Compatibility):指老版本可以处理新版本产生的数据。比如老版本的Word还可以打开新版本Word创建的文档,当然显示上或者功能上会有些缺失。更常见的是在协议领域。比如TCP协议,经过多年的发展完善,由多个RFC组成。一个基础版本和后续多个扩展版本。但是实现了基础版本的设备依然可以跟新的设备通信,当然也会缺少对扩展功能的支持。

要实现向后兼容相对容易,也更常见。只要保持老的指令或者API不变,开发新功能的时候额外新增即可,即新版本是老版本的一个超集。但是历史包袱会越来越重。

向前兼容相对困难,也不太常见。实现的方式通常是扩展或者插件的方式。但是这对基础版本的设计要求很高,必须保留足够的扩展性。

分叉

区块链因为新的操作依赖之前所有的历史数据,因此特别注重兼容性。其兼容性也可以采用类似的分类方式。

  • 软分叉,验证条件变得更严格,即新的交易和区块对于老的协议也是有效的,但反过来,老的交易和区块对于新的协议是无效的。这个对应向前兼容。比如比特币的Pay-to-Script-Hash(P2SH)[1]。
  • 硬分叉,验证条件变宽松即新的交易和区块对于老协议是无效的,但是依然兼容历史数据。这个对应向后兼容。比如以太坊经历The DAO事件之后的分叉。

软分叉的好处是不用强迫所有节点都升级:

  1. 部分验证节点升级新协议的情况下,系统依然可以提供服务(可用性可能有部分下降),并且保证分叉后的新协议(可能部分)生效。这里的“部分”依赖于升级新版本的节点在全部节点中占的比例。当全部验证节点升级新协议,则新协议完全生效,这种情况被称为miner-activated softfork (MASF)。
  2. 部分非验证节点升级新协议的情况下,系统依然可以提供服务,不影响可用性,并且保证分叉后的新协议(可能部分)生效。当所有非验证节点升级为新协议之后,即使验证节点不升级,新协议也会完全生效,这种情况被称为user-activated softfork (UASF)。

相比之下,硬分叉需要所有节点都升级,否则将会分叉出两条独立的链,比如ETH和ETC。

因为区块链去中心化的特点,节点由匿名的机构或者个人完全掌控。让全网所有节点在指定的时间点之前完成升级新版本,成本非常高。因此软分叉对于区块链来说非常有吸引力。

实际实施的分叉中,软分叉也占了较大的比重(参考资料1)。通常做法是不新增字段,而是通过扩展原有字段来增加新功能。下面以 P2SH 为例,详细讲述一下软分叉的细节。
比特币本身支持简单的脚本功能,交易的校验逻辑也是由脚本来描述。

OP_HASH160 6af7caf9b09224af8a171318f69d254c1756e54e OP_EQUAL

这段脚本的意思是,谁能提供中间这段哈希值的原像,谁就有权支配对应的一笔比特币。
但是实际上不会有人这样写脚本,因为这段脚本由很大的安全隐患。
区块链的交易校验需要所有的节点各自都运行一下校验脚本。这就意味着,接受这笔比特币的人,要把哈希的原像,也就是这段脚本的答案,发给所有人。这样所有人都知道答案了,其他人就可以抢先把这笔比特币转走。
所以这段脚本是合法,但是没有用的。
P2SH 分叉之后的新版本赋予这段脚本一个新的含义。这个哈希的原像又是一段新的脚本,必须提供新的脚本,并且新的脚本也验证通过,原来这段脚本才算通过。相当于用哈希作为脚本的指针,可以一直扩展下去。提供了很高的扩展性,可以实现多重签名等高级功能。
而且这段脚本对没有升级的节点也是有效的,并且能够通过验证,因为用户确实提供了这个哈希的原像。所以这个分叉是向前兼容的,是一个软分叉。

这个情况有点像一个网络用语——“囧”。其本身是一个生僻的汉字,含义为光明。但是太不常见,因此在网络上被赋予新的含义,成为一个表情。

但是我们也要看到,没有升级的节点的验证是不充分的。因为老版本并不知道原像是一段脚本,也没有对这段新的脚本进行验证。这就存在一个安全隐患,可以针对这个隐患发起攻击。
比如这笔比特币真正的主人把哈希的原像发了出来。一个恶意节点收到之后就可以构造一个交易,妄图把这笔比特币据为己有。升级后的节点肯定能识破,因为还需要新的脚本的答案。但是对于未升级节点,这个攻击交易是可以校验通过的。当整个系统中未升级的节点算力占优的情况下,攻击就能成功。
因此比特币一开始规定软分叉激活的前提是升级新版本的算力达到55%以上。但是依然出现了被攻击的情况,后来又进一步将门槛提高到95%。

我们可以看到,软分叉的缺点是验证不充分。在兼容性的前提下,新版本一定是老版本的超集。因此新版本一定有老版本所没有的处理逻辑,虽然表面看起来没有新增字段或者指令。因此验证不充分是必然的,而区块链的安全性又非常依赖全网节点的校验,因此安全隐患也是必然的。
想要消除安全隐患,就得像比特币一样,将软分叉激活的门槛设置的非常高,但是这样相比硬分叉的优势就没那么大了。

还有一种反对硬分叉的看法,觉得硬分叉有造成社区分裂的潜在风险,例如前面提到的ETH和ETC的例子。因为区块链的价值来源于网络效应,社区分裂会导致整个链的价值下降。
但是从前面的分析可以看到,软分叉所营造的统一只是表面上的,部分节点升级时,大家其实是貌合神离。而且部分节点升级只是一个过程,最终还是要所有节点都升级到新协议,升级才算是完全结束。
因此在社区分裂的风险上面,两者其实没有太大差别。

社区里面其实对软分叉和硬分叉也有相关讨论(参考资料2和3)。

参考文献

[1]https://en.bitcoin.it/wiki/P2SH

[2]On consensus and forks: What is the difference between a hard and soft fork?:https://medium.com/@octskyward/on-consensus-and-forks-c6a050c792e7

[3]Hard Forks, Soft Forks, Defaults and Coercion:https://vitalik.ca/general/2017/03/14/forks_and_markets.html

[4]比特币共识分叉的完整历史:https://blog.bitmex.com/zh_cn-bitcoins-consensus-forks/