第四章 實驗結果
第一節 Jellyfish Merkle tree 實驗結果
第一段 資料結構詳述
Jellyfish Merkle tree 用於在 Libra 中儲存帳本狀態,由 Libra 團隊所研發的的 一種稀疏默克爾樹,理論上最多可以有2256個葉子節點。
Jellyfish Merkle tree 是一種改良過的稀疏默克爾樹(Sparse Merkle tree),其特 點在於任何沒有值的葉子節點在根節點到該葉子節點之間的節點都將被省略,以 節省儲存空間。
圖 4 稀疏默克爾樹計算雜湊範例
上圖說明此改良過的稀疏默克樹,該子樹僅A、B、C 三個位置有值,那麼其 他不存在值的地方都會被省略。此方法不僅減少儲存空間,間接地也減少取雜湊 的次數,上圖狀況的Root hash = Hash(a, Hash(b, c)),僅需取 2 次雜湊值,若是原 本左邊的方式需要取15 次雜湊值。
13
Jellyfish Merkle tree 有兩種節點,分別是內部節點(Internal node)和葉子節點 (Leaf node),內部節點最可以包含 16 個子樹,葉子節點則是儲存帳戶地址和 hash(blob),其中 blob 指的是該個帳戶的資訊,如餘額、交易次數等等。
第二段 操作流程
本段將說明本論文以程式去實作Jellyfish Merkle tree 方法,第一先說明如何 在程式中實現該架構,接著說主要的操作流程。
首先介紹儲存的架構,上段有提到Jellyfish Merkle tree 主要以兩種節點組成:
內部節點與葉子節點,如下圖所示,內部節點會紀錄哪個子節點下有子樹存在,
並記錄該子樹的根雜湊,葉子節點則是紀錄帳戶資訊。另外這兩種節點都會儲存 現在節點的路徑(Path),用於當作定位方式。
圖 5 Jellyfish Merkle tree 節點類型
這個路徑指的是從最上層的內部節點,也就是根節點(Root node)一直到目前 這個節點的路徑,其中根節點的路徑為空(Empty),也就是根節點中儲存路徑的位 置所儲存的會是一個空值,為根節點的特徵。
接下來說明主要的操作流程,主要有以下幾個:(1)在空樹中創建葉子節點、
(2)探索葉子節點、(3)新創共同節點、(4)更新葉子節點和(5)計算雜湊值,以下將一 一介紹。
14
(1) 在空樹中創建葉子節點
所有的操作流程都必須從根節點開始操作,因此不管是什麼操作,首先都確 認是否有根節點,若不存在根節點則必須先創建一個根節點,前面提到根節點也 是一個內部節點,只是他的路徑欄位將永遠是空的。
圖 6 Jellyfish Merkle tree 根節點
(2) 探索一個葉子節點
接下來根據輸入的帳戶地址來從跟節點開始來探索葉子節點,會從帳戶的第 一個字元開始探索,假設今天輸入的帳戶地址是 0xa171355,則第一個被探索的 將會是”a”,目前探索到的節點為上圖的 Node 1,”a”的位置是空的,表示該子樹 下沒有任何的值,因此必須在該位置上新增一個葉子節點(Leaf node)。
圖 7 Jellyfish Merkle tree 根節點下附帶一個葉子節點
15
現在已經新增完成了,當我們再一次去探索0xa171355 這個帳戶地址時,一 樣從根節點Node1 開始,並取從帳戶的第一個字元”a”開始探索,發現 Node1 在”a”
這個位子是有子節點的,就將目前節點位置移到Node2,發現 Node2 是一個葉子 節點,便比較該葉子節點的帳戶地址與目前在探索的帳戶地址是否相同,發現相 同,則表示探索到該帳戶所代表的葉子節點。
(3) 新創共同路徑
接續前一個段落,若假設今天要探索的帳 戶地址不是 0xa171355 而是 0xaf79365,比較完 Node2 的帳戶地址會發現不相同,於是將目前的 Node2 放置 到暫存區,並取出兩個帳戶地址共同的前綴路徑,共同的路徑為”a”,於是在前這 個位置在新增和共同路徑長度相同的內部節點,共同路徑長度為 1,所以僅需再 創造一個新的內部節點,並將其的路徑設置為”a”,如下圖所示。
圖 8 Jellyfish Merkle tree 根節點下附帶一個內部節點
將暫存區中的Node2 取出,再從目前探索到的點再向下探索,目前探索到的 路徑是”a”,探索到的節點則是剛剛新增的內部節點 Node3,Node2 的帳戶地址在
16
去除共同路徑後的下個字元為”1”,目前 Node3 的”1”這個位置是空的,便直接將 Node2 放置於此,將路徑修改為帳戶地址與共同路徑比對後再多放置一個字元,
即將Node2 的路徑修改為”a1”,結果如下圖。
圖 9 Jellyfish Merkle tree 根節點下附帶一個內部節點與一個葉子節點
目前探索的帳戶地址在去除共同路徑後的下個字元為f,目前 Node3 的”f”這 個位置也是空的,於是在該位置上新增一個葉子節點(Leaf node),將該節點的路 徑設定為”af”,結果如下圖。
圖 10 Jellyfish Merkle tree 根節點下附帶一個內部節點與一個葉子節點
17
(4) 更新葉子節點
更新葉子節點的方式只需先探索到該個葉子節點後,直接修改該葉子節點的 blob 為新的值即可。
(5) 計算雜湊值
每個內部節點看似都是一個有 1 層 16 個子節點的節點,但在計算該內部節 點的雜湊值時,是將其模擬成有個4 層的 2 元樹來做計算,這棵 4 層的 2 元樹的 根雜湊(Root hash)就是該個內部節點的雜湊值,如下圖所示。
圖 11 Jellyfish Merkle tree 內部節點展計算雜湊值範例 1
但他依然保有稀疏默克爾樹的特性,只要該子節點沒有值就會被省略,因此 最後在計算這個內部節點(Internal node)的雜湊時,只需計算 hash(4,hash(8,b))
圖 12 Jellyfish Merkle tree 內部節點展計算雜湊值範例 2
18