Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 247 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
# Optimism Enclave Light Client (ELC) Specification

## 1. Introduction

This document defines the **Enclave Light Client (ELC)** protocol for tracking the state of an Optimism-based L2 chain in a secure and deterministic manner. Unlike traditional light clients that verify state using block headers and Merkle proofs, this client performs full **execution-based verification** of the L2 chain derivation (replay of L2 chain execution) from L1 data, closely resembling full node behavior while remaining stateless.

## 2. Overview

This section describes an overview of the Optimism ELC (hereafter referred to as "OP ELC").

The first is the purpose of the OP ELC. When an OP ELC instance is initialized, a specific Optimism-based L2 chain and a specific smart contract (address) deployed on it are designated. These two parameters remain constant within the OP ELC instance. Based on this configuration, the OP ELC aims to verify whether a given data exists or does not exist in a specified storage slot of the specified smart contract at a particular block height on the designated L2 chain.

Functionally, OP ELC provides two types of verification operations, which together fulfill the stated objective:

- Verification of the storage root of the target smart contract at a given block height (`update_client`)
- Verification of the presence or absence of slot data under the given storage root (`verify_membership`)

The latter one is a simple Merkle proof against the storage root. The former is implemented through the following three-step verification procedure:

1. Verifies the finality of an L1 head via Ethereum’s ***Sync Committee Protocol***
2. Verifies the finality of an L2 head via Optimism’s ***L2 Chain Derivation***
- Recursively applies a ***Preimage Oracle*** to the verified L1 head to deterministically reconstruct required L1/L2 data
- Executes **L2 derivation logic** using the reconstructed L1/L2 data up to the target L2 head
3. Verifies the existence of the storage root of a target smart contract in the verified L2 head

### Sync Committee Protocol

The Sync Committee Protocol is a Light Client Protocol used to verify the existence and finality of Ethereum blocks. Its details are beyond the scope of this document.

### L2 Chain Derivation

L2 chain derivation is the process used to obtain a new L2 head.
This process begins with a previously verified L2 block and replays the L2 history up to the target L2 block.
To do so, it starts from a given L1 head and traverses the L1 history backward to reconstruct the necessary L1 data.
From this L1 data, it extracts both L2 deposit transactions and batch data.
Using these L2 inputs, the derivation process re-executes the L2 chain logic to deterministically reconstruct the target L2 head.

To carry out this process, the ability to retrieve preimages for various cryptographic commitments (e.g., hash value) is required.
Examples include:

- Retrieving the previous L1 block header from a given L1 block hash
- Extracting individual contract storage entries from a state root of an L2 block

Such capabilities rely on a **preimage oracle** that provides the necessary preimages on demand.

### Preimage Oracle

"Preimage oracle" is a conceptual component that returns a preimage for a given cryptographic commitment.

Cryptographic commitments have a property known as the hiding property, which ensures that it is computationally infeasible to derive the preimage from the commitment value alone.
Nevertheless, there are limited ways to realize the functionality of a preimage oracle in practice.
For example, a block header corresponding to a given block hash can be obtained by querying a blockchain node.
Alternatively, if some commitment–preimage pairs are preloaded and stored, the oracle can return the correct preimage for those specific commitments.

In addition, cryptographic commitments also possess the binding property.
This means that, regardless of how the preimage oracle is implemented, its behavior is cryptographically guaranteed to be deterministic --- i.e., a specific commitment corresponds to a unique preimage.

- Online Preimage Oracle
- A preimage oracle that accepts various types of commitments as input and queries L1/L2 blockchain nodes to retrieve the corresponding preimages.
- By using this type of oracle to execute L2 chain derivation, all commitment–preimage pairs required during the derivation process can be cached in a key-value store.
- This oracle is used for generating the input data passed to the Enclave Light Client (ELC).
- Offline Preimage Oracle
- A preimage oracle based on a key-value store, where commitments are used as keys and their corresponding preimages as values.
- This oracle is constructed from the cache generated by the aforementioned Online Preimage Oracle. By using it, L2 chain derivation can be executed again without accessing any blockchain node
- This type of oracle is used during the verification process of the Enclave Light Client (ELC).

## 3. Architecture

This section describes the basic architecture of the Optimism Enclave Light Client (OP ELC).

### Operations

The OP ELC runs within a Trusted Execution Environment (TEE) via the Light Client Proxy (LCP). It receives inputs through the LCP and performs one of the following four operations:

