Merkle tree及其在区块链等领域的应用

1. 引言

本文重点解释何为Merkle tree,及其如何在Bitcoin、Amazon的Dynamo DB 、ZFS filesystem 以及 Git version control system 中运用。

参考 Is there a difference between perfect, full and complete tree?有:

  • Full Binary Tree:是每个节点具有0个或2个子节点。
    在这里插入图片描述

  • Complete Binary Tree:最底层具有左右节点或者只具有左节点;除最底层外,所有节点据具有左右节点。
    在这里插入图片描述

  • Perfect Binary Tree:是指所有节点都有左右子节点。
    在这里插入图片描述

2. 何为Merkle tree?

Merkle tree又称为Hash tree,本质为hash值的分级集合,其层级结构为:

  • Merkle leaf:实际的数据对应的hash值。
  • Merkle branch:中间hash值。
  • Merkle root:将所有数据汇总为一个hash值。

基本的Merkle tree 示意为:
在这里插入图片描述
上图:

  • Data1~ Data4:为来自应用的实际数据。
  • Hash1~ Hash4:为Data1~ Data4 对应的hash值。为Merkle leaf。
  • Hash12和Hash34:为Merkle branch。Merkle tree为层级分布的,除Merkle leaf和Merkle root之外的所有均称为Merkle branch。
  • Hash1234:为Merkle root。

以上Merkle tree中的每一层的数量都为偶数,都可形成精准的pair对,又可称为balanced Merkle tree。但实际,存在奇数数量的情况——如具有5个Data Node,此时,Data1+Data2形成一个Merkle branch,Data3+Data4形成一个Merkle branch,而Data5落单了。这种Merkle tree为unbalanced。

针对unbalanced Merkle tree的处理方式有:

  • Bitcoin的做法是,复制落单的Data5的hash值来形成一个Merkle branch,具体示意为:【复制了Hash5和Hash55】
    在这里插入图片描述
  • Monero的做法是:简单地服用落单的Data5对应的hash值,让它保持un-paired状态。如下图所示的cf54b hash 值。Monero这种简单复用的实际效果与Bitcoin中复制的效果是一样的。【可见 mukatee编写的示例代码
    在这里插入图片描述
    而实际在 Monero的代码库tree_hash.c 中,将Merkle tree转换为了perfect binary tree:【可见 mukatee编写的Monero Merkle tree 示例代码
    在这里插入图片描述
    实际的计算思路为:假设Merkle tree中包含有5个data node(或称交易),而5的next_power_of_two为8,8-5=3,因此应从第4个(Data4)开始运行iteration 1。【详细可参见 Teemu Kanstrén 2021年2月16日 medium博客 Merkle Trees: Concepts and Use Cases

3. 区块链中的Merkle tree

在Bitcoin等区块链平台,使用Merkle tree来对区块中的交易进行汇总和验证,并将Merkle root作为对所有交易的汇总 嵌入到block header中,详细示意为:
在这里插入图片描述
在每个区块中,包含有:

  • 当前block ID value:为当前区块header域的hash值,Merkle root为该header域的一部分。
  • previous block ID:上图中的Parent是指前一区块的block ID值。

由于每个block ID中都包含了相应区块中所有交易的Merkle root,通过以上链式结构,保证了交易的不可篡改性。

扫描二维码关注公众号,回复: 12681443 查看本文章

实际Bitcoin的block header中包含了:

  • Difficulty target value(Bitcoin中称为bits);
  • 当前区块中所有交易的Merkle root;
  • Nonce:a value changed in mining to find accepted blocks;
  • previous block hash (block ID):在上图中将该previous hash称为parent。实现了将当前区块与前序区块的链接。
  • Timestamp:Time of mining (creating the hash for) the block;
  • Block version:用于标识所支持的features和formats(同时在Monero中也用于区分所使用的hash函数)。

以上所有block header内容均被打包hash以形成相应的block ID。这就使得几乎不可能对block header进行修改。而将Merkle root包含进block ID中,进一步保证了几乎不可能对区块中的交易进行修改。

3.1 Merkle tree用于保证区块中交易的不可篡改性

在Bitcoin中,将区块中所有交易的Merkle root包含在block header中,借此保证没有任何交易被篡改过。

如将上述例子中的Data4替换为Data6,则相应的Merkle tree修改为:【相应的Merkle root由aa8d3变为了f8932,由此可知,任何交易数据的变动都将造成Merkle root的修改,使得其不再与block header中所记录的Merkle root匹配。借助block header的链接,这种交易的不可篡改性可传递至整个区块链网络。】
在这里插入图片描述
为何选择Merkle tree方案来 保证交易数据不可篡改呢?似乎:

  • 将所有的交易数据拼接然后hash成一个单独的root hash值,并将该root hash值包含进block header中 也可以满足保证交易数据不可篡改的目标。
    在这里插入图片描述
    在这里插入图片描述

