以太坊Glamsterdam升級的Hoodi分叉喊卡,稽核發現了什麼問題?

ETH
以太坊升級智能合約稽核發現GlamsterdamHoodi分叉gas規則EIP-8037
9 小時前來源: crypto.news
以太坊Glamsterdam升級的Hoodi分叉喊卡,稽核發現了什麼問題?

以太坊開發者已暫緩 Glamsterdam 的 Hoodi 測試網分叉,同時正在研究當交易燃料不足時應用程式行為的相關發現。此次升級改變了網路對某些涉及或擴展其狀態的操作收費的方式,而稽核人員發現,即使是升級前編寫的合約,在擬議規則下也可能表現出不同的行為。

摘要

  • 以太坊開發者原定於 10 月 26 日進行 Hoodi 分叉,隨後將其延後。11 月 6 日的開發者更新表示,在團隊處理審查期間提出的問題時,分叉仍處於暫緩狀態。
  • 兩項提案 EIP-8037 和 EIP-8038 影響建立狀態和存取現有狀態的成本。此變更可能改變合約在執行中某一特定時點剩餘的燃料量。
  • ChainSecurity 發現了一些情況:呼叫可能失敗,而發起該呼叫的合約仍能完成其失敗處理程序。在較早的燃料規則下,同一路徑可能導致外層交易回滾。
  • 開發者正在檢查各客戶端實作和現有合約中的假設。根據以太坊基金會的更新,ChainSecurity、Dedaub 和內部審查人員參與了此次審查。
  • Hegota 的工作仍在並行推進。值得關注的 Glamsterdam 證據是修訂後的測試網時程,以及其背後測試的結果。

以太坊開發者原定於 10 月 26 日分叉 Hoodi。他們推遲了該測試,並於 11 月 6 日,以太坊基金會開發者 Marius van der Wijden 表示該測試仍處於暫緩狀態,同時開發者正在處理燃料審查中發現的問題。

此疑慮的核心在於一個大多數人只有在交易失敗時才會遇到的細節。合約可以呼叫其他合約,並決定當這些呼叫返回不成功時該怎麼做。做出該決定的程式碼在升級後可能看起來完全相同,卻會走上不同的路徑,因為網路現在對操作的部分環節收費方式不同了。

這就是為什麼一項針對以太坊狀態記帳方式的升級,已成為應用程式開發者以及編寫以太坊客戶端的團隊共同面臨的問題。兩者都需要知道哪些舊有假設能在變更後繼續成立。

Glamsterdam 對燃料的改變

EIP-8037 改變了協議對建立狀態操作的記帳方式。以太坊的狀態包括合約儲存等記錄。變更可以跨交易持續存在,因此其成本會對在原始交易完成後維護鏈的節點產生影響。該提案將某些狀態建立的記帳與一般執行燃料分開,並設有一個可供符合條件操作動用的儲備池。

EIP-8038 重新定價存取狀態的操作。這兩項提案影響執行路徑的不同部分。合約可能讀取一個值、進行外部呼叫並寫入結果。僅審查最終寫入的擬議價格,會忽略較早的讀取和呼叫對執行到達該處時可用預算的影響。

因此,即使使用者提供相同的交易輸入,一個熟悉的應用程式也可能產生不同的結果。重要的問題是,哪些差異反映了預期的重新定價,哪些則暴露了客戶端或合約所依賴的假設。

一次失敗的呼叫如何改變最終結果

設想一個合約呼叫第二個合約,以在更大的操作中執行一個步驟。如果第二個合約失敗,呼叫方可以停止一切,或處理該失敗並繼續。批次處理器可能會記錄一個不成功的項目然後繼續。另一個應用程式可能期望,如果失敗的呼叫耗盡足夠的 gas,整個操作就會回滾。