- `create_client`: Initializes a new OP ELC instance.
- `update_client`: Updates the internal state of an existing OP ELC instance.
- `verify_membership`: Verifies that specified data exists in the target smart contract at a given block height.
- `verify_non_membership`: Verifies that specified data does not exist in the target smart contract at a given block height.

For all of these operations, the OP ELC first verifies the input. If the verification is successful, it returns a signed response proving the result.

For `create_client` and `update_client`, if and only if verification succeeds, the ELC also writes certain pieces of internal state into the key-value store provided by the LCP.

### Internal State

The internal state of each OP ELC instance is created via `create_client` and updated via `update_client`.

This state consists of two components: `ClientState` and `ConsensusState`.

- **`ClientState`**
- Created by `create_client`and stored persistently for each OP ELC instance.
- Most fields in this structure are immutable configuration parameters, such as identifiers for the L1/L2 chains being verified or the address of the target smart contract.
- Mutable fields include, for example, the latest verified L2 block height.
- **`ConsensusState`**
- Created by `create_client` and `update_client`, and stored per L2 block height.
- Contains:
- The storage root of the target smart contract at the corresponding L2 block
- Sync committee data (current and next) used to verify future L1 heads
(This data enables the client to verify the validity of the L1 head during the next `update_client` operation)

### Inputs

- **`Header`**
- Used as the input to the `update_client` operation
- Contains both:
- The data to be stored in the new `ConsensusState`
- The proofs required to verify a new L1 head via **the Sync Committee Protocol**
- The preimages required to verify a new L2 head via **the L2 Chain Derivation**

## 4. Data Structures

This section outlines the key data structures used in the Optimism Enclave Light Client (ELC).

- `optimism_elc::ClientState`
- L1/L2 immutable configuration
- latest L2 height
- flag that specifies whether this client is frozen or not
- `optimism_elc::ConsensusState` (for each L2 height)
- storage root (of the target smart contract)
- L2 output root
- L1 origin
- sync committee information
- `optimism_elc::Header`
- newly claimed L1/L2 block information
- proof data that support the above claims
- proof required for sync committee protocol
- preimages required for L2 chain derivation
- `optimism_derivation::MemoryOracleClient`
- an implementation of the offline preimage oracle

## 5. Functions

This section describes the core functions that make up the Optimism Enclave Light Client (ELC) behavior.

- `optimism_elc::ClientState::check_header_and_update_state`
- Overview
- core logic of ELC’s `update_client`
- verifies a `Header` and stores the storage root in it into `ConsensusState`
- Details
1. `optimism_elc::Header::verify_l1`
- verifies that the newly claimed L1 head is finalized in L1 using the Ethereum’s sync committee protocol
2. `optimism_elc::Header::verify_l2`
- executes L2 chain derivation using the offline preimage oracle
- logic: `optimism_derivation::run` (≒ `kona_client::single::run`)
- oracle: `optimism_derivation::MemoryOracleClient`
- verifies that the derived L2 head is identical to the claimed L2 head
3. `optimism_elc::AccountUpdateInfo::verify_account_proof`
- verifies that the storage root of the target smart contract is included in the claimed L2 head’s state trie
4. `optimism_elc::validate_state_timestamp_within_trusting_period`
- verifies that the claimed L2 head has not expired the trusting period
- `optimism_elc::ClientState::verify_membership`
- verifies that a state (e.g. IBC packet) exists in the verified storage trie (`ConsensusState::storage_root`)
- `optimism_elc::ClientState::verify_non_membership`
- verify that a state (e.g. IBC packet) does NOT exist in the verified storage trie (`ConsensusState::storage_root`)
- `optimism_preimage_maker::derivation`
- performs L2 chain derivation starting from the already verified L2 head to the newly claimed L2 head using the online preimage oracle
- caches all commitment-preimage pairs required during a L2 state derivation

> Note: `optimism_preimage_maker` is not part of the enclave light client itself, but is a reference implementation to prepare inputs. It performs L2 chain derivation starting from the given L2 head and target block number, populating the required preimage oracle by querying the L1/L2 nodes and caching the results.

## 6. Security Assumptions

This section outlines the security assumptions under which the Optimism Enclave Light Client (ELC) is designed to operate. These assumptions are necessary to ensure the correctness and finality of the data verified by the ELC.

### L1 Assumptions

- For each block height, there is a **unique finalized L1 block** that cannot be reverted.
- The **Sync Committee protocol** is correctly implemented and secure, allowing light clients to verify the existence and finality of any L1 block.

### L2 Assumptions

