1. 程式人生 > >MPT樹詳解

MPT樹詳解

目錄

@

MPT樹定義

一種經過改良的、融合了默克爾樹和字首樹兩種樹結構優點的資料結構,以太坊中,MPT是一個非常重要的資料結構,在以太坊中,帳戶的交易資訊、狀態以及相應的狀態變更,還有相關的交易資訊等都使用MPT來進行管理,其是整個資料儲存的重要一環。交易樹,收據樹,狀態樹都是採用的MPT結構。

ps:

  1. 交易樹:記錄交易的狀態和變化。每個塊都有各自的交易樹,且不可更改 
  2. 收據樹(交易收據):交易收據的儲存
  3. 狀態樹(賬戶資訊):帳戶中各種狀態的儲存。如餘額等。
  4. Storage Trie 儲存樹 :儲存只能合約狀態 ,每個賬號有自己的Storage Trie 。

回想我們我們上一次所講的RLP:
在網路節點的本地以trie樹的形式儲存,傳送給客戶端的時候序列化成列表。這不就是RLP的作用嘛,用來對trie樹種所有的條目進行編碼
這個樹,在以太坊,指的就MPT樹

MPT樹的作用是什麼?

  1. 儲存任意長度的key-value鍵值對資料;
  2. 提供了一種快速計算所維護資料集雜湊標識的機制;
  3. 提供了快速狀態回滾的機制;
  4. 提供了一種稱為默克爾證明的證明方法,進行輕節點的擴充套件,實現簡單支付驗證;

字首樹與默克爾樹

字首樹

字首樹(又稱字典樹),用於儲存關聯陣列,其鍵(key)的內容通常為字串。字首樹節點在樹中的位置是由其鍵的內容所決定的,即字首樹的key值被編碼在根節點到該節點的路徑中。


如下圖所示,圖中共有6個葉子節點,其key的值分別為(1)to(2)tea(3)ted(4)ten(5)A(6)inn。

默克爾樹

merkle樹是自底向上構建的。在下圖的例子中,首先將L1-L4四個單元資料雜湊化,然後將雜湊值儲存至相應的葉子節點。

將相鄰兩個節點的雜湊值合併成一個字串,然後計算這個字串的雜湊,得到的就是這兩個節點的父節點的雜湊值。

重要結論:
若兩棵樹的根雜湊一致,則這兩棵樹的結構、節點的內容必然相同。

分析:

在p2p網路下載網路之前,先從可信的源獲得檔案的Merkle Tree樹根。一旦獲得了樹根,就可以從其他從不可信的源獲取Merkle tree。通過可信的樹根來檢查接受到的MerkleTree。如果Merkle Tree是損壞的或者虛假的,就從其他源獲得另一個Merkle Tree,直到獲得一個與可信樹根匹配的MerkleTree。

三種節點型別

知道了Merkle Tree,知道了Patricia Tree,MPT(Merkle Patricia Tree)就是這兩者混合後的產物。下面我們介紹一下MPT樹的三種節點型別

  • 分支結點(branch node):包含16個分支,以及1個value
  • 擴充套件結點(extension node):只有1個子結點
  • 葉子結點(leaf node):沒有子結點,包含一個value

    需要注意的是:Key-value 這裡的value儲存的是key,key儲存在路徑上
    詳細解釋:

    葉子節點,表示為[key,value]的一個鍵值對,其中key是key的一種特殊十六進位制編碼。
    擴充套件節點,也是[key,value]的一個鍵值對,但是這裡的value是其他節點的hash值,這個hash可以被用來查詢資料庫中的節點。也就是說通過hash連結到其他節點。
    分支節點,因為MPT樹中的key被編碼成一種特殊的16進位制的表示,再加上最後的value,所以分支節點是一個長度為17的list,前16個元素對應著key中的16個可能的十六進位制字元,如果有一個[key,value]對在這個分支節點終止,最後一個元素代表一個值,即分支節點既可以搜尋路徑的終止也可以是路徑的中間節點。
    葉子節點和擴充套件節點是新增加的!(對比於前綴樹來說)

