Vitalik 新作速讀:多維 Gas 定價

維塔利克·布特林
2024-05-09 20:05:19
收藏
Vitalik 談以太坊多維 Gas 定價,該如何權衡與選擇?

作者:Vitalik Buterin

編譯:Karen,Foreisght News

在以太坊中,資源直到最近還是有限的,並通過一種稱為「 Gas 」的單一資源來定價。 Gas 是衡量處理特定交易或區塊所需「計算量」( computational effort )的度量單位。 Gas 將多種類型的「計算量」融合在一起,其中最重要的包括:

1、原始計算( Raw computation ,例如 ADD 、 MULTIPLY );

2、讀寫和寫入以太坊存儲(例如 SSTORE 、 SLOAD 、 ETH 轉帳);

3、數據帶寬;

4、生成區塊的 ZK - SNARK 證明的成本。

例如,我發送的這筆交易總共消耗了 47,085 Gas 。其中包括:( i )基本成本為 21000 Gas ,( i i )作為交易一部分包含的 calldata 字節消耗了 1556 Gas ,( i i i )讀寫存儲消耗了 16500 Gas ,( i v)生成日誌( log )消耗了 2149 Gas ,其餘用於 EVM 執行。用戶必須支付的交易費用與交易消耗的 Gas 成正比。 一個區塊最多可以包含 3000 萬 Gas ,並且 Gas 價格通過 EIP -1559 target i ng 機制不斷調整,確保每個區塊平均包含 1500 萬 Gas 。

這種方法有一個主要的優勢:因為所有內容都合併為一個虛擬資源,所以市場設計非常簡單。優化交易以最小化成本很容易,優化區塊以收取盡可能高的費用相對容易(不包括 MEV ),並且沒有奇怪的激勵機制鼓勵一些交易與其他交易捆綁以節省費用。

然而,這種方法也存在低效性:它將不同的資源視為可以相互轉換,而實際的底層限制並不一樣。要理解這個問題,你可以先看下面這張圖表:

Gas 限制強加了一個約束條件:

實際的底層安全約束通常更接近:

這種差異導致 Gas 限制要麼無端地排除了實際安全的區塊,要麼接受了實際上不安全的區塊,或者兩者兼而有之。

如果有 n 種資源具有不同的安全限制,那麼一維 Gas 可能會使吞吐量最多降低 n 倍。因此,長期以來,人們一直對多維 Gas 的概念感興趣,而通過 EIP -4844,我們現在實際上已經在以太坊上實現了多維 Gas 。本文探討了這種方法的優點,以及進一步進行增強的前景。

Blob : Dencun 中的多維 Gas

今年年初,平均區塊大小為 150 kB 。其中很大一部分是 Rollup 數據: Layer2 協議在鏈上存儲數據。這些數據非常昂貴:儘管 Rollup 上的交易成本僅為以太坊 L1 上相應交易的 5-10 倍,但即使這樣的成本對於許多用例來說也太高了。

那為什麼不降低 calldata 的 Gas 成本(目前非零字節為 16 Gas ,零字節為 4 Gas ),以使 Rollup 更便宜呢?我們之前這樣做過,現在也可以再次這樣做。但這裡的答案是:區塊的最大大小是 30,000,000/16=1,875,000 非零字節,而網絡勉強能或者幾乎不能處理這樣大小的區塊了。再將成本降低 4 倍會使最大值提高到 7.5 MB ,這將給安全性帶來巨大風險。

這個問題最終通過在每個區塊中引入一個獨立的、對 Rollup 友好的數據空間(稱 blob )來解決。

這兩種資源有不同的價格和限制:在 Dencun 硬分叉之後,一個以太坊區塊最多可以包含( i )3000 萬 Gas 和( i i )6 個 blob ,每個 blob 可以包含約 125 kB 的 calldata 。這兩種資源都有單獨的價格,並通過單獨的類似於 EIP -1559 的定價機制進行調整,目標是每區塊平均使用 1500 萬 Gas 和 3 個 blob 。