ChainSecurity 的分析描述了新的會計方式如何影響這種區別。以太坊已經根據 EIP-150 規則限制了呼叫方可以向前傳遞多少 gas。在相關情況下,大約六十四分之一可以留在呼叫方手中。問題在於,一旦執行返回,呼叫方實際可用多少 gas,以及完成該路徑上的指令需要多少成本。

假設一個應用程式將呼叫失敗視為普通的業務結果。如果它有足夠的 gas 來完成失敗處理程序,它可能會記錄一個結果或繼續交易的其餘部分。如果在這樣做的過程中耗盡 gas,外層交易就會回滾。儘管內層呼叫在兩種情況下都失敗了,但這些結果會留下不同的記錄。

稽核人員還檢視了基於 gasleft() 的檢查。合約可以使用該指令將其剩餘的執行預算與硬編碼的最小值進行比較。在某一排程下校準的閾值在另一排程下可能成為糟糕的預測指標,尤其是當合約遇到狀態操作或將 gas 轉發到另一個地址時。合約沒有自動方式來修訂其開發者在部署時嵌入的數字。

稽核人員需要確立的事項

基金會的十一月更新描述了正在審查的八項假設。至少存在兩個不同的測試問題。實作新規則的客戶端必須對給定交易得出相同的結果。應用程式審查者還必須找出該共享結果與現有合約預期不同的情況。

針對第一個問題的測試可以對多個客戶端執行相同的交易,並比較狀態和 gas 結果。針對第二個問題的測試需要遵循應用程式自身的邏輯。關鍵在於合約是否將失敗的回呼視為繼續進行的提示、是否在呼叫前記錄狀態變更,以及是否能夠區分業務拒絕與從未有足夠 gas 的呼叫。

這些路徑在常規部署測試中可能很容易被遺漏。典型的交易預算可能會在兩種排程下都承載呼叫及其處理程序。刻意收緊的預算可以暴露差異。因此,邊界測試必須包含失敗的呼叫,以及接近進入或完成失敗處理程序所需 gas 量的情況。

Hoodi 能展示什麼

Glamsterdam 已經到達以太坊的 Sepolia 測試網,開發者在那裡測試了 2 億 gas 上限。Hoodi 將為開發者提供另一個共享部署,以演練修訂後的升級。

公共測試網分叉為客戶端團隊和應用程式營運者提供了一個共同的環境來執行這些檢查。營運者可以按照共享排程更新客戶端、比較結果,並針對分叉規則測試工具。應用程式團隊可以檢查交易模擬和 gas 估算是否考慮了他們在執行期間看到的相同變更。

成功的 Hoodi 分叉將為開發者提供有關他們所測試的版本和交易的證據。更長期的問題是代表性應用程式在其 gas 預算極限下的行為。新的分叉日期將更容易結合以下記錄來評估:哪些案例被重現、相應改變了什麼,以及團隊如何測試它。

gas 工作與其他修復並行進行。在 Hoodi gas 審查進行的同時,以太坊開發者另行修訂了驗證者存款規範。這些修復需要各自的測試,因為它們影響分叉的不同部分。

目前,最新的關於 gas 風險的開發者更新給出了暫緩的理由,並表示 Hegota 的工作仍在繼續。它將下一次 Glamsterdam 測試的時間留待後續決定。

Gas 上限與狀態成本如何相互配合

更高的區塊 gas 上限讓以太坊在其會計系統下有更多空間處理更多工作。分配給單一操作的價格決定了該操作佔用多少空間。因此,上限的變動與價格的變動可能影響同一筆交易的不同部分。

有些工作在交易結束時就結束了。建立狀態則不同,因為資料可以持續存在,讓節點營運者日後仍需儲存與處理。一個新的儲存槽、帳戶或合約可能增加這項負擔,即使建立它的應用程式之後幾乎沒有流量。

EIP-8037 改變了某些狀態建立成本的計算方式。EIP-8038 重新定價對狀態的存取,其中可能包含涉及已存在紀錄的操作。一筆讀取數值、呼叫另一個合約並建立儲存項目的交易,可能在單次執行中同時遇到這兩項變更。

