使用覆蓋層改變以太坊狀態樹的格式

買賣虛擬貨幣
賬戶和合約儲存資料的方式是影響以太坊的眾多問題之一。以太坊協議選用了 Merkle Patricia Tree(MPT,默克爾帕特里夏樹)來組織賬戶及合約資料。儘管這種資料結構在理論上效果很好,但在實際應用中,它帶來的問題卻比它能夠解決的問題多。核心開發者們已經討論多年,想要把這種資料結構換為二叉樹,我將在這篇文章中闡述我對這個問題的看法以及如何實現這種轉變。我所提議的處理方法包括一段時間的過渡期,在這段時間內,網路要同時維護兩種樹結構。這樣做的好處是,轉換樹結構的過程不會影響鏈的執行,並且可以確保所有的賬戶都被轉換成了二進位制格式。背景目前,以太坊的狀態樹是十六叉制的。十六叉製表示每個節點有 16 個孩子節點。理論上講,這種方式挺好的,因為孩子節點多意味著只需要更少的 “層” (即樹高)便可儲存所有資料。

例如,下圖是用十六叉樹表示的鍵值對 (170, v)。十六進位制中,170 記作 0xaa,因此你只需要兩層:第一層記錄第一個 a,第二層記錄第二個 a。

可以看出,上圖的樹很矮,而且很寬。給定相同的鍵值對,下圖展示了二叉樹儲存的情形。170 在二叉樹中被表示為 10101010。

- 圖 2. 與圖 1 相同的鍵值對,儲存在二叉樹中。為了簡潔,不相關的子樹被表示為“...” -
從圖中可見,二叉樹要深得多,也窄得多。以太坊中,每個區塊包含一個 stateRoot 欄位,這是該塊處理完成後表示以太坊全域性狀態的 MPT 的樹根雜湊值。總的來說,這個雜湊值是對根節點的 16 個孩子節點的雜湊值所組成的列表作雜湊運算得到的。這些孩子節點的雜湊值又是孩子的 16 個孩子節點的雜湊值所組成的列表做雜湊運算得到的,以此類推。每次打包交易生成新區塊時,礦工都會更新賬戶樹,重新計算根雜湊。根雜湊儲存在新區塊的 stateRoot 欄位,然後新區塊被共識。

問題在於:如果要對所有節點做雜湊,重新計算根雜湊的時間就太長了,因此,為了計算根節點的雜湊,礦工將從資料庫中檢索 同層節點的兄弟雜湊值(sibling hashes) 。雖然後者(礦工從資料庫檢索兄弟雜湊值)花費的時間沒有前者(礦工從資料庫庫得到所有的葉子節點並做雜湊)那麼多,這個操作還是很耗時。因為每個雜湊都必須從資料庫中取出。

在十六叉樹中,通常每一層你都需要取出 15 個兄弟雜湊值。在上面那個我構造的例子(圖 1)中,(重計算根雜湊)就需要 30 個雜湊值。

儘管二叉樹層次更深一點,但在每一層只需要一個兄弟雜湊值。在上述例子(圖 2)中,僅僅需要 8 個雜湊值!這就是為什麼在實際中二叉樹更優。

覆蓋層轉變方法

不幸的是,轉換為二叉樹並不簡單。需要轉換的資料 太多了,執行轉換花費的時間將多於 15 秒的區塊生成時間 。

除此以外,設想你要翻譯一本 5000 頁的書,作者還在不停地告訴你他們對故事做了些修改,並且這些修改會影響你已經翻譯過的頁 …… 那這個過程就沒完沒了。轉換狀態樹的格式也是一樣的問題:可能你剛完成某個地址的格式轉換,使用者就使用了該地址(因此更新了該地址的狀態),那你又得從頭轉換一遍(因為一個地址的狀態更新也會影響到整棵狀態樹)。

解決這個問題的辦法是增加一個過渡期,過渡期間,在十六叉樹基層上建立一棵覆蓋樹(overlay tree)。這棵覆蓋樹是二叉樹格式的,它的作用是儲存狀態上發生的所有變化,直到基層十六叉樹完全轉換為二叉樹。轉換分為 3 步進行。

第 1 步 —— 轉換

在這種方法下,區塊高度為 h2 時肯定會有 兩個 狀態根:一個是 “基層” 十六叉樹狀態根,一個是 “覆蓋層” 二叉樹狀態根。

十六叉樹被設定為只讀,因此對狀態的任何更新都將在覆蓋樹上進行。

當一筆交易讀取或者更新一個賬戶時,系統首先會搜尋覆蓋樹。如果在覆蓋樹中找不到賬戶,接著將會在舊的十六叉樹中搜尋值。

與此同時,十六叉樹在後臺進行轉換。此時不需要擔心值插入的問題,因為所有的改變都會儲存在上層的覆蓋樹中。

第 2 步 —— 基層樹切換

當後臺轉換過程完成,礦工對外宣告,他們已經準備好用轉換結果(只讀二叉樹根)來替換隻讀的十六進位制基層樹根。對狀態的讀寫與步驟 1 階段是一樣的。(譯者注:此時的只讀二叉基層樹是根據原本的十六進位制狀態樹得到的)

當足夠多的一系列區塊對轉換所得的二叉基層樹根給出了相同的值,意味著大多數礦工都完成了轉換,並且認可轉換後的樹。合併過程則開始。(譯者注:此時的合併是針對只讀二叉基層樹和可讀寫二叉覆蓋樹)

第 3 步 —— 合併兩棵樹

合併過程不斷推進:每產生一個新的區塊,就從覆蓋樹上刪除 n 個鍵,把它們重新插入二叉基層樹。此過程一直持續,直到所有的鍵都從覆蓋樹上移除。到達這步時,區塊頭就不再保留覆蓋狀態樹的樹根。

整個步驟的核心只有一個:如果交易執行時要寫的鍵存在於覆蓋樹上,這個鍵就會從覆蓋樹上刪除,寫操作直接在二叉基層樹上進行。

下一步

為了估計完成轉換所需要的時間,我已經做了一個低轉換率的原型系統。我們確信,整個過程花費的時間不會太離譜,也就是說幾天時間就夠了。我們會隨著演算法的改進而公佈更多細節。

致謝

此提議得益於 Alexey Akhunov、Vitalik Buterin、Anna George、Sina Mahmoodi、Tomasz Stanczak 以及 Martin H. Swende 的寶貴意見。

原文連結:
https://medium.com/@gballet/ethereum-state-tree-format-change-using-an-overlay-e0862d1bf201
作者: Guillaume Ballet
翻譯&校對: 裴奇 & 阿劍

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;