外匯天眼APP訊 : DeFi 應用中鎖定的資金量已超過 15 億美元;幾乎每天都有新的 dApp 官宣。照這個速度下去,以太坊可能會死於太過成功。就基礎設施層而言,狀態無限增長是一大難題。
幾天之前,Alexey 在 EthResearch 論壇上發佈了一篇文章,提出了一個有趣的設想,並將其命名為 ReGenesis 。
這個設想比較簡單,乍看之下可能會讓人覺得很激進:定期(例如,每 100 萬個區塊)刪除存儲在本地的所有狀態,保留最新區塊的根哈希,然後重新開始構建狀態,再過 100 萬個區塊之後,進行下一次狀態清零。
-ReGenesis :每 N 個區塊重設狀態。隨着狀態增長,需要的證明越少,直到下一個 ReGenesis 啓動-
要想理解這個設想為什麼可行且值得研究,你需要先了解一些背景知識和講解。
這就是本文的主題。
目前情況
1. 狀態存儲集中化
在以太坊上發送交易非常容易,你自己不需要用到什麼狀態數據。交易發送者沒有保存任何狀態的動力。
如果你(礦工或交易所)正在運行一個基礎設施節點,你需要確保自己擁有驗證及廣播交易所需的一切狀態。如果你是礦工,你還需要更多狀態。
因此,當前狀態存儲都集中於大型實體(Infura、大礦工、交易所等)運行的基礎設施節點。
2. 狀態繼續無限增長
截至發稿時(6 月 29 日),Turbo-Geth 客户端中的 “當前狀態” 大約 40 GB ,而且還在繼續增長。
這裏的問題並不在於狀態大小本身,而在於狀態增長不受限制。當然了,我們也可以祈禱固態硬盤容量的增長速度超過區塊鏈狀態。
到目前為止,我們還算幸運,不過單憑運氣絕非長久之計。
3. 無狀態以太坊很難對 Gas 重新定價
對於無狀態以太坊計劃來説,對區塊見證(witness)定價是非常困難的。這些見證是由礦工生成的,交易發送方在發送交易時很難預測區塊見證的大小。
因此,我們需要在不影響現有智能合約的情況下,找到一種能夠通過智能合約行為推測見證價格的方法。
目前已經有了一些提案,如,Oil ,不過這確實是個棘手的問題。
ReGenesis 後如何運行交易
好了,現在我們都知道了,要將所有當前狀態清零,只保留根哈希。數據量從 40 GB 減少到 32 字節。
太棒了,硬盤空間省下了,但是我該如何發送交易呢?
這時,無狀態以太坊就派上了用場。為了能夠運行交易,你需要提供見證。見證包含所用賬户、代碼和合約存儲內容,以及能夠用來驗證根哈希的默克爾證明(點擊此處,瞭解更多關於見證和無狀態以太坊的信息)。
然而,ReGenesis 和 Stateless Ethereum 之間有一個區別。在解釋這個區別之前,我想先介紹兩個術語:顯式狀態(explicit state)和隱式狀態(implicit state)。
假設你在運行一個 geth 節點。無論你的對等節點何時向你發送了新的區塊 N ,該節點都假定你已經擁有了驗證該區塊內所有交易所必需的狀態數據,並且已經同步了區塊 N-1 。
- 現行的以太坊:假設兩個節點擁有一切必需狀態 -
這就是 100% 隱式狀態。對等節點假定你已經擁有了狀態,因此沒有在區塊中添加任何狀態。
在無狀態以太坊中,當你運行一個節點時,對等節點向你發送了一個新的區塊 N,並且認為你在任何情況下都沒有隱式狀態。它們會將你運行區塊 N 所需的一切都打包進區塊 N 。這就是區塊見證(block witness)。
- 無狀態以太坊:我們提供顯式狀態 -
你的對等節點向你發送顯式狀態。
ReGenesis 則位於兩者中間。
假設 ReGenesis 在區塊 10.000.000 啓動。目前,位於區塊鏈頂端的是區塊 10.001.000 。我們可以認為任何 ReGenesis 節點都擁有區塊 10.000.000 和區塊 10.001.000 之間所有數據的隱式狀態。這些區塊中用到的每個賬户、每個存儲條目和每個合約已經存儲在每個節點上,因此不需要區塊見證。這樣就可以大幅削減見證的大小,正如我們在準-無狀態同步實驗中看到的那樣。
- ReGenesis:區塊 1 提供節點 1 所缺少的信息 -
- ReGenesis:將來自區塊 1 的狀態合併到節點 1 的隱式狀態中 -
如果你(作為交易發送方)需要將新的交易發送到當前區塊高度為 10.001.000 的網絡,你需要執行以下步驟:
創建你想要的交易;
查看自上一次 ReGenesis 啓動以來生成的隱式狀態;
為不包含在隱式狀態內的條目創建顯式狀態,將其打包為交易見證(下文會作詳細討論);
將帶有見證的交易發送至網絡;
等一下,這是不是就意味着,交易發送方必須擁有一些 ReGensis 啓動前狀態?!
沒錯。
如果你想在 ReGenesis 啓動後發送交易,你可能需要擁有一些 ReGenesis 啓動前的狀態信息,才能生成見證。
然而,對於大多數 dApp 來説,它們需要存儲實際使用的一小組合約和賬户的狀態(當然還有默克爾證明)。
這種優化就不會太過激進。從好的方面來看,這種做法有助於推動數據存儲的去中心化。
交易見證
你可能已經注意到了,我在上文提到了交易見證這個詞。
交易見證 vs 區塊見證
- 組合式區塊見證 -
我們沒有為整個區塊生成見證(區塊見證),而是為每個交易生成見證。
- 交易見證 -
交易見證包含交易中使用的所有賬户、存儲條目和代碼的顯式狀態,以及用於驗證狀態的默克爾證明。
- 區塊見證是由礦工生成的。我們需要通過複雜的 Gas 定價機制來補償他們 -
交易見證有一個很重要的優點。它們是由交易發送方生成的,與交易一起發送。因此,我們可以立即知道交易見證的大小以及如何為其定價。我們不需要通過 EVM 來重新定價。
- 交易見證是由交易發送方生成的,補償起來容易得多 -
使用交易見證的一個潛在缺陷是數據復 制。假設一個區塊中的所有交易都由兩個相同的賬户達成,交易見證內將包含重複的數據。
另一個缺陷是,使用交易見證的算法更復雜一點。
區塊見證由礦工生成。礦工知道區塊中交易的確切順序,因此區塊見證總是包含最新數據。
交易見證來自交易發送方。因此,應該有一個智能合併機制,將交易見證與區塊中較早的交易所生成的隱式狀態合併起來。
但是,整個 ReGenesis 設想需要用到交易見證,所有這沒什麼大不了的。
為什麼我們現在還無法使用交易見證?
簡單來説,是因為動態狀態訪問(DSA)和惡意參與者搶跑交易的潛在風險。
具體來説,在無狀態以太坊中,你需要提供這個交易的完整狀態,我們假定接收方沒有任何狀態。如果你的交易使用 DSA ,那麼你的代碼讀取哪些存儲部分取決於代碼其他部分的值。
從理論上來説,這就有可能招致 DoS 攻擊。
假設 Alice 的智能合約基於存儲地址 K 讀取狀態條目 A 或 B 。Bob 在 Alice 的交易被執行之前搶先讓自己的交易被執行(這就是 “搶跑交易”),更改 K 值導致 Alice 的交易失敗。
如果 Alice 提供了一個包含 A 的證明,Bob 可以在 Alice 的交易被打包之前更改 K ,導致 Alice 交易失敗。如果 Alice 提供了一個包含 B 的證明,Bob 可以故技重施。
當然了,Alice 可以提供包含 A 和 B 的證明,但是如果存儲地址是由 uint64 決定的,Alice 就要在證明中包含完整的狀態來防止被攻擊,但要包含完整的狀態是根本不可行的。
當然了,這種攻擊是理論層面上的。不過,還有可能出現更多類似的攻擊。鑑於 dApp 持有大量資金,我們需要非常謹慎,不能破壞任何東西。
ReGenesis 是如何緩解這個問題的?
ReGenesis 的確定性可以幫助我們確定節點擁有多少狀態。對於我們確定節點擁有的那些狀態,我們不需要相關證明。
為了緩解這個問題,無論交易是成功還是因狀態不足失敗,我們都要確保我們所提供的證明被包含在狀態中。
我們接着上文的例子來看。
假設 Alice 發送了一筆交易,帶有路徑 A 所需的證明,但是 Bob 更改了 K ,讓 Alice 的合約只能選擇路徑 B 。
雖然 Alice 的交易失敗,但是該交易將路徑 A 所需的一切證明都添加到了節點的隱式狀態中。
現在,Alice 可以重新發送這筆交易,提供路徑 B 所需的證明。Bob 無法再通過更改 K 來阻止 Alice 的交易,即使他通過更改 K 來讓交易選擇路徑 A ,那也太遲了,路徑 A 所需的證明已經包含在了節點的隱式狀態中,因此交易無需任何證明即可發送至節點。如果交易被導向路徑 B ,那麼它正好擁有 B 所需的證明。
結論
最後,讓我們來快速回顧一下 ReGenesis 的設想和要點:
每生成 N 個區塊,我們就會將所有狀態清零,只保留根哈希;
ReGenesis 啓動的頻率不能太高,可以設定為每 100 萬個區塊、每 1000 萬個區塊等;
交易發送者需要提供顯式狀態(作為交易見證);
交易發送者基於交易見證的大小為其支付 gas 費;
為此,交易發送者必須保留其感興趣的 合約/賬户 的 ReGenesis 啓動前狀態;
如果交易因為顯式狀態不足而失敗,我們會將該交易提供的證明添加到隱式狀態中,這樣我們在下一次發送交易時就不需要提供同樣的證明了;
通過智能合併機制將來自交易證明的顯式狀態與區塊中較早運行的交易所生成的隱式狀態合併起來。
從宏觀角度來看,ReGenesis 方案有以下幾個優點:
改變交易發送者和基礎設施節點之間的激勵平衡,從而提高狀態存儲的去中心化程度;
通過 ReGenesis 來限制狀態增長;
允許使用交易見證並簡化每個交易見證的 gas 定價。
當然了,首先,我們還應該對很多東西進行測試、檢驗和證明。我認為這是一個很有趣也很有前景的研究領域,能夠帶來很多潛在好處。