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



Arbitrum 是怎麼處理跨鏈消息傳遞,以及抗審查交易的?

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

在上一篇文章《前 Arbitrum 技術大使解讀 Arbitrum 的元件結構(上)》,我們介紹了 Arbitrum 核心元件中的 排序器、Validator、Sequencer Inbox 合約、Rollup Block、非互動式欺詐證明的作用,而在今天的文章中,我們將重點講解 Arbitrum 核心元件中與跨鏈消息傳遞及抗審查交易入口相關的元件。

此前的文章中,我們曾提到,Sequencer Inbox 合約專門在 Layer1 上接收排序器發佈的交易數據包 Batch。同時,我們指出,Sequencer Inbox 又被稱作快箱,與之相對的是慢箱 Delayed Inbox(簡稱 Inbox)。下面,我們將對 Delayed Inbox 等與跨鏈消息傳遞相關的元件進行細緻解讀。

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

跨鏈與橋接的原理

跨鏈交易可分為 L1 到 L2(儲值)與 L2 到 L1(提現)。注意這⾥所說的儲值和提現未必與資產跨鏈相關,可以是不直接附帶資產的消息傳遞。所以這兩個詞僅僅表示跨鏈相關行為的兩個⽅向。

跨鏈交易與純 L2 交易相⽐,跨鏈交易在 L1 和 L2 這兩個不同的系統中進⾏了資訊互換,因此過程更復雜。

另外,通常我們說的跨鏈⾏為,是在兩個毫不相關的⽹絡上,⽤⻅證⼈模式的跨鏈橋進⾏的跨鏈,這種跨鏈的安全性取決於跨鏈橋的運營者,歷史上基於見證人模式的跨鏈橋被盜事件頻繁發生。

⽽在 Rollup 與 ETH 主⽹之間的跨鏈⾏為,與上述跨鏈有本質不同,因為 Layer2 的狀態是由記錄在 Layer1 上的數據決定的,只要你使⽤的是 Rollup 官⽅的跨鏈橋,其在運作結構上是絕對安全的。

這也凸顯出 Rollup 的本質,它只是在⽤戶角度看,像⼀條獨立的鏈,但實際上所謂的「Layer2」只是 Rollup 對⽤戶敞開的快速展示窗⼝,它的真實鏈式結構還是刻錄在 Layer1 上。所以,我們可以認為 L2 算半條鏈,或者說是「在 Layer1 上創造出的一條鏈」。

可重試票據 Retryables

需要注意,跨鏈都是非同步和非原子性的,它不可能像在一條鏈上一樣做完一筆交易確認後就知道結果,也不能保證另一側一定會在某個時間點發生某些事。因此跨鏈有可能因為一些軟性問題而失敗,但只要使用正確的手段,諸如可重試票據(Retryable Ticket),就不會發生資金卡住等硬性問題。

可重試票據是通過 Arbitrum 官方橋儲值時,用到的基本工具,ETH 和 ERC20 的儲值都會使⽤到。其⽣命週期分為三步:

1.在 L1 上提交票據。在 Delayed Inbox 合約中使用 createRetryableTicket() 方法創建儲值票據,並提交。

2. L2 上自動兌付。大部分情況下,排序器可以自動幫用戶兌付票據,無需後續的手動操作。

3. L2 上手動兌付。部分邊緣情況,如 L2 上 gas 價格突然激增,票據上預付的 gas 不夠,則無法自動兌付。此時需要用戶手動操作。

注意,如果自動兌付失敗,需要在 7 日內手動兌付票據,否則要麼票據將會被刪除(資金會永久損失),要麼需要為票據的保存支付一定費用來續租。

另外,對於 Arbitrum 官方橋的提現流程,雖然和儲值行為在流程上有一定對稱相似性,但並沒有 Retryables 這個概念,一方面可以從 Rollup 協定本身理解,另一方面我們可以從一些區別進行理解:

  • 提現的過程中不存在自動兌付,因為 EVM 沒有計時器或自動化,而 L2 上可以實現自動兌付,是排序器幫忙實現的,所以 L1 上用戶要手動與 Outbox 合約交互,以 Claim 取回資產。

  • 提現也不存在票據過期的問題,只要過了挑戰期,可以在任意時間領取。

ERC-20 資產跨鏈 Gateway

ERC-20 資產的跨鏈是複雜的。我們可以思考幾個問題:

  • 一個在 L1 上部署的代幣,它在 L2 上要如何部署?

  • 它的 L2 對應合約需要預先手動部署,還是系統可以自動為跨過來的、但尚未部署合約的代幣 自動部署資產合約?

  • L1 上的 ERC-20 資產,在 L2 對應的合約地址是什麼?是否該和 L1 一致?

  • 在 L2 上原生發行的代幣,如何跨鏈至 L1?

  • 擁有特殊功能的代幣,如可調整數量的 Rebase 型代幣,自增長生息代幣,如何跨鏈?