單單提高區塊上限並不能說明該序列會花費更多還是更少。它描述的是整個區塊可用的空間。交易的執行路徑與每項操作的價格,決定了它能否容納於發送者提供的 gas 之內。

當 Sepolia 以 2 億 gas 上限開始測試 Glamsterdam 時,這項區別就已具有相關性。該測試顯示了開發者在該網路上執行的內容。Hoodi 的暫緩則涉及這些規則是否已準備好迎接下一個測試網,包括依賴先前 gas 假設的應用程式行為。

正在審查的八項假設

以太坊基金會的稽核儲存庫依操作價格的變更與 gas 追蹤方式的變更來分組其範例。儲存庫中的數字來自提案規格的固定版本,若提案修訂則可能改變。

第一組疑慮涉及固定配額與呼叫後完成工作的成本。開發者可能為某項操作設定了 gas 上限,而該操作現在成本更高。原本用於支付最終寫入的保留額可能已不再足夠。在另一種情況下,呼叫者保留的一小部分可能足以完成應用程式先前預期會回滾的失敗路徑。

會計變更帶來了其他可能性。如果一個獨立的儲備池仍能資助符合條件的狀態建立,呼叫者即使其一般執行預算吃緊,也能在呼叫失敗後寫入一筆紀錄。呼叫者的最終結果便可能取決於哪些操作使用了該獨立預算。

在審查中的規格裡,清除同一筆交易中較早建立的儲存槽可以立即返還部分狀態 gas。回滾的呼叫也可以返還狀態 gas。因此,基於「回滾前消耗的所有 gas 都已消失」這一假設所寫的程式碼,可能會誤判實際發生的情況。

同樣地,兩次 gasleft() 測量可能對工作成本給出不完整的看法。使用兩者差值向某人收費或計算退款的合約,依賴於兩次讀數之間 gas 如何變化的假設。從獨立池中扣除的費用與執行期間返還的狀態 gas 可能改變這一關係。

第八個案例涉及 EIP-7702,它允許帳戶授權委託給合約程式碼。即使交易內的授權因 gas 不足而未生效,該交易仍可能被納入。僅憑交易被納入就推斷委託已生效的錢包或服務,可能會將未完成的動作視為已完成。

該儲存庫表示,其作者收到的許多發現都與固定金額或保留額有關。它要求開發者與稽核人員針對這些範例測試其應用程式並回報問題。這份清單指出了需要審查的模式。它並不意味著使用其中任一模式的每個應用程式都會產生損失。

一次失敗的呼叫如何仍能留下成功的交易

一筆以太坊交易可以包含多個呼叫。一個合約可以請求另一個合約執行某個步驟,然後決定如何回應結果。失敗的內部呼叫與失敗的交易是不同的結果。

批次處理器提供了一個有用的例子。如果某個項目失敗,處理器可能會記錄該失敗並繼續處理下一個項目。如果它在能夠記錄結果之前耗盡 gas,外層交易可以回滾並撤銷先前的變更。因此,同一個內部失敗會根據呼叫者之後能做什麼而留下不同的最終狀態。

另一個應用程式可能會將失敗的呼叫視為改變誰可以提交請求或是否允許再次嘗試的理由。如果呼叫者能夠完成一條應用程式預期會回滾的路徑,產生的狀態就可以持續存在。安全後果取決於完成的路徑實際記錄了什麼。

行為者可能能夠選擇一筆交易提供多少 gas。如果該人能留下足夠的 gas 讓外層合約進入某條路徑,但留下太少的 gas 讓內部呼叫無法完成,則該失敗可以由交易預算所誘發。對失敗採取行動的合約需要將該情況與一個已到達被呼叫方並合法失敗的呼叫區分開來。

