通過創造新的狀態形式來實現狀態的超大規模擴展

本文為機器翻譯
展示原文

特別感謝 Guillaume Ballet、Marius van der Wijden、Jialei Rong、CPerezz、Han、soispoke、Justin Drake、Maria Silva 和 Anders Elowsson 的反饋和審閱。

為了在未來五年內擴展以太坊,我們需要擴展三種資源:執行(EVM 計算、簽名驗證等)、數據(交易發送方、接收方、簽名、調用數據等)和狀態(賬戶餘額、代碼、存儲)。我們的目標是將以太坊的容量擴展約 1000 倍。但是,前兩種資源與第三種資源之間存在著根本性的不對稱性。


短期長期
執行ePBS、區塊級訪問列表 (BAL) 和 gas 重新定價 →增長約 10-30 倍ZK-EVM(大多數節點可以完全避免重複執行區塊)→性能提升約 1000 倍

對於某些特定類型的計算(例如簽名計算、SNARK/STARK 計算),鏈下聚合可以將性能提升約 10000 倍。
數據p2p 改進,多維氣體 →增長約 10-20 倍塊存儲 + PeerDAS → 8 MB/秒(約 500 倍提升
狀態與 BAL 同步、P2P 改進、數據庫改進 →性能提升約 5-30 倍

短期內,我們可以提高這三種資源的效率。但要實現長期所需的1000倍提升,我們需要一些“靈丹妙藥”。ZK-EVM是執行效率的“靈丹妙藥”,PeerDAS是數據效率的“靈丹妙藥”,但狀態管理方面卻沒有這樣的“靈丹妙藥”。那麼,我們該怎麼辦?

本文提出了一個雄心勃勃的解決方案:除了對當前狀態進行漸進式改進(例如二叉樹、葉子過期)以及對多維 gas 等進行定價改進之外,我們還在現有狀態之外引入了新的(更便宜但限制性更強的)狀態形式

主要的權衡之處在於,如果我們把狀態增長的“目標”水平設定為例如今天的 20 倍,執行速度的“目標”水平設定為今天的 1000 倍,那麼執行速度和存儲速度之間的“相對價格”將與現在相比發生巨大變化。創建一個新的存儲槽位可能真的比驗證一個 STARK 驗證還要貴(!!)。很可能兩者都很便宜,但人們對哪種更便宜的認知模型將會發生巨大改變。

因此,開發者將面臨選擇:如果他們繼續沿用目前的應用開發方式,則可以獲得相對較低的交易費用;或者,如果他們重新設計應用以利用新型存儲方式,則可以獲得極低的交易費用。對於常見用例(例如 ERC20 餘額、NFT),將會有標準化的工作流程。而對於更復雜的用例(例如 DeFi),開發者則需要自行摸索出針對特定應用的技巧。

為什麼我們不能將現有狀態放大 10-20 倍以上?


920×542 31.5 KB

目前,狀態數據正以每年約 100 GB 的速度增長。如果增長 20 倍,則每年增長 2 TB。4 年後,狀態數據的大小將達到 8 TB。

完全驗證節點無需存儲此狀態(因為它們可以通過 ZK-EVM + PeerDAS 獲取所需的一切),FOCIL 節點也無需存儲(VOPS 的容量要小得多;即使沒有任何更改,容量也將低於 1 TB,很可能低於 512 GB 甚至 256 GB,而且還可以進一步優化)。但構建者(不僅是高級構建者,也包括運行“原生”軟件的本地“家庭構建者”)需要它。

在磁盤上存儲 8TB 數據本身並不難。我們可能需要一些技巧,比如只存儲部分“熱”狀態數據,並對其他部分收取額外的 gas 費用,以便將它們存儲在平面文件而不是數據庫中。但歸根結底,8TB 的磁盤很容易獲得。難點有兩個:一個是短期的,一個是長期的。

  • 短期目標:數據庫效率。目前客戶端的數據庫並非為處理數TB級的狀態而設計。如今的一個主要問題是,狀態寫入需要對樹進行log(n)次更新,而每次更新本身在數據庫中也需要log(n)次操作,一旦n遠大於內存,具體的計算量就會迅速增長。目前已經有一些數據庫設計方案可以解決這個問題;它們只需要進一步完善並得到廣泛應用。
  • 長期目標:同步。我們希望構建過程無需權限,且設置簡便。即使效率完美,同步 8TB 的數據也需要很長時間,而且在很多情況下甚至會達到每月帶寬限制。

除了上述問題之外,還有狀態同步的來源、RPC節點的運行者以及其他諸多問題。粗略估計,狀態大小每翻一番,願意無私地(甚至有償地)使用狀態的參與者數量就會減少一半。數據庫效率的提升,例如使用HDD和平面文件代替SSD和數據庫等等,只能部分解決部分問題,而對另一些問題則完全無濟於事。

與數據和計算不同,這些領域並非我們可以說“我們依賴專業建造者來擴大規模,如果他們全部消失,普通建造者也可以建造只有原來10%大小的方塊”的領域。要建造一個方塊,你需要完整的狀態信息。降低gas限制並不會縮小狀態信息的大小。

這意味著 (i) 我們需要對狀態比對計算和數據更加保守,(ii) 許多適用於計算和數據的“分片”技術並不適用於狀態存儲。

為什麼強無國家狀態可能不足以解決問題

解決此問題的一個主要策略是強無狀態性。我們要求進行交易的用戶:(i) 指定其交易讀取和寫入的賬戶和存儲槽位,並規定任何超出此範圍的讀取或寫入操作都將失敗;(ii) 提供 Merkle 分支以證明其狀態訪問。

如果我們這樣做,就不再需要構建者來存儲完整的狀態。相反,用戶自己可以存儲與自身使用相關的狀態(以及更新後的證明),或者由去中心化網絡來存儲狀態(例如,每個節點可以隨機保留 1/16 的狀態)。


581×491 25.1 KB

這種方法有三個主要缺點:

  • 鏈下基礎設施依賴性:實際上,用戶無法存儲與其自身使用相關的狀態和證明,因為“與其自身使用相關”的內容會不斷變化,而且許多用戶無法始終在線下載更新的分支。因此,我們需要一個去中心化網絡來進行狀態存儲和檢索。這也會對用戶的隱私造成影響。
  • 向後不兼容:訪問存儲是交易執行動態函數的應用,從根本上來說與綁定訪問列表不兼容。這可能包括鏈上訂單簿、可追加列表以及許多其他類型的結構。對於這些應用,用戶需要在本地進行模擬,創建訪問列表,然後大部分情況下,鏈上交易會失敗(同時消耗 gas),用戶不得不反覆重試。
  • 帶寬成本:每次訪問存儲槽位,交易都需要提供約 1000 字節的證明。這將大大增加交易大小(例如,一個簡單的 ERC20 轉賬可能需要 4 kB 的見證數據:一個分支用於發送方賬戶,一個用於 ERC20 代幣,一個用於發送方餘額,一個用於接收方餘額,而目前僅需約 200 字節)。

弱化版的強無狀態概念被稱為“冷狀態”。其核心思想是,某些狀態(例如,一年以上未被訪問的狀態)仍然可以訪問,但存在異步延遲(實際上,延遲時間介於一秒到一格之間)。這樣,構建者無需實際存儲這些狀態即可運行,因為每當需要讀取數據時,他們都會向去中心化網絡請求數據。

這個方案或許可行,但由於其對基礎設施的依賴性過強,因此非常脆弱,而且同樣存在向後不兼容的問題。在最壞的情況下,某些事務會涉及複雜的多跳依賴關係圖,需要經過不同的冷狀態區域:調用 A,根據其輸出結果調用另一個地址 B,根據 B 的輸出結果調用另一個地址 C……

為什麼狀態過期機制很難實現向後兼容?

過去十年間,人們一直在嘗試提出狀態過期機制:這種設計會將長時間未被訪問的狀態自動從活動狀態中移除,而想要繼續使用該狀態的用戶必須主動“恢復”它。

這些設計都不可避免地會遇到一個問題:當你創建一個新的狀態時,如何證明之前那裡從來沒有任何東西

如果你在地址 X 創建一個賬戶,你必須證明在地址 X 上沒有創建過任何其他東西,不僅是今年或去年,而是以太坊歷史上的每一年。


531×261 12.7 KB

如果我們每年創建一個新樹來表示該年修改的狀態(“重複再生”),那麼在第 N 年創建一個新帳戶需要 N 次查找。


為了緩解這個問題,我們提出了一種地址週期機制:我們添加了一個新的賬戶創建規則集(“CREATE3”),允許您創建一個僅在年份 >= N 時有效的地址。當您創建這樣的賬戶時,無需為任何年份 < N 提供證明,因為在那些年份不可能存在這樣的賬戶。

然而,一旦我們嘗試將這種設計集成到以太坊的實際環境中,就會發現它存在重大侷限性。尤其需要注意的是,對於每個新賬戶,我們不僅需要創建賬戶,還需要創建存儲槽位。如果您創建了一個名為 X 的新賬戶,那麼對於您想要持有的每個代幣,您都必須為 X 創建相應的 ERC20 餘額。更糟糕的是,現有的 ERC20 代幣無法“理解”地址週期機制:即使以太坊協議可能理解,一個地址通過某種新的地址生成機制編碼了“2033”的賬戶 X 不可能創建於 2033 年之前,但 X 餘額的存儲槽位卻是 sha256(…, X),這是一種協議無法理解的不透明機制。

我們可以用一些巧妙的技巧來解決這個問題。一種方法是設計新的 ERC20 代幣,使其每年生成一個新的子合約,用於存儲當年關聯的賬戶餘額。另一種方法是創建一種新型存儲方式,這種存儲方式可以由代幣合約擁有,但與你的賬戶“共存”,因此可以與你的賬戶一起過期和復活。但是,這兩種方法都需要 ERC20 代幣合約完全重寫其邏輯,因此不向下兼容。

所有旨在使狀態過期機制向後兼容的嘗試似乎都遇到了類似的問題,這些問題都源於缺乏有效方法來證明狀態不存在。此外,遺憾的是,目前無法創建一個比當前狀態更簡潔或更小的“哪些地址/存儲槽之前未被創建”的映射。一個映射 {32 字節鍵:{0,1}} 的實現複雜度與一個映射 {32 字節鍵:32 字節值} 的實現複雜度完全相同。

從這些探索中吸取到的經驗教訓

我們可以將對強無國家狀態和國家消亡的研究得出的宏觀教訓概括為兩個主要的“典型事實”:

  1. 將所有狀態訪問都替換為 Merkle 分支會佔用過多帶寬,而將特殊情況下的狀態訪問替換為 Merkle 分支是可以接受的。 “狀態過期”實際上就是後者的一個例子:假設例如 90% 的狀態訪問訪問的是六個月以內的狀態,而 10% 訪問的是更早的狀態,那麼我們可以只將最近的狀態保留在“構建者必須訪問”的容器中,並要求對較早的狀態提供見證。這樣一來,我們平均只需支付 2 倍的開銷(加上原始交易),而不是 20 倍。

    這種探索似乎不可避免地會得出這樣的結論:我們需要分層狀態:區分高價值狀態(我們知道它們會被頻繁訪問)和低價值狀態(我們預期它們會被很少訪問)。分層可以通過兩種方式實現:(i) 按訪問時間(例如狀態過期提案)進行分層;(ii) 通過顯式劃分不同的狀態類別(例如,VOPS 就是這種分層方式的一個非常有限的版本)。

  2. 向後兼容非常困難。較低層級的狀態不僅在某些方面(尤其是動態同步調用)操作成本更高,而且根本無法以這些方式操作。因此,如果我們想要避免徹底破壞應用程序,唯一的選擇可能是將現有應用程序遷移到成本更高的狀態層,並要求開發人員主動選擇使用更新、成本更低的狀態層。

創建新型的、成本更低的國家會是什麼樣子?

如果現有狀態無法以向後兼容的方式失效,那麼自然的解決方案就是接受缺乏向後兼容性的事實,轉而採取“啞鈴式解決方案”。

  • 保持現有狀態幾乎完全不變,但允許其相對成本更高(例如,執行成本可能降低 1000 倍,但創建新狀態的成本可能只降低 20 倍)。
  • 創建從一開始就設計成易於實現極高可擴展性的新型狀態

在設計這些新型狀態時,我們應該牢記以太坊當前狀態的大部分是由哪些類型的對象構成的現實:例如 ERC20 代幣和 NFT 等餘額。

臨時存儲

一種思路是創建一種新的臨時存儲類型,其持續時間為中等長度。例如,我們可以創建一個新的樹狀結構,每當一個新的週期(例如 1 個月)開始時,該結構都會被清零。

這種存儲方式非常適合處理鏈上事件的臨時狀態:例如拍賣、治理投票、遊戲中的單個事件、防欺詐挑戰機制ETC。它的 gas 成本可以設置得非常低,使其能夠隨著執行速度的提升而擴展 1000 倍。

要在這種狀態下實現 ERC20 風格的餘額,必然會遇到一個問題:如果有人進入山洞超過一個月會發生什麼?

ERC20 的一個優點是它支持亂序恢復。例如:如果您在 2025 年收到 100 Dai ,然後忘記了,接著在 2027 年同一賬戶又收到 50 Dai ,最後您突然想起之前還有餘額,於是恢復了餘額,您將拿回 150 Dai 。您甚至無需提供任何證據證明您的賬戶在 2026 年是否發生過任何事件(如果您當時也收到了代幣,可以稍後提供證明)。我們唯一要防止的是使用相同的歷史狀態兩次恢復餘額。

以下是復活可能運作方式的示意圖:

  • 作為樹形設計的一部分,在每個節點中存儲該節點“下方”的葉子節點總數。這樣,​​在證明任何葉子節點時,就可以同時驗證該葉子節點在樹中的索引(從左到右):只需在證明中將所有左側的姊妹節點的總數相加即可。
  • 每個月,我們都會存儲一個永久狀態位域,刪除時樹中的每個值對應一位。該位域初始狀態為全零。
  • 如果賬戶 X 在第 N 個月擁有寫入槽位 Y 的權限,那麼在任何大於 N 的月份,該賬戶都可以編輯其對應的位域值。此外,任何人隨時都可以提供證明。

961×301 9.01 KB

  • ERC20 合約默認會將餘額存儲在當前樹中,但它會有一個餘額恢復功能,該功能以證明發送者歷史狀態條目的分支作為輸入,並在將位從 0 翻轉為 1 的同時恢復餘額,因此它不能再次恢復。

如今,以太坊的狀態數據每年增長約 100 GB。如果我們將以太坊的規模擴大 1000 倍,我們可以想象狀態數據的增長速度也會乘以 1000,但所有數據都存儲在臨時樹中。這意味著大約需要 8 TB 的狀態數據(假設狀態數據過期時間為 1 個月),再加上少量永久存儲空間(每個 64 字節的狀態條目佔用 1 位,因此每月需要 8 TB * 1/8 / 64 = 16 GB)。

UTXO

或者,我們可以將臨時存儲的概念推向極致:將過期時間設為零。本質上,合約可以創建記錄,這些記錄會被哈希到該區塊中的一棵樹裡,並立即進入歷史記錄。對於每個區塊,狀態中會有一個位域來存儲記錄是“已花費”還是“未花費”,這將是永久狀態,除此之外就沒什麼了。


791×378 13.7 KB

理論上,UTXO 可以通過複用現有的 LOG 機制,並在其上添加狀態位域機制來構建。如果確實需要,甚至可以完全採用協議外的 ERC 方式,但這也有一些缺點:少數隨機用戶需要支付比其他用戶高出 256 倍的費用,才能率先創建一個代表位域中 256 個字節的新存儲槽。

ERC20、NFT 和各種其他狀態都可以建立在這些類型的 UTXO 之上。

還有一種介於這兩種方案之間的混合方案。我們使用 UTXO,但允許直接從狀態訪問最近一個月的樹數據,無需見證人。這降低了帶寬負載(但需要更大的存儲空間)。與臨時存儲方案的主要區別在於,這裡只需要一個“接口”來處理先前創建的對象(作為 UTXO),而不是兩個(一個作為當前紀元的存儲槽,另一個作為前一個紀元的 UTXO)。

強無狀態存儲樹

我們還可以創建一個單一的存儲樹,訪問該存儲樹需要使用默克爾分支(或者,節點需要存儲其前 N-8 層,即 1/256 的大小,並且節點需要提供 256 字節的見證)。這個新的存儲樹將與現有的存儲樹並存,因此我們將擁有兩個存儲樹:一個是需要見證且成本較低的存儲樹,另一個是不需要見證且成本較高的存儲樹。

然而,我認為這種方案不如臨時存儲方案。原因在於,從長遠來看,如果這樣一棵樹的大部分內容都是被遺忘的垃圾信息,而人們只關心其中的一小部分,那麼網絡最壞的情況是必須存儲整棵樹(包括垃圾信息),最好的情況也只是存儲證明有用狀態的超長默克爾分支(因為樹中的每個有用狀態對象都會被垃圾信息“包圍”)。雙樹設計僅允許兩層存儲,而臨時存儲設計則為在其上構建狀態過期機制創造了空間,從而允許在經濟分層之上疊加近期分層。

對開發者體驗的影響

下面簡要概述了一些應用程序和工作流程如何在這種分層架構下運行:

  • 用戶帳戶(包括與原生 AA 關聯的新的每個帳戶的狀態)將永久存儲。因此,用戶帳戶可以隨時以低成本且便捷的方式訪問。
  • 智能合約代碼將全部永久存儲。
  • NFT、ERC20 代幣餘額ETC將存儲在 UTXO 或臨時存儲中。
  • 與短期事件相關的狀態(例如拍賣、防欺詐遊戲、預言機遊戲、治理行動)將存儲在臨時存儲中。
  • 核心 DeFi 合約將永久存儲,以最大限度地提高可組合性。
  • 在許多情況下, defi 活動的各個單元(例如 CDP)將存在於 UTXO 或臨時存儲中。

初期,開發者可以繼續將所有內容存入現有的永久存儲中。NFT 和 ERC20 代幣餘額可能最容易轉移到 UTXO 或臨時存儲中。之後,生態系統會逐步優化,以實現更高效的存儲利用。

這裡的基本假設是,“混合永久存儲和UTXO”比“僅使用UTXO”更容易開發。以太坊作為開發者平臺如此成功的一個重要原因在於,賬戶和存儲槽位比UTXO對開發者更加友好。如果我們能夠提供對開發者友好的抽象,例如,允許95%的狀態使用輕鬆遷移到UTXO,並將剩餘的5%保留為永久存儲(同時允許對這種做法感到困惑的開發者以更高的成本為代價,繼續使用永久存儲來存儲所有數據),那麼我們就可以同時獲得UTXO的大部分擴展性優勢和以太坊式賬戶和存儲槽位的大部分開發者友好性優勢。


來源
免責聲明:以上內容僅為作者觀點,不代表Followin的任何立場,不構成與Followin相關的任何投資建議。
喜歡
收藏
評論