結果是, Rollup 的成本降低了 100 倍, Rollup 上的交易量增加了 3 倍以上,而理論上的最大區塊大小僅略有增加:從約 1.9 MB 增加到約 2.6 MB 。

注: Rollup 交易費用,由 Growthepie.xyz 提供。 Dencun 分叉發生於 2024 年 3 月 13 日,引入了多維定價 blob 。

多維 Gas 和無狀態客戶端

在不久的將來,無狀態客戶端( stateless clients )的存儲證明也會出現類似的問題。無狀態客戶端是一種新型客戶端,將能夠驗證鏈而無需在本地存儲大量或任何數據。無狀態客戶端通過接受該區塊中交易需要訪問的以太坊狀態的特定部分的證明來實現這一點。

上圖展示了一個無狀態客戶端接收一個區塊,以及證明該區塊執行所觸及的狀態特定部分(例如,賬戶餘額、代碼、存儲)當前值的證明,這使得節點能夠在沒有任何存儲的情況下驗證一個區塊。

一次存儲讀取需要花費 2100-2600 Gas ,具體取決於讀取類型,而存儲寫入成本更高。平均而言,一個區塊會執行大約 1000 次存儲讀寫操作(包括 ETH 餘額檢查、 SSTORE 和 SLOAD 調用、合約代碼讀取和其他操作)。然而,理論上的最大值是 30,000,000/2,100=14,285 次讀取。無狀態客戶端的帶寬負載與該數字成正比。

目前的計劃是通過將以太坊的 State tree 設計從 Merkle Patricia tree s 轉變為 Verkle tree s 來支持無狀態客戶端。然而, Verkle tree s 不具備抗量子性,並且對於較新的 STARK 證明系統來說並不是最優選擇。因此,許多人有興趣通過二進制 Merkle tree s 和 STARK s 來支持無狀態客戶端,要麼完全跳過 Verkle ,要麼在 Verkle 過渡幾年後,一旦 STARK 變得更加成熟,就進行升級。

基於二進制哈希樹分支的 STARK 證明具有許多優點,但其關鍵弱點在於生成證明的時間很長: Verkle 樹可以每秒證明十萬個以上的值,基於哈希的 STARK s 通常只能每秒證明幾千個哈希,而證明每個值都需要包含許多哈希的「分支」( branch )。

考慮到今天從 Binius 和 Plonky3 等超優化證明系統以及 Vision - Mark -32 等專用哈希中預測的數字,我們似乎將在一段時間內處於一個實用範圍內,即每秒證明 1000 個值是可行的,但證明 14,285 個值則不可行。平均區塊會沒問題,但潛在最壞情況下的區塊(由攻擊者發布)會破壞網絡。

我們處理此類情況的 default 方法是重新定價:提高存儲讀取的成本,以減少每個區塊的最大值到更安全的水平。但是,我們已經這樣做了很多次,如果再次這樣做,會使太多應用變得太昂貴。一個更好的方法是多維 Gas :分別對存儲訪問進行限制和收費,將平均使用量保持在每個區塊 1,000 次存儲訪問,但設置每個區塊的上限進行設置,例如 2000 次。

多維 Gas 的普遍性

另一個值得考慮的資源是狀態大小的增長:即增加以太坊狀態大小的操作,這些操作之後需要全節點來保存。狀態大小增長的獨特之處在於,限制它的理由完全來自於長期持續的使用,而不是峰值。

因此,為增加狀態大小的操作(例如, zero - to -non zero SSTORE 、合約創建)添加一個單獨的 Gas 維度可能是有價值的,但目標不同:我們可以設定一個浮動價格來針對特定的平均使用量,但完全不設置每個區塊的限制。