实际上,Merkle tree 相比于 以上拼接hash方案,除了能保证交易的不可篡改性之外,额外的优势为——在hash验证中提供了更多的粒度,使得其可运用某些聪明的技巧来更高效的处理区块链,如:
Bitcoin白皮书中额外提及了将Merkle tree用于:

  • blockchain pruning
  • simplified payment verification (SPV)

除此之外,在Stratum mining pool protocol中也基于Merkle tree进行了巧妙的运用。

3.2 将Merkle tree用于blockchain pruning

随着时间的推移,区块链中的区块越来越多,变得越来越大。
如截止2021年2月,Bitcoin区块链已达380GB。

blockchain pruning 借助 Merkle tree实现了对空间的裁剪——将本地不再需要的交易数据移除。

事实上,我们仍然需要全量数据来进行全面的验证和历史追溯,但是,并不是P2P网络中的所有节点都需要全量数据。
在Bitcoin白皮书中提出可通过运用Merkle tree来prune (remove) 区块中的 spent (used) transactions。

如下图所示,假设Tx1 (Data1)、Tx2 (Data2)、Tx4 (Data4) 为已花费交易,而Tx3 (Data3)和Tx5 (Data5)为未花费交易:
在这里插入图片描述
接下来,针对的是不关注全量数据的非全节点,其仅需要维护可花费交易列表。
中本聪的提议是:
将区块中的已花费交易移除,仅保留需要验证未花费交易相关的Merkle tree branch。可示意为:
在这里插入图片描述
若在此基础上再假设Tx3 (Data3)也为已花费交易:
在这里插入图片描述
则相应的Merkle tree可进一步裁剪为:
在这里插入图片描述
通过以上区块裁剪,可节约:【总共可节约约80%的存储空间】

  • 4 out of 5 个交易的存储空间;
  • 6 out of 9 个Merkle tree node的存储空间。

随着区块越来越长,已花费交易也会越来越多,因此也可节约更多的空间。

实际上,在 Bitcoin StackExchange 中就区块裁剪实际方案有很多深入讨论,尽管Merkle tree裁剪是一个很聪明的办法,但是在Bitcoin的核心软件层面并没有做相应实现,主要基于以下考虑:

  • 需要下载和验证所有区块后,才能进行裁剪操作;
  • 当不需要维护old blocks和old merkle trees时,可以通过裁剪仅维护unspent outputs和相应的scriptPubKeys。裁剪后将无法用于帮助新节点进行区块同步。

实际Bitcoin实现的区块裁剪方案为:
自Bitcoin Core v0.8.0起,将validation database (又名 “chainstate”或“UTXO set”或“account balance sheet”)从区块链上分离了出来。当有新区块时,将对该database进行remove spent inputs和add outputs操作。这就意味着,区块的下载和验证方式仍然保持跟之前一样,但之后它们就不再被用于验证了。区块文件仍然存储在磁盘中以便于其它节点同步时进行发送区块 操作,或者以便于对旧交易进行rescan。
而自Bitcoin Core v0.11.0起,就可能以真正的裁剪模式运行,即区块文件随后会从本地磁盘删除;自v0.12起,可能可支持钱包以裁剪模式运行;自v0.14起,可能可支持手工裁剪(不再由应用程序决定,而可通过RPC命令来实现)。

Bitcoin实际实现是将未花费交易存储在独立的数据库中,以满足快速查找的目的。初次启动时,通过扫描区块链来构建该数据库,后续每当有新的和已花费的交易时,对该数据库进行更新。每当有新的区块在Bitcoin网络中广播时,该数据库将随之持续更新。对于裁剪节点,将仅依赖该数据库就足够了。

对于基本操作,运行裁剪节点就足够了,但是裁剪节点无法完整支持区块链的所有功能,因此实际区块链网络中,仍然需要一些节点来维护全量数据。

3.3 将Merkle tree用于simplified payment verification (SPV)

在Bitcoin白皮书中提及了 simplified payment verification (SPV)
SPV,简单支付验证,是一种不用运行全节点、只需保存所有的区块头,就可以验证支付的技术手段。是一个在轻客户端环境下,就能验证支付有效性的过程。
注意SPV 是支付验证,不是交易验证。SPV 只负责判断用于支付的那笔交易,是否已经被验证过,有多少个确认数。而不是全节点操作的复杂的交易验证。

