完整的比特币数据库(也就是区块链)需要的磁盘空间是巨大的,到目前为止需要超过 140 G 的磁盘空间,这对普通用户来说还是很高的。因为区块链网络的去中心化特性,网络中的每个节点必须是独立,不受其它节点的制约,每个节点必须存储一个区块链的完整副本,才能完成相应的工作。并且,由于节点是网络中的完全参与者,它们还需要去对其它交易进行验证,并参与挖矿。要想与其他节点交互和下载新块,也有一定的网络流量需求。
文 | 王映
图 | 闫燕
但如此一来,随着使用比特币的人数不断增长,这条规则就很难被广大群众接受了。因为不可能每个人都去运行一个全节点,去完成大部分我并不关心的事情。比如买卖双方,关心的只是我这笔交易的付款和发货情况,其它数据并不关心。
在中本聪对 比特币网络的设计文件中,解决这个问题可以采用“简易支付验证”(Simplified Payment Verification, SPV)。SPV 是一个比特币轻节点,它不需要下载整个区块链,也不需要验证区块和交易。它在区块链网络中查找交易以便对支付情况进行验证。
由于SPV节点不存储全部区块链数据库的内容,所以它需要连接到一个全节点来检索必要的数据。这个机制允许在仅运行一个全节点的情况下有多个轻钱包。
普通用户绝大多数都是以轻量节点的身份出现的,全节点只占很小的一部分。所谓的“比特币扩容”重点是全节点的扩容,因为随着链的伸长,交易信息量越来越大,存储容量爆满,而轻量节点则不存在这个问题,很小的存储容量就足够了。
为了实现 SPV,需要有一个方式来检查是否一个区块包含了某笔交易,而无须下载整个区块。这就是 Merkle 树所要完成的事情。
从前面的学习我们知道了区块链整个体系是由两大类数据结构相互嵌套组合而成的,第一类数据结构是“哈希链”结构,这可看做是区块链的纵向逻辑结构;第二类数据结构是“默克尔树”结构,这可看作是区块链的横向结构,实际上是使用了哈希指针的二叉树结构,如下图所示:
Merkle树是区块链的基本组成部分,它采用一个二叉树的结构,树上的每个节点保存的都是一个哈希值。Merkle根节点字段对区块体中所有交易记录。以二叉树的形式迭代地两两拼接 、进行哈希操作,可以得到一个最终的哈希值,称之为Merkle根哈希。这个根哈希值是包括在区块头信息里的。我们常说的区块哈希,实际上是指整个区块头的哈希值,并不包括区块体中打包的交易哈希。
在默克尔树结构中,所有的区块可被两两分组,指向这些区块的指针被存储在上一层的父区块中,这些父区块再次被两两分组,再指向上一层的父区块,以此类推,直达创世区块。
通过哈希链和默克尔树两套数据结构,我们可以很严格地倒推验证每笔交易的真实性。Merkle根哈希相当于是对区块中所有交易记录进行了一个快照,区块中交易记录的任意改动都可以通过比较Merkle根哈希而很容易地察觉。Merkle根哈希主要用于简单支付验证(SPV),在验证某个交易是否在区块中时,也能极大地减少网络传输成本。
SPV节点只需要从全节点那里获取一笔交易对应的的Merkle根节点哈希值及打包路径过程中的哈希值即可验证一笔交易的有效性。用户只需要存储区块头(含有Merkle root),在需要时获取Merkle树路径,即可对一笔交易进行验证。
由上述分析,有同学可能已经看出了,即使没有默克尔树,区块链也是可以运转的,但这样一来系统效率就会变的很低。因为要把所有交易信息打包进区块里,这样一来每个区块只能容纳很少量的交易信息,这在大规模交易场景下是无法容忍的。
而不含交易信息的区块头(Block header)大小仅有80字节。一年产生的数据4.2MB。(80 bytes * 6 * 24 * 365 = 4.2MB)。100年也只有400M,目前最低端的电脑也可以满足运行需求。
我们以16个交易为例对Merkle的原理进行说明,如下图所示,16个交易分别用字母a~p表示。Ha表示对交易a进行哈希计算,得到的一个交易指纹。
上图中,SPV轻节点提供交易e的交易ID给全节点,如果全节点查到这笔交易,则反馈给SPV节点另外5个哈希值,如上图橙色部分。这里需要注意的是,轻节点提交给全节点的是这笔交易的ID,并不是交易的哈希值,所以全节点需要查询后才能知道这个交易ID的哈希值是多少,所以这个过程全节点是无法伪造一个哈希值的。
SPV节点对本交易e进行哈希计算后,再与由全节点提供的哈希值Hf合并进行哈希计算,得到Hef,以此类推,最后计算出Merkle根的哈希值。再将计算出的Merkle根值,与全节点反馈的Merkle根值进行比较,如果两者一致,则证明这笔交易的确被打包进本区块中了。
当区块大小由16笔交易(4KB)急剧增加至65,535笔交易(16MB)时,Merkle的搜索路径长度增长却极其缓慢。只需要一个区块头部结构,再加一个这样的搜索路径的开销,一个节点就能花费很小的代价快速定位一个交易。一般来说,包含N个交易的区块体,通过Merkle确认其中一笔交易的算法复杂度为
。
由以上分析可知,SPV节点对交易进行验证时,由于SPV本身没有保存全网全部交易数据,所以它本身是不知道这笔交易被打包到哪个区块中了。SPV节点需要连接到一个全节点,从全节点那里查询某个交易ID的相关信息,包括打包进的区块高度、Merkle根及交易哈希路径。
在SPV节点向全节点提交查询请求时,提供给全节点的只是这笔交易的ID,并不是这笔交易的哈希值。全节点不知道这笔交易对应的哈希值是什么,只能从区块中读取。所以全节点无法伪造一份Merkle根及路径哈希来欺骗SPV节点。
根据从全节点反馈的区块高度,以前从全网获取的当前最新区块高度,就可以知道这笔交易经过了多少次确认。如果经过了6次确认,即打包区块的后面,有6个以上的新区块,则可以证明交易被确认,无法再修改了。
需要注意的是,比特币系统中有两种验证:交易验证和支付验证。
以上我们所说的是支付验证,是验证存在,就是验证一笔支付交易是不是存在于区块链网络主链上,经过了多少次确认。
而交易验证则是验证这笔交易的合法性,它是由矿工完成的,需要验证的内容比支付验证复杂很多。需要验证一个地址有没有足够的余额,是否存在双重支付,交易脚本是否能够执行通过。
通过Merkle树我们可以大大减少区块链中的数量量,减化验证过程。从上文中我们知道了有一种厉害的加密技术名为哈希算法,这是非对称加密技术的一种。在区块链中得到了广泛的使用。所以下一次我们将针对非对称加密技术与大家一起探讨,欢迎持续关注,谢谢!
(to be continued...)
网友评论