這展示了多維 Gas 的一個強大屬性:它讓我們能夠分別針對每個資源,詢問( i )理想平均使用量是多少?( i i )每個區塊的安全最大使用量是多少?與基於每個區塊的最大值來設定 Gas 價格,並讓平均使用量跟隨其後不同,我們有 2n 自由度來設定 2n 參數,根據對網絡安全的考慮來調整每一個參數。

更複雜的情況,例如當兩種資源的安全性考慮部分相加時,可以通過使一個操作碼或資源消耗多種類型的 Gas 的某種數量來處理(例如,一個 zero - to -non zero SSTORE 可能消耗 5000 個無狀態客戶端證明 Gas 和 20000 個存儲擴展 Gas )。

每筆交易 Max (選取數據或計算消耗更大的那種)

令 𝑥1 為數據的 Gas 成本, 𝑥2 為計算 Gas 成本,因此在一維 Gas 系統中我們可以寫出一筆交易的 Gas 成本:

在這個方案中,我們將交易的 Gas 成本定義為:

也就是說,交易不是根據數據加計算來收費,而是根據它消耗的兩種資源中哪一種資源更多來收費。這可以輕鬆擴展以覆蓋更多維度(例如 𝑚𝑎𝑥(…,𝑥3∗𝑠𝑡𝑜𝑟𝑎𝑔𝑒_𝑎𝑐𝑐𝑒𝑠𝑠) )。

應該很容易看出這如何在保證安全性的同時提高吞吐量。理論上一個區塊中的最大數據量仍然是 Gas LIMIT /𝑥1,與一維 Gas 方案中完全相同。類似地,理論上的最大計算量是 Gas LIMIT /𝑥2 ,同樣與一維 Gas 方案中完全相同。然而,任何消耗數據和計算的交易的 Gas 成本都會降低。

這大概是提議的 EIP -7623 中採用的方案,以減少最大區塊大小,同時進一步增加 blob 計數。 EIP -7623 中的精確機制稍微複雜一些:它保持當前的 calldata 價格為每字節 16 Gas ,但增加了每字節 48 Gas 的 floor price ;交易支付 ( 16 * bytes + execution _ Gas ) 和 ( 48 * bytes ) 中的較高者。因此, EIP -7623 將區塊中理論最大交易調用數據從約 1.9 MB 減少到約 0.6 MB ,同時保持大多數應用程序的成本不變。這種方法的好處是它與當前的一維 Gas 方案相比變化非常小,因此非常容易實現。

不過這種方法有兩個缺點:

1、即使區塊中的所有其他交易只使用很少的該資源,但大量佔用一種資源的交易仍然會不必要地收取大量費用;

2、它激勵數據密集型和計算密集型交易合併到一個捆綁包中以節省成本。

我認為, EIP -7623 這樣的規則,無論是對於交易 calldata 還是其他資源,都可以帶來足夠大的好處,即使存在這些缺點,也是值得的。

然而,如果我們願意投入(顯著更高的)開發努力,就會出現一種更理想的方法。

多維 EIP-1559:更困難但理想的策略

讓我們首先回顧一下常規 EIP -1559 的工作原理。我們將重點關注 EIP -4844 中針對 blob 引入的版本,因為它在數學上更加優雅。

我們跟蹤一個參數 excess _ blobs 。在每個區塊期間,我們設置:

excess _ blobs \<-- max ( excess _ blobs + len ( block . blobs ) - TARGET , 0)

其中 TARGET = 3 。也就是說,如果某個區塊的 blob 數量多於目標,則 excess _ blob s 會增加,如果某個區塊的 blob 數量少於目標,則 excess _ blob s 會減少。然後我們設置 blob _ basefee = exp ( excess _ blob s / 25.47) ,其中 exp 是指數函數 𝑒𝑥𝑝(𝑥)=2.71828\^𝑥 的近似值。