EIP-150 轉發限制是其中一部分。在相關規則下,盡可能轉發 gas 的呼叫者大約保留六十四分之一。保留的金額仍然必須支付後續指令的費用。那些指令是否完成取決於排程以及應用於它們的計費方式。

一個合約可能對狹窄範圍的預算存在脆弱性。給內部呼叫足夠的 gas,它就能正常運作。給整筆交易太少的 gas,外層路徑就會回滾。有問題的區間是內部呼叫失敗,而呼叫者仍有足夠的 gas 執行開發者並未為該失敗所預期的動作。

為什麼更改固定的 gas 數值可能無法解決問題

硬編碼的閾值可以為合約提供一種簡單的方式,在進行呼叫之前檢查它是否有足夠的 gas。開發者可能已經用常見交易測試過該閾值,並為後續工作留下了緩衝。該數值成為對其被選定時所處排程的一種依賴。

一個操作的成本也可能因應用程式是在更新現有記錄還是建立新記錄而有所不同。轉帳給已經有餘額的人可能會遇到與建立首次餘額的轉帳不同的儲存路徑。僅涵蓋重複接收者的測試可能會遺漏更昂貴的路徑。

合約測量 gas 的時機很重要。在呼叫之前立即讀取與在數次狀態存取及呼叫本身之後讀取是不同的。從後者讀取推斷失敗原因的合約,假設它了解其間可能被收取或返回了什麼。

更改津貼可能有其自身的後果。它可以讓先前失敗的路徑完成,也可以給被呼叫方足夠的 gas 執行在舊允許量下無法執行的工作。開發者在調整之前需要知道該允許量原本旨在防止什麼。

有些合約可以透過治理或管理流程進行更改。其他合約則是不可變的,或依賴於無法就地更改的組件。即使合約可以被修訂,對其交易進行估算、贊助或轉發的服務也可能需要更新其自身的假設。

一個有說服力的重現需要展示什麼

一個測試可以在舊規則與擬議規則下,以相同的交易、狀態和 gas 限制開始。比較應識別哪個呼叫返回失敗、呼叫者接下來做什麼,以及交易是否記錄了先前未持續存在的任何變更。

測試略高於和略低於閾值的預算有助於顯示該影響是否佔據一個狹窄範圍。它也可以識別執行在何處發生分歧。早期的餘額檢查、轉發給被呼叫方的金額以及失敗處理程序中的寫入,是變更可能顯現的不同時點。

然後審查者必須詢問誰能夠到達該路徑。在測試合約中重現的變更確立了執行上的差異。真實的應用程式可能需要授權、檢查一個單獨的條件,或使受影響的操作可重試。這些細節決定了某人是否能夠強制產生不想要的結果。

客戶端團隊還有一項單獨的測試。所有執行客戶端在相同的分叉配置下,對同一筆交易應得出相同的結果。客戶端之間的分歧,與所有客戶端一致產生應用程式未預期的結果,是兩個不同的問題。

測試套件既需要成功路徑,也需要失敗路徑。強制每個失敗的呼叫都回退,或許能防止一次不想要的狀態變更,但也會移除完成批次其餘部分的合法能力。預期的應用程式行為決定了修復需要保留什麼。

良好的重現應讓最終狀態易於檢視。如果失敗記錄在一次執行後仍存在,而在另一次執行後消失,測試就能顯示確切的差異,而不必依賴關於 gas 用量的一般性報告。這使得評估風險與擬議變更都更容易。

在本地重現之後,公共測試網還能補充什麼

開發者可以在本地分叉或受控的客戶端環境中測試邊緣案例。公共測試網則讓多個營運者執行相同的升級,並在共享條件下比較其行為。它也為錢包與基礎設施團隊提供了針對現行規則測試自身軟體的地方。

Sepolia 與 Hoodi 在該流程中服務於不同的步驟。Sepolia 的啟用顯示開發者能在該網路上執行計畫中的程式碼,並在配置的 gas 上限下檢視其運作。Hoodi 則在處理了審查期間變得重要的發現之後,為他們提供進一步的部署。

