以太坊 Istanbul 硬分叉內容介紹

NIC Lin
CryptoCow
Published in
7 min readNov 23, 2019

距離上次的 Constantinople 硬分叉即將滿九個月,難度炸彈雖然還有三個月的時間,但為了避免一次進行太多升級,這次將會有 Istanbul 和 Berlin 兩個硬分叉。

Constantinople 硬分叉:

Istanbul 預計於區塊 9069000(2019/12/7 )進行主鏈的分叉。
Berlin 預期於 2020 進行分叉。

這次 Istanbul 硬分叉包含了影響開發者甚巨的變動 — EIP 1884 及 EIP 2200

Istanbul 硬分叉所包含的 EIP 如下:
EIP 152: 新增一個 precompiled contract — 用於 BLAKE2 雜湊演算法的壓縮函式 F
EIP 1108:降低 precompiled contract — alt_bn128 的 gas 定價
EIP 1344:新增 ChainID opcode
EIP 1884:調整部分讀取帳戶狀態 opcode 的 gas 價格
EIP 2028:調降 Transaction Input Data 的 gas 定價
EIP 2200:調整 SSTORE opcode 的計價方式(結合 EIP 1283 和 EIP 1706)

註:以下介紹順序沒有按照 EIP 編號。

EIP 1884:調整部分讀取帳戶狀態 opcode 的 gas 價格

節點在處理每筆交易前,要從狀態樹(state trie)讀取相關帳戶的狀態。隨著鏈上資料越來越多,狀態樹越來越大,讀取所需的資源也越來越高。因此這個 EIP 要調高部分讀取帳戶狀態 opcode 的 gas 價格:

SLOAD:如果該帳戶是個合約,則讀取該合約的某個變數會從 200 調高到 800 gas。
BALANCE:讀取指定帳戶的餘額,從 400 調高到 700 gas。
EXTCODEHASH:讀取某個指定合約的程式碼的雜湊值,從 400 調高到 700 gas。
新增 SELFBALANCE:如果是讀取本身帳戶的餘額,只需要 5 gas。

這個改動影響了不少已經部署的合約,因為某些函式有 gas 消耗總量的限制,所以這些 opcode 調漲可能會導致該函式無法成功執行。

更詳細的分析、探討請參考:
英文:https://github.com/holiman/eip-1884-security
中文:https://ethfans.org/posts/security-considerations-for-eip-1884

另外社群也提出了一些提案,希望能降低未來這種調整 opcode gas 的提案所造成的影響。例如 EIP 1702 提議每個帳戶新增一個版本(version)值,指定該帳戶使用的 EVM 版本,如此一來即便之後硬分叉,還是要使用指定的 EVM 版本規則來執行該合約。

EIP 2200:調整 SSTORE opcode 的計價方式(結合 EIP 1283 和 EIP 1706)

EIP 1283 原本預計在 Constantinople 硬分叉實行,但即時發現有漏洞後而延遲。這次加入了 EIP 1706 來防堵漏洞,EIP 1283 的介紹請參考 Constantinople 那篇文。
註:和 EIP 1283 有些不同 — 請把 EIP 1283 裡提到 200 gas 的地方換成 800 gas (因為 SLOAD200 調高到 800 gas)。

原本的漏洞在於 SSTORE 調整後修改變數的成本大幅降低,低到原本只有 2300 gas 額度的 sendtransfer 功能都能順便修改變數(原本修改變數至少需要 5000 gas,現在最低只需要 800 gas),因此會有 re-entrancy 攻擊的可能性。
所以加入了 EIP 1702 的限制:如果 gas 餘額低於或等於 2300 gas,則修改變數會導致錯誤。

EIP 1344:新增 ChainID opcode

當初 ETC 和 ETH 分道揚鑣後,為了避免彼此的交易被誤用或被有意拿到另外一條鏈上執行,所以提出了 EIP 155 — 藉由調整交易簽章規則讓一方的交易在另一方的鏈上會被視為無效的。