也就是說,每當 excess _ blob s 增加約 25 時, blob 基本費用就會增加約 2.7 倍。如果 blob 變得太貴,平均使用量就會下降,並且 excess _ blob s 開始減少,從而自動再次降低價格。 Blob 的價格不斷調整,以確保平均而言,區塊是半滿的,也就是說,每個區塊平均包含 3 個 Blob 。

如果使用量出現短期峰值,則會出現限制:每個區塊最多只能包含 6 個 blob ,在這種情況下,交易可以通過提高優先費來相互競爭。然而,在正常情況下,每個 blob 只需支付 blob _ basefee 加上一小部分額外的優先級費用作為被納入的激勵。

這種 Gas 定價在以太坊中已經存在多年:早在 2020 年, EIP-1559 就引入了非常相似的機制。通過 EIP-4844,我們為 Gas 和 Blobs 設置了兩個獨立的浮動價格。

注:2024 年 5 月 8 日一小時內的 Gas 基本費用,單位為 gwei 。來源:ultrasound.money

原則上,我們可以為存儲讀取和其他類型的操作添加更多獨立浮動的費用,不過我在下一節中將詳細闡述一個需要注意的問題。

對於用戶來說,這種體驗與今天非常相似:你不再支付一筆基本費用( basefee ),而是支付兩項基本費用,但你的錢包可以將其從你的手中抽象出來,只向你顯示可以預期支付的預期費用和最高費用。

對於區塊構建者來說,大多數時候最佳策略與今天相同:包括任何有效的內容。大多數區塊都未滿------無論是 Gas 還是 Blob 。一個具有挑戰性的情況是,當有足夠的 Gas 或足夠的 Blob 超過區塊限制時,構建者需要潛在地解決多維 knapsack 問題以最大化其利潤。然而,即使存在相當好的近似算法,在這種情況下,通過制定專有算法來優化利潤所獲得的收益也比使用 MEV 進行相同操作所獲得的收益要小得多。

對於開發人員來說,主要的挑戰是需要重新設計 EVM 及其相關基礎設施的功能,這些功能目前是基於單一價格和單一限制設計的,而現在需要將其改造成能夠適應多個價格和多個限制的設計。

應用程序開發人員面臨的一個問題是優化變得稍微困難:在某些情況下,您不能再明確地說 A 比 B 更高效,因為如果 A 使用更多的 calldata 而 B 使用更多的執行,那麼當 calldata 為便宜,當 calldata 昂貴時則更昂貴。

應用開發者面臨的一個問題是優化會變得稍微困難一些:在某些情況下,你無法明確地說 A 比 B 更有效率,因為如果 A 使用了更多的 calldata ,而 B 使用了更多的執行,那麼當 calldata 便宜時 A 可能更便宜,而當 calldata 昂貴時 A 可能更貴。

然而,開發者仍然可以通過基於長期歷史平均價格進行優化,來獲得相當不錯的結果。

多維定價、 EVM 和 sub-calls

有一個問題在 blobs 中沒有出現,在 EIP -7623 或甚至是針對 calldata 的完整多維定價實現中也不會出現,但如果我們試圖對狀態訪問或其他任何資源進行單獨定價,那麼這個問題就會出現:即子調用( sub - calls )中的 Gas 限制。

EVM 中的 Gas 限制存在於兩個地方。首先,每筆交易都會設置一個 Gas 限制( Gas Limit ),限制了該交易中可以使用的 Gas 總量。其次,當一個合約調用另一個合約時,該調用可以設置自己的 Gas 限制。這允許合約調用他們不信任的其他合約,並且仍然保證他們在調用後仍有剩餘的 Gas 來執行其他計算。

注:賬戶抽象交易的蹤跡,其中一個賬戶調用另一個賬戶,並且僅向被調用者提供有限數量的 Gas ,以確保即使被調用者消耗了分配給它的全部 Gas ,外部調用也可以繼續運行。

挑戰在於:讓不同類型的執行之間實現多維 Gas 似乎需要子調用為每種類型的 Gas 提供多個限制,這將需要對 EVM 進行非常深入的更改,並且與現有應用程序不兼容。

