# OP 共学 02 | 从上层的视角看看 OP Chain 的架构和工作流程

By [Optimism 中文](https://paragraph.com/@optimismcn) · 2024-06-03

---

本篇由 OP 共学小组 Cooper 书写，由 Yiwen 进行排版和编辑，详细记录了 OP Chain 的架构和工作流程

按照先看整体，再究细节的思路，这篇文章将从上层的视角向大家介绍一条由 OP Stack 创建的 **Layer2 chain 的架构**。方便大家对 OP Chain 的整体工作流程建立一个直观的印象，为后续深入源码打下基础。

要理解 OP Chain 的工作流程并不复杂，只需要弄明白几张图即可。这几张图合在一起，共同解释了以下几个关键问题：

1.  网络的参与者有哪些？
    
2.  用户如何参与到网络中？
    
3.  L1 的 ETH 如何到 L2 上去？
    
4.  OP Chain 有哪些模块？
    
5.  L2 是以什么规则来构建链的？
    

对这些问题有了一定的了解后，再看源码，才不会云里雾里。

**网络参与者有哪些？**
-------------

那么，让我们先从网络的参与者有哪些开始。

![](https://storage.googleapis.com/papyrus_images/2664a421a2cf43c00b16cb4be28df84d104e6d59af6b9f4ecf538e4c1c125e9d.png)

上图展示了 4 个参与者，分别是 **Users**、**Sequencers**、**Verifiers**、**ETH L1 Chain**。

1）Users

*   在 OP Chains 中，用户可以通过将交易发送到以太坊主网上的合约，在 L2 上存入或提取任意交易（对应 Bridges 的功能）。
    
*   向使用 ETH 一样，使用部署在 L2 上的智能合约，唯一的差别是，交易是发送到 **Sequencers**上，而不是 ETH 节点。
    
*   可以查询交易、区块等信息。
    

2）Sequencers

*   接收来自用户的链下交易（相对于 L1 而言）。
    
*   监控和收集链上（ L1 ）的交易信息，主要是质押事件信息。
    
*   按特定顺序将上述两种交易合并到 L2 区块中。
    
*   向 L1 提交批次信息和断言信息。
    

**Sequencers** 是主要的 L2 区块生产者。

3）Verifiers

验证者有两个目的：

*   为用户提供 Rollup 数据；
    
*   验证 Rollup 的完整性并质疑无效的断言。
    

为了网络保持安全，必须至少有一个诚实的**验证者**能够验证汇总链的完整性并为用户提供区块链数据。

4）ETH L1 Chain OP Stack 目前只支持 **EVM** 链。L1 链是 L2 数据有效性和可信任的基石。

从这张图上，我们可以了解到对于 OP Chain 的网络来说，都包含了哪些参与者。用户是网络的交互核心，用户可以向网络发送交易，也可以查询信息。

**L1 的 ETH 是如何到 L2 上去的？**
-------------------------

![](https://storage.googleapis.com/papyrus_images/0ff8312c7b85934e8062ebf8c9572c35d7bf19b7d287f3c50bfc6b1518154251.png)

上图展示了 OP Chain Sequencer 模块同步用户 Deposits 和接受用户交易的流程。图中为每个行为都标了序号，这些序号基本上代表了逻辑顺序，除了 **4.Send Transaction** 有一点要注意的外，根据序号观看就好。当然，本文的目的就是为了让大家更轻松的建立直观印象，因此下面会介绍整个流程，也会说明为什么**流程 4** 需要注意。

一步步来，首先是用户发起了 **1.Submit Deposit** 的操作。Deposit 操作的其中一种方式是，用户在 L1 发起一笔转账交易，转账给标准桥合约地址，转账金额是你想跨链到 L2 的 ETH 的数额。

**流程 2. Get Blocks(including deposit event)** ，Rollup Node( op-node 承担) 会按照一定的规则(后面会讲到)，获取 L1 区块的信息，并作为 L2 区块的输入信息提供给 L2 区块使用。其中用户在操作 1 发起的 Deposit 交易，会在此时被解析出来。包含用户 Deposit 信息的 L2 Block ,先称为 Deposit Block。

**流程 3.Insert deposit block**，Rollup Node 通过 Engine API 调用，将 Deposit Block 提交给 Execution Engine( op-geth 承担)。此时，用户在 L1 的 Deposit 信息，就已经被 L2 接收到了，但还没有最终确认。

**流程 4.Send Transaction**，如果仅从 Deposit L1  ETH 到 L2 的操作的角度来看，流程 4 是不必要的，用户在 L1 发起了 Deposit 交易后，OP Chain 会自动完成剩下的动作，用户不需要额外的再对 L2 发起交易。但它这个图还包含了接收交易的演示，因此他将这个行为作为流程 4 表现了出来。不要把 **Submit Deposit** 和 **Send Transaction** 关联起来（当然，必须通过 Deposit 在 L2 有了 ETH，才能在 L2 发起交易，但他们在 OP Chain 系统里不是线性关系），这就是上面说的需要注意的地方。

**流程 5.Get latest sequencer blocks**，获取最近的排序好的区块，并通过 Engine API 推送到 Execution Engine 中。

**流程 6.Submit sequencer blocks(ie. a batch) to the batch inbox**，将进行批处理后的 sequencer blocks 提交的 Batch Inbox 上。关于批处理，我们暂时理解为压缩，后面再探讨具体细节。记住它有可以减少 sequencer blocks 的体积(压缩)，L2 可以从 L1 上获取之前提交给它的信息，根据该信息可以解析出原来的 sequencer blocks(解压缩)，这样的特性即可。

Batch Inbox 是一个 L1 上的常规的 EOA 账户。

**流程 7.Get latest assertable block hash**，获取最新的区块哈希断言。

**流程 8.Verify block hash in the fault proof VM to detect on chain <-> off chain divergence**，验证故障证明虚拟机中的块哈希以检测链上 <-> 链下分歧。

**流程 9.Submit validated block hash assertion**，提交经过验证的区块哈希断言。

流程 7，8，9 涉及到故障证明相关的内容，这一部分较为复杂，暂时不在这里展开。我们先记住它是用来检测和处理 L1 和 L2 链的状态分歧的即可，不影响我们理解 OP Chain 的工作流程。然后，**L2 Output Oracle** 是一个合约，该合约主要用来存储 **L2 output roots**（一个 32 字节值，用作对 L2 链当前状态的承诺。由 sequencer 生成和提交）。

以上就是 Sequencer 同步 Deposit 信息和接受用户交易并处理的流程。

### **OP Chain 有哪些模块？**

![](https://storage.googleapis.com/papyrus_images/c17e5fee6d730b48c7ab77dd6fd16cb6fb0422beb01b769c4039cd5d0fa56987.png)

上图展示了 OP Chain 的核心组件。从 L1 和 L2 两个层级来看， L1 层包含以下组件：

*   OptimismPortal 一个部署在 L1 上的合约。会将 Deposit 交易存在这个合约中，而不是 token。会抛出 TransactionDeposited 事件，Rollup Driver 会读取事件信息，然后处理质押汇款。
    
*   BatchInbox 如前文所述，这是一个常规的 EOA 账户。**Batch Submitter** 将 batch 信息提交到这个地址上。这种方式，可以通过不执行任何 EVM 代码来节省 Gas 成本。
    
*   L2OutputOracle 如前文所述，这是一个存储 L2 output roots 的智能合约，用于提款和故障证明。
    

L2 层包含以下组件：

*   **Rollup Node**
    
    1.  独立、无状态的二进制文件。
        
    2.  接收用户的 L2 交易。
        
    3.  同步并验证 L1 上的 rollup 数据。
        
    4.  应用特定的 rollup 块生成规则来从 L1 合成块。
        
    5.  使用 Engine API 将块追加到 L2 链。
        
    6.  处理 L1 的重组。
        
    7.  将未提交的块分发给其他 Rollup Node。
        
*   **L2 Execution Engine**
    
    1.  一个普通的 Geth 节点，经过少量修改以支持 Optimism。
        
    2.  维持 L2 状态。
        
    3.  将状态同步到其他 L2 节点以实现快速加入。
        
    4.  向 Rollup Node 提供 Engine API。
        
*   Batch Submitter 一个专门将 transaction bathes 提交到 BatchInbox 的后台程序。
    
*   Output Submitter 将 L2 output commitments 提交到 L2OutputOracle 的后台程序。
    

此外，上图还可以将 Rollup Node 和 L2 Execution Engine 的关系再展开一下，得到下图：

![](https://storage.googleapis.com/papyrus_images/c2aa6a13e182fcc4fb2957f18f7cc0cdea961ae1f586be2c0ecba51f2a6e4eaa.png)

这个图展示了以下几个关键信息：

1.  执行引擎( EE )之间使用独立于 Rollup Node 的对等网络进行通信。可以同步交易，区块状态等。
    
2.  Rollup Node 之间也存在一个特有的 \*\*P2P 网络，\*\*使用这个网络进行通信，而不是 EE 之间的 P2P 网络。
    
3.  Rollup Node 通过 Engine API 和执行引擎交互。
    

**L2 是以什么规则来构建链的？**
-------------------

1.

![](https://storage.googleapis.com/papyrus_images/24bb586a7324eb06aa378caca00541e9920f509907a5c73184a513e0d02b3191.png)

1.  给定一条 L1 链，Rollup Chain 可以基于 L1 的区块信息，将 L2 链完全恢复出来。上图展示了 OP Chain 从 L1 恢复 L2 链的基础逻辑。
    
    让我们先了解一下图中各个元素的含义：
    
    *   Epoch 每个 L1 区块，对应一个 L2 的 Epoch。每个 Epoch 可以包含多个 L2 区块，起始的 L2 区块必须是包含 L1 Deposit 信息的 L2 区块( Deposit Block )。
        
    *   D1…… D3 表示 Epoch 1 中所有的 Deposit 信息，这些信息是从 `OptimismPortal` 合约上获得的。
        
    *   B1…… B7 Transaction Batches。交易 Batch 不仅可以包含一个 L2 区块的交易，还可以包含多个 L2 区块排序好后的交易。每个 Batch 都包含了 parent hash,  L1 epoch 的区块哈希和区块编号。
        
    *   一个 L2 区块中既可以包含 Deposit 交易，也可以包含 Batch 交易。
        
    
    D1 是在 L1 上发现的第一个 **Deposit** 信息，以包含该信息的 L1 块为基础，作为 Epoch1。推导出 L2 的第一个区块。B1 作为同一个 L1 区块上的 batch，和 D1 放在同一个 L2 区块中。
    
    以 ETH 作为 L1 和上一个教程中部署的 L2 参数为例，ETH 出块的平均时间为 12s, L2 的平均出块时间为 2s。这些值意味着一个 Epoch 的跨度为 12s, 在这 12s 内，可以包含 6 个区块。这也是上图中，会有 B2, B4, B5, B6, B7 的原因。注意，如果从 L2 的视角来看，B2 不代表只有一个区块，它可能是多个区块，因为一个 **Batch** 可以从多个排好序的区块中整合交易。
    
    按照同样的逻辑，我们根据在 L1 的第二个区块中的 D2 信息，推导出 L2 上的第二个 Deposit Block，也是 Epoch2 的起始区块。后面的推导都是这样的一个逻辑，一直循环直到达到 L1 的最新的的区块为止。
    
    基础逻辑就是上面说的这样了，现在在这个基础上再补充一个细节，这个细节在上图中没有体现，但非常重要。这个细节就是：**SEQUENCING\_WINDOW\_SIZE**。
    
    让我们先反转一下观察角度，之前是 L1 -> L2, 现在我们看 L2 -> L1。假设我们在 D2 追上了 L1 的最高点，后面需要提交 B4,B5,B6…… (从这里开始，不是在解释上图了，只是利用一下，表述的内容并不相同)。OP Stack 协议定义了一个 SEQUENCING\_WINDOW\_SIZE，在 `n(epoch 编号)` + `SEQUENCING_WINDOW_SIZE` 内，指定 epoch 内的 Batch 必须被提交到 L1 上，否则是无效的。另一方面，这也意味着 B4,B5,B6…… 可以提交到后面的 epoch 所对应的 L1 区块上，如 epoch3,4,5…，尽管 Batch 记录的 epoch 为 epoch2，但只要还在 SEQUENCING\_WINDOW\_SIZE 的范围内，就有效。
    
    再回过来看 L1 -> L2， 也就是说推导 L2 区块时，对于 batches 的检索，需要检索 `n` + `SEQUENCING_WINDOW_SIZE` 的区块，才能确保检索出了当前 epoch 中包含的所有的 batches。
    
    还有一张图，对这个过程做了更详细的描述，不过这个图中涉及了更多的代码概念，准备放到后面，在源码阶段再展开讲述。
    

![](https://storage.googleapis.com/papyrus_images/b3c30708921163dc1e9d5c60788867f45e0432cd2107d59e022ad30dcb14f450.png)

读者朋友如果感兴趣的话，也可以提前看看，整体逻辑上和前面的简化图是差不多的，只是加入了更多实现上的细节。可以结合 OP Stack 规格书的 **derivation\[1\]** 一节来看。

**总结**
------

这篇文章，我尝试以上层的视角，来向大家介绍 OP Chain 的整体架构，以及主要的工作流程。让大家建立一个直观的印象，这样后续结合源码时，能够更轻松，更容易理解。

文章中的内容，全部来源于 OP Stack 规格书以及 optimism 仓库的源码。目前我也还处于学习理解的阶段，而系统本身有一定的复杂度，难免有所疏漏，还请海涵指正!

最后，感谢大家的阅读~

### **找到我们**

OP 中文力量是由 GCC、LXDAO、PlanckerDAO，登链社区和 TraDAO 共同发起的 Optimism 中文开发者社区，是一个传播 Optimism 技术和公共物品理念的组织，旨在成为链接华语社区和 Optimism 生态的桥梁，促进 Optimism 生态和华语社区内的双向交流，促进公共物品的繁荣。

OP 中文力量是 GCC 中文力量计划旗下专注 OP 生态的中文社区，由 GCC 捐助孵化成立。

**Notion**：[https://www.notion.so/lxdao/Optimism-99a78f831195451a9f16724342c0c4ed](https://www.notion.so/lxdao/Optimism-99a78f831195451a9f16724342c0c4ed)

**Telegram**：[https://t.me/optimism\_cn](https://t.me/optimism_cn)

**Mirror**: [https://mirror.xyz/optimismcn.eth](https://mirror.xyz/optimismcn.eth)

### **支持社区**

![](https://storage.googleapis.com/papyrus_images/c0e9e38e4deb0a9833a961a4b83f073714fb805b2346150e79f45afa05d693aa.png)

---

*Originally published on [Optimism 中文](https://paragraph.com/@optimismcn/op-02-op-chain)*
