Merkle Tree演算法
Merkle Tree 是由電腦科學家 Ralph Merkle 在很多年前提出的,並以他本人的名字來命名。不過,Merkle Tree 確實涉及到了很多有意思的實際應用,如比特幣錢包服務用 Merkle Tree 的機制來作”百分百準備金證明“ (http://blog.csdn.net/lucky_greenegg/article/details/51155252), Git 版本控制系統,ZFS 檔案系統以及點對點網路 BT 下載,都是通過 Merkle Tree 來進行完整性校驗,就是檢查一下資料有沒有損壞。
完整性校驗
其實要實現完整性校驗,最簡單的方法就是對要校驗的整個的資料檔案做個雜湊運算。現在網上最流行的檔案校驗方式是計算機MD5和SHA1,微軟釋出Windows作業系統或其它軟體,現在都採用CRC32結合SHA1的方式,幾乎百分之一百不會發生碰撞。
但從理論角度,CRC不能完全可靠的驗證資料完整性,因為CRC多項式是線性結構,很容易通過改變資料方式達到CRC碰撞,假設一串帶有CRC校驗的程式碼在傳輸中,如果連續出現差錯,當出錯次數達到一定次數時,那麼幾乎可以肯定會出現一次碰撞(值不對但CRC結果正確)。
資料分塊
在點對點網路中作資料傳輸的時候,我們會從同時從多個機器上下載資料,而且其中很多機器可以認為是不穩定或者是不可信的,這時需要有更加巧妙的做法。實際中,點對點網路在傳輸資料的時候,其實都是把比較大的一個檔案,切成小的資料塊。
下載者要下載檔案內容,需要先得到相應的.torrent檔案,然後使用BT客戶端軟體進行下載。載時,BT客戶端首先解析.torrent檔案得到Tracker地址,然後連線Tracker伺服器。Tracker伺服器迴應下載者的請求,提供下載者其他下載者(包括髮布者)的IP。下載者再連線其他下載者,根據.torrent檔案,兩者分別告知對方自己已經有的塊,然後交換對方沒有的資料。此時不需要其他伺服器參與,分散了單個線路上的資料流量,因此減輕了伺服器負擔。下載者每得到一個塊,需要算出下載塊的Hash驗證碼與.torrent檔案中的對比,如果一樣則說明塊正確,不一樣則需要重新下載這個塊。這種規定是為了解決下載內容準確性的問題。
一般的HTTP/FTP下載,釋出檔案僅在某個或某幾個伺服器,下載的人太多,伺服器的頻寬很易不勝負荷,變得很慢。而BitTorrent協議下載的特點是,下載的人越多,提供的頻寬也越多,種子也會越來越多,下載速度就越快
這樣的好處是,如果有一個小塊資料在傳輸過程中損壞了,那我只要重新下載這一個資料塊就行了,不用重新下載整個檔案。當然這就要求每個資料塊都擁有自己的雜湊值。BT 下載的時候,在下載真正的資料之前,我們會先下載一個雜湊列表的。這時有一個問題就出現了,那麼多的雜湊,我們怎麼保證它們本身都是正確地呢?答案是我們需要一個根雜湊。把每個小塊的雜湊值拼到一起,然後對整個這個長長的字串再做一次雜湊運算,最終的結果就是雜湊列表的根雜湊。於是,如果我們能夠從伺服器得到一個正確的根雜湊(Torrent檔案),就可以用它來校驗雜湊列表中的每一個雜湊都是正確的,進而可以保證下載的每一個數據塊的正確性了,這裡就要用到Merkle Tree演算法。
Merkle Tree
先看它的結構。
在最底層,和雜湊列表一樣,我們把資料分成小的資料塊,有相應地雜湊和它對應。但是往上走,並不是直接去運算根雜湊,而是把相鄰的兩個雜湊合併成一個字串,然後運算這個字串的雜湊,這樣每兩個雜湊就結婚生子,得到了一個”子雜湊“。如果最底層的雜湊總數是單數,那到最後必然出現一個單身雜湊,這種情況就直接對它進行雜湊運算,所以也能得到它的子雜湊。於是往上推,依然是一樣的方式,可以得到數目更少的新一級雜湊,最終必然形成一棵倒掛的樹,到了樹根的這個位置,這一代就剩下一個根雜湊了,我們把它叫做 Merkle root.
相對於 Hash List,Merkle Tree 的明顯的一個好處是可以單獨拿出一個分支來(作為一個小樹)對部分資料進行校驗,這個很多使用場合就帶來了雜湊列表所不能比擬的方便和高效。
如上圖所示,葉子節點node7的value = hash(f1),是f1檔案的HASH;而其父親節點node3的value = hash(v7, v8),也就是其子節點node7 node8的值得HASH。就是這樣表示一個層級運算關係。root節點的value其實是所有葉子節點的value的唯一特徵。
假如A上的檔案5與B上的不一樣。我們怎麼通過兩個機器的merkle treee資訊找到不相同的檔案? 這個比較檢索過程如下:
1、首先比較v0是否相同,如果不同,檢索其孩子node1和node2.
2、v1 相同,v2不同。檢索node2的孩子node5 node6;
3、v5不同,v6相同,檢索比較node5的孩子node 11 和node 12
4、v11不同,v12相同。node 11為葉子節點,獲取其目錄資訊。
5、檢索比較完畢。
以上過程的理論複雜度是Log(N)。實際過程是大於這個複雜度的,因為不同value的節點需要每個子節點進行比較。