前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)



一文科普Arbitrum的運轉機理。

撰文:羅奔奔,前 Arbitrum 技術大使、極客 web3 貢獻者

本文是 Arbitrum 前技術大使 及 智慧合約自動化審計公司 Goplus Security 前聯合創始人羅奔奔 對 Arbitrum One 的技術解讀。

因為中文圈子裡涉及 Layer2 的文章或資料,缺乏對 Arbitrum 乃至 OP Rollup 的專業解讀,本文試圖通過科普 Arbitrum 的運轉機理,填補這一領域的空缺。由於 Arbitrum 本身的結構太複雜,全文在盡可能簡化的基礎上,還是超過了 1 萬字篇幅,所以分成了上下兩篇,建議作為參考資料收藏轉發!

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图1

Rollup 排序器簡述

Rollup 擴容的原理可以概括為兩點:

成本優化:將⼤部分運算與存儲任務移交至 L1 鏈下也即 L2 上。L2 大多是運⾏在單臺服務器也即排序器(Sequencer/Operator)上的⼀條鏈。

排序器在觀感上接近於一臺中心化服務器,在「區塊鏈不可能三⻆」中捨棄「去中心化」來換取 TPS 與成本上的優勢。⽤戶可以讓 L2 來代替以太坊處理交易指令,成本比在以太坊上交易要低得多。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图3

安全保障L2 上的交易內容與交易後的狀態,會同步⾄以太坊 L1,通過合約來校驗 狀態轉換的有效性。同時,以太坊上會保留 L2 的歷史記錄,排序器即便永久宕機,他⼈也可以通過以太坊上的記錄,還原出整個 L2 的狀態。

從根本上來說,Rollup 的安全性是基於以太坊的。排序器如果不知道某個賬戶的私鑰,就無法用該賬戶的名義發起交易,或者無法篡改該賬戶的資產餘額(即便這麼做了,也很快被識破)。

雖然排序器作為系統中樞帶有中⼼化色彩,但在成熟度比較高的 Rollup 方案中,中心化排序器僅能實施交易審查等軟性作惡⾏為,或者惡意宕機,但在理想狀態的 Rollup ⽅案中,有相應的⼿段進⾏遏制(比如強制提款或排序證明等抗審查機制)。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图5

(路印協定在 L1 上的合約源碼中設置的,供用戶調用的強制提款函數)

而防止 Rollup 排序器作惡的狀態校驗⽅式,分為欺詐證明(Fraud Proof)和有效性證明(Validity Proof)兩類。使⽤欺詐證明的 Rollup ⽅案稱為 OP Rollup(Optimistic Rollup,OPR),⽽因為一些歷史包袱,使⽤有效性證明的 Rollup 往往被稱為 ZK Rollup(Zero-knowledge Proof Rollup,ZKR),而不是 Validity Rollup。

Arbitrum One 是典型的 OPR,它部署在 L1 上的合約,並不主動驗證提交過來的數據,樂觀地認為這些數據沒有問題。如果提交的數據有錯誤,L2 的驗證者節點會主動發起挑戰。

因此OPR 也暗含一條信任假設:任意時刻⾄少有⼀個誠實的 L2 驗證者節點。⽽ ZKR 的合約則通過密碼學計算,主動但低成本地驗證排序器提交的數據。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图7

(樂觀 Rollup 運轉方式)

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图9

(ZK Rollup 運轉方式)

本文會深度介紹樂觀式 Rollup 中的龍頭專案——Arbitrum One,覆蓋整個系統的方方面面,仔細閱讀完後你將對 Arbitrum 和樂觀式 Rollup/OPR 有深刻的理解。

Arbitrum 的核心元件與工作流程

核心合約:

Arbitrum 最重要的合約包括SequencerInbox, DelayedInbox, L1 Gateways, L2 Gateways, Outbox, RollupCore, Bridge 等。後續將詳細介紹。

排序器 Sequencer:

接收用戶交易並進行排序,計算交易結果,並迅速(通常<1s)返還給用戶回執。用戶往往在幾秒內就能看到自己的交易在 L2 上鏈,體驗就如同 Web2 平臺。

