区块链中的数据结构之 Merkle Tree

基础的密码学知识

在阅读本文之前,建议大家可以先 Google 了解一下非对称加密算法和 Hash 算法,这里就不详细介绍了。下面我们只描述一下非对称加密传输信息的一个大致流程:

  1. Sender(发送者) 首先用相关的 hash 算法对要发送的 message(信息) 进行 hash 生成 digest (数字摘要),然后用 private key(私钥) 对 digest 加密生成 digital signature(数字签名)。
  2. Recevier(接受者) 会收到 message 和 digital signature 以及 public key(在区块链中 public key 是公开,类似于 https 则会引入一个第三方权威中心化机构 CA 来颁发确认 public key 避免中间人攻击)。用 public key 对 digital signature 解密生成 digest,然后用 hash 算法对 message 生成 digest,如果生成的 digest 一致的,则证明 message 是 public key 所有者发送的并且 origin message 没有被修改。

在比特中使用的 hash 算法是 SHA(Secure Hash Algorithm),其摘要长度为 256 bits,即 32个 字节,故称 SHA256,对于一个区块都会对其区块头(header)进行 double sha256。

在比特币中使用的非对称加密算法是 ECDSA, 椭圆曲线数字签名算法的原理这里就不介绍了。

区块的组成

一个区块是由区块头和区块体组成。区块体则是所有 transaction 的集合,区块头由五个部分组成,这篇我们重点来看一下 merkle root。剩下的几个元素以后在单独写一篇 mining 相关的文章描述。

  1. 上一个区块头的 Hash,previous hash。由上个区块的 block header 进行 double sha256 生成。32 bytes。
  2. 时间戳,timestamp。4 bytes。
  3. 挖矿难度值 target。4 bytes。
  4. 工作量证明随机数,nonce。Miner 通过 nonce 达到某一个 target,达到这个 target 的 diffculty 随着时间的推移会越来越大。
  5. merkle root,merkle root 可以简单理解为 transaction set 的一个唯一 hash 标识。32 bytes。
  6. version。4 bytes。

一个 block header 的组成如下:

02000000 ........................... Block version: 2

b6ff0b1b1680a2862a30ca44d346d9e8
910d334beb48ca0c0000000000000000 ... Hash of previous block's header
9d10aa52ee949386ca9385695f04ede2
70dda20810decd12bc9b048aaab31471 ... Merkle root

24d95a54 ........................... Unix time: 1415239972
30c31b18 ........................... Target: 0x1bc330 * 256**(0x18-3)
fe9f0864 ........................... Nonce
复制代码

比特币的 SPV(Simplified Payment Verification 简单支付验证) 机制,保证了每次只需要下载区块头(80 bytes),而不需要加载整个区块。平均每个 transaction 至少是 250 bytes,而且平均每个区块包含 2000 个transaction。因此,包含完整交易的区块比区块头的 4k 倍还要大。

BitTorrent 下载中的 Hash List

单文件

当我们去下载一个文件的时候,下载链接后面提供了一个MD5(MD5也是一种Hash算法),这样我们可以在下载之后对文件计算MD5,如果MD5与提供的MD5相等,说明文件有没有被损坏或者没有被恶意劫持。

多文件

在 p2p,比如我们下载一个 BT 种子的时候,如果这个文件比较大比如下载一步电影,这个大电影文件会被分成多个小的 data block (数据块)。这些小的 data block 会从多个不同的机器下载,如何保证从其他机器下载的 data block 没有被修改呢?

开始下载之前,我们会先下载一个 hash list(哈希列表),如果有一个 data block 损坏了,只需要重新下载这个 data block 就行了。如下图所示,把 hash list 中的各个 hash 值拼接成一个长的字符串,在对这个长字符串做一次 hash,得到 top hash(根哈希)。把这个 top hash 和 origin top hash 来判断有没有数据块缺失以及是否有数据库被篡改。

事实上 hash list 可以看做是一课树高为 merkle tree,top hash 就是 blockchain 中一个节点的 merkle root。

比特币中的 Merkle Tree

如上图所示,Lx 可以是做是 blockchain 中的一笔 transaction。

在比特币中确认一个 transaction 是否合法有五个步骤:

  1. 从网络中获取并保存最长链的所有区块头信息。
  2. 根据 block header 验证这个 transaction 所在的区块是否在上面的最长链中。block header 在 Merkle block 中获取。
  3. 从 Merkle block 中的 Merkle 路径获得所需要验证的 hash。
  4. 根据这些 hash 值计算出一个 Merkle Root。如果计算出 Merkle Root 值和区块头中的 Merkle Root 是否相等。

p.s: 一个 SPV 节点想知道它钱包中某个比特币地址即将到达的支付。该节点会在节点间的通信链接上建立起 bloom filter,限制只接受含有目标比特币地址的交易。当对等体探测到某交易符合 bloom filter,它将以 Merkleblock 消息的形式发送该区块。Merkleblock 消息包含区块头和一条连接目标交易与 Merkle 根的 Merkle 路径。

我们重点来看一下上面的步骤三。

如上图所示我们相验证交易 K 是否合法即是否包含在区块中。Merkleblock 中返回的 Merkle 路径会包含 H(L),H(IJ),H(MNOP),H(ABCDEFGH),根据这五个 hash 值就可以确定一个 Merkle Root,和使用 hash list 相比,不需要将所有小 hash 做一次 hash,也就是只需要得到 Merkle 路径下面的四个路径加上这个 transaction 本身的 hash 就可以了不需要得到所有 transaction 的 action。在实际应用场景,当一个区块中交易数非常多的时候,验证速度非常快,是呈对数增长的。

Merkleblock

第一次看这部分的时候,当时有两个比较困惑的问题,这里列一下,如果能回答出了这两个问题,对于 Bitcoin 的 merkle tree 的 spv 验证的基本原理就差不多了。

  1. spv 知道 transaction 的 address,但是如何知道 transaction 在哪个 block 里面?
  2. 知道了 transaction 对应的 block header,如何拿到的 Merkle Path,也就是 H(L),H(IJ),H(MNOP),H(ABCDEFGH)?

SPV 本身没有 block 信息,都是从全节点拿到的。其中的 getdata 请求中如果指定了 inventory type 为 MSG_MERKLEBLOCK,全节点就会在响应中回复一个 MerkleBlock

SPV 解析 MerkleBlock 的过程如下:

以太坊中的 Merkle Tree

以太坊使用的是 Merkle Patricia Tree,和比特币有很大不同要复杂一些,这个准备下一篇文章在详细介绍。总的来说比特币中交易是无状态,比如我们要查一个账户的余额是无法直接实现的,我们平时看到的 balance 都是比特币相关的 wallet client 自己实现生成计算的。在区块链中交易是有状态的,不仅仅是有一棵 Merkle Tree,有三棵 Merkle Tree:

  1. Transaction Tree。
  2. Receipt Tree。展示每一笔交易影响的数据条。
  3. State Tree。

See Also

TODO: Git 和 IPFS 中对于 Merkle Tree 的应用。

bitcoin.org/en/develope…

blog.ethereum.org/2015/11/15/…

github.com/ethereum/wi…

easythereentropy.wordpress.com/2014/06/04/…

Last: 最近在 GitHub 上整理学习 BlockChain 相关的笔记,欢迎关注交流~

猜你喜欢

转载自juejin.im/post/5b7973a7e51d4538e1604b4a
今日推荐