Rollup 的大補帖:Proto-Danksharding(一)

NIC Lin
Taipei Ethereum Meetup
12 min readAug 18, 2022

本文將介紹 EIP-4844:Shard Blob Transaction,也稱為 Proto-Danksharding,一個將會大幅降低 Rollup 成本的技術提案。

https://www.eip4844.com

如果對 Rollup 及資料可用性還不熟悉的讀者,可以先參考這篇:

Recap:Rollup 不上傳資料到 L1 的優點與缺點

優點

省下資料上傳到 L1 的成本,這也是 Rollup 主要的成本所在。

缺點

ZK Rollup 若不上傳資料到 L1,當保管資料的第三方消失或藏資料,則使用者可能會無法離開 Rollup,但使用者不用擔心安全性,例如錢被捲走的可能。

Optimistic Rollup 若不上傳資料到 L1,當保管資料的第三方消失或藏資料,則 Rollup 將不再安全,因為其他人沒辦法成功挑戰攻擊者提交的錯的狀態(例如這個錯的狀態裡 Rollup 所有的錢都在攻擊者身上)。

上傳資料到 L1 有多貴?

上傳到 L1 都是以 calldata 的形式,1 個非零 byte 要 16 gas,一筆交易資料大小約數十至數百 byte,也就是耗費約數百到數千 gas。如果假設一筆交易資料需要 1000 gas,那把 L1 區塊塞到滿也只能塞 30m / 1k = 30k 筆交易。

這還不包含每一批交易額外的處理成本,下面這個 thread 去撈了當前 Optimism、Arbitrum 及 zkSync 平均每一批交易所花的 gas 總量,可以發現雖然每筆交易資料只花數百到數千 gas,但固定的交易處理成本都高達數十萬 gas(像是 ZK Rollup 本身驗證零知識證明就要耗費數十萬 gas)。

EIP-4488

EIP-4488 是短期最粗暴簡單來降低上傳資料到 L1 的成本的方式:直接把 calldata 每 byte 從 16 gas 降為 3 gas。

但這麼做是有代價的,目前每個區塊大小平均約 80–100 KB,如果極端情況發生,攻擊者用一筆交易的 calldata 塞滿無意義資料來耗掉所有 gas,那區塊大小會變成 30m / 16 byte,約等於 1.78 MB,在可接受範圍。但如果直接降低 calldata 成本為 3 gas,則極端情況中區塊大小會變成接近 10 MB,這就很有可能會造成一些網路比較差的節點開始落後而被淘汰,降低節點去中心化程度。

所以這個 EIP 另外加了規則是每個區塊最多的 calldata 大小不能超過 1 MB + 300 Byte * number_of_txs。如果攻擊者在區塊只放一筆交易,嘗試用這筆交易的 calldata 塞滿無意義資料,那它最多也只能塞入 1 MB + 300 Byte 的 calldata 資料;如果它在區塊放多筆交易,希望透過提高 number_of_txs 來提高 calldata 大小上限,則此時它會受限於每筆交易都會有的一個基本 21000 gas 消耗,因此這個區塊最多只能塞入 30m / 21k 約等於 1400 筆的交易,也就是 calldata 大小上限最多只能被提高到 1 MB + 300 Byte * 1400 約等於1.4 MB,這的大小甚至比目前的可接受範圍上限還低,所以就不需要擔心。

前面介紹了 Rollup 資料上傳成本及 EIP 4488,接下來將進入到今天的主題:將大幅降低 Rollup 成本的 EIP-4844 Shard Blob Transaction。

Recap:Rollup 上傳資料到 L1 的目的

Rollup 為了達成資料可用性而把資料上傳到 L1 ,但這並不是要讓 L1 合約能藉由這些上傳上去的資料來執行或驗算,我們只是需要這些資料放在 L1,讓所有人都看得到。而這也是為什麼 Shard Blob Transaction 可以協助降低 Rollup 資料上傳成本的原因:Rollup 的資料要讓大家看得到,但是它不需要用 calldata 的方式!它不需要讓合約能讀取到。