測試網上的應用程式、流量與歷史狀態都與主網不同。一次順暢的分叉能提供關於客戶端一致性和常規交易的證據,卻未涵蓋使用者依賴的每一種合約模式。針對性的重現則能提供關於某個邊緣案例的證據,而該案例可能不存在於普通的測試網流量中。

升級指示是測試的另一部分。營運者需要一個實作預期配置的版本,以及一個精確的啟用時點。應用程式需要知道其模擬應在何時開始使用修訂後的規則。新的日期與這些細節一併提供會很有用。

十月的延期與十一月的狀態報告在不同時間描述了同一次暫停。前者移除了預定的 Hoodi 日期。後者說明這些問題仍須解決。下一次的部署通知則能顯示哪些變更已準備好供營運者測試。

錢包如何在某個動作失敗時仍回報成功

錢包通常會在請使用者簽署之前估算 gas。該估算取決於節點在其模擬中所套用的狀態與規則。使用較舊分叉配置的服務可能給出一個不再適合當前鏈所執行之交易的估算。

一筆回退的交易仍可能讓發送者花費 gas。一筆在捕捉到內部失敗後才完成的外層交易可能更難解讀。鏈可以將整筆交易記錄為成功,而其中的某個動作卻沒有發生。錢包可能需要應用程式的事件或狀態,才能向使用者解釋其中的差異。

中繼者與交易贊助者面臨相關的問題。他們可能為他人請求的交易選擇預算或支付成本。如果預算不再涵蓋預期的路徑,贊助者可能為未能交付所請求動作的執行付費。

索引器能在執行後看到效果。一條如今會完成的失敗路徑,可能產生下游系統先前未曾見過的日誌或狀態變更。索引器仍遵循鏈的實際狀態。依賴索引器的應用程式可能需要改變其解讀所產生記錄的方式。

端對端測試可以比較錢包的估算、中繼者提交的預算、客戶端的執行結果,以及介面的說明。每一步都能各自成功,而使用者仍收到關於哪些動作已生效的誤導性描述。在應用程式將某個結果視為最終結果的地方,這種區別最為重要。

什麼能解除 Hoodi 的暫停

基金會正請應用程式團隊找出他們所使用的假設,並提供開發者能夠重現的案例。有些問題或許能透過修改擬議的 gas 規則來解決。其他問題則可能需要應用程式或基礎設施供應商修訂其處理新行為的方式。

如果規格改變,相關的測試就是某個先前出現分歧的案例如今是否達到預期結果。如果開發者保留某項行為變更,應用程式團隊就需要足夠的細節,以判定其軟體是否依賴先前的結果。這兩種結果都取決於描述受影響的呼叫,以及在其之後仍持續存在的內容。

修訂後的規範也必須送達客戶端建置,供營運者執行。支援較早 Glamsterdam 配置的建置可能不包含後續的變更。新的 Hoodi 通知中的版本號碼將指出哪些版本可以一起測試。

基金會的十一月更新表示,Hegota 的工作仍在平行進行。這意味著對較早分叉的暫緩並不涵蓋下一個分叉的每一項開發決策。對於 Glamsterdam,下一個相關的里程碑是修訂後的 Hoodi 時程,其配置是開發者已準備好公開執行的。

成功的分叉將為團隊提供一份共享記錄,以便在主網決策之前進行檢視。促使延遲的那些案例,仍然是修訂後規則是否準備就緒的最明確測試。這些測試必須顯示當呼叫在其 gas 限制附近失敗,而外部交易仍有工作待完成時會發生什麼。

提議的 gas 數字對不同路徑的說明

基金會的儲存庫提供了一個具體範例,說明建立狀態與更新狀態之間的差異。在其固定的 Glamsterdam 規範下,建立新槽位的冷寫入被拆分為執行成本和顯著更大的狀態費用。對現有槽位的寫入也會重新定價,但遵循不同的計算方式。

