默克爾樹(Merkle Tree)

hickey發表於2022-06-08

Merkle 樹結構

默克爾樹(又叫雜湊樹)是一種典型的二叉樹結構,有一個根節點一組中間節點一組葉節點組成。默克爾樹最早由 Merkle Ralf 在 1980 年提出,曾廣泛用於檔案系統P2P系統中。比如 git區塊鏈IPFS 等。

主要特點:

  • 最下面的葉節點包含儲存資料或其雜湊值;
  • 非葉子節點(包括中間節點和根節點)都是它的兩個孩子節點內容的雜湊值

默克爾樹可以推廣到多叉樹的情形,此時非葉子節點的內容為它所有的孩子節點的內容的雜湊值。

默克爾樹逐層記錄雜湊值的特點,讓它具有了一些獨特的性質。例如,底層資料的任何變動,都會傳遞到其父節點,一層層沿著路徑一直到樹根。這意味著根的值實際上代表了對底層所有資料的“數字摘要”。

應用場景

目前,默克爾樹的典型應用場景包括以下幾種。

證明某個集合中存在或不存在某個元素

透過構建集合的默克爾樹,並提供該元素各級兄弟節點中的 hash 值,可以不暴露集合完整內容而證明某元素存在。

另外,對於可以進行排序的集合,可以將不存在元素的位置用空值代替,以此構建稀疏默克爾樹(Sparse Merkle Tree)。該結構可以證明某個集合中不包括指定元素。

快速比較大量資料

對每組資料排序後構建默克爾樹結構。當兩個默克爾樹根相同時,則意味著所代表的兩組資料必然相同。否則,必然不同。

由於 hash 計算的過程可以十分快速,預處理可以在短時間內完成。利用默克爾樹結構能帶來巨大的比較效能優勢

快速定位修改

以下圖為例,基於資料 D0……D3 構造默克爾樹,如果 D1 中資料被修改,會影響到 N1,N4 和 Root。
Merkle 樹示例
因此,一旦發現某個節點如 Root 的數值發生變化,沿著 Root –> N4 –> N1,最多透過 O(lgN) 時間即可快速定位到實際發生改變的資料塊 D1。

零知識證明

它指的是證明者能夠在不向驗證者提供任何有用的資訊的情況下(沒有洩露資訊),使驗證者相信某個論斷是正確的。

有個很簡單的例子:A 要向 B 證明自己擁有某個房間的鑰匙,假設該房間只能用鑰匙開啟鎖,而其他任何方法都打不開。這時有兩個方法:

  1. A 把鑰匙出示給 B, B 用這把鑰匙開啟該房間的鎖,從而證明 A 擁有該房間的正確鑰匙。
  2. B 確定該房間內有某一物體,A 用自己擁有的鑰匙開啟該房間的門,然後把物體拿出來出示給 B,從而證明自己確實擁有該房間的鑰匙。

後面的第二種方法屬於零知識證明。它的好處在於,整個證明的過程中,B 始終不能看到鑰匙的樣子,從而避免了鑰匙的洩漏。

在默克爾樹中,我們仍舊以上圖為例,如何向他人證明我擁有 D0 這個資料,而不用暴露更多系統的資訊呢?模仿上面的例子,驗證者隨機提供資料 D1D2D3,證明者構造如圖的默克爾樹,並公佈 N1N5Root。驗證者自行計算 Root 值,看是否一致,從而檢驗 D0 是否存在,因為如果存在,N0 一定相同,那麼 N4(N0-N1) 也一定相同、Root(N4-N5)也一定相同。整個過程中驗證著沒有得到任何除了 D0 外的敏感資訊(其他的 D)。

程式碼示例

以下展示部分程式碼,完整程式碼

// Content 代表一個資料塊
type Content interface {
    CalculateHash() ([]byte, error)
    Equals(other Content) (bool, error)
}

// MerkleTree 默克爾樹
type MerkleTree struct {
    Root         *Node            // 根節點
    merkleRoot   []byte           // 根節點的雜湊值
    Leafs        []*Node          // 所有的葉子節點
    hashStrategy func() hash.Hash // 計算雜湊的方法
}

// Node 表示默克爾樹中的葉節點、非葉節點或 Root
type Node struct {
    Tree   *MerkleTree // 所在的 Merkle Tree
    Parent *Node       // 父節點
    Left   *Node       // 左孩子
    Right  *Node       // 右孩子
    leaf   bool        // 是否葉子節點
    dup    bool        // 是否複製節點
    Hash   []byte      // 如果是葉子節點,則為葉子節點資料的雜湊值;如果非葉子節點,則為左右孩子雜湊值組合後的雜湊值
    C      Content     // 葉子節點儲存的資料塊
}

引用:Merkle 樹結構

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章