以太坊 layer2: optimism 原始碼學習 (一)

2022-07-30 18:01:41

作者:林冠宏 / 指尖下的幽靈。轉載者,請: 務必標明出處。

掘金:https://juejin.im/user/1785262612681997

部落格:http://www.cnblogs.com/linguanh/

GitHub : https://github.com/af913337456/

出版的書籍:


前序:

對於區塊鏈每個階段的風口產品,我都會挑選其中某個研究其原始碼,當作學習並增加經驗。早前看的是 zkSync,難度巨大而能力有限,遂轉於 Optimism

本次是系列文章,這是第一篇。

這裡就不說什麼是 Layer2 了,可以去網路搜尋其它文章來閱讀。在 Layer2 的擴容方案中目前有 3 種,Rollups 是其中一種,稱為打包。打包又分兩大派別:

這兩派的風格各異,特點突出。Optimistic rollups智慧合約的支援可以說是完全相容,而 ZK rollups目前對智慧合約支援不友好,但是在交易提款上鍊這塊非常快、更安全卻計算量巨大,技術難度複雜。關於它們的對比,我後續再寫篇文章詳細說說


目錄:

  • Op 簡介
  • Op 的程式元件
  • 如何使用 Op
  • 原始碼分析 --- 充值與提現
    • L1 合約層原始碼
    • L2 層原始碼
    • 提現

1. 正題,Op 簡介

Layer2 是公鏈下的第二層。比如安卓系統下的底層軟體。

Optimism,下面簡稱 Op,是基於 Optimistic rollups 方案所實現的 Layer2 應用,下面簡稱 L2。作用是幫助 以太坊 擴容以及加速交易。

特點如下:

  1. 提款到 Layer1 的週期,約一週。下面簡稱 L1;
  2. 速度,L2 內交易,極快,手續費很低;
  3. 通用性,EVM 相容,基於以太坊的修改
  4. 技術複雜度,簡單;
  5. 鏈下成本,低。鏈上成本,高;
  6. 交易安全保證,基於默克爾樹--樹根雜湊的欺詐證明
  7. 原始碼:https://github.com/ethereum-optimism/optimism

2. Op 的程式元件

雖說 Op 是個 L2 應用,但它的組成程式元件非常多。我這裡列出會和我本文內容相關的元件:

  1. 合約,這些會被部署在 L1 公鏈上面,由 L2 元件或使用者來呼叫,包含不限於有:
    • L2 側鏈,基於 geth 原始碼改造的鏈,執行在 Op 生態裡;
    • L1StandardBridge.sol 垮鏈橋合約,用來處理充值 Token 到 Op 地址或從 Op 地址提現到 L1 地址 所用;
    • CanonicalTransactionChain.sol 規範處理 L2 --> L1 的交易,下面簡稱 CTC
    • L1CrossDomainMessenger.sol 跨鏈信使合約,裡面主要編寫進行了各種要觸發跨鏈事件的函數。
  2. DataTransportLayer,定時掃描 L1 區塊,從中獲取到 TransactionEnqueued 事件,並儲存到 LevelDB 資料庫;
  3. Sequencer
    • 接受使用者發來 L2 的交易;
    • 定期從資料庫中獲取 DataTransportLayer 儲存的 TransactionEnqueued 事件資料,並把交易在 L2 鏈中執行,使之正常被打包到 L2 區塊中;
  4. Batch-Submitter,定期從 L2 區塊中將交易資料以打包的形式組裝到交易:
    • 打包批次交易 txBatch 提交到 L1 的 CTC 合約;
    • 打包批次狀態 stateBatch 提交到 L1 的StateCommitmentChain.sol
    • 之後這些交易進入等待挑戰視窗,挑戰方式就是欺詐證明
  5. Relayer,定時從 L2 區塊中過濾交易中的 SentMessage 事件資料:
    • 判斷當前交易是否過了挑戰時間;
    • 為此交易生成證明,呼叫 L1 上的 L1CrossDomainMessenger.relayMessage 函數,使之完成合約檢查然後在內部呼叫目標合約,最終在 L1 完成 L2 交易的最終目的;

它們的組合通訊流程圖如下:

注:

目前所有的 Op 組建,都由官方執行著,欺詐證明還在完善。使用者必須要相信官方不會做惡。

3. 如何使用 Op

使用 Op 網路分兩種情況:

  1. 直接使用原生 Token 進行交易,即以太坊,那麼:
    1. 需要先在 L1 存取 L1StandardBridge.sol 進行充值到 Op;
    2. 充值結束後,到賬了,可以進行 Op 網路內的交易活動;
    3. 提現到 L1 的地址;
    4. 流程到這裡閉環
  2. 其他協定,比如 ERC-20:
    1. 先去 Op 網路部署對應的合約;
    2. 在 L1 的 L1StandardBridge.sol 充值 Token 到 L2 地址;
    3. 到賬後,便可自由交易。提現動作和 ETH 的一樣。

4. 原始碼分析 --- 充值與提現

充值部分 --- L1 合約層原始碼

按照流程,使用者需要呼叫 L1 上的 L1StandardBridge.sol 智慧合約充值,如下圖所示:

注意,payable 就是 solidity 語法中標明可以接收 ETH 的語法糖。此時充值 ETH 到了 Op 的 L1StandardBridge 跨鏈橋合約中。

上圖,函數走完了,都沒有痕跡告訴我們如何在為 L2 的地址充值了 ETH,我們只需要留意其中的 IL2ERC20Bridge.finalizeDeposit.selector 這一行。這裡設定了一個 L2 到時需要呼叫的函數。

上圖,結合我們前面的結論 DataTransportLayer,會定時掃描 L1 區塊,從中獲取到 TransactionEnqueued 事件,並儲存到 LevelDB 資料庫。

所以在 _sendXDomainMessag 內部,最終會觸發 emit TransactionEnqueued 事件。L1 層面的閉環結束

ERC-20 的充值也是一樣的,只是函數不一樣。如下圖:

// TransactionEnqueued 事件在 enqueue 內發生
function _sendXDomainMessage(
    address _canonicalTransactionChain,
    bytes memory _message,
    uint256 _gasLimit
) internal {
    // slither-disable-next-line reentrancy-events
    ICanonicalTransactionChain(_canonicalTransactionChain).enqueue(
        Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,
        _gasLimit,
        _message
    );
}
充值部分 --- L2 層原始碼

在這裡我們主要看 Sequencer 的是如何執行 TransactionEnqueued 中的交易到 L2 的。

Sequencer 的啟動中,首先是它會進入一個定時從資料庫中獲取交易的函數,如下圖所示:

接下來的呼叫鏈是: s.sequnece --> syncQueueToTip --> syncQueue --> syncQueneTransaction

如下圖所示,在 syncQueneTransaction 中,呼叫 GetEnqueue 從遠端介面即 DataTransportLayer 服務中獲取目標交易資料。最後執行 applyTransaction 執行交易

回到前面合約層的 IL2ERC20Bridge.finalizeDeposit.selector 這一句,最後交易的執行會走到 L2 合約層的 L2ERC20Bridge 合約的 finalizeDeposit 函數,如下圖所示,最終 mint 操作完成充值流程,至此閉環。

提現

內容比較多,提現留給下一篇。持續關注