這種差異可能影響兩個提出看似相同應用請求的使用者。一位使用者可能以前使用過該服務,因此合約更新現有條目。另一位使用者可能需要全新的記錄。對第一位使用者有效的 gas 額度,對第二位使用者可能失敗。

該儲存庫還表示,在其測試的配置中,只有在超過指定的交易 gas 限制時,才會提供一個獨立的儲備池。在較小的交易中,狀態成本則來自普通預算。該閾值使得測試多種預算變得重要,而不是假設儲備池對每次呼叫的行為都相同。

因此,讀取剩餘 gas 的程式碼在某些情況下只能觀察到交易資源的一部分。它所讀取的資料對於該指令所暴露的預算仍然有意義。改變的是應用程式對於已消耗或仍可用的總資源所能得出的推論。

這些 gas 範例與提議的配置相關。它們並未提供一個可套用於錢包現有估算的單一乘數。首次儲存寫入、使用固定津貼的呼叫以及失敗的委託各自需要單獨檢查,因為它們會遇到規則的不同部分。

這也是為什麼修訂後的 Hoodi 日期若能搭配規範修訂以及該版本涵蓋的案例清單會更有用。這些細節將讓團隊能夠重新執行與其應用程式相符的測試,然後再從測試網的整體穩定性得出結論。

重點觀察

  • Hoodi 時程:修訂後的分叉日期應指明用戶端版本,以及營運者預期要執行的分叉設定。
  • 用戶端共識:跨用戶端測試可顯示執行用戶端在新邊界附近是否達到相同狀態與 gas 結果。
  • 合約行為:重現案例應顯示失敗的外部呼叫何時會讓呼叫方留下足夠 gas 完成執行,以及外層交易會記錄什麼。
  • 提案修訂:對 EIP-8037 或 EIP-8038 的變更將有助於顯示哪些審查發現需要修改協定。
  • 應用工具:模擬與 gas 估算結果可顯示錢包與基礎設施供應商是否正確反映分叉規則。

常見問題

什麼是 Hoodi?

Hoodi 是一個以太坊測試網,用於在共享環境中演練網路升級。被延後的分叉原本會在那裡套用 Glamsterdam 規則,讓營運者與應用團隊能一起觀察這些規則。

為什麼分叉被延後?

開發者正在審查與 gas 計算以及既有應用如何處理失敗呼叫相關的發現。他們也在確認各用戶端實作對於提案規則下的行為是否一致。

這次暫緩會改變今日的以太坊主網嗎?

十一月的更新涉及 Hoodi 測試分叉。它並未宣布在主要網路上啟用提案的 gas 規則,也未提供新的主網日期。

合約能在沒有更新的情況下改變行為嗎?

可以。其指令會在網路的 gas 排程下執行。如果變更後的收費讓外部呼叫或其失敗處理常式留下不同的預算,相同的指令可能導致不同的結果。

失敗的呼叫是否總是回退整筆交易?

呼叫方可以處理不成功的外部呼叫並繼續執行。外層交易是否完成,取決於呼叫方的指令以及執行這些指令所剩餘的 gas。

gas 儲備的作用是什麼?

在該提案下,它為符合條件的狀態建立操作提供一個獨立追蹤的預算。審查者必須考慮該預算與呼叫方可檢視或向前傳遞的執行 gas 之間如何互動。

為什麼稽核人員要測試低 gas 路徑?

預算充裕的呼叫在兩種排程下可能行為相同。一筆接近其執行上限的交易則可揭示處理常式是否在一種排程下完成、而在另一種排程下回退。

Hegota 的工作已經停止了嗎?

基金會十一月的更新表示 Hegota 的工作仍在平行進行。該工作有其自身的里程碑,而 Glamsterdam 的 Hoodi 分叉仍取決於 gas 審查。