引介 | 準無狀態下的同步實驗



本實驗用到的原始數據和腳本:https://github.com/mandrigin/ethereum-mainnet-resolver-witness-stats

引言

有一種辦法也許能加速初始同步過程(initial sync process,指從創世塊開始的區塊鏈同步),就是使用區塊見證數據(witness)預先建構出緩存樹(cache trie),來避免速度較慢的狀態訪問。這樣做需要額外佔用硬盤空間和網絡帶寬,但也許可以大幅加速同步過程。

其中的原理是,一般來說,要執行一個區塊,我們就需要默克爾樹上的一些數據。雖然在某個塊執行以前,默克爾樹上已經有一些數據了,但這些數據可能不足以執行區塊。所以,正常來說,我們還要從狀態數據庫(state db)中提取出數據並加到默克爾樹上,然後才能驗證交易。這個過程可能會很慢,因爲 硬盤訪問 / 數據庫查詢 的速度比較慢。

根據這個問題描述,我們可以劃分出三種不同的方案:

1)正常流程(也就是當前在以太坊節點中使用的方案)

  1. 在區塊 B 執行以前,我們有狀態樹 T1;
  2. 在需要執行 B 的時候,我們把 T1 中遺漏的數據添加到 T1 上,形成 T1',T1'',等等。每次遇到 T1 上沒有的信息,我們就在數據庫中查找(速度慢)。
  3. 執行完 B 之後,我們有了狀態樹 T2,T2 具備執行 B 所需的所有賬戶狀態。
  4. 保持 T2,以備後續使用。

2)無狀態流程

  1. 在區塊 B 執行以前,我們並沒有狀態樹;不過,我們可以拿到一個見證數據 W,來重組執行這個區塊所需的狀態樹。
  2. 我們執行 W,獲得了狀態樹 T2。
  3. 在 T2 上執行區塊 B,不需要查找數據庫。
  4. 區塊執行完之後就把 T2 丟掉。

3)準無狀態流程(semi-stateless folw)(即本實驗要測試的方案)

  1. 在區塊 B 執行之前,我們有狀態樹 T1,見證數據 W1、W2、……,足以將 T1 轉成 T2
  2. 依次在 T1 上執行 W1、W2、……,最後獲得 T2,也不需要查詢數據庫。
  3. 在 T2 上執行區塊 B,也不需要查詢數據庫。
  4. 留着 T2 以備後續使用。

在初始同步中使用準無狀態流程可以獲得無狀態流程的大部分好處 ,又不需要傳輸那麼多數據,因爲我們重用了狀態樹緩存。 在準無狀態方案中,區塊的並行執行會受到更大的限制那麼,爲了測試準無狀態方案的性能,我們需要測量兩件事:

  • 這一方法需要額外佔用多少 硬盤 / 帶寬?與完全富狀態的方法相比,它真的更好嗎?
  • 其初始同步速度會快多少?

本文中我們會集中測試硬盤需求。

建立實驗

  • 狀態樹(默克爾樹)的最大規模:100 萬個 node。一旦節點數超過這個值,我們就驅逐 LRU 節點,以釋放內存。用這種辦法,我們就能控制狀態樹對內存的使用。

  • 部分見證數據會存儲在數據庫中(我們用的是 boltdb)。每個條目的結構如下:

    key: [12]byte // 區塊號 + 狀態樹上節點的最大數量 value: []byte // 見證數據,按文檔中的描述予以序列化
  • 我們不會在見證數據裏存儲合約代碼(這是我們當前架構的不足)。

數據按下述方法得到(需要一個同步好的 turbo-geth 節點)

                     * 

(in the turbo-geth repository)make state./build/bin/state stateless — chaindata ~/nvme1/mainnet/mainnet/geth/chaindata — statefile semi_stateless.statefile — snapshotInterval 1000000 — snapshotFrom 10000000 — statsfile new_witness.stats.compressed.2.csv — witnessDbFile semi_stateless_witnesses.db — statelessResolver — triesize 1000000 \

實驗結果

**

**

存儲

從創世塊開始同步 6, 169, 246 (619 萬)區塊,見證數據的數據庫(bolt db)達到了 99GB。

見證數據大小的分位數分析

``` *

     python quantile-analysis.py cache_1_000_000/semi_stateless_witnesses.db.stats.1.csv

![引介 | 準無狀態下的同步實驗](https://img.chainnews.com/material/images/e112bcb324148bcb39ebcd7e3414ab8c.jpg)

    平均值     0.038 MB 中值       0.028 MB90 分位值    0.085 MB95 分位值    0.102 MB99 分位值    0.146 MB 最大值       2.350 MB

###**
**

### **數據大小**
```      * 

python absolute_values_plot.py cache_1_000_000/semi_stateless_witnesses.db.stats.1.csv

從創世塊到 610 萬區塊高度的階段的見證數據大小,圖表在 1MB 處截頂了。按 1024 個塊取滑動平均值。引介 | 準無狀態下的同步實驗

正常情況下的數據大小(解決上海攻擊之後的階段)

      * 

absolute_values_plot.py cache_1_000_000/semi_stateless_witnesses.db.stats.1.csv 3000000

解決上海 DDoS 攻擊之後的見證數據大小,按 1024 個區塊取滑動平均值。引介 | 準無狀態下的同步實驗

**

**

放大看 DDoS 攻擊時期的見證數據大小

``` *

     python ddos_zoom.py cache_1_000_000/semi_stateless_witnesses.db.stats.1.csv

放大看 DDoS 攻擊對見證數據大小的影響(原始數據)。![引介 | 準無狀態下的同步實驗](https://img.chainnews.com/material/images/3eca0fd82d0316ed0d441fb6de06da10.jpg) 可以看到,在 230 萬高度到 250 萬高度,以及 265 萬高度到 275 萬高度期間,見證數據的大小顯著增大。  


### **完全無狀態 vs. 準無狀態 下見證數據的大小**
```      * 

python full_vs_semi.py cache_1_000_000/semi_stateless_witnesses.db.stats.1.csv

引介 | 準無狀態下的同步實驗完全無狀態下的見證數據大小是根據準無狀態下的見證數據加上缺失的合約代碼部分調整得來的 . 從這張圖可以看出,使用準無狀態方法,可以節約大量數據(與完全無狀態方法相比)。

結論

加上一個無狀態解析器會讓每個區塊需要 傳輸 / 存儲 的數據量增加 0.4 MB。這個值與按區塊提供見證數據相比,節約太多,即使算上我們改變狀態樹模式能夠得到的增益相比,也節約非常多(關於十六進制樹和二進制樹模式下見證數據大小的區塊,可見我的上一篇文章)(譯者注:中譯本見文末超鏈接)。如果這個性能還算可以,那麼它顯然是加速初始同步的好辦法;而且它的數據需求比完全無狀態方法更小。

    (完)

    (文內有許多超鏈接,可點擊左下 ”閱讀原文“ 從 EthFans 網站上獲取)

    * * *

    **原文鏈接 :**

     https://medium.com/@mandrigin/semi-stateless-initial-sync-experiment-897cc9c330cb

    **作者 :** Igor Mandrigin

    **翻譯 :** 阿劍_本文由原作者授權 EthFans 翻譯及再出版。_

    * * *

    **你可能還喜歡:**

觀點 | 無狀態以太坊: 二進制狀態樹實驗

觀點 | 無狀態客戶端: 以太坊 1.x 的新動向

乾貨 | Eth2.0 的中繼者網絡與手續費機制

來源鏈接:mp.weixin.qq.com