Skip to content

Commit

Permalink
Merge pull request #328 from ethereum-optimism/sc/protocol-diagrams
Browse files Browse the repository at this point in the history
feat: add protocol diagrams to overview
  • Loading branch information
tynes authored Aug 13, 2024
2 parents bb2c54a + 1205a63 commit 3ab4f82
Show file tree
Hide file tree
Showing 2 changed files with 1,646 additions and 665 deletions.
332 changes: 283 additions & 49 deletions specs/protocol/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
**Table of Contents**

- [Architecture Design Goals](#architecture-design-goals)
- [Components](#components)
- [L1 Components](#l1-components)
- [L2 Components](#l2-components)
- [Architecture Overview](#architecture-overview)
- [Core L1 Smart Contracts](#core-l1-smart-contracts)
- [Notes for Core L1 Smart Contracts](#notes-for-core-l1-smart-contracts)
- [Core L2 Smart Contracts](#core-l2-smart-contracts)
- [Notes for Core L2 Smart Contracts](#notes-for-core-l2-smart-contracts)
- [Smart Contract Proxies](#smart-contract-proxies)
- [L2 Node Components](#l2-node-components)
- [Transaction/Block Propagation](#transactionblock-propagation)
- [Key Interactions In Depth](#key-interactions-in-depth)
- [Deposits](#deposits)
Expand Down Expand Up @@ -42,45 +46,275 @@ This document assumes you've read the [background](../background.md).
mechanisms.
- Running a replica is as simple as running a Geth node.

## Components

![Components](../static/assets/components.svg)

### L1 Components

- **OptimismPortal**: A feed of L2 transactions which originated as smart contract calls in the L1 state.
- The `OptimismPortal` contract emits `TransactionDeposited` events, which the rollup driver reads in order to process
deposits.
- Deposits are guaranteed to be reflected in the L2 state within the _sequencing window_.
- Beware that _transactions_ are deposited, not tokens. However deposited transactions are a key part of implementing
token deposits (tokens are locked on L1, then minted on L2 via a deposited transaction).
- **BatchInbox**: An L1 address to which the Batch Submitter submits transaction batches.

- Transaction batches include L2 transaction calldata, timestamps, and ordering information.
- The BatchInbox is a regular EOA address. This lets us pass on gas cost savings by not executing any EVM code.

- **L2OutputOracle**: A smart contract that stores [L2 output roots](../glossary.md#l2-output) for use with withdrawals
and fault proofs.

### L2 Components

- **Rollup Node**:
- A standalone, stateless binary.
- Receives L2 transactions from users.
- Syncs and verifies rollup data on L1.
- Applies rollup-specific block production rules to synthesize blocks from L1.
- Appends blocks to the L2 chain using the Engine API.
- Handles L1 reorgs.
- Distributes unsubmitted blocks to other rollup nodes.
- **Execution Engine (EE)**:
- A vanilla Geth node with minor modifications to support Optimism.
- Maintains L2 state.
- Sync state to other L2 nodes for fast onboarding.
- Serves the Engine API to the rollup node.
- **Batch Submitter**
- A background process that submits [transaction batches](../glossary.md#sequencer-batch) to the `BatchInbox` address.
- **Output Submitter**
- A background process that submits L2 output commitments to the `L2OutputOracle`.
## Architecture Overview

### Core L1 Smart Contracts

Below you'll find an architecture diagram describing the core L1 smart contracts for the OP Stack.
Smart contracts that are considered "peripheral" and not core to the operation of the OP Stack system are described separately.

```mermaid
graph LR
subgraph "External Contracts"
ExternalERC20(External ERC20 Contracts)
ExternalERC721(External ERC721 Contracts)
end
subgraph "L1 Smart Contracts"
BatchDataEOA(<a href="../glossary.html#batcher-transaction">Batch Inbox Address</a>)
L1StandardBridge(<a href="./bridges.html">L1StandardBridge</a>)
L1ERC721Bridge(<a href="./bridges.html">L1ERC721Bridge</a>)
L1CrossDomainMessenger(<a href="./messengers.html">L1CrossDomainMessenger</a>)
OptimismPortal(<a href="./withdrawals.html#the-optimism-portal-contract">OptimismPortal</a>)
SuperchainConfig(<a href="./superchain-configuration.html">SuperchainConfig</a>)
SystemConfig(<a href="./system-config.html">SystemConfig</a>)
DisputeGameFactory(<a href="../fault-proof/stage-one/dispute-game-interface.html#disputegamefactory-interface">DisputeGameFactory</a>)
FaultDisputeGame(<a href="../fault-proof/stage-one/fault-dispute-game.html">FaultDisputeGame</a>)
AnchorStateRegistry(<a href="../fault-proof/stage-one/fault-dispute-game.html#anchor-state-registry">AnchorStateRegistry</a>)
DelayedWETH(<a href="../fault-proof/stage-one/bond-incentives.html#delayedweth#de">DelayedWETH</a>)
end
subgraph "User Interactions (Permissionless)"
Users(Users)
Challengers(Challengers)
end
subgraph "System Interactions"
Guardian(Guardian)
Batcher(<a href="./batcher.html">Batcher</a>)
end
subgraph "Layer 2 Interactions"
L2Nodes(Layer 2 Nodes)
end
L2Nodes -.->|fetch transaction batches| BatchDataEOA
L2Nodes -.->|fetch deposit events| OptimismPortal
Batcher -->|publish transaction batches| BatchDataEOA
ExternalERC20 <-->|mint/burn/transfer tokens| L1StandardBridge
ExternalERC721 <-->|mint/burn/transfer tokens| L1ERC721Bridge
L1StandardBridge <-->|send/receive messages| L1CrossDomainMessenger
L1StandardBridge -.->|query pause state| SuperchainConfig
L1ERC721Bridge <-->|send/receive messages| L1CrossDomainMessenger
L1ERC721Bridge -.->|query pause state| SuperchainConfig
L1CrossDomainMessenger <-->|send/receive messages| OptimismPortal
L1CrossDomainMessenger -.->|query pause state| SuperchainConfig
OptimismPortal -.->|query pause state| SuperchainConfig
OptimismPortal -.->|query config| SystemConfig
OptimismPortal -.->|query state proposals| DisputeGameFactory
DisputeGameFactory -->|generate instances| FaultDisputeGame
FaultDisputeGame -->|store bonds| DelayedWETH
FaultDisputeGame -->|query/update anchor states| AnchorStateRegistry
Users <-->|deposit/withdraw ETH/ERC20s| L1StandardBridge
Users <-->|deposit/withdraw ERC721s| L1ERC721Bridge
Users -->|prove/execute withdrawals| OptimismPortal
Challengers -->|propose output roots| DisputeGameFactory
Challengers -->|verify/challenge/defend proposals| FaultDisputeGame
Guardian -->|pause/unpause| SuperchainConfig
Guardian -->|safety net actions| OptimismPortal
Guardian -->|safety net actions| DisputeGameFactory
Guardian -->|safety net actions| DelayedWETH
classDef extContracts stroke:#ff9,stroke-width:2px;
classDef l1Contracts stroke:#bbf,stroke-width:2px;
classDef l1EOA stroke:#bbb,stroke-width:2px;
classDef userInt stroke:#f9a,stroke-width:2px;
classDef systemUser stroke:#f9a,stroke-width:2px;
classDef l2Nodes stroke:#333,stroke-width:2px
class ExternalERC20,ExternalERC721 extContracts;
class L1StandardBridge,L1ERC721Bridge,L1CrossDomainMessenger,OptimismPortal,SuperchainConfig,SystemConfig,DisputeGameFactory,FaultDisputeGame,DelayedWETH,AnchorStateRegistry l1Contracts;
class BatchDataEOA l1EOA;
class Users,Challengers userInt;
class Batcher,Guardian systemUser;
class L2Nodes l2Nodes;
```

#### Notes for Core L1 Smart Contracts

- The `Batch Data Address` described above (**highlighted in GREY**) is *not* a smart contract and is instead an arbitrarily
selected account that is assumed to have no known private key. This account is typically chosen as the account
`0xFF0000....<L2 chain ID>` where `<L2 chain ID>` is chain ID of the Layer 2 network for which the data is being posted.
For instance, for OP Mainnet, this account is chosen as `0xFF00000000000000000000000000000000000010`. However, this is
not a strict requirement and some OP Stack chains may not follow this convention.
- Smart contracts that sit behind `Proxy` contracts are **highlighted in BLUE**. Refer to the
[Smart Contract Proxies](#smart-contract-proxies) section below to understand how these proxies are designed.
- The `L1CrossDomainMessenger` contract sits behind the [`ResolvedDelegateProxy`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol)
contract, a legacy proxy contract type used within older versions of the OP Stack. This proxy type is used exclusively
for the `L1CrossDomainMessenger` to maintain backwards compatibility.
- The `L1StandardBridge` contract sits behind the [`L1ChugSplashProxy`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol)
contract, a legacy proxy contract type used within older versions of the OP Stack. This proxy type is used exclusively
for the `L1StandardBridge` contract to maintain backwards compatibility.

### Core L2 Smart Contracts

Here you'll find an architecture diagram describing the core OP Stack smart contracts that exist natively on the L2 chain
itself.

```mermaid
graph LR
subgraph "Layer 1 (Ethereum)"
L1SmartContracts(L1 Smart Contracts)
end
subgraph "L2 Client"
L2Node(L2 Node)
end
subgraph "L2 System Contracts"
L1Block(<a href="./predeploys.html#l1block">L1Block</a>)
GasPriceOracle(<a href="./predeploys.html#gaspriceoracle">GasPriceOracle</a>)
L1FeeVault(<a href="./predeploys.html#l1feevault">L1FeeVault</a>)
BaseFeeVault(<a href="./predeploys.html#basefeevault">BaseFeeVault</a>)
SequencerFeeVault(<a href="./predeploys.html#sequencerfeevault">SequencerFeeVault</a>)
end
subgraph "L2 Bridge Contracts"
L2CrossDomainMessenger(<a href="./predeploys.html#l2crossdomainmessenger">L2CrossDomainMessenger</a>)
L2ToL1MessagePasser(<a href="./predeploys.html#l2tol1messagepasser">L2ToL1MessagePasser</a>)
L2StandardBridge(<a href="./predeploys.html#l2standardbridge">L2StandardBridge</a>)
L2ERC721Bridge(<a href="./predeploys.html">L2ERC721Bridge</a>)
end
subgraph "Transactions"
DepositTransaction(Deposit Transaction)
UserTransaction(User Transaction)
end
subgraph "External Contracts"
ExternalERC20(External ERC20 Contracts)
ExternalERC721(External ERC721 Contracts)
end
subgraph "Remaining L2 Universe"
OtherContracts(Any Contracts and Addresses)
end
L2Node -.->|derives chain from| L1SmartContracts
L2Node -->|updates| L1Block
L2Node -->|distributes fees to| L1FeeVault
L2Node -->|distributes fees to| BaseFeeVault
L2Node -->|distributes fees to| SequencerFeeVault
L2Node -->|derives from deposits| DepositTransaction
L2Node -->|derives from chain data| UserTransaction
UserTransaction -->|can trigger| OtherContracts
DepositTransaction -->|maybe triggers| L2CrossDomainMessenger
DepositTransaction -->|can trigger| OtherContracts
ExternalERC20 <-->|mint/burn/transfer| L2StandardBridge
ExternalERC721 <-->|mint/burn/transfer| L2ERC721Bridge
L2StandardBridge <-->|sends/receives messages| L2CrossDomainMessenger
L2ERC721Bridge <-->|sends/receives messages| L2CrossDomainMessenger
GasPriceOracle -.->|queries| L1Block
L2CrossDomainMessenger -->|sends messages| L2ToL1MessagePasser
classDef extContracts stroke:#ff9,stroke-width:2px;
classDef l2Contracts stroke:#bbf,stroke-width:2px;
classDef transactions stroke:#fba,stroke-width:2px;
classDef l2Node stroke:#f9a,stroke-width:2px;
class ExternalERC20,ExternalERC721 extContracts;
class L2CrossDomainMessenger,L2ToL1MessagePasser,L2StandardBridge,L2ERC721Bridge l2Contracts;
class L1Block,L1FeeVault,BaseFeeVault,SequencerFeeVault,GasPriceOracle l2Contracts;
class UserTransaction,DepositTransaction transactions;
class L2Node l2Node;
```

#### Notes for Core L2 Smart Contracts

- Contracts highlighted as "L2 System Contracts" are updated or mutated automatically as part of the chain derivation
process. Users typically do not mutate these contracts directly, except in the case of the `FeeVault` contracts where
any user may trigger a withdrawal of collected fees to the pre-determined withdrawal address.
- Smart contracts that sit behind `Proxy` contracts are **highlighted in BLUE**. Refer to the
[Smart Contract Proxies](#smart-contract-proxies) section below to understand how these proxies are designed.
- User interactions for the "L2 Bridge Contracts" have been omitted from this diagram but largely follow the same user
interactions described in the architecture diagram for the [Core L1 Smart Contracts](#core-l1-smart-contracts).

### Smart Contract Proxies

Most OP Stack smart contracts sit behind `Proxy` contracts that are managed by a `ProxyAdmin` contract.
The `ProxyAdmin` contract is controlled by some `owner` address that can be any EOA or smart contract.
Below you'll find a diagram that explains the behavior of the typical proxy contract.

```mermaid
graph LR
ProxyAdminOwner(Proxy Admin Owner)
ProxyAdmin(<a href="https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/universal/ProxyAdmin.sol">ProxyAdmin</a>)
subgraph "Logical Smart Contract"
Proxy(<a href="https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/universal/Proxy.sol">Proxy</a>)
Implementation(Implementation)
end
ProxyAdminOwner -->|manages| ProxyAdmin
ProxyAdmin -->|upgrades| Proxy
Proxy -->|delegatecall| Implementation
classDef l1Contracts stroke:#bbf,stroke-width:2px;
classDef systemUser stroke:#f9a,stroke-width:2px;
class Proxy l1Contracts;
class ProxyAdminOwner systemUser;
```

### L2 Node Components

Below you'll find a diagram illustrating the basic interactions between the components that make up an L2 node as well
as demonstrations of how different actors use these components to fulfill their roles.

```mermaid
graph LR
subgraph "L2 Node"
RollupNode(<a href="./rollup-node.html">Rollup Node</a>)
ExecutionEngine(<a href="./exec-engine.html">Execution Engine</a>)
end
subgraph "System Interactions"
BatchSubmitter(<a href="./batcher.html">Batch Submitter</a>)
OutputSubmitter(Output Submitter)
Challenger(Challenger)
end
subgraph "L1 Smart Contracts"
BatchDataEOA(<a href="../glossary.html#batcher-transaction">Batch Inbox Address</a>)
OptimismPortal(<a href="./withdrawals.html#the-optimism-portal-contract">OptimismPortal</a>)
DisputeGameFactory(<a href="../fault-proof/stage-one/dispute-game-interface.html#disputegamefactory-interface">DisputeGameFactory</a>)
FaultDisputeGame(<a href="../fault-proof/stage-one/fault-dispute-game.html">FaultDisputeGame</a>)
end
BatchSubmitter -.->|fetch transaction batch info| RollupNode
BatchSubmitter -.->|fetch transaction batch info| ExecutionEngine
BatchSubmitter -->|send transaction batches| BatchDataEOA
RollupNode -.->|fetch transaction batches| BatchDataEOA
RollupNode -.->|fetch deposit transactions| OptimismPortal
RollupNode -->|drives| ExecutionEngine
OutputSubmitter -.->|fetch outputs| RollupNode
OutputSubmitter -->|send output proposals| DisputeGameFactory
Challenger -.->|fetch dispute games| DisputeGameFactory
Challenger -->|verify/challenge/defend games| FaultDisputeGame
classDef l2Components stroke:#333,stroke-width:2px;
classDef systemUser stroke:#f9a,stroke-width:2px;
classDef l1Contracts stroke:#bbf,stroke-width:2px;
class RollupNode,ExecutionEngine l2Components;
class BatchSubmitter,OutputSubmitter,Challenger systemUser;
class BatchDataEOA,OptimismPortal,DisputeGameFactory,FaultDisputeGame l1Contracts;
```

### Transaction/Block Propagation

Expand Down Expand Up @@ -121,7 +355,7 @@ Both deposit types are represented by a single custom EIP-2718 transaction type
#### Overview

The rollup chain can be deterministically derived given an L1 Ethereum chain. The fact that the entire rollup chain can
be derived based on L1 blocks is _what makes Optimism a rollup_. This process can be represented as:
be derived based on L1 blocks is *what makes Optimism a rollup*. This process can be represented as:

```text
derive_rollup_chain(l1_blockchain) -> rollup_blockchain
Expand All @@ -137,21 +371,21 @@ Optimism's block derivation function is designed such that it:

The rollup chain is subdivided into epochs. There is a 1:1 correspondence between L1 block numbers and epoch numbers.

For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be derived after a _sequencing window_
For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be derived after a *sequencing window*
worth of blocks has passed, i.e. after L1 block number `n + SEQUENCING_WINDOW_SIZE` is added to the L1 chain.

Each epoch contains at least one block. Every block in the epoch contains an L1 info transaction which contains
contextual information about L1 such as the block hash and timestamp. The first block in the epoch also contains all
deposits initiated via the `OptimismPortal` contract on L1. All L2 blocks can also contain _sequenced transactions_,
deposits initiated via the `OptimismPortal` contract on L1. All L2 blocks can also contain *sequenced transactions*,
i.e. transactions submitted directly to the sequencer.

Whenever the sequencer creates a new L2 block for a given epoch, it must submit it to L1 as part of a _batch_, within
Whenever the sequencer creates a new L2 block for a given epoch, it must submit it to L1 as part of a *batch*, within
the epoch's sequencing window (i.e. the batch must land before L1 block `n + SEQUENCING_WINDOW_SIZE`). These batches are
(along with the `TransactionDeposited` L1 events) what allows the derivation of the L2 chain from the L1 chain.

The sequencer does not need for a L2 block to be batch-submitted to L1 in order to build on top of it. In fact, batches
typically contain multiple L2 blocks worth of sequenced transactions. This is what enables
_fast transaction confirmations_ on the sequencer.
*fast transaction confirmations* on the sequencer.

Since transaction batches for a given epoch can be submitted anywhere within the sequencing window, verifiers must
search all blocks within the window for transaction batches. This protects against the uncertainty of transaction
Expand All @@ -168,7 +402,7 @@ have been elided):

#### Block Derivation Loop

A sub-component of the rollup node called the _rollup driver_ is actually responsible for performing block derivation.
A sub-component of the rollup node called the *rollup driver* is actually responsible for performing block derivation.
The rollup driver is essentially an infinite loop that runs the block derivation function. For each epoch, the block
derivation function performs the following steps:

Expand All @@ -182,7 +416,7 @@ This process is then repeated with incrementing epochs until the tip of L1 is re
### Engine API

The rollup driver doesn't actually create blocks. Instead, it directs the execution engine to do so via the Engine API.
For each iteration of the block derivation loop described above, the rollup driver will craft a _payload attributes_
For each iteration of the block derivation loop described above, the rollup driver will craft a *payload attributes*
object and send it to the execution engine. The execution engine will then convert the payload attributes object into a
block, and add it to the chain. The basic sequence of the rollup driver is as follows:

Expand Down
Loading

0 comments on commit 3ab4f82

Please sign in to comment.