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/…

相關文章
相關標籤/搜索