這篇文章的目的是正式公開一個對以太坊平臺的嚴重威脅,其危險性清晰而明確,直到“柏林”硬分叉才解除。
狀態
我們先來了解一些以太坊和“狀態”的背景知識。
以太坊狀態是一棵帕特里夏-默克爾樹。本文不會深入過多細節,你只要知道,隨著狀態數量的增長,這個樹結構的分支會變得越來越密。以太坊區塊鏈上每多一個賬戶,這棵樹就多一個葉子節點。在樹的根節點與葉子節點,是許多所謂的“中間”節點。
為了查找某個賬戶,或者說在這棵龐大的樹上找到某片“葉子”,需要解析6~9個哈希值,從根節點開始,經由中間節點,最終解析到一個能夠給予我們所需數據的哈希值。
用大白話來說:無論什么時候要在這棵樹上查找某個賬戶,都要經過8~9次解析操作。每次解析操作都是一次數據庫查詢,而每一次數據庫查詢都意味著不確定數量的多次硬盤操作。硬盤操作的次數很難估計,但是因為狀態樹的“鍵”是密碼學哈希值,所以這些鍵都是隨機的,這對所有數據庫來說都屬于最壞的情況。
隨著以太坊狀態的增加,就有必要提高訪問狀態樹的操作的Gas消耗量。早在2016年10月,我們就曾用“橘子口哨”分叉做過這樣的事。EIP150大幅提高了特定操作的Gas消耗量,并引入了一系列的措施來保護網絡免于DoS攻擊;這是在所謂的“上海攻擊”之后推出的。
EraLend:將部署經派盾審計的新版本協議,舊協議更名為EraLend Classic:8月8日消息,此前遭遇黑客攻擊的借貸協議Eralend發文宣布,將部署經派盾(PeckShield)審計的新版本協議,新協議將按原計劃進行開發升級,此前受攻擊影響的舊版本協議將更名為EraLend Classic。今后,EraLend將繼續努力追蹤并收回被盜資金,直到完全追回。EraLend將聘請慢霧(SlowMist)作為安全顧問,后者將在追贓以及后續產品安全方面為Eralend提供支持。 Eralend將逐步引入其他還款來源,包括籌款、潛在的zkSync空投和多元化的平臺收入等等。新版協議EraLend將取消SyncSwap LP代幣作為抵押品,且所有費用收入均將用來賠償受害者。舊版協議EraLend Classic則將從UTC時間8月8日00:00開始停止所有貸款功能,還款及提款功能將繼續開放,直到所有用戶退出。[2023/8/8 21:32:13]
另一次這樣的Gas消耗量提升是在“伊斯坦布爾”分叉的時候,在區塊高度?9069000?激活,引入了EIP1884。1884的內容包括:
SLOAD?操作碼的Gas消耗量從?200?提高到?800?gas
BALANCE?消耗量從?400?提高到?700?gas
加密支票賬戶提供商Juno:強烈建議用戶將加密資產提取到自托管錢包:1月5日消息,加密支票賬戶提供商Juno發文表示,強烈建議用戶將加密資產提取到自托管錢包,或通過合作銀行在Juno支票賬戶中出售加密貨幣以換取現金,相關賬戶由聯邦存款保險公司(FDIC)提供支持,最高保額達25萬美元。
Juno表示其現任托管人Wyre準備在未來幾周內逐步減少其業務,「我們正在更換托管人,因為我們預計Wyre可能會出現潛在問題,因為他們可能會縮減規模或縮減規模」。接下來正在努力盡快重啟加密貨幣購買和存款功能。[2023/1/5 9:53:39]
EXTCODEHASH?消耗量從?400?提升到?700?gas
問題
在2019年3月,MartinSwende測量了EVM操作碼的性能。這一研究后來導致了EIP-1884的創建。在1884激活的幾個月前,這篇以“BrokenMetre”為名的論文發表。
兩位以太坊安全研究員——HubertRitzdorf和MatthiasEgli——與這篇論文的作者之一DanielPerez展開了合作,并“武器化”了一個漏洞,并提交給了以太坊的bug懸賞項目。那是在2019年10月4日。
我們建議你完整地閱讀他們提交的報告,寫得非常好。
流動性質押協議stake.link推出LINK質押池:12月7日消息,面向Chainlink 2.0的流動性質押協議stake.link宣布推出LINK質押池。截止發稿,協議已質押16.9萬枚LINK。此前報道,去中心化預言機網絡Chainlink官方宣布,其質押v0.1測試版本計劃于北京時間12月7日13:00時上線以太坊主網。
符合提前體驗測試版本條件的地址將可在v0.1質押池中質押最多7000枚LINK。此外,v0.1質押池將于北京時間12月9日13:00面向所有普通用戶開放,每個地址質押上限為7000枚LINK,質押池總量上限為2500萬枚LINK。[2022/12/7 21:27:59]
在一個專門討論跨客戶端安全性的頻道里,來自Geth客戶端、Parity客戶端和Aleth客戶端的開發者被告知了這份報告,就在同一天。
該漏洞的本質是觸發隨機的樹查找。一個非常簡單的變體是:
在他們的報告里,研究員通過?eth_call?RPC端點對同步到主網的節點執行了這一負載,下面是它們消耗1000萬gas所需的時間。
使用?EXTCOEHASH?耗盡1000萬gas
Parity:約90秒
David Chaum:區塊鏈有很多機會和增長空間:金色財經報道,加密貨幣教父、密碼學家David Chaum在接受采訪時表示,非常棒的是,比特幣將他的愿景的形象提升到了當權者無法忽視的程度,而這正在改變游戲規則。
他認為區塊鏈有很多機會和增長空間。然而,目前的隱私狀況是他最關心的問題。當被問及他對 Tornado Cash 和 Circle 將使用 USDC 的地址轉移到“黑名單”相關地址的看法時,他指出這“非常令人不安”。Chaum隨后聲稱這“有點超出他的范圍,但實際上,他對底層技術有著深刻的理解。[2022/8/21 12:38:54]
Geth:約70秒
使用?EXTCODESIZE?消耗1000萬gas
Parity:約50秒
Geth:約38秒
顯而易見的是,EIP-1884確實減少了攻擊的效果,但還是遠遠不夠的。
那時候離大阪Devcon已經很近了。在Devcon期間,關于這一問題的知識在主網的客戶端開發者之間傳開來。我們也會晤了Hubert和Mathias,還有GregMarkou。ETC區塊鏈的開發者們也收到了這份報告。
隨著2019年接近尾聲,我們發現,這問題比我們之前以為的還要棘手,惡意的事務可能導致出塊時間延長到以分鐘計。更難辦的是,開發者社區已經對EIP-1884感到不滿,它打破了一些合約,而且用戶和礦工都希望提高區塊的GasLimit。
Bifrost:首批Kusama vsBond將于8月6日到期,請及時處理贖回:據官方消息,Bifrost Kusama作為 SALP(插槽競拍流動性協議)的首批支持項目,vsBond-20220516-KSM-BNC的贖回使用期截至時間為2022年8月6日,用戶可進入bifrost.app完成贖回。
在SALP協議中,vsKSM代表了同質化的通證屬性,而vsBond則以非同質化的屬性代表了某條平行鏈的貢獻贖回權以及租賃到期時間。當平行鏈到期,vsBond與vsKSM搭配可完成對KSM的1:1贖回,贖回使用期為84天,過期后vsBond將無法進行贖回。
據介紹,為了避免vsBond被惡意囤積,導致某種vsBond可能發生單點控制風險,對正常的兌換造成不良影響。因此SALP在協議設計層面為vsBond設置了84天的贖回使用期,過期的vsBond無法參與贖回,從而打消了惡意囤積vsBond的動機。
對于已過期的vsBond ,贖回(Redeem)與掛單交易(Order)功能即關閉。但用戶仍可使用Convert(轉換)功能將過期的vsBond轉換為vsKSM,從而挽回部分損失。
注:Bifrost是一個為Staking提供跨鏈流動性的Web 3.0基礎設施,通過跨鏈通信協議(XCMP)為多鏈提供去中心化、可跨鏈的Liquid Staking服務。[2022/7/6 1:54:38]
此外,僅僅兩個月之后,到了2019年12月,PartiyEthereum就宣布要退出了,OpenEthereum項目接管了Parity客戶端的代碼維護工作。
于是大家創建了一個新的客戶端協作頻道,Geth、Netheremind、OpenEthereum和Besu的開發者繼續合作。
解決方案
我們意識到,只有雙管齊下才能解決這個問題。一方面,我們要改進以太坊協議,也就是在協議層解決這個問題;最好是不要打破合約,也不要懲罰“善意”的行為,但又能防止攻擊。
另一方面,我們可以依靠軟件工程,改變客戶端內的數據模式和結構。
協議層工作
處理此類攻擊的第一個思路是這個。在2020年2月,其正式版本作為EIP2583發布。該提案背后的觀念是增加一個懲罰措施,每次樹查找導致miss時就觸發。
不過,Peter找出了一個繞過它的辦法——“shieldedrelay”攻擊——使得本質上懲罰有了一個上限。
懲罰miss?方法的問題在于,必須先有查找的過程,然后才能確定要不要實施懲罰。但如果剩余的gas已不足于實施懲罰,則一個沒有得到充分支付的消耗流程又已經執行了。即使這會導致拋出錯誤,這些狀態讀取也可以封裝到嵌套調用中,使得外部調用者可以重復執行攻擊而不必支付懲罰。
因此,這個EIP也被拋棄了,我們要尋找更好的替代方案。
AlexeyAkhunov研究了Oil的概念——一種次級的“Gas”,但與Gas完全不同的是,它對執行層是不可見的,而且可能導致事務全局回滾。
Martin提了一個類似的提案,稱為“Karma”,在2020年5月。
雖然這許多方案都有進展,VitalikButerin提議僅僅提高Gas消耗量,并維護一個“訪問清單”。在2020年8月,Martin和Vitalik開始迭代后來成為EIP-2929及其同伴EIP-2930?的想法。
EIP-2929在根本上解決了許多上面提到的問題。
與EIP-1884相反;1884是無條件提高Gas消耗量,但2929僅提高訪問新對象的Gas消耗量。這使得凈成本僅增加了不到一個百分點。
同樣地,與EIP-2930配合后,就不會打破任何合約。
它還可以通過提高Gas消耗量來進一步調整
在2021年4月14日,這兩個EIP都在“柏林”分叉時激活。
開發工作
Peter嘗試用動態的狀態快照解決這個問題,時值2019年10月。
快照是一個次級的數據結構,用來以扁平格式存儲以太坊狀態。快照可在Geth節點正常運行期間創建,無需下線專門執行。快照的好處是,它可以作為狀態訪問的一種加速結構:
不再是執行?O(logN)?次硬盤讀取來訪問一個賬戶/存儲項,快照可以提供直接的,O(1)?級別的訪問時間。
快照還支持以每個條目?O(1)?的復雜度迭代賬戶和存儲項,這使得遠程節點可以檢索連續的狀態數據,比以往便宜非常多。
快照的存在還支持其它更奇怪的用途,比如離線修剪狀態樹,以及遷移到另一種數據格式。
弊端是,快照等于是完全復制了賬戶和存儲項的未經處理的數據。若在主網環境中使用,這意味著需要額外25GB的固態硬盤空間。
動態快照的想法從2019年中就有了,當時的主要目標是啟用“快照同步”。那時候Geth團隊還在開發許多“大項目”:
離線的狀態修剪
同態快照快照同步
通過共享狀態實現LES狀態分散
不過,后來他們決定一心一意做快照功能,推遲了其他項目。這些工作為后來的?snap/1?同步算法打下了基礎。這一算法已在2020年3月合并到了代碼庫中。
有了“動態快照”功能,我們就能喘口氣了。如果以太坊網絡遭到攻擊,那會是很痛苦的,但至少,我們能通知用戶打開快照功能。生成快照需要花一些時間,而且還沒有辦法同步快照,但網絡至少能繼續運行了。
結合
在2021年3月/4月,?snap/1?協議已經在geth客戶端推出,節點能夠使用新的、基于快照的算法來同步區塊鏈了。雖然還不是默認的同步模式,這是使快照能不僅作為攻擊保護措施,也能顯著提高用戶體驗的一部。
在協議層,“柏林”升級已于2021年4月激活。
在我們的AWS監控環境中,我們的基準測試結果如下:
“柏林”前,沒有快照,處理2500萬gas:14.3秒
“柏林”前,有快照,處理2500萬gas:1.5秒
“柏林”后,沒有快照,處理2500萬gas:約3.1秒
“柏林”后,有快照,處理2500萬gas:約0.3秒
這個的數字表明,“柏林”升級使攻擊的效率降低了5倍,而快照使之降低了10倍,最終使其影響降低了50倍。
我們估計,在當前的主網上,不使用?快照的geth節點可能可以做到只需2.5~3秒就能執行一個區塊。隨著狀態的增長,這個數字會繼續惡化。
如果gas返還機制被用來造成單個區塊的實際gas使用量提升,這個惡化的倍數是2倍。在EIP-1559實施后,區塊的GasLimit會有更高的彈性,在短時間內可爆發出最大2倍的惡化乘數。
至于實施這種攻擊的可行性,攻擊者買斷一個區塊的成本大概在幾個ETH這樣的級別。
為何要在此時公開
這一威脅在很長時間里都是“公開的秘密”——因為疏忽,它至少被公開披露過一次;而且在核心開發者會議中也多次提到它,雖然沒有公開細節。
因為我們已經激活了“柏林”升級,也因為geth客戶端已經默認使用快照功能,我們認為,威脅已經足夠低,而透明化才是更重要的了。所以是時候把幕后的工作都公開了。
重要的是,社區得到了一次理解和思考這些影響用戶體驗的變更的機會。
大家好,我是狀元,擅長運用波浪理論、K線、布林帶、MACD、市場數據綜合對行情進行專業的分析預測.
1900/1/1 0:00:00木頭姐仍對比特幣表示信心,更大手買進Coinbase。她稱:“我仍然認為比特幣價格會達到50萬美元/枚。比特幣目前正經歷踏空,但不一定處于底部,現階段行情非常情緒化.
1900/1/1 0:00:00親愛的庫幣用戶, 為慶祝庫幣交易機器人合約網格全面開放給所有用戶,我們準備了總計10,000USDT獎池的活動邀您來參加!活動時間:2021年5月20日19:00(UTC8)-2021年5月26.
1900/1/1 0:00:00曉娜:大家好,歡迎收看少數圓桌派,我是曉娜,譚老師晚上好。老譚:曉娜晚上好,我們又見面了。曉娜:譚老師,對,譚老師,我記得我們前兩次做節目的時候,我們有一個約定,我不知道你還記不記得,因為我記得.
1900/1/1 0:00:00尊敬的ZT用戶: 由于杠桿ETF產品THETABEAR的精度過于冗長造成了用戶交易體驗差。我們將在2021年5月20日23:00啟動份額合并機制,屆時將關閉THETABEAR/USDT交易對交易.
1900/1/1 0:00:00親愛的庫幣用戶: 5月19日21:15左右,受行情劇烈波動的影響,庫幣移動端用戶流量激增,導致庫幣移動端服務器出現短時的故障.
1900/1/1 0:00:00