我們不打算全部回答這些問題,因為展開太過複雜。這些問題僅是用來說明 ERC20 跨鏈的複雜性。

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

目前非常多擴容方案使用的都是白名單 + 手動清單的方案,來規避各種複雜的問題和邊界情況。

Arbitrum 使用了 Gateway 系統,解決了大部分 ERC20 跨鏈的痛點,具有以下特性:

  • Gateway 元件在 L1 和 L2 成對出現。

  • Gateway Router 負責維護 Token L1<->Token L2 之間的地址映射,以及 some token<->some gateway 之間的映射。

  • Gateway 本身可分為 StandardERC20 gateway,Generic-custom gateway,Custom gateway 等等,用以解決不同類型的和功能 ERC20 的橋接問題。

我們以比較簡單的 WETH 跨鏈為例,來說明自定義 gateway 的必要性。

WETH 是一種 ETH 的 ERC20 等價物。Ether 作為主幣,很多 dApp 中的複雜功能是無法實現的,因此需要一個 ERC20 的等價物。向 WETH 合約內轉入一些 ETH,它們會被鎖在合約內,並生成出相同數量的 WETH。

同理,也可以銷毀 WETH,取出 ETH。顯然,流通的 WETH 和鎖倉的 ETH 數量永遠是 1:1 的。

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

如果現在把 WETH 直接跨鏈到 L2 上,我們會發現一些奇怪的問題:

  • 無法在 L2 上把 WETH 進行 Unwrap 變成 ETH,因為 L2 上並沒有鎖倉對應的 ETH。

  • Wrap 功能可以使用,但這些新生成的 WETH 如果跨回到 L1,也無法在 L1 上解封裝為 ETH,因為L1 和 L2 上的 WETH 合約不是「對稱的」

顯然這違反了 WETH 的設計原理。那麼 WETH 在跨鏈時,不論是儲值還是提現,都需要先 Unwrap 成 ETH 後,再跨到對面,然後 Wrap 成 WETH。這個也就是 WETH Gateway 的作用。

其他有更復雜邏輯的代幣同理,需要更復雜和精心設計的 Gateway 才能正常在跨鏈環境下工作。Arbitrum 的自定義 Gateway 繼承了普通 Gateway 的跨鏈通信邏輯,並允許開發者自定義與代幣邏輯相關的跨鏈行為,可滿足大部分需求。

慢收件箱 Delayed Inbox

與快箱也即 SequencerInbox 相對應的是慢箱 Inbox (全稱 Delayed Inbox)。為什麼要有快慢之分呢?因為快箱是專⻔接收排序器發佈的 L2 交易 Batch 的,所有未經排序器在 L2 網路內預處理的交易,都不該出現在快箱合約中。

慢箱的第⼀點作⽤是,處理 L1 到 L2 的儲值⾏為。⽤戶通過慢箱進⾏儲值,排序器監聽到後再反映在 L2 上,最終這筆儲值記錄會被排序器包含進 L2 的交易序列中,並提交⾄快箱合約 Sequencer Inbox。

在這個例⼦中,⽤戶直接向快箱提交儲值交易是不合適的,因為提交到快箱 Sequencer Inbox 中的交易,會干擾到 Layer2 正常的交易排序,然後會影響到排序器的工作。

慢箱的第⼆個作⽤,是抗審查。用戶直接提交⾄慢箱合約中的交易,排序器⼀般會在 10 分鐘內歸集到快箱中。但如果排序器惡意忽略你的請求,慢箱還有⼀個強制歸集 force inclusion功能:

如果交易被提交至 Delayed Inbox 中,經過 24 小時,慢箱中的交易仍未被排序器包含至交易序列中,用戶可以在 Layer1 上手動觸發 force inclusion 函數,把被排序器忽略掉的交易請求,強制歸集到快箱 Sequencer Inbox 中,之後就會被全體 Arbitrum One 節點監聽到,會被強制包含進 Layer2 交易序列裡。

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

我們剛才提到過,快箱⾥的數據就是 L2 的歷史數據實體。所以在被惡意審查的情況下,通過慢箱可以讓交易指令最終包含進 L2 賬本中,這涵蓋了強制提款等逃離 Layer2 的場景。

由此可以看出,對任何⼀個⽅向和層次的交易,排序器最終都⽆法永久審查你。

慢箱 Inbox 的幾個核心函數:

  • depositETH(),最簡單的儲值 ETH 的函數。

  • createRetryableTicket(),可用於 ETH 和 ERC20 以及消息的儲值。相較 depositETH() 而言,有更高的靈活性,例如可指定儲值後 L2 的收款地址等。

  • forceInclusion(),也即強制歸集功能,任何⼈都可以調⽤。該函數會校驗,提交至慢箱合約中的某筆交易,是否過了 24 小時還沒被處理。如果條件滿⾜,則將對消息進⾏強制歸集。