簡單來說,EIP 155 會把 ETH 的交易簽章加上一個固定值。如果是屬於 ETH 的客戶端就會知道要先把簽章扣掉這個固定值再驗證,而 ETC 的客戶端就會直接驗證這個簽章並將其視為無效。

而 EIP 1344 則是直接新增一個 ChainID opcode,讓合約可以透過這個 opcode 知道自己目前是在哪一條鏈上(以前合約無法判斷自己是在哪一條鏈上)。如此在合約裡驗證 meta- transaction 時便可再加上 ChainID 的驗證,避免新舊鏈的 meta-transaction 混在一起。

EIP 152:新增一個 precompiled contract — 用於 BLAKE2 雜湊演算法的壓縮函式 F

原本沒有以 precompiled contract 方式支援這個壓縮函式 F 的話,開發者必須要自己刻出相同功能的合約(以 EVM 去模擬這個函式),這會耗費大量的 gas。以 precompiled contract 方式則大大降低了 gas 花費。

Zcash 或其他以 Equihash 算法為基礎的 PoW 鏈會使用到 BLAKE2 雜湊函式,有了這個 precompiled contract 後讓合約驗證那些鏈的 PoW 成本大大降低,也讓跨鏈互動變得更可行。

EIP 1108:降低 precompiled contract — alt_bn128 的 gas 定價

alt_bn128 precompiled contract 在 Byzantium 硬分叉中被加入。

大意上是說在 alt_bn128 這條橢圓曲線上的 Pairing 演算法有被調整,並且客戶端也有進行優化,所以這個 precompiled contract 現在耗費的資源更少、執行得更快,因此調降這個 precompiled contract 的 gas 定價。

ECADD(橢圓曲線純量加法)由 500 gas 調降至 150 gas。
ECMUL(橢圓曲線純量乘法)由 40000 gas 調降至 6000 gas。
Pairing check(橢圓曲線配對驗證)由 80 000 * k + 100 000 調降至 34 000 * k + 45 000k 是驗證的數量。

調降後,zkSNARK 相關應用的交易成本將大幅降低。

EIP 2028:調降 Transaction Input Data 的 gas 定價

一筆交易(Transaction)包含不同欄位,有接收方地址(To)、多少 Ether(Value)等等的,Input Data 是其中一個。如果是單純轉錢的交易,則通常 Input Data 不會填入任何東西;如果是要執行合約,則 Input Data 要填入你要執行的函式和相關參數。

在這個 EIP 之前, Input Data 裡每一個值為零的 byte 會收 4 gas,每一個非零的 byte 會收 68 gas;在這個 EIP 之後,每一個值為零的 byte 一樣收 4 gas,但每一個非零的 byte 只會收 16 gas。

有許多零知識證明應用會需要在 Input Data 帶入該證明所要驗證的交易(這個交易指的是應用層的交易,用 Tx_App 代稱,不是一般的協議層交易,用 Tx 代稱),所以除了執行橢圓曲線運算所要耗費的 gas 是零知識證明應用目前的吞吐量瓶頸外,每筆交易(Tx)能帶入的交易(Tx_App)資料數量也是瓶頸之一。

因此調降了 Input Data 的 gas 定價後,零知識證明應用也能提高其交易吞吐量。同時要留下情話或揭露公司機密到鏈上也更便宜了。

更流暢的硬分叉規劃

隨著 Eth 1.X 的規劃慢慢完整,未來還有許多硬分叉規劃已經是可以預期的。因此社群提出了一些硬分叉規劃的建議:

提議大致包含
1. 明確訂立硬分叉頻率、時程,讓開發者、使用者能更有效掌握並應對硬分叉帶來的影響。
2. 該次硬分叉要納入的 EIP 必須是已經有共識、有實作,可以隨時部署的狀態,而不是決定要納入哪些 EIP 再來開始實作。
3. EIP 要先由一個獨立的 Working Group 來實作、測試,證明其可行性後客戶端團隊再各自實作,而不是由各個客戶端團隊同時從無到有實作、測試。同時 Working Group 要有一個主要負責人,統整 EIP 進度和對外聯繫。

更詳細的內容請參考原文。

--

--