什麼是merkle tree
假設你已經知道了什麼是雜湊演算法以及雜湊是用來幹啥的。
網路傳輸資料的時候,A收到B的傳過來的檔案,需要確認收到的檔案有沒有損壞。如何解決。
有一種方法是B在傳檔案之前先把檔案的hash結果給A,A收到檔案再計算一次雜湊然後和收到的雜湊比較就知道檔案有無損壞。
但是當檔案很大的時候,往往需要把檔案拆分很多的資料區塊各自傳輸,這個時候就需要知道每個資料區塊的雜湊值。怎麼辦呢。
這種情況,可以在下載資料之前先下載一份雜湊列表(hash list),這個列表每一項對應一個資料區塊的雜湊值。對這個hash list拼接後可以計算一個根hash。實際應用中,我們只要確保從一個可信的渠道擷取正確的根hash,就可以確保下載正確的檔案。
似乎很完美了。但是還不夠好。
上面基於hash list的方案這樣一個問題:
有些時候我們擷取(遍曆)所有資料區塊的hash list代價比較大,只能擷取部分節點的雜湊。
有沒有一種方法可以通過部分hash就能校正整個檔案的完整性呢。
答案是肯定的,merkle tree能做到。它長這樣子:
特點如下:
1、資料結構是一個樹,可以是二叉樹,也可以是多叉樹(本BLOG以二叉樹來分析)
2、Merkle Tree的葉子節點的value是資料集合的單中繼資料或者單中繼資料HASH。
3、Merke Tree非葉子節點value是其所有子節點value的HASH值。
很明顯,這種結構跟hash list相比較,根雜湊不是用所有的資料區塊雜湊拼接起來計算的,而是通過一個層級的關係計算出來的。
在上圖中,葉子節點node7的value(v7) = hash(f1),是f1檔案的HASH;而其父親節點node3的value = hash(v7, v8),也就是其子節點node7 node8的值得HASH 其它應用情境 檔案下載
假設我有兩台機器,A和B,有一個檔案從A傳輸到B。B首先擷取可信的檔案merkle tree,當檔案下載完畢後,B通過自己構建的merkle tree根節點和擷取的根節點比較,如果不一致,通過這種二叉樹的結構可以在log(N)的複雜度快速定位到出錯的資料區塊。 副本同步
一個叢集裡的所有機器,需要保持資料的同步,如果資料不一致,需要快速的定位到不一致的節點。
可以在每台機器上針對每個區間裡的資料構造一棵Merkle Tree,這樣,在兩台機器間進行資料比對時,從Merkle Tree的根節點開始進行比對,如果根節點一樣,則表示兩個副本目前是一致的,不再需要任何處理;如果不一樣,則遍曆Merkle Tree,定位到不一致的節點也非常快速 merkle tree應用在區塊鏈上
下面是本文的重點。
比特幣系統的區塊鏈中,每個區塊都有一個merkle tree。
可以看到merkle root雜湊值存在每一個區塊的頭部,通過這個root值串連著區塊體,而區塊體內就是包含著大量的交易。每個交易就相當於前面提到的資料區塊,交易本身有都有自己的雜湊值來唯一標識自己。 什麼是SPV
為了更好的解釋,這裡先插播一個概念,SPV。也就是中本聰描述到的“簡化支付驗證” 正是有了SPV,才讓區塊鏈和比特幣更加廣泛的被傳播。
我們大部分人在電腦安裝的比特幣錢包都是輕量級(非全節點)的,也就是本地並沒有所有的區塊資料(上百G)。理論上來說,要驗證一筆交易,錢包需要遍曆所有的區塊找到和該筆交易相關的所有交易進行逐個驗證才是可靠的。
但是輕量級的錢包沒有完整的資料,如何驗證一筆支付的合法性呢?
merkle tree就起到了關鍵的作用。
當然SPV有它的局限性(這個有空再寫文章細講)。 這裡是分割點
比特幣系統是如何驗證一筆交易的合法性呢。
首先區塊鏈中每個區塊中的merkle tree的根雜湊都是公開可信的。假設現在alice轉賬給bob一個比特幣,比特幣錢包需要確認這筆交易是否被包含在了區塊鏈中。
入上圖所示,
假設我們要判斷HK代表的交易是否存在,只需要產生一個僅有 4 個雜湊值長度的 Merkle 路徑,來證明區塊中存該筆交易。該路徑有 4 個雜湊值(在圖中由藍色標註)HL、HIJ、HMNOP 和 HABCDEFGH。
由這 4 個
雜湊值產生的認證路徑, 再通過計算另外四對雜湊值 HKL、 HIJKL、 HIJKLMNOP
和 Merkle 樹根(在圖中由虛線標註),任何節點都能證明 HK(在圖中由綠色
標註)包含在 Merkle 根中。
具體認證路徑的產生,主要是通過遍曆。有專門的演算法,有興趣的可以自行搜尋相關的論文
參考
[1] http://www.cnblogs.com/fengzhiwu/p/5524324.html
[2] <<精通比特幣>>