MPT中的Merkle

即指向下一級節點的指標是使用 節點的確定性加密hash,而不是傳統意義上下一級節點地址的指標

如果給定的trie的根雜湊是公開的,則任何人都可以 通過給出給定path上的所有節點, 來證明在給定path上存在一個給定值 ,對於攻擊者,不可能提供一個不存在的(key,value)對的證明, 因為根雜湊最終基於它下面的所有雜湊,所以任何修改都會改變根雜湊。

HP編碼

HP-編碼:特殊的十六進位制字首編碼

引入:對nibble和節點奇偶性進行編碼

Nibble是什麼?
引進一種特殊的終止符標識來標識key所對應的是值是真實的值,還是其他節點的hash。如果終止符標記被開啟,那麼key對應的是葉節點,對應的值是真實的value。如果終止符標記被關閉,那麼值就是用於在資料塊中查詢對應的節點的hash。
為什麼需要對節點奇偶性進行編碼?
資料最小的表示單位為一位16進位制,如1、a等,但在程式設計實現中,資料的最小表示單位往往是byte(8bit,2位16進位制數),這樣在用byte來表示一串奇數長度的16進位制串時會出現問題。
例如"5b3"和"5b30",直接轉成byte都是5b30。

舉例:
對"0x5b3ed"編碼(奇數位)
"0x5b3ed" = "0005 1011 0003 1110 1101" t=0 時, "0001"+"0005 1011 0003 1110 1101"->"00010005 10110003 11101101"->"0x15b3ed"
t !=0時 "0011"+"0005 1011 0003 1110 1101"->"00110005 10110003 11101101"->"0x35b3ed“

對"0x5b3e"編碼(偶數位)
"0x5b3e" = "0005 1011 0003 1110" t=0 時, "0000"+"0005 1011 0003 1110 1101"->"00000005 10110003 11101101"->"0x005b3e"
t !=0時 "0010"+"0005 1011 0003 1110 1101"->"00100005 10110003 11101101"->"0x205b3e"

這裡的t就是是否結束的標誌位
最低位表示奇偶性,第二低位編碼終止符狀態。
最低位為0的時候表示偶數位置,反之奇數。
第二低位為1的時候表示結束,反之不結束。

官方表示形式

這裡的prefix就是HP編碼!對終止符的狀態和奇偶性進行編碼。最低位表示奇偶性,第二低位編碼終止符狀態。
總共有2個擴充套件節點,2個分支節點,4個葉子節點。 右邊是葉子節點的情況,左邊代表的是節點的prefix(HP編碼)
這就是一個狀態樹的儲存形式,其實他應當長的樣子,我們可以細細想一下,他的key被編碼成一種特殊的16進位制的表示,value是一些rlp後的資料,而且比上圖要大的多的多。

相關MPT樹

現在,我們來回看一下,狀態、儲存以及交易樹使用的MPT樹。
首先說,全域性狀態樹,這個全域性狀態樹包含了以太坊網路中每一個賬戶的一組鍵值對。
對全域性狀態樹的幾點說明:

  1. 狀態字首樹包含了以太坊網路中每一個賬戶的一組鍵值對。
  2. 他的Key是一個 160 位的識別符號(以太坊賬戶的地址)。
  3. 全域性狀態樹中的 “值” 是通過編碼以太坊賬戶中的如下細節來得到的(使用RLP的方法):
  • nonce 值
  • 餘額
  • 儲存字首樹根節點雜湊
  • 程式碼雜湊
    我們可以從下圖很清晰的瞭解:

儲存樹是智慧合約資料儲存的位置,每一個以太坊賬戶都有自己的儲存樹。
本圖接上圖;

參考目錄

[1]. 深入淺出以太坊MPT(Merkle Patricia Tree)
[2]. 以太坊學習(2)MPT樹--白話版
[3]. Merkle Patricia Tree 梅克爾帕特里夏樹(MPT)規範
[4]. merkle樹、Trie樹、MPT樹、以太坊中的那些樹