简单介绍一下哈希算法(hash):可以将任意长度的二进制值映射为较短的固定长度的二进制值的算法。hash主要用于提取特征指纹,用于比较和验证。比特币中使用的是SHA256和RIPEMD160。一个优秀的hash算法,需要满足以下几个条件:
- 正向快速:给定明文和 hash 算法,在有限时间和有限资源内能计算出 hash 值。
- 逆向困难:给定(若干) hash 值,在有限时间内很难(基本不可能)逆推出明文。
- 输入敏感:原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。
- 冲突避免:很难找到两段内容不同的明文,使得它们的 hash 值一致(发生冲突)。
为什么哈希能将一个任意长度的二进制值映射为较短的还能不冲突?从理论上讲,一个很大的集合映射到一个小的集合上必然会出现冲突,hash函数之所以很少出现冲突的原因在于虽然输入的数据长度可以很大,但其实人类产生的数据并非全空间的,这些数据往往是相对有序(低熵值)的,实际上也是一个相对较小的集合。当然,这个集合自身可能比输出的结果要大,但这个冲突的概率远没有输入是全空间集合时那么夸张。
比特币主要采用双hash的算法,即对目标数据进行两次hash计算。SHA256,主要应用在两个地方:hash指针与算法难题,下面会具体介绍;RIPEMD160主要用于钱包地址生成,区块链中的钱包地址,采用一次SHA256,一次RIPEMD160进行加密压缩。RIPEMD160的主要用途是缩小结果值,方便存储。
1.2 哈希指针
hash指针和普通指针相比,不仅是一种检索信息的方法,同时它也是一种信息防篡改的方法。普通指针一般存储数据地址;hash指针存储的是对应数据的密码学哈希值,同时也能指向数据所在位置。
hash指针在区块链中主要有两个用途。一个是构成区块链表:区块链内,除了创世区块外,每一个区块的区块头部都保存着父区块的hash指针,从而构建成一条完整的链路,尾部是创世区块,头部是最新的区块。另外一个是构成二元默克尔树:每一个区块体中的交易按照一定的顺序,两两成对,再层层堆积,最终形成一颗二元树,顶层的hash指针就是区块头中的Merkle根。
1.2.1 区块链的防篡改
在区块链路上,如果修改第n个区块的数据,那n+1区块头部的哈希指针将失效,无法指向新的n区块,链路被截断;如果想要恢复链路,必然也要同时修改n+1区块头部的hash指针。同样,n+2区块头部的hash指针也需要被修改,直至最新的区块。只要保证最新区块的hash指针无法被修改,让所有人达成共识,就能保证数据不被篡改。区块链中,篡改的难度主要体现在数据的去中心化存储及分布式共识等。首先数据是全量存储于所有节点,意味着最新的节点分布在所有网络中,要篡改基本不可能;其次区块链遵守最长链原则,要修改hash指针形成的链表,需要从修改的地方开始,进行全链路调整,且长度必须大于等于原始正确链路长度,要在有限的时间内(正确的链路也在不断加长)做这样的工作,以目前的算力,基本不可能。
1.2.2 哈希树的作用
哈希树,中心节点都是由两个子节点组合计算成的哈希值。只要任意叶子节点的数据发生变化,由于“输入敏感”和“冲突避免”的特性,区块头的Merkle根会很容易校验到变化,所以这种结构能够快速比较大量数据。
由于每个中心节点都存储着以本节点为根的树结构哈希值,所以如果任意节点数据发生变化,其上一层的节点哈希值会最早发生变化,基于这样的特点,哈希树能够快速定位被修改的元素位置。
当需要验证一个叶子节点数据(一笔交易)时,我们不需要知道数据本身的具体信息,可以通过和数据关联的树链路,用已证实的哈希值来比较验证,这就是零知识证明数据存在。
1.3 哈希难题
区块链中的hash难题是指:通过暴力尝试,寻找一个随机数nonce,使nonce和其他一些输入组成的数据的hash值小于难度目标值。由于hash的“逆向困难”特性,基本不可能从结果倒推出这个随机数,暴力尝试是最快的方式。
计算哈希值的5个输入分别是区块头中的版本号、父区块哈希值,区块体默克尔根、时间戳、随机数。其中版本号、父区块哈希值是相对固定的,其他3个在不同节点中都有一定的差异。每一个矿工需要遍历随机数,使得这5个输入组成的数据做双重SHA256哈希形成的数据小于目标难度值。
nonce的存储长度是32位,数据范围在2e32内,而难度目标是一个256位的数据,数据量差距较大。如果在nonce的一次完整遍历中,2e32的数据都找不到符合目标的数值,则需要调整时间戳或者coinbase交易中的coinbase数据(俗称extra nonce数据,间接影响区块头的默克尔根)来重新遍历查找随机数。
挖矿是一个计算密集型的工作,从09年开始,先后经历了CPU(2009)、GPU(2010年)、FPGA(2011年末)、ASIC矿机(2013年初)、矿池等时期。矿池一定程度上违背了聪哥当年的去中心化设计,全网的算力集中在一些节点,有可能造成作弊等问题。
为了解决比特币的拥堵问题,许多组织提出了各种BIP(Bitcoin Improvement Proposal 比特币改进建议)。在各种竞标的方案中,有三类方法最受关注:
2.1 区块扩容
拥堵的主要原因,是区块的1M大小限制。比特币最初限制的区块大小是32M,由于交易量较小,为了避免浪费计算资源,同时也为了避免DDOS攻击,聪哥通过一个说明为”Clear up“的Commit把区块容量改成了1M。以当时的比特币交易量来说,这1MB足够使用并且还绰绰有余。这么看来,其实区块链本身可以支持更大的区块限制,假如将限制提高的32M,那理论上就可以支持6.67*32/s的交易速度,会极大的提高交易效率,降低费率。区块扩容的缺点是会带来硬分叉,而且扩容后,交易不断增多,也会给节点带来很大的压力,最终只有机构的电脑才能存储全量信息,导致中心化。
2.2 闪电网络
闪电网络是一种通过链外的微支付通道来增大交易吞吐量的技术。大致做法是不对区块本身进行扩容,而是在原有链路外,提供一种线下交易的手段,来扩充链路中单笔交易能够承载的信息。假定交易双方之间存在一个“微支付通道”(资金池)。双方都预存一部分资金到“微支付通道”里,之后每次交易,就对交易后的资金分配方案共同进行确认,同时签字作废旧的版本。当需要提现时,将最终交易结果写到区块链网络中,被最终确认。可以看到,只有在提现的时候,才需要通过区块链确认交易。通过这种方式,多笔交易被浓缩到一笔最终交易,间接提高了交易效率。闪电网络的缺点是网络本身不是比特币网络,容易被大机构控制,导致中心化。
2.3 隔离见证
目前区块链上每个区块内不仅记录了每笔转账交易的具体信息,即在哪个时间点账户收到或转出多少比特币,还包含了每笔交易的数字签名,用来验证该交易的合法性。矿工在打包区块的时候需要用数字签名一一验证每笔交易,确认没有问题之后才会将该笔交易记录在区块里。对于普通用户来说,他只关心每个账户有多少资产,并不需要一一验证每笔交易。隔离见证就是把区块内的数字签名信息拿出去,让每个区块可以承载更多笔交易,从而达到扩容的目的。通过隔离见证,比特币区块容量将从1MB提升到2MB,交易速度将提高2倍。隔离见证的缺点是,本身对比特币网络要有一次巨大的改动,万一失败了,那影响就大了。目前隔离见证(
SegWit)已经被激活,单区块能支持的交易量上限已经提高。下图展示了历史上区块大小变化及交易量变化的趋势:
区块链从09年运行至今,无论是为了解决自身的缺陷,还是为了适应外部环境的变化,都需要做出一系列的改进,来保证系统的稳定运行。因此,区块链需要不断地迭代更新,升级版本。但区块链是一个去中心化的分布式系统,不存在中心服务器给客户端发个补丁或升级包就能完成的情况。区块链想要升级,需要网络中的每个节点都达成共识,一起升级。如果有节点不升级,就会产生分叉,新老节点会各自维护自己认为正确的分支,使得多分支并存,导致诸如“重放攻击”等的一系列不良影响。所以分叉可以描述为对区块链“共识”的修改,导致的多种“共识”各自维护自己链路的结果。所谓共识,不仅包括区块本身的结构,还包括内部交易格式等。一般把分叉分为软分叉和硬分叉,关于两者的界限存在多种说法,主要是官方给了一个很模糊的“临时性分叉”概念。这里只选择其中一种进行讨论,分别介绍一下软分叉和硬分叉。
3.1 软分叉
软分叉是指比特币交易的数据结构(即“共识”)发生改变时,未升级的节点可以验证已经升级的节点生产出的区块,而且已经升级的节点也可以验证未升级的节点生产出的区块。软分叉可以保证不想升级的节点不去升级,新旧节点可以并存于网络中,是一种灰度升级的理想方式。但是,软分叉的升级空间及其有限,鉴于目前的比特币交易数据结构和区块数据结构所有字段都已经详细定义好了,要保证向前兼容,就不能增加新的字段,否则旧节点就会拒绝。软分叉虽然影响小,但能带来的效益有限,基本都是微小改动,比较有名是:CSV软分叉和P2SH软分叉。
CSV软分叉,用于改善比特币网络的扩展性并引入了 4 个不同的比特币改进提议(BIP9、BIP68、BIP112、BIP113),用以解决比特币区块大小以及交易积压问题。这次软分叉是利用交易数据输入结构中的“序列号”(参考第二篇文章的比特币结构)字段进行的。因为原来比特币交易数据结构中这一个字段定义较为模糊,没有被使用,所以能被重新定义。这个字段在旧版本节点上不会被仔细验证,所以新版本的节点按照定义过的规则生产新区块,可以被旧版本节点验证接受;新版本的节点只要兼容旧规则就可以验证接受旧版本节点产生的区块。但是,这种字段用一次就没了,不是长远之计。
P2SH软分叉,对比特币交易签名脚本的一次修改,使得比特币可以很方便的通过多重签名的方式来发送交易。这次软分叉是修改了交易数据输出结构中的“锁定脚本”(参考第二篇文章的比特币结构)字段进行的。原来这个字段叫做P2PKH,升级后的版本,不仅支持P2PKH,还能支持一种P2SH的标准交易类型。P2SH是一种比P2PKH更为严格的规范,旧节点也能验证通过新节点产生的P2SH锁定脚本。
3.2 硬分叉
硬分叉是指比特币区块格式或交易格式(即“共识”)发生改变时,未升级的节点拒绝验证已经升级的节点生产的区块,但已经升级的节点可以接受未升级节点产生的区块,然后大家各自延续自己认为正确的链路,形成两条分支。从软硬分叉的定义来看,不管何种分叉,都需要做到向后兼容(升级过的节点接受没有升级的节点生产的交易和区块),主要区别在于能否向前兼容(没有升级的节点接受升级过的节点生产的交易和区块)。
当硬分叉发生时,新旧节点将分裂为两个阵营,各自维护自己认为正确的链路。可能的结果有三种:
第一种,旧节点掌握着50%以上的算力,随着链路加长,旧节点阵营的链路长于新节点阵营。由于区块链只认可最长链路,新节点为了维护自己的利益,会倒戈到旧节点阵营,回退版本,导致版本升级失败,最终共同维护旧节点阵营形成的链路。
第二种,新节点掌握着50%以上的算力。随着链路加长,新节点阵营的链路长于旧节点阵营。同样由于最长链路的原则,旧节点为了维护自己的利益,会主动升级到新版本,使得新版本在全网生效,最终共同维护新“共识”的链路。
第三种,无论算力分布怎样,新旧节点水火不容,谁都不愿意接受另外一条链路,一直各自维护自己的链路,形成永久分叉。这是谁都不愿意看到的,说到底分叉形成的根本原因是人性的自私。只要人人都献出一片爱,为了某个长远的目标达成共识,区块链世界将变成美好的人间。
3.3 版本号
版本号是区块头的第一个字段(参考第二篇文章的比特币结构),表示本区块遵守的验证规则。版本号是软件行业通用的一种设计,当软件版本发生较大修改时,应该升级版本号,明确这次升级的具体变化,让所有参与者感知到这一行为。聪哥最初设计时,希望通过版本号实现区块链的硬分叉升级,这种愿望是美好的,符合长远发展的。但在实际操作中,区块链核心组开发却习惯采用软分叉的形式升级区块链,虽然操作难度小,影响面可控,但也使得升级的目标变得模糊,新旧版本以一定的方式相互欺骗,使区块链背负越来越多的技术债。从这个层面上说,硬分叉优于软分叉,区块链最好的维护方式,应该是通过版本号变更,采用硬分叉形式强制升级。
从比特币官网的版本变更统计可以看出,比特币主要经历了v1,v2,v3,v4,
SegWit,
SegWit2x,
Bitcoin Unlimited等,各版本的占比如下图所示:
版本升级一般的做法是指定一段时间的投票期,让所有矿工进行投票支持,时间结束后,查看最近1000个区块的投票信号,统计支持新版本的比例,当比例大于某个数值时,激活新版本,拒绝旧版本区块。投票信号一般采用coinbase交易中的coinbase数据字段(参考第二篇文章的比特币结构),每个版本会指定一个标记,当有这个标记时,就表示支持这个版本。比如
SegWit是SW标记,
Bitcoin Unlimited是BU标记等。矿工投票,实质是算力投票,因为只有计算出区块的矿工才有真正的投票权。从这个角度上说,支持的算力多少决定了版本能否升级,所以网上一般也以百分多少的算力支持,作为激活一个版本的条件。
版本升级也不完全取决于算力,区块链设计的初衷是去中心化,如果完全按照算力去决定版本,那目前的几大矿池联合完全可以左右版本走向,这样不稳定的系统是不会得到认可的。说到这里,就要引出目前区块链的两大势力:
一个是以core dev为代表的核心技术开发团队,可以叫BTC,有理想化比特币的倾向。在广大用户中,拥有极大的话语权,在技术上也更为专业。他们的偶像和精神领袖是中本聪,他们有自己的理想和信念并且认为比特币就是他们手中的改造世界的工具,但手中掌握的算力有限。
一个是以挖矿公司为代表的比特币世界的最大利益相关方,可以叫矿工,他们在乎的是自己的利益最大化而不是虚无缥缈的去中心化等等口号。他们掌握了比特币世界几乎所有的算力,干的是最苦最累的活,他们渴望的是真金白银的回报,他们希望的是更多的交易费和更高的比特币价格。
SegWit(见证隔离)是BTC提出的,可以解决目前比特币拥堵的方案。一方面它真实解决了1M限制带来的拥堵问题,另一方面,它也在渐渐瓦解目前存在的算力中心化(几大矿池掌握着大部分算力,能左右比特币发展)问题。SegWit是闪电网络的一个前置条件,它可以将算力转移到线下,用闪电网络的规范来制约算力中心化问题。显然这伤害了矿工的利益,在长远健康发展但是暂时会损伤利益 和 短期快速实现收益但不利于长期发展 两条路上,矿工往往会偏向后者。所以矿工主张直接扩容区块大小上限,并实践了多次暴动,这种变更相对
SegWit简单易实施,而且扩容后可能导致的算力需求增多(矿工手中的筹码会越来越大,因为他们掌握大部分算力),手续费变多(随着交易量增多,不管怎么扩容,最终都会拥堵,使得单笔手续增多;加上每个区块的交易数量变多,手续费肯定会越来越多)正是矿工希望看到的。为此BTC与矿工进行了一次博弈,显然按照算力而言,矿工拥有绝对的优势,BTC说白了只是一个拥有方法论的白面书生,根本不掌握实权。SegWit的升级一度陷入僵局,分叉呼之欲出,BTC坚持理想主义,毫无畏惧。此时矿工们意识到,BTC还是拥有一定的话语权,分叉肯定会导致比特币的贬值,掌握着大量利益的矿工会遭受严重的损失,但BTC就是一群一穷二白的码农,根本没啥损失。顾及到自己的利益,矿工们纷纷倒戈,最终实现了SegWit的升级。这在一定程度上,也说明比特币是一个技术中心化的产物。相比算力中心化带来的危害,这种无欲无求,只想创造新世界的技术中心化更有利于区块链的发展。