於是 Shard Blob Transaction 就被設計出來:一個新的交易格式專門來讓 Rollup 放「能讓大家看的到但是又不會被合約讀取到的資料」。

EIP-4844:Shard Blob Transaction

這個 EIP 會引進一個新的 L1 交易格式,稱作 Shard Blob Transaction。它和原本的交易格式幾乎一樣,除了它多了一個 Blob 欄位。每個 Blob 為一個長度 4096 的陣列,陣列裡的每個元素都是一個 32 byte 的值,因此每個 Blob 的大小為 4096 * 32 Byte,約為 128 KB。每個區塊可以有多筆 Shard Blob Transaction。

Blob 特色 1:不可以被合約存取

但是 Blob 裡面的值是不可以在合約內被存取的,只有把 Blob 裡面所有的值做成的 commitment 才可以被合約存取。「做成 commitment 」你可以想像成把 Blob 裡頭的元素一起組成一個 Merkle Tree,然後只有 Merkle Root 能被合約存取。至於為什麼要這樣設計,待會就會提到。

只有元素們的 commitment 能被合約存取

註:實際上不會是以 Merkle Tree 的方式來做成 commitment,而是用 KZG。KZG Proof 大小比 Merkle Proof 小的許多,驗證步驟也比 Merkle Proof 少的許多,但缺點是它需要經過可信任設置(Trusted Setup)及不防量子攻擊。

Blob 特色2:有保存期限

除了 Blob 裡面的值不可以被合約內存取的特色外,還有另一個特色是:Blob 裡面的值在經過一段時間後(例如一個月)節點就可以將其刪除。

一段時間後節點就可以刪除 Blob 裡的元素,不需再保存在硬碟裡

為什麼會需要一種資料是合約不能存取然後又有保存期限?

如前面所述,我們只是需要 Rollup 資料能 讓所有人都看得到,但不需要合約能讀取到

  • 以 Optimistic Rollup 為例,其所上傳的交易資料只有在什麼時候才會真正被 L1 合約使用到?答案是有人在 L1 合約去發起挑戰並揭曉結果的時候
  • 又或著是 ZK Rollup,零知識證明已經證明了狀態的更新是正確的,上傳交易資料只是讓使用者能自己算出最新的狀態,例如完整的 State Tree(L1 合約只會存 State Root)

這表示大部分的時間交易資料都是不需要被合約所使用的,而且即便在 Optimistic Rollup 發起挑戰時會需要交易資料,參與方只要能證明交易資料「出現過」即可,不需要在交易上傳時就先把它記錄在合約裡,等著哪天被挑戰時可以派上用場

如果今天我們把 Rollup 交易放在 Blob 資料裡,雖然合約存取不到,但至少這些交易的 commitment 能被合約存取到,只要在合約裡記錄這個 commitment (32 byte)即可。將來哪一天挑戰機制會需要某一個 commitment 裡面所包含的交易時,我只要提供交易資料並證明這筆交易資料真的是屬於那個 commitment 就可以了(就像用 Merkle Proof 證明一筆交易存在在一個 Merkle Tree 裡)!如此就能說服合約該筆 Rollup 交易真的存在於歷史中,並將這筆交易資料交給挑戰機制使用。

用 Merkle Proof 證明 Tx 屬於一個 commitment(Merkle Root),src

那為什麼會需要設一個保存期限呢?這也是 Ethereum 在往解決State Bloat 的路上的其中一步:我們只需要保存所需資料久到讓節點都能有足夠時間同步資料即可,而保存所有完整歷史資料的任務應該交給對那些資料有興趣的人。