在SPV中,轻量级区块链客户端仅存储block headers,但也希望验证它在区块链中收到的付款是否为有效交易。由于缺少完整的交易细节,SPV客户端使用Merkle tree 与完整节点协作来有效地验证交易细节。

借助上面的裁剪的例子,SPV client想要验证该区块中的TX5,示意为:
在这里插入图片描述
此时,SPV client节点需向全节点请求the Merkle branches required to build the Merkle root with the TX5 data。By rebuiding the Merkle root (aa8d3) from the transaction of interest (TX5), and the Merkle branches (96b8d) provided by the full node, the SPV client can have confidence in having received a valid transaction。将rebuilt的Merkle root和区块头中存储的Merkle root对比,SPVCclient就可确认the whole tree (and thus TX5) is in fact valid, and is a part of the blockchain。

SPV 可很好的说明Merkle tree是如何使用的。
将 SPV 与 (block) data filtering (Bitcoin use Bloom filters) 结合,可用于:

  • synchronize and verify existence and correctness of selected data in a distributed system。

3.4 将Merkle tree用于矿池 Stratum protocol

传统的加密货币的产生都是通过proof of work (Pow) hashing 挖矿产生的。
矿池是指一种小型矿工联合起来,并根据他们对矿池贡献的算力(hash)获得采矿奖励的方式。
这就需要一个中心实体,即采矿池来协调矿工。它需要一种在所有客户端上有效地分发和跟踪整个挖掘过程的方法。通过一些巧妙的技巧,Stratum protocol 使用Merkle tree来实现这一点。

第一个版本的Stratum 使用Merkle tree来实现挖矿工作的高效分发:

  • Pool server为每个矿工节点提供构建block所需的block header elements——如部分Merkle tree,以及the branches calculated for all other transactions except the Coinbase transaction。【注意Coinbase transaction为一种用于支付挖矿奖励的特殊交易】详细示意如下:【图中的pool data是指矿池地址等。】
    在这里插入图片描述
    上图主要包含3大部分:

  • the Merkle tree template:
    1)由矿池提供给矿工,包含the pre-calculated Merkle branches for the transactions in the block (此处为96b8d,从而大大降低了矿工的带宽和计算需求)。
    2)矿工需要根据server提供的coinbase template构建合适的coinbase transaction,并将该coinbase transaction插入到Merkle tree template中。
    3)若插入的coinbase transaction使得最终的Merkle root hash值(为一个合适小的值)匹配区块链网络的难度级别,则该矿工就为赢家。

  • the Coinbase template:
    1)由矿池提供,由矿工来自主填写相应的nonceextranonce field。

  • the search for the nonce(s)
    1)当将coinbase template插入到Merkle tree template中时,通过尝试不同的nonceextranonce值,直到某个block hash命中网络难度目标时,则成功了。【详细见 Bitcoin block hashing 算法
    2)若矿工为Merkle template找到了满足网络hash难度的nonce值,就可将其提交给矿池。
    在coinbase template中包含了矿池地址,以保证矿池可收到相应的区块奖励,以分发给所有矿工。

总之,此处,将Merkle tree用于分发部分解决方案(预先计算的Merkle tree branches和coinbase template),同时允许不同的分布式节点独立工作,以尝试找到缺少部分的解决方案(coinbase交易的nonce以构建可接受的PoW hash值)。通过将矿池地址嵌入到模板中,可确保所有分布式节点都为共同目标做出贡献,并且可以共享奖励。

4. AWS Dynamo DB中的Merkle tree

Dynamo DB 为亚马逊分布式云数据库。其架构设计见:

在该论文中的第4.7节,提及了使用Merkle tree来高效同步差异节点。
在这里插入图片描述
在这里插入图片描述

5. ZFS分布式文件系统中的Merkle tree

ZFS 为一种分布式文件系统,支持数据spread over multiple volumes。

ZFS借助Merkle tree来保证数据的完整性。

ZFS uses Merkle trees to checksum data, to identify issues where some part of the data written to, or read from, disk is corrupted (or misread etc.)

6. Git Version Control系统中的Merkle tree

Git Version Control系统 中构建了 directed acyclic graph (DAG) 来管理commit:【可将该DAG看成是一种特殊的Merkle tree】
在这里插入图片描述

参考资料

[1] Teemu Kanstrén 2021年2月16日 medium博客 Merkle Trees: Concepts and Use Cases

猜你喜欢

转载自blog.csdn.net/mutourend/article/details/114384264