不過需要注意,force Inclusion 函數實際上位於快箱合約中,只是為了⽅便理解,我們將其放在慢箱這⾥⼀起講解。

出站箱 Outbox

出站箱 Outbox 只與提現有關,可以理解為提現行為的記錄和管理系統:

  • 我們知道,Arbitrum 官方橋的提現需要等待約 7 天的挑戰期結束, Rollup Block 最終敲定後,提款行為才可以實施。⽤戶在挑戰期結束後,向 Layer1 上的 Outbox 合約提交相應的 Merkle Proof,它再與其他職能的合約通信(如解鎖其他合約中鎖定的資產),最終完成提現。

  • OutBox 合約會記錄哪些 L2 到 L1 的跨鏈消息已經被處理過,以防止有人反覆提交執行過的提現請求。它通過

  • mapping(uint256 => bytes32) public spent,記錄提現請求的 spent Index 與資訊對應關係,如果 mapping[spentIndex] != bytes32(0) 則該請求已被提現過。原理類似於防止重放攻擊的交易計數器 Nonce。

下⾯我們將以 ETH 為例完整講解儲值與提現的流程。ERC20 與之不同的僅僅是⾛了 Gateway,就不再贅述。

ETH 儲值

1.用戶調用慢箱的 depositETH() 函數。

2.該函數會繼續調用 bridge.enqueueDelayedMessage(),在 bridge 合約中記錄該消息,並將 ETH 發送往 bridge 合約。所有的 ETH 儲值資金,都保管在 bridge 合約中,相當於一個儲值地址。

3.排序器監聽到慢箱中的儲值消息,將儲值操作反映⾄ L2 資料庫中,⽤戶可以在 L2 網路看到自己充進來的資產。

4.排序器將該筆儲值記錄包含進交易批次 batch,提交給 L1 上的快箱合約。

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

ETH 提現

1. ⽤戶在 L2 上調⽤ ArbSys 合約的 withdrawEth() 函數 ,在 L2 上銷毀相應數量的 ETH。

2.排序器將該提現請求發送⾄快箱。

3.Validator 節點根據快箱中的交易序列,創建新的 Rollup Block,其中會包含上述提款交易。

4. Rollup Block 度過了挑戰期並被確認後,⽤戶可以在 L1 上調用 Outbox.execute Transaction() 函數,證明參數由前面提到的 ArbSys 合約給出。

5. Outbox 合約確認⽆誤後,解鎖 bridge 中相應數額的 ETH 發送給⽤戶。

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

快速提現

使⽤樂觀 Rollup 官方橋提現就會出現等待挑戰期的問題。我們可以⽤私營的第三方跨鏈橋來規避這個問題:

  • 原⼦鎖交換。這種⽅式只是在雙⽅在各⾃的鏈內進⾏了資產的互換,並且具有原⼦性,只要⼀⽅提供了 Preimage,雙⽅⼀定可以得到應有的資產。但問題是流動性⽐較稀缺,需要點對點地尋找對⼿⽅。

  • ⻅證⼈跨鏈橋。⼀般類型的跨鏈橋都屬於⻅證⼈橋。⽤戶提交⾃⼰的提現請求,提現⽬的地指向第三方橋的運營者或流動性池。⻅證⼈發現跨鏈交易已提交到 L1 的快箱合約後,就可以直接在 L1 端向⽤戶轉賬。這種⽅式本質上是⽤另⼀套共識系統來監視 Layer2,並根據其已提交至 Layer1 上的數據進⾏操作。問題是,這種模式下的安全係數不如 Rollup 官方橋⾼。

強制提現

force Inclusion() 強制歸集功能用於對抗定序器的審查,任何 L2 本地交易、L1 到 L2 交易和 L2 到 L1 交易,都可以使用該功能實現。定序器的惡意審查嚴重影響了交易體驗,大部分情況下我們會選擇提現離開 L2,因此下面以強制提現為例介紹 forceInclusion 的用法。

回顧在 ETH 提現步驟中,只有步驟 1、2 是涉及到定序器審查的,所以只需要更改這兩步:

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

  • 調用 L1 上慢箱合約中的 inbox.sendL2Message(),輸入參數就是在 L2 上調用 withdrawEth() 時需要輸入的參數。該消息會共享給 L1 上的 bridge 合約。

  • 等待 24 小時的強制歸集等待期後,調用快箱中的 force Inclusion() 進行強制歸集,快箱合約會檢視 bridge 中是否有對應消息。

最終用戶可以在 Outbox 中提現,其餘步驟由同正常的提現相同。

另外,arbitrum-tutorials 中也有使用 Arb SDK 的詳細教程去指導用戶如何通過 forceInclusion() 去進行 L2 本地交易和 L2 到 L1 交易。

聯系郵箱:0xniumao@gmail.com