假設要給 Optimistic Rollup 來使用 Shard Blob Transaction,我們就要確保 Blob 資料保存時間至少要比 Optimistic Rollup 的挑戰期來的長,避免要發起挑戰時卻要不到資料。而當挑戰期結束,Blob 資料也就沒有必要一直存著了,因為也沒辦法挑戰了。

要確保節點在挑戰期結束前還保存著 Blob 內容,也就是交易資料

剩下就是讓有動機要保存資料的角色,例如 L1 Archive Node、L2 節點、 L2 Block Explorer 等等去繼續保存所需的資料,因此我們也要確保保存期限久到讓這些角色有足夠多的時間來取得這些資料。

而「不可被合約存取」及「有保存期限」這兩個特色也正是為什麼 Shard Blob Transaction 可以替 Rollup 降低大幅的成本,因為有這兩個特色的資料遠比「可被合約存取」及「需要永久保存」的 calldata 資料還來得便宜非常非常多。

註:calldata 會需要節點在執行交易時把它寫進記憶體裡,而不可被合約存取的 Blob 資料則完全可以直接寫進硬碟裡不管它,這兩者所消耗的節點資源是不一樣的。

Blob 會因其特性而比 calldata 來得便宜許多

Optimistic Rollup + Proto-Danksharding

Optimistic Rollup 使用 Proto-Danksharding 的方式如前面一段所述,只有在挑戰發生時才需要上傳並讓合約存取到 Blob 裡的交易資料,並驗證交易資料和當時的 commitment 對的起來。

為了方便並便宜的驗證交易資料及 commitment 之間的關係,這個 EIP 新增了一個 Precompile 合約(Point Evaluation Precompile)專門來做這個驗證:將 Blob 內容(交易資料)及 commitment 交給這個 Precompile 合約,Precompile 合約會回傳該交易資料是否和該 commitment 對應。

交易上傳時,在合約紀錄 commitment
當發生挑戰需要交易資料時,透過 Precompile 證明交易資料及 commitment 關係

ZK Rollup + Proto-Danksharding

不像 Optimistic Rollup,ZK Rollup 不需要挑戰機制,因為安全性是由 Validity Proof 保證,因此 ZK Rollup 不需交易資料可被合約存取,不過我們必須要確保 Operator 放到 Blob 裡的交易資料和 Validity Proof 所驗證的交易是對的起來的,否則 Operator 可以在 Validity Proof 裡驗證交易 A ,但在 Blob 裡放交易 B。

Operator 放在 Blob 裡的交易和 Validity Proof 驗證的交易不一樣

因此 ZK Rollup 除了要利用 Point Evaluation Precompile 來證明一筆交易資料和 commitment 的關係,同時也要產生相對應的 proof 來證明 Validity Proof 所驗證的也是一樣的交易,例如我們要同時驗證在 Blob 裡的第三筆交易,也是 Validity Proof 驗證的第三筆交易。這個驗證比對方式稱作 Proof of Equivalence。

用 Precompile 及另一個證明來確保 tx1 同時是 Blob 中及 Validity Proof 中的第一筆交易

Versioned Hash

前面有提到 commit 的方式是使用 KZG commitment 而不是 Merkle Tree。但為了向前兼容,例如未來可能用其他 commitment 方式取代 KZG,因此實際上合約能存取到的 commitment 值會是 KZG commitment 值再經過一次 keccak256 雜湊,稱作 Versioned Hash。如此就能避免驗證 commitment 時只能受限於 KZG 的驗證方法。

總結

當前 Rollup 一個主要成本為將資料上傳到 L1 的成本,為了避開這個成本,出現了其他設計或模式(例如 Validium, Arbitrum AnyTrust)將資料交給第三方或其他鏈,但這也衍生出信任問題。

EIP-4844 Proto-Danksharding 則將幫助 Rollup 重返榮耀,在不犧牲安全性或信任假設的前提下,由 L1 新增一種交易格式及 Precompile 合約,藉此讓 Rollup 上傳資料的成本大幅降低。

--

--