這就是多維 Gas 提案通常停留在兩個維度的原因之一:數據和執行。數據(無論是交易 calldata 還是 blob )僅在 EVM 外部分配,因此 EVM 內部無需更改任何內容即可使 calldata 或 blob 單獨定價。

我們可以想出一個「 EIP -7623 式的解決方案」來解決這個問題。這是一種簡單的實現:在執行期間,對存儲操作收取 4 倍的費用;為了簡化分析,假設每個存儲操作有 10000 氣體。交易結束時,退款 min (7500 * storage _ operations , execution _ Gas ) 。結果是,在扣除退款後,用戶需要支付以下費用:

execution _ Gas + 10000 * storage _ operations - min (7500 * storage _ operations , execution _ Gas )

這等於:

max ( execution _ Gas + 2500 * storage _ operations , 10000 * storage _ operations )

這反映了 EIP -7623 的結構。另一種方法是實時跟蹤 storage _ operations 和 execution _ Gas ,並根據當時 max ( execution _ Gas + 2500 * storage _ operations , 10000 * storage _ operations ) 上漲多少收取 2500 或 10000。操作碼被調用。這避免了交易需要過度分配 Gas ,而這些 Gas 主要通過退款來收回。

我們沒有獲得子調用的細粒度許可:子調用可能會消耗交易的所有 allowance 以進行廉價的存儲操作。

但我們確實得到了一些足夠好的東西,即進行子調用的合約可以設置一個限制,並確保一旦子調用執行完畢,主調用仍有足夠的 Gas 進行所需的後處理( post - processing )。

我能想到的最簡單的「完整的多維定價解決方案」是:我們將子調用 Gas 限制視為成比例的。也就是說,假設有 𝑘 種不同的執行類型,並且每個交易設置了多維限制 𝐿1…𝐿𝑘 。假設在當前執行點,剩餘 Gas 為 𝑔1…𝑔𝑘 。假設調用 CALL 操作碼,並使用子調用 Gas 限制 𝑆 。讓 𝑠1=𝑆 ,然後 𝑠2=𝑠1/𝑔1∗𝑔2 , 𝑠3=𝑠1/𝑔1∗𝑔3 ,以此類推。

也就是說,我們將第一種類型的 Gas (實際上是 VM 執行)視為一種特殊的「賬戶單位」,然後分配其他類型的 Gas ,以便子調用在每種類型的 Gas 中都獲得相同百分比的可用 Gas 。這種方法有點難看( ugly ),最大限度地保證了向後兼容性。

如果我們想在不犧牲向後兼容性的情況下,使該方案在不同類型的 Gas 之間更加「中立」,我們可以簡單地將子調用的 Gas 限制參數表示為當前 context 中剩餘 Gas 的一部分(例如,[1…63]/64)。

然而,無論在哪種情況下,都值得強調的是,一旦開始引入多維執行 Gas ,固有的複雜性( ugliness )就會增加,這似乎很難避免。

因此,我們的任務是做出一個複雜的權衡:我們是否接受在 EVM 層面上的某種程度的複雜性( ugliness )增加,以安全地解鎖顯著的 L1 可擴展性增益,如果是的話,哪種具體提案對協議經濟和應用程序開發者最有效?很有可能,我上面提到的兩個方案都不是最好的,但仍有空間提出更優雅、更好的方案。

特別感謝 Ansgar Dietrichs 、 Barnabe Monnot 和 Davide Crapis 的反饋和審查。

鏈捕手ChainCatcher提醒,請廣大讀者理性看待區塊鏈,切實提高風險意識,警惕各類虛擬代幣發行與炒作,站內所有內容僅係市場信息或相關方觀點,不構成任何形式投資建議。如發現站內內容含敏感信息,可點擊“舉報”,我們會及時處理。
ChainCatcher 與創新者共建Web3世界