- The system assumes the **at least one honest validator** property: any invalid proposal will eventually be rejected via the dispute game (fault proof mechanism).
- All valid L2 state updates are **eventually reflected on L1** through a canonical proposal process.

### Preimage Oracle / Cryptographic Commitment Assumptions

- **Hiding Property**:
- It is computationally infeasible to recover a preimage from a cryptographic commitment.

- **Binding Property**:
- Each commitment corresponds to a **unique** preimage.
- This ensures that the behavior of the preimage oracle is deterministic, regardless of how it is implemented (e.g., online vs. offline oracle).

### LC Security under These Assumptions above

- The Optimism ELC
- uses the **Sync Committee protocol** to verify the finality of the L1 head.
- performs L2 chain derivation using the (offline)preimage oracle starting from the verified L1 head.
- Due to the uniqueness of the behavior of the preimage oracle, the L2 head obtained by L2 chain derivation is correct and unique.
- Because valid L2 states are guaranteed to be reflected on L1, the derived L2 head is canonically correct.

## 7. Misbehaviour Detection

Among the Security Assumptions described above, the OP ELC can detect occurrences of misbehaviour that violate the assumptions related to either L1 or L2, using the procedures outlined below.

### Misbehaviour Detection for L1 Assumptions

If a Sync Committee acts in violation of the Sync Committee Protocol, the OP ELC will be unable to correctly verify the provided L1 head. Such misbehaviour is defined and the detection procedure is described in the following document. The OP ELC can detect it using the same method:

[https://github.com/datachainlab/ethereum-ibc-rs/blob/v0.1.0/README.md#misbehaviour-detection](https://github.com/datachainlab/ethereum-ibc-rs/blob/v0.1.0/README.md#misbehaviour-detection)

### Misbehaviour Detection for L2 Assumptions

In this section, we assume that the L1 assumptions hold --- that is, the OP ELC is provided with a finalized L1 head --- and we describe scenarios in which misbehaviour related to the L2 assumptions can occur, as well as how such misbehaviour can be handled.

The L2 head, derived from the L1 head via L2 state derivation, is cryptographically unique. The OP ELC also derives the L2 head from the L1 head using this derivation logic. Therefore, a conflicting L2 state can only be reflected on L1 in the case where an invalid proposal --- one that is inconsistent with the L1 data (e.g., deposit or batch data) bound to the L1 head --- remains unchallenged until the end of the challenge period. We refer to this type of misbehaviour as `NoHonestValidatorMisbehaviour`.

`NoHonestValidatorMisbehaviour` can be detected if the OP ELC instance possesses a `ConsensusState` containing an L2 block hash, along with a conflicting proposal and the necessary proofs to trace from the height of the former to that of the latter. The pseudocode for this detection is as follows.

```rust
// This function returns true if a misbehaviour is detected
fn check_misbehaviour(
agreed_l1_origin_hash: H256,
agreed_l2_block_hash: H256,
dispute_game_address: H160,
oracle: &PreimageOracle,
) -> bool {
// agreed L1Origin + L2Block
let agreed_l1_origin = oracle.get_block_by_hash(agreed_l1_origin_hash);
let agreed_l2_block = oracle.get_block_by_hash(agreed_l2_block_hash);

// fields of the target dispute game
let dispute_game_root = oracle.get_storage_root(agreed_l1_origin.state_root, dispute_game_address);
let dispute_l1_head_hash = oracle.get_storage_entry(dispute_game_root, L1_HEAD_SLOT);
let dispute_l1_head = oracle.get_block_by_hash(dispute_l1_head_hash);
let dispute_status = oracle.get_storage_entry(dispute_game_root, STATUS_SLOT);
let dispute_root_claim = oracle.get_storage_entry(dispute_game_root, ROOT_CLAIM_SLOT);
let dispute_l2_block = oracle.get_block_from_output_root(dispute_root_claim);

// prerequisites
if dispute_l1_head.slot >= agreed_l1_origin.slot {
return false;
}
if dispute_status != DEFENDER_WINS {
return false;
}

// MISBEHAVIOUR1: The target proposal claims a future (non-existent) L2 output root
if dispute_l2_block.height > agreed_l2_block.height {
return true;
}

// MISBEHAVIOUR2: The target proposal claims an inconsistent L2 output root
let contradict_l2_block = oracle.get_block_by_height_diff(agreed_l2_block, (agreed_l2_block.height - dispute_l2_block.height));
return calc_output_root(contradict_l2_block) != dispute_root_claim;
}
```