Exploring Eclipse's Canonical Ethereum Bridge and Proving System

Eclipse is Ethereum's fastest Layer 2, powered by the Solana Virtual Machine (SVM).

As mentioned in our initial architecture post, Eclipse combines the best pieces of the modular stack: Ethereum as the settlement layer for our enshrined validating bridge, Celestia as the data availability layer, RISC Zero to generate our zero-knowledge fraud proofs, and Solana's SVM as the execution environment.

In this article, we will cover Eclipse's canonical bridge and fraud proof design. The upcoming release of our monorepo will contain the canonical bridge smart contracts, relayers, and a Docker container to run a test network for local development.

An Overview of Our Canonical Bridge

Eclipse is composed of three layers:

  1. Execution: A fork of the Solana Labs client (v1.17) for SVM transaction execution

  2. Settlement: Our canonical bridge defining Eclipse's fork-choice rule exists on Ethereum, where fraud proofs will also be submitted

  3. Data Availability: Eclipse publishes the data necessary to produce fraud proofs as data blobs on Celestia

The diagram below illustrates how these modules interact:

The rest of this article will focus on Eclipse's Ethereum bridge, as shown in the diagram. Blobstream will relay attestations signed by Celestia's validator set to certify to Ethereum that the data for a batch of Eclipse's slots was published correctly. This allows Eclipse's bridge to verify the data provided for fraud proofs against the signed data roots from Celestia. In the rest of this section, we will outline the processes by which:

  1. funds are deposited via our bridge,

  2. data blobs of batches of Eclipse's blocks are posted on Celestia,

  3. withdrawals via the bridge are handled, and

  4. fraud proofs are generated in worst-case scenarios.

Depositing via Eclipse's Native Ethereum Bridge

The flow when a user deposits onto Eclipse via the native Ethereum bridge is summarized as follows:

  • A user calls Eclipse's Deposit Bridge contract on Ethereum

  • From within Eclipse's SVM executor [1], the relayer [2] observes the user's deposit and destination address

  • Next, the relayer calls the SVM bridge program, which is responsible for transferring a user's deposit to the applicable destination address

  • The relayer verifies the deposit transaction via a zk-light client (to be implemented)

  • Finally, the block containing the subsequent post-deposit transfer transaction is finalized and published via a Solana Geyser Plugin

The diagram below shows the interactions between Ethereum, Celestia, and the SVM Executor during the deposit flow described above:

Publishing Eclipse's Slots to Celestia as Data Blobs

The flow for publishing batches of Eclipse's slots to Celestia as data blobs is summarized below:

  • The SVM executor publishes each Eclipse slot to the message queue via Geyser

  • The SVM executor posts batches of Eclipse's slots to Celestia as data blobs

  • The Celestia validator set produces commitments to the data blobs submitted, which can be used to prove the inclusion of a transaction on Eclipse's chain against the data root

  • The data roots contained in every single Celestia block header are relayed to Eclipse's bridge contract on Ethereum via Blobstream

The diagram below from Celestia explains how the commitment of the data within a given Celestia block is stored in the block header:

Withdrawing and Submitting Fraud Proofs to Eclipse's Ethereum Bridge

Similarly to other L2s that use fraud proofs (Arbitrum, Fuel, and many others), withdrawals from Eclipse require a challenge period during which verifiers can submit fraud proofs in the case of an invalid state transition:

  • At a regular cadence, the SVM executor posts a commitment to an epoch (a predetermined number of batches) of Eclipse's slots to Ethereum, along with collateral

  • Eclipse’s bridge contract conducts some basic checks to ensure that the data posted is well-formed (described in the Fraud Proof Design section)

  • If the submitted batch passes these basic checks, there is a predefined window during which verifiers can post fraud proofs in the case that the batch commitment implies an invalid state transition

  • If a verifier posts a successful fraud proof, they win the executor's collateral, the posted batch is rejected, and the canonical state of the Eclipse L2 is rolled back to the last valid batch commitment. Here, Eclipse's governance would have the ability to elect a new executor

  • If the challenge period elapses with no successful fraud proof, the executor recovers its collateral along with a reward

  • Consequently, the Eclipse bridge contract will now complete any withdrawal transactions that were included in the finalized batch

Fraud Proof Design

In this final section, we will detail Eclipse's fraud proof system design, inspired by Anatoly Yakovenko and John Adler. Generally, for any fraud proof, a verifier must:

  1. Identify a transaction containing an invalid state transition

  2. Provide the inputs to said transaction with the invalid state transition

  3. Demonstrate that re-executing said transaction with the given inputs results in an output that is not equal to what was committed on-chain

In Eclipse's case, (1) Celestia merklizes blobs of batches of blocks that Eclipse's SVM executor posts, allowing transaction inclusion proofs via Merkle witnesses. For (2), unlike EVM-based L2s, which post a Merkle root to the global state tree, for performance reasons Eclipse does not update a global state tree on a transaction-by-transaction basis, but we will explain how we ensure the correctness of inputs in more detail below. Finally, in the case of (3), Eclipse's verifier generates a zk-proof of the output(s) for a given transaction, unlike the interactive verification game approach common across EVM-based L2s.

All Eclipse transactions can be represented as taking a list of input accounts, executing a transaction, and producing a list of resultant output accounts:

The critical observation for our fraud proof design is that for transaction execution, it is always the case that any S_InputAccount must have been the S_OutputAccount of some previous transaction. This allows us to reference the last transaction in the chain that produced a given input account instead of providing a Merkle witness to a global state tree. As a result of our design, we introduce additional fraud accusation types, such as a reference to the previous transaction not being valid or the input account already being "spent" by some later transaction. We describe this process in more detail below:

Transaction Inputs Posted to Celestia

  • Transaction data (posted by the sequencer)

  • Transaction data (posted by the SVM executor) which contains the following:

    • Transaction count [3]

    • Celestia namespace location of the transaction data

    • Account hash [4] for each input, with transaction count resulting in each

    • List of sysvars used and value of each, with transaction count resulting in each (if applicable) [5]

    • Transaction output, if the transaction was successful; otherwise, an indicator that the transaction failed (either because it failed to parse or because it was unable to execute)

Batch Commitments Posted to The Ethereum Bridge

In addition, the batches of transaction data posted to Celestia have their commitments relayed to the Ethereum contract. The commitments consist of:

  • The Celestia namespace location of the transaction data of the last transaction included in the batch

  • The Celestia namespace location of the execution data [6] of all included transactions

  • A list of deposits, withdrawals, and overrides, each of which comes with the transaction count of the associated Eclipse transaction

Criteria for an Invalid Batch

As explained above, there are several ways a batch can be found to be incorrect:

  • One of the linked Celestia namespace locations is malformed or does not point to data of the required type

  • There is a transaction on Celestia with no associated execution data, which can be due to two reasons:

    • The transaction, which was supposed to be the most recent in the batch, has no associated execution data.

      • In such a case, a verifier verifies that this is the case and the Ethereum bridge contract checks that the latest entry in the execution data list does not correspond to the correct transaction data
    • The execution data of a different transaction is missing

      • A verifier posts the Celestia namespace location of the transaction data of the offending transaction and the previous and following transactions in the order that was successfully executed. Following this, the bridge contract checks that this transaction was skipped
  • There is a transaction whose execution data is incorrect, which could be caused by the following:

    • The transaction count associated with an account hash or sysvar does not produce the claimed output.

      • In this case, a verifier posts the Celestia namespace location of the execution data for the given transaction with the corresponding count, and the bridge contract checks that the given value is incorrect.
    • The transaction count associated with an account hash or sysvar is outdated

      • A verifier posts the Celestia namespace location of the execution data for a newer transaction, modifying the value in question, and the bridge contract checks that this is indeed newer.
    • The transaction output is incorrect, or the transaction uses an input that is not listed:

      • In this case, a zk-proof of the correct execution of the transaction or a zk-proof that the transaction uses an input that is not listed is needed. This can be obtained in two ways:

        • A verifier posts the proof, or

        • A verifier posts the index of the transaction claimed to be fraudulent, and the Eclipse bridge contract uses this to solicit a zk-proof from RISC Zero's Bonsai

    • There was a deposit from Ethereum more than N batches ago, but there is no corresponding deposit in the transaction list (included in the batch commitment posted to the bridge contract) for the N past batches. Alternatively, there is a deposit in the transaction list with no related Ethereum deposit transaction, or the transaction exists but has already been included in another Eclipse batch

      • The bridge contract in all of these cases can determine that this has happened and regard such a batch as invalid
    • There is a deposit or withdrawal executed with no corresponding entry in the transaction list

      • In such a case, a verifier posts the Celestia namespace location of the given execution data, and the bridge contract checks this fact to judge the transaction as invalid
    • There is a deposit or withdrawal in the transaction list whose associated Eclipse transaction is not performing the expected action or whose transaction count is not within its expected transaction count range. In such a case, either one of the following would happen:

      • The bridge would automatically determine this is the case and refuse the corresponding batch

      • A verifier notices the invalid state transition and posts proof of the offending transaction, which is then verified by the bridge contract

If any commitment batch is found to be incorrect, the Eclipse bridge contract will roll back the bridge to that of the last provably correct batch commitment. Note that transactions are never removed from the chain, even in the case of fraud, so only the commitment needs to be re-computed.

Parting Thoughts

This article aimed to give a high-level guide to Eclipse's trust-minimized bridge on Ethereum and explain some details about our fraud proof design. Given the modular nature of our L2 and the nascence of our technology stack, we will continue to release articles and documentation about various aspects of Eclipse in the coming weeks.

To get involved with Eclipse Testnet, please follow our instructions here. You can contact us on Twitter or Discord with specific inquiries about our Testnet, bridge, or technical questions.


[1]: The node which computes the results of SVM transactions and applies the eventual output to Eclipse’s new state

[2]: An operator which passes on-chain events between Ethereum and Eclipse

[3]: Note that the executor, not the sequencer, posts this. If it were included in the data posted by the sequencer, it would add the complication that the sequencer could skip over a count, making it impossible for the executor to do their job correctly. This could be compensated for in the fraud proof design, but it would add extra complexity. A second advantage of having only the executor post the count is that it makes it easy to allow transaction overrides to be posted to Celestia, if desired.

[4]: SVM accounts can be represented with a unique hash. The only way this hash is modified is via a transaction.

[5]: To do this without an excessive amount of hashing, we will run a trace on each executed program to see which parts of each used sysvar are actually accessed. This is possible, but will require modifying Solana's BPF interpreter.

[6]: This includes data for attempted transactions that failed to execute.

Subscribe to Eclipse Labs
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
This entry has been permanently stored onchain and signed by its creator.