同時,排序器還會在以太坊鏈下即時廣播最新產生的 L2 Block,任何一個 Layer2 節點都可以非同步的接收。但此時,這些 L2 Block 不具備最終確定性,可以被排序器回滾掉。

每隔幾分鐘,排序器會將排序後的 L2 交易數據進行壓縮,聚合成批次(Batch),提交至 Layer1 上的收件箱合約 SequencerInbox,以保證數據可用性和 Rollup 協定的運轉。一般而言,被提交至 Layer1 上的 L2 數據無法回滾,可以具備最終確定性。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图11

從以上流程中我們可以概括:Layer2 有自己的節點網路,但這些節點數量稀少,且一般沒有公鏈慣用的共識協定,所以安全性是很差的,必須要依附於以太坊來保證,數據發佈的可靠性與狀態轉換的有效性。

Arbitrum Rollup 協定:

定義 Rollup 鏈的區塊 RBlock 的結構,鏈的延續方式,RBlock 的發佈,以及挑戰模式流程等⼀系列的合約。注意,這⾥說的 Rollup 鏈並不是大家理解的 Layer2 賬本,而是 Arbitrum One 為了施展欺詐證明機制,而獨立設置的一條抽象出來的「鏈狀數據結構」。

⼀個 RBlock 可以包含多個 L2 區塊的結果,⽽且數據也迥異,它的數據實體 RBlock 存儲在 RollupCore 的⼀系列合約中。如果⼀個 RBlock 存在問題,Validator 將⾯向該 RBlock 的提交者對其進⾏挑戰。

驗證者 Validator:

Arbitrum 的驗證者節點其實是 Layer2 全節點的特殊子集,目前有白名單準入。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图13

Validator 根據排序器提交至 SequencerInbox 合約的交易批次 batch,來創建新的 RBlock(Rollup 區塊,也叫斷⾔ assertion),並監控當前 Rollup 鏈的狀態,對排序器提交的錯誤數據進⾏挑戰。

主動型的 Validator 需要事先在 ETH 鏈上質押資產,有時我們也稱其為 Staker。不進⾏質押的 Layer2 節點雖然也可以監控 Rollup 的運⾏動態,向⽤戶發送異常報警等,但⽆法在 ETH 鏈上直接對排序器提交的錯誤數據進行⼲預。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图15

挑戰:

基礎步驟可以概括為多輪互動式細分、單步證明。在細分環節,挑戰雙⽅先對有問題的交易數據進⾏多輪迴合制細分,直⾄分解出有問題的那⼀步操作碼指令,並進⾏驗證。「多輪細分 – 單步證明」這種範式,被 Arbitrum 開發者認為是欺詐證明中最節省 gas 的實現⽅式。所有環節都在合約控制之下,沒有⼀⽅可以作弊。

挑戰期:

由於 OP Rollup 的樂觀 optimistic 本質,每個 RBlock 提交上鏈後,合約並不主動檢查,預留給驗證者一段時間窗⼝期去證偽。此時間窗⼝即為挑戰期,在 Arbitrum One 主⽹上為 1 周。挑戰期結束後,該 RBlock 才會被最終確認,塊內對應的從 L2 傳遞到 L1 的消息(比如通過官方橋執行的提款操作)才能被放行。

ArbOS, Geth, WAVM:

Arbitrum 採用的虛擬機名為 AVM,包含 Geth 和 ArbOS 兩部分。Geth 是以太坊最常⽤的客戶端軟體,Arbitrum 對其進⾏了輕量化的修改。ArbOS 負責所有 L2 相關的特殊功能,如⽹絡資源管理、⽣成 L2 區塊、與 EVM 協同⼯作等。我們將兩者的組合視為⼀個 Native AVM,也就是 Arbitrum 採用的虛擬機。WAVM 是把 AVM 的代碼編譯為 Wasm 後的結果。Arbitrum 挑戰流程中,最後的那個「單步證明」,驗證的就是 WAVM 指令。

在此,我們可以將上述各個元件之間的關係和⼯作流⽤下圖來表示:

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图17

L2 交易生命週期

一筆 L2 交易的處理流程如下:

1.用戶向排序器發送交易指令。

2.排序器先對待處理交易進數位簽名等數據的驗證,剔除無效交易,並進行排序和運算。

3.排序器將交易回執發送給⽤戶(通常都⾮常快),但這只是排序器在 ETH 鏈下進行的「預處理」,處於 Soft Finality 的狀態,並不可靠。但對於信任排序器的⽤戶(⼤部分⽤戶),可以樂觀的認為交易已經完成,不會被回滾。

4.排序器將預處理後的交易原始數據,⾼度壓縮後封裝為⼀個 Batch(批次)。

5.每隔⼀段時間(受到數據量、ETH 擁堵程度等因素影響),排序器會向 L1 上的 Sequencer Inbox 合約發佈交易 Batch。此時可認為,交易已擁有最終性 Hard Finality。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图19

Sequencer Inbox 合約

合約會接收排序器提交的交易 batch,保證數據可⽤性。深⼊地看,SequencerInbox 中的 batch 數據完整記錄了 Layer2 的交易輸入資訊,即使排序器永久宕機,任何⼈都可以根據 batch 的記錄還原 Layer2 的當前狀態,接替故障 / 跑路的排序器。

⽤物理的⽅式理解,我們所看到的 L2,只是 SequencerInbox 中 batch 的投影,光源則是 STF。因為光源 STF 不會輕易變化,所以影⼦的形狀只由充當物體的 batch 來決定。

Sequencer Inbox 合約⼜稱為快箱,排序器專門向其提交已經被預處理的交易,且只有排序器可向其提交數據。對應快箱的是慢箱 Delayer Inbox,其功能在後續流程中會有描述。

Validator 會一直監聽 SequencerInbox 合約,每當排序器向該合約發佈 Batch 後,就會拋出一個鏈上事件,Validator 監聽到這個事件發生後,就會去下載 batch 數據,在本地執⾏後,向 ETH 鏈上的 Rollup 協定合約發佈 RBlock 。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图21

Arbitrum 的 bridge 合約內有個叫累加器 accumulator 的參數,會針對新提交的 L2 batch,以及慢 Inbox 上新接收的交易數和資訊,進行記錄。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图23

(排序器向 SequencerInbox 不斷提交 batch)

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图25

(Batch 的具體資訊,data 欄位對應著 Batch 數據,這部分數據尺寸很大,截圖沒顯示完)

SequencerInbox 合約有兩個主要函數:

add Sequencer L2Batch From Origin(),排序器每次都會調用該函數向 Sequencer Inox 合約提交 Batch 數據。

force Inclusion(),該函數任何人都可以調用,用於實現抗審查交易。這個函數的生效方式,會在後面談到 Delayed Inbox 合約時詳細解釋。

上述兩個函數都會調用 bridge.enqueueSequencerMessage(),來更新 bridge 合約內的累加器參數 accumulator。

Gas 定價

顯然,L2 的交易不可能免費,因為這樣會引來 DoS 攻擊,另外則是排序器 L2 本身的運⾏成本,以及在 L1 上提交數據都會有開銷。⽤戶在 Layer2 網路內發起交易時,gas 費的結構如下:

佔用 Layer1 資源產生的數據發佈成本,主要來自於排序器提交的 batch(每個 batch 有很多用戶的交易),成本最終由交易發起者們均攤。數據發佈產生的手續費定價算法是動態的,排序器會根據近期的盈虧狀況、batch ⼤⼩、當前以太坊 gas 價格進⾏定價。

用戶因佔用 Layer2 資源產生的成本,設定了⼀個可以保證系統穩定運⾏的,每秒處理的 gas 上限(⽬前 Arbitrum One 是 700 萬)。L1 和 L2 的 gas 指導價格均由 ArbOS 跟蹤並調整,公式暫時不在此贅述。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图27

雖然具體的 gas 價格計算過程⽐較複雜,但⽤戶無需感知到這些細節,可以明顯感到 Rollup 交易費⽤比 ETH 主網便宜的多。

樂觀式欺詐證明

回顧上文,L2 實際上只是排序器在快箱中提交的交易輸入 batch 的投影,也即:

Transaction Inputs -> STF -> State Outputs。輸入已經確定,STF 是不變的,則輸出結果也是確定的,而欺詐證明和 Arbitrum Rollup 協定這套系統就是把輸出的狀態根,以 RBlock (aka 斷言)的形式發佈到 L1 上並對其進行樂觀式證明的一套系統。

在 L1 上有排序器發佈的輸⼊數據,也有驗證者發佈的輸出狀態。我們再仔細考量⼀下,是否有必要向鏈上發佈 Layer2 的狀態呢?

因為輸⼊已經完全決定了輸出,而輸入數據是公開可見的,再提交輸出結果 – 狀態似乎是多餘的?但這種想法忽略了 L1-L2 兩個系統之間實際上需要狀態結算,也即 L2 向 L1 ⽅向的提現⾏為,需要有對狀態的證明。

在搭建 Rollup 的時候,⼀條最核⼼的思想就是把⼤部分運算和存儲放到 L2 上來規避 L1 ⾼昂的費⽤,這也就意味著,L1 並不知道 L2 的狀態,它僅僅幫助 L2 排序器發佈全體交易的輸入數據,但並不負責計算出 L2 的狀態。

⽽提現⾏為,本質上是依照 L2 給出的跨鏈消息,從 L1 的合約⾥解鎖相應資⾦,劃轉到⽤戶的 L1 賬戶中或完成其他事情。

此時 Layer1 的合約就會問:你在 Layer2 上的狀態是怎樣的,怎麼證明你真的擁有這些聲明要跨走的資產。這個時候用戶要給出對應該的 Merkle Proof 等。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图29

所以,如果我們構建⼀條沒有提現功能的 Rollup,理論上不向 L1 進⾏狀態同步是可以的,也不需要欺詐證明等狀態證明系統(雖然可能帶來其他問題)。但在現實應⽤中,這顯然是不可⾏的。

所謂的樂觀式證明中,合約不會去檢查提交到 L1 的輸出狀態是否正確,樂觀地認為一切都是準確無誤的。樂觀證明系統會假設,在任意時刻都有⾄少⼀名誠實的 Validator,如果出現錯誤的狀態,則通過欺詐證明進⾏挑戰。

這麼設計的好處是,不需要主動驗證每⼀個發佈到 L1 上的 RBlock,避免浪費 gas。實際上對於 OPR ⽽⾔,對每⼀個斷⾔進⾏驗證也是不現實的,因為每個 Rblock 都包含著一或多個 L2 區塊,要在 L1 上去對每筆交易重新執⾏⼀遍,與直接在 L1 上執行 L2 交易無異,這就失去了 Layer2 擴容的意義。

⽽ ZKR 不存在這個問題,因為 ZK Proof 有簡潔性,只需要驗證⼀個很⼩的 Proof,不需要真地去執⾏該 Proof 背後所對應的許多條交易。所以 ZKR 並不是樂觀式運⾏,每次發佈狀態都會有 Verfier 合約進⾏數學驗證。

欺詐證明雖然不能像零知識證明那樣具有⾼度的簡潔性,但 Arbitrum 使⽤了⼀種「多輪分割 – 單步證明」的輪流式交互流程,最終需要證明的僅僅是單⼀的虛擬機操作碼,成本相對較⼩。

Rollup 協定

我們先來看一下,發起挑戰和啟動證明的入口,也即 Rollup 協定是如何工作的。

Rollup 協定的核心合約是 RollupProxy.sol,在保證數據結構一致的情況下,使用了一個罕見的雙重代理結構,一個代理對應兩個實現 RollupUserLogic.sol 和 RollupAdminLogic.sol,在 Scan 等工具中目前還無法很好的解析。

另外還有ChallengeManager.sol 合約負責管理挑戰,OneStepProver 系列合約來判定欺詐證明。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图31

在 RollupProxy 中,記錄由不同 Validator 提交的一系列 RBlock(aka 斷言),也即下圖中的方塊:綠色 – 已確認,藍色 – 未確認,黃色 – 已證偽。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图33

RBlock 中包含了自上一個 RBlock 以來,一個或多個 L2 區塊執行後的最終狀態。這些 RBlock 在形態上構成了一條形式上的 Rollup Chain(注意 L2 賬本本身相區別)。在樂觀情況下,這條 Rollup Chain 應該是沒有分叉的,因為有分叉意味著有 Validator 提交了彼此衝突的 Rollup Block。

要提出或認同斷言,需要驗證者先為該斷言質押一定數量的 ETH,成為 Staker。這樣在發生挑戰 / 欺詐證明時,輸者的質押品將被罰沒,這是保障驗證者誠實行為的經濟學基礎。

圖中右下角的 111 號藍色塊最終會被證偽,因為其父塊 104 號區塊是錯誤的(黃色)。

此外,驗證者 A 提出了 106 號 Rollup Block,而 B 不同意,對其進行挑戰。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图35

在 B 發起挑戰後,ChallengeManager 合約負責驗證對挑戰步驟的細分過程:

1.細分是一個雙方輪流互動的過程,一方對某個 Rollup Block 中包含的歷史數據進行分段,另一方指出是哪部分數據片段有問題。類似於二分法(實際是 N/K)不斷漸進縮小範圍的一個過程。

2.之後,可以繼續定位至哪條交易及結果有問題,再進一步細分至該交易中有爭議的某條機器指令。

3.ChallengeManager 合約只檢查對原始數據進行細分後,產生的『數據片段』是否有效。

4.當挑戰者和被挑戰者定位到了將被挑戰的那條機器指令後,挑戰者調用 oneStepProveExecution(),發送單步欺詐證明,證明這條機器指令的執行結果有問題。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图37

單步證明

單步證明是整個 Arbitrum 的欺詐證明的核心。我們看一下單步證明具體證明的是什麼內容。

這需要先理解 WAVM,Wasm Arbitrum Virtual Machine,它是一個由 ArbOS 模塊和 Geth(以太坊客戶端)核心模塊共同編譯成的虛擬機。由於 L2 與 L1 有許多截然不同的地方,原始的 Geth 核心必須經過輕量修改,並且配合 ArbOS 一起工作。

所以,L2 上的狀態轉換其實是 ArbOS+Geth Core 的共同手筆。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图39

Arbitrum 的節點客戶端(排序器、驗證者、全節點等),是將上述 ArbOS+Geth Core 處理的程式,編譯為節點主機能直接處理的原生機器代碼(for x86/ARM/PC/Mac/etc.)。

如果把編譯後得到的目標語言更改為 Wasm,就得到了驗證者生成欺詐證明時使用的 WAVM,而驗證單步證明的合約上,類比的也是 WAVM 虛擬機的功能。

那為什麼在生成欺詐證明時,要編譯為 Wasm 位元組碼?主要還是因為,驗證單步欺詐證明的合約,要用以太坊智慧合約類比出 能處理某套指令集的虛擬機 VM,而 WASM 易於在合約上實現類比。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图41

但 WASM 相比於 Native 機器代碼,運行速度略慢,所以只有在欺詐證明生成及驗證的時候,Arbitrum 的節點 / 合約才會用到 WAVM。

在之前的多輪互動細分後,單步證明最終證明的是 WAVM 指令集中的單步指令。

下面的代碼中可以看到,OneStepProofEntry 首先要判定,待證明指令的操作碼屬於哪個類別,再調用相應的 prover 如 Mem,Math 等,將單步指令傳入該 prover 合約。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图43

最終結果 afterHash 會回到 ChallengeManager,如果該哈希與 Rollup Block 上記錄的,指令運算後的哈希不一致,則挑戰成功。如果一致,則說明 Rollup Block 上記錄的這個指令運行結果沒問題,挑戰失敗。

前 Arbitrum 技術大使解讀 Arbitrum 元件結構(上)插图45

在下一篇文章中,我們將解析 Arbitrum 乃至於 Layer2 與 Layer1 之間處理跨鏈消息 / 橋接功能 的合約模塊,並進一步闡明,一個真正意義的 Layer2 應該怎麼實現抗審查。

聯系郵箱:0xniumao@gmail.com