比特幣區塊結構Merkle樹及簡單支付驗證分析

Tiny熊發表於2017-11-17

最新內容會更新在主站深入淺出區塊鏈社群
原文連結:比特幣區塊結構Merkle樹及簡單支付驗證分析

在比特幣網路中,不是每個節點都有能力儲存完整的區塊鏈資料,受限於儲存空間的的限制,很多節點是以SPV(Simplified Payment Verification簡單支付驗證)錢包接入比特幣網路,通過簡單支付驗證可以在不必儲存完整區塊鏈下對交易進行驗證,本文將分析區塊結構Merkle樹及如何進行交易驗證。

區塊結構

工作量證明中出現過一個區塊資訊截圖:
區塊#493050

細心的同學一定已經在裡面發現了很多未講的其他資訊,如:時間戳,版本號,交易次數,二進位制雜湊樹根(Merkle根)等。

我們來看看一個區塊結構到底是怎樣的:

區塊結構圖

如上圖(下文稱:區塊結構圖)所示:每個資料區塊包含區塊頭和區塊體。
區塊頭封裝了當前版本號、前一區塊雜湊值、當前區塊PoW要求的隨機數(Nonce)、時間戳、以及Merkle根資訊。
區塊體則包括當前區塊經過驗證的、 區塊建立過程中生成的所有交易記錄。這些記錄通過 Merkle樹的雜湊過程生成唯一的Merkle根並記入區塊頭.

區塊雜湊值實際上並不包含在區塊的資料結構裡,其實區塊打包時只有區塊頭被用於計算雜湊(從網路被接收時由每個節點計算出來),常說的區塊雜湊值實際是區塊頭雜湊值,它可以用來唯一、明確地標識一個區塊。

區塊頭是80位元組,而平均每個交易至少是250位元組,而且平均每個區塊包含2000個交易。因此,包含完整交易的區塊比區塊頭的4千倍還要大。
SPV節點只下載區塊頭,不下載包含在每個區塊中的交易資訊。這樣的不含交易資訊的區塊鏈,大小隻有完整區塊鏈的幾千分之1,那SPV節點是如何驗證交易的呢?

雜湊驗證

上面先留一個引子,先來回顧下雜湊函式,記賬原理我們知道原始資訊任何微小的變化都會雜湊完全不同的雜湊值。

簡單檔案驗證

我們通常用雜湊來檢驗下載的檔案是否完整,我經常看到這樣的下載頁面:
下載hash
可以看到下載連結後面提供了一個MD5(MD5也是一種Hash演算法),這樣我們可以在下載之後對檔案計算MD5,如果MD5與提供的MD5相等,說明檔案有沒有被損壞,這個驗證過程相信大家都能理解。

多點檔案驗證(雜湊列表)

現在複雜度提高一點,在P2P網路中下載時,會把大檔案切成小檔案,同時從多個機器上下載資料,這個時候怎麼驗證資料呢?

以BT下載為例,在下載真正的資料之前,我們會先下載一個雜湊列表的(每個下小塊計算出一個雜湊),如果有一個小塊資料在傳輸過程中損壞了,那我只要重新下載這一個資料塊就行了,這時有一個問題就出現了,那麼多的雜湊,怎麼保證它們本身(雜湊列表中的雜湊值)都是正確地呢?

答案是把每個小塊資料的雜湊值拼到一起,然後對這個長字串在作一次雜湊運算,得到雜湊列表的根雜湊。只要根雜湊校對比一樣就說明驗雜湊列表是正確的,再通過雜湊列表校驗小資料塊,如果所有的小資料塊驗證通過則說明大檔案沒有被損壞。

Merkle樹

驗證交易的過程和檔案驗證很相似,可以人為每個交易是一個小資料塊,但比特幣使用Merkle樹的方式進行驗證,相對於雜湊列表,Merkle樹是一種雜湊二叉樹,它的明顯的一個好處是可以單獨拿出一個分支來(作為一個小樹)對部分資料進行校驗,更加高效。

我們回看下上面的區塊結構圖,區塊體就包含這樣一個Merkle樹,Merkle樹被用來歸納一個區塊中的所有交易。

每個葉子節點是每個交易資訊的雜湊,往上對相鄰的兩個雜湊合併成字串再雜湊,繼續類似的操作直到只剩下頂部的一個節點,即Merkle根,存入區塊頭。

因為Merkle樹是二叉樹,所以它需要偶數個葉子節點。如果僅有奇數個交易需要歸納,那最後的交易就會被複制一份以構成偶數個葉子節點,這種偶數個葉子節點的樹也被稱為平衡樹。

簡化支付驗證

SPV節點不儲存所有交易也不會下載整個區塊,僅僅儲存區塊頭,我們來看看它是如何對交易資料進行驗證的。

假如要驗證區塊結構圖中交易6,SPV節點會通過向相鄰節點索要(通過Merkleblock訊息)包括從交易6雜湊值沿Merkle樹上溯至區塊頭根雜湊處的雜湊序列 (即雜湊節點6, 5, 56, 78, 5678, 1234 1~8 - 稱為認證路徑) 來確認交易的存在性和正確性。(在N個交易組成的區塊中確認任一交易只需要計算log2(N)個位元組的雜湊值,非常快速高效)

大家明白了嗎?

深入淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術部落格

相關文章