Merkle Tree 入门

基础的密码学知识

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

  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。github

在比特币中使用的非对称加密算法是 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 的组成以下:bash

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相等,说明文件有没有被损坏或者没有被恶意劫持。wordpress

多文件

在 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。spa

比特币中的 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/…

相关文章
相关标签/搜索