1. 程式人生 > >區塊鏈 -- Merkle Tree

區塊鏈 -- Merkle Tree

每一個 最終 client 接受 alt cap 根據 gpo ack

我們地球上大部分人應該連它的名字都沒有聽過,而且說實話它也是個比較傳統的概念了。Merkle Tree 是由計算機科學家 Ralph Merkle 在很多年前提出的,並以他本人的名字來命名。不過,Merkle Tree 確實涉及到了很多有意思的實際應用。最近幾年才有的一個例子是,比特幣錢包服務用 Merkle Tree 的機制來作”百分百準備金證明“ ( http://blog.bifubao.com/2014/03/16/proof-of-reserves/ )。不過今天,我們還是從數據的“完整性校驗”這個角度來聊 Merkle Tree。 Git 版本控制系統,ZFS 文件系統以及我們自己下載電影常用的點對點網絡 BT 下載,都是通過 Merkle Tree 來進行完整性校驗的。順便說一句,所謂的完整性校驗,就是檢查一下數據有沒有損壞。

技術分享圖片

先說哈希( Hash )

其實要實現完整性校驗,最簡單的方法就是對要校驗的整個的數據文件做個哈希運算,把得到的哈希值公布在網上,這樣我們把數據下載到手之後,再次運算一下哈希值,如果運算結果相等,就表示我們下載過程中文件沒有任何的損壞。因為哈希的最大特點是,如果你的輸入數據,稍微變了一點點,那麽經過哈希運算,你得到的哈希值將會變得面目全非。這樣做的一個目的是可以防止有人根據哈希值反推出原始輸入數據的一些特征。前面我錄了一期視頻專門關於哈希的,大家可以看看。

技術分享圖片

如果我們從一個穩定的服務器上進行下載,那麽采用單個哈希來進行校驗的形式是可以接受的。

再說哈希列表( Hash List )

但是在點對點網絡中作數據傳輸的時候,我們會從同時從多個機器上下載數據,而且其中很多機器可以認為是不穩定或者是不可信的,這時需要有更加巧妙的做法。實際中,點對點網絡在傳輸數據的時候,其實都是把比較大的一個文件,切成小的數據塊。這樣的好處是,如果有一個小塊數據在傳輸過程中損壞了,那我只要重新下載這一個數據塊就行了,不用重新下載整個文件。當然這就要求每個數據塊都擁有自己的哈希值。BT 下載的時候,在下載真正的數據之前,我們會先下載一個哈希列表的。這時有一個問題就出現了,那麽多的哈希,我們怎麽保證它們本身都是正確地呢?

技術分享圖片

答案是我們需要一個根哈希。把每個小塊的哈希值拼到一起,然後對整個這個長長的字符串再做一次哈希運算,最終的結果就是哈希列表的根哈希。於是,如果我們能夠保證從一個絕對可信的網站,或者從我們的朋友手裏拿到一個正確的根哈希,就可以用它來校驗哈希列表中的每一

個哈希都是正確的,進而可以保證下載的每一個數據塊的正確性了。

技術分享圖片

這種方式挺好,但是實際的應用中,其實還是有著它的不足之處的,這就是為什麽 Merkle 教授要發明 Merkle Tree 了。

最後是 Merkle Tree

先看它的結構。

技術分享圖片

在最底層,和哈希列表一樣,我們把數據分成小的數據塊,有相應地哈希和它對應。但是往上走,並不是直接去運算根哈希,而是把相鄰的兩個哈希合並成一個字符串,然後運算這個字符串的哈希,這樣每兩個哈希就結婚生子,得到了一個”子哈希“。如果最底層的哈希總數是單數,那到最後必然出現一個單身哈希,這種情況就直接對它進行哈希運算,所以也能得到它的子哈希。於是往上推,依然是一樣的方式,可以得到數目更少的新一級哈希,最終必然形成一棵倒掛的樹,到了樹根的這個位置,這一代就剩下一個根哈希了,我們把它叫做 Merkle root.

再說它的優點。

技術分享圖片

相對於 Hash List,Merkle Tree 的明顯的一個好處是可以單獨拿出一個分支來(作為一個小樹)對部分數據進行校驗,這個很多使用場合就帶來了哈希列表所不能比擬的方便和高效。

好,這一期就說這麽多,大家現在概念上有個認識,後面我們會有專門的文章講 Merkle Tree 實用的例子。

參考資料

  • https://www.youtube.com/watch?v=Js535LqapFE#t=238
    給出了 Merkle Tree 相對於 Hash List 的優勢。
  • http://en.wikipedia.org/wiki/Merkle_tree

區塊鏈 -- Merkle Tree