cLabs Proposal for Celo to transition to an Ethereum L2

Appendix: Design Proposal

This Appendix specifies each of the deviations from the OP stack highlighted in the Section “Proposed Upgrade” of the forum post. It also discusses the reasoning behind these proposals in more detail. This Appendix assumes an understanding of the OP Stack and their terminology. We recommend reading Optimism’s Bedrock Explainer and then diving into their excellent technical specifications for additional context.

Decentralized Sequencer

In this section, we will outline our proposal for modifying the OP Stack’s sequencer role to leverage Celo’s existing PBFT consensus mechanism and validator set as a decentralized sequencer.

In Optimism, the sequencer is responsible for:

  • Gathering pending transactions into an “unsafe” block (more details on unsafe blocks and block finality in Finality and Reorgs in Optimism Bedrock.
  • Signing and propagating this block to other L2 full nodes through the p2p network.
  • Extracting the TransactionBatch (ordered list of transactions, plus some metadata) from the block and sending it as transaction calldata to the BatchInbox address on the L1. (For the sake of clarity, we omit details about how data is compressed and sent in channel frames.)

When deriving the canonical L2 chain from L1 inputs, full nodes filter data sent to the BatchInbox address on the centralized sequencer’s well-known public key, ensuring that only the correct TransactionBatches are included.

In the event of transaction censorship, users can always deposit transactions on the L1 which are then force-included when full nodes derive the L2.

In our design, the rotating block proposer would become a rotating transaction sequencer. At a high-level, the proposer for a round would:

  1. Propose an L2 block including an ordered TransactionBatch.
  2. Go through PBFT consensus to obtain signatures from ⅔ of sequencers (current Celo validators) over the TransactionBatch, submit the signed TransactionBatch to the DA layer (see Off-chain Data Availability with EigenDA below for more DA-specific details). (Note: we are also exploring the option of submitting the entire L2 block or even the TransactionBatch and signed state root, which is discussed in more detail in Light Clients & Bridging below.)
  3. Obtain a DA Certificate from the DA layer and post this certificate to Ethereum, likely maintaining the TransactionBatch structure but simply replacing the full transaction data with this pointer to the DA layer. (Note: we are continuing to examine and find mitigations for the case where malicious DA nodes prevent specific validators from storing data and obtaining DA Certificates. One option we are considering here is to require validators to actually submit the previous block to EigenDA instead of their current proposed block, and to include the received certificate in the header of the block they propose.)

Full nodes deriving the L2 chain would need to then confirm and filter data batches based on who the authorized sequencer (elected block proposer) is for a given L2 block and whether 2/3rds of the elected sequencers have signed each transaction batch

1-Block Finality

Celo currently promises 1-block finality, but to be specific, this really means that there is a large imposed cost to prevent malicious actors from rewriting chain history (ignoring some other nuanced changes Celo has made to prevent reorgs even during equivocation). When thinking about finality, it may be helpful to reframe this as “resistance to chain reorgs” more generally. In order to provide reorg resistance at Celo-economic security in our design, we need to address two sources of possible reorgs: 1) avoid those caused by Ethereum reorgs and 2) impose sufficiently high costs to those caused by discrepancies in what the decentralized sequencer shares over the p2p network and posts to the L1. Once DA Certificates posted to Ethereum are finalized, those blocks benefit from additional economic security guarantees, with data secured by restaked ETH in EigenDA (data availability) and DA Certificates (consensus) by Ethereum’s finality guarantees. We will first look at the status quo of finality and reorgs in Optimism before digging into our proposed mitigations.

Finality and Reorgs in Optimism Bedrock

Optimism L2 blocks have three levels of finality:

  • “Unsafe”: blocks are shared by the sequencer over the p2p network and can be reorged with no penalty.
  • “Safe”: blocks are deterministically derived from inputs and TransactionBatches posted to not-yet-finalized Ethereum blocks. These blocks are susceptible to Ethereum reorgs.
  • “Finalized”: blocks are derived from finalized blocks on Ethereum and can practically not be reorged without massive economic costs.

When deriving a safe block, a full node might already have an unsafe block stored for the same block height. In this case, the node will check if the newly derived block is the same, and in that case it will just update its “safe head”. If the two differ, then a reorg will occur on the L2 chain and the safe block will become the new head of the L2; that is, the unsafe portion of the chain reorgs.

Unsafe head reorgs could happen in the following scenarios:

  • If the sequencer shares an unsafe block on the p2p network but misses the “sequencing window” to post the corresponding TransactionBatch to Ethereum. As a result, there won’t be a valid TransactionBatch for that height, and the safe head will reorg to use a generated empty TransactionBatch.
  • If the sequencer distributes an unsafe block on the p2p network but posts a different TransactionBatch for the same block height to Ethereum, the safe head will reorg to use the data on Ethereum.

Safe head reorgs can occur in the following situations:

  • If an L1 block is reorged, then the corresponding sequencing epoch’s blocks will need to be updated to account for the changes in the L1 Origin (specifically, to L1 Attributes Deposited Transaction). Note: this situation can also cause an unsafe head reorg.
  • If Ethereum reorgs such that a TransactionBatch posted either no longer exists or now falls outside of the sequencing window, then the corresponding (previously safe) L2 block will become an empty block.

Mitigating Ethereum Reorgs

Essentially, we need to mitigate Ethereum reorgs that affect L1 deposited transactions (L1 Attributes and user-deposited transactions) to prevent reorgs on Celo L2.

To do this, we propose modifying the L1 Origin used to follow only finalized blocks on Ethereum. In other words, that means constructing L1 Attributes from the most recently finalized block, as well as waiting until user-deposited transactions have finalized before including them as L2 transactions. Because of the way that finalization currently works on Ethereum (i.e. an entire epoch is justified and finalized at once, as opposed to individual blocks being continually finalized), we will need to modify how sequencing epochs in Celo are derived from L1 blocks; for instance, perhaps they will need to map to Ethereum epochs instead of L1 blocks. As long as we rely on finalized L1 inputs when deriving L2 blocks, we should be able to practically avoid L2 reorgs.

Only using finalized data has the potential downside of relying on out-of-date data when calculating gas fees as well as increasing the time for user-deposited transactions to be included in the L2. In addition, we may need to diverge further from the OP Stack in terms of how L2 sequencing epochs are derived, since an entire Ethereum epoch will be finalized at once. We plan to continue exploring the implications of this.

Mitigating Sequencer-Caused Reorgs

These reorgs are caused by the sequencer failing to post the expected data batch (and/or posting a different data batch) to L1 within the sequencing window. That is, this may occur either when the sequencer fails to post any batch when one was expected or posts a different TransactionBatch corresponding to an unsafe L2 block shared over the p2p network. (Note that a different batch can include posting a batch when the consensus slot was missed, resulting in an empty block over the p2p network).

To address unsafe head reorgs with a decentralized sequencer, we must impose on-chain slashing conditions on sequencers that either fail to post the shared data within the sequencing window or post a TransactionBatch that differs from that shared over the p2p network. In the event of validators double-signing a TransactionBatch for the same block height, all participating validators should have their stake slashed (similar to how double signing is handled in Celo today).

One other mitigation strategy we plan to investigate further is allowing the unpermissioned submission of DA Certificates for a block height. For instance, it may be possible to simply add a derivation rule to accept the first posted batch for a given block height that has the required 2/3rds BLS signatures of the sequencers. This would prevent validators from maliciously causing a reorg by simply not posting their batch, as any honest node could submit the signed batch or block.

Additionally, monitoring validators’ sequencer performance can allow Celo voters to play a role in ensuring that responsible validators remain elected. By adding these slashing conditions, we would obtain “Celo-security” level resistance to unsafe head reorgs.

Off-chain Data Availability with EigenDA

In the OP Stack, the DA layer (Ethereum) provides both 1) transaction ordering (consensus) and 2) availability of the full transaction data. Together, these two roles are necessary to deterministically derive the Optimism L2 from L1 data alone. Without (1), there is no canonical system state in the first place. Without (2), there is no way for full nodes to actually derive the L2 chain, meaning that it’s also impossible to verify or disprove proposed state roots.

For Celo L2, we propose using off-chain data availability to keep transaction costs low. In order to fulfill the responsibilities above, we propose sending the full transaction data to EigenDA and storing ‘pointers’ (DA Certificates) to the full data batches on the consensus layer (Ethereum). An L2 full node would then be able to look up the stream of pointers on Ethereum associated with TransactionBatches and “dereference” them by querying EigenDA for the full data.

EigenDA is a data availability service built on top of EigenLayer. EigenDA node operators can opt-in and receive payment to store erasure encoded blobs of data for a specified length of time; if node operators are found (through Proof of Custody) to misbehave by not storing data that they have attested to storing, their stake is slashed. EigenDA is stated to achieve DA rates that meet or exceed danksharding, enabling Celo L2 to keep transaction fees low. For more information about EigenDA, we recommend watching this talk about it.

In our design, some node (likely the sequencer, though this is an area of continued exploration):

  1. constructs the transaction batch for an L2 block signed by 2/3 of the validators
  2. prepays the DA node operators for storing the batch for the required amount of time*
  3. splits and encodes the data batch into erasure-encoded blobs using EigenDA’s encoding software and submits this to the nodes
  4. aggregates DA node signatures over the hash of the data verifying that the data has been stored
  5. upon receiving a quorum of signatures, posts the aggregated signature to Ethereum as a DA Certificate mapped to the L2 block

*We are continuing to explore the minimum length of time required for block data storage to still leverage the higher security provided by this design. One option here includes checkpointing blockchain state at regular intervals.

When full nodes are syncing with Celo, they can obtain the DA Certificates posted to Ethereum within a sequencing window and check that the data batch hashes match those shared in the p2p network. In the event that there is a discrepancy for the same block height, the full node can request it from the DA nodes and treat this as the canonical block data after verifying the BLS signatures on the block. If there are two distinctly signed tx batches, these two batches can be submitted on-chain to slash validators that have double-signed at that block height.

Off-chain vs. On-chain Data Availability

We should note that as long as we are not using Ethereum for full transaction data availability, there is a potential system liveness concern if the DA nodes decide not to serve data. As long as the data is still available on the p2p network, the hashes could be checked against those posted on Ethereum, but proving DA node misbehavior on-chain is a known shortcoming of the system that may require social consensus to remediate. (Proof of Custody ensures that they store the required data but not that they serve the data requested by anyone.)

CELO tokens as native currency on L2

The OP Stack uses ETH to pay gas fees on L2. If the Celo blockchain chooses to become an L2 based on the OP Stack, the CELO token must be the native currency and be used to pay gas fees on L2. Alternative fee currencies (e.g. ETH) will still be available in the same way they currently are on the Celo blockchain. All of this is important to maintain compatibility with existing Celo applications and preserve the Celo token economics.

Paying gas fees on L2 in a different currency than on L1 can have implications in places where both layers interact. So these interactions must be checked and adapted if necessary:

L2 transaction costs: On Optimism, transactions incur an L1 data fee in addition to the normal gas fee. This fee is used to cover the costs of making the transaction data available on L1. The calculation of the data fee needs to be adapted for multiple reasons:

  • Using EigenDA for data availability has a different cost structure than using Ethereum as a DA layer (see Off-chain Data Availability with EigenDA).
  • Reading L1 gas prices only from finalized blocks increases the time between reading L1 gas prices and writing to L1, thereby increasing the risk of significant price changes (see 1-Block Finality).
  • Using different gas currencies on L1 and L2 adds exchange rate risks.

Luckily, there are also factors at play that mitigate these difficulties:

  • By using EigenDA, the L1 costs for data availability are greatly reduced (and with it the exchange rate and L1 gas price volatility risk).
  • EigenDA can be configured to use CELO tokens to pay data provider nodes, avoiding all risks related to CELO/ETH conversion.
  • The sequencer has a strong incentive to make transaction data available even if the cost of doing so goes somewhat beyond the earned data fees, because it will be slashed if it fails to provide the data (see 1-Block Finality). It is sufficient that the economics work out on average.

It is too early to decide on a specific formula for the data fee, but the rough structure will be

celo_data_fee = tx_data_size * eigenda_data_price

eth_data_fee = eigenda_certificate_size * L1_gas_price

total_data_fee (in CELO) = celo_data_fee + eth_data_fee * exchange_rate * safety_margin

Celo already successfully uses oracles to convert between different gas currencies and the native CELO token, so retrieving an exchange rate between ETH and CELO via a similar mechanism should not be a problem.

Purchasing guaranteed L2 gas on L1: Optimism allows depositing transactions on L1 to force execution of these transactions in L2. The L2 gas required for execution is paid for by burning ETH on L1 at a price which is determined by an EIP-1559 market. Since this market sells gas directly, without going through the L2 gas price, the L2 gas currency is not involved at all. So no changes are necessary due to using CELO tokens as a gas currency on L2.

Light Clients & Bridging

The above proposal creates 1-block finality by letting the decentralized sequencer sign transaction batches and forcing it to publish the same signed batch. This lets full nodes quickly derive the block state from trusted (with Celo-level security) data.

In contrast to full nodes, light clients and bridges can’t derive the state themselves and have to rely on state created by another party. In classic Celo blockchain, the validators signed the block, not only the transactions contained in the block, allowing light clients and full nodes to rely on the signed state. Without this, they have to wait for a state root to be published and the challenge period to pass without a successful challenge.

The desirable property of having a trusted state root available quickly could be brought back by letting the decentralized sequencer sign a state root in addition to the transaction batch. This would allow light clients and bridges to work on a state with the same latency and security guarantees as today’s Celo blockchain. The sequencer executes the transactions as part of its operations anyway, so no overhead for transaction execution would be added.

The specifics of this approach have not been worked out yet, but there is ongoing work being done in the Celo ecosystem outside of cLabs to verify Plumo proofs (Celo’s zk-SNARK-based light client) on Ethereum cheaply using a Halo2 proof on BN254. The reorg resistance provided by the transactions 1-block finality might even allow publishing and signing the state root along with the transaction batch, but this needs further examination of potential failure cases.

Analysis of System Properties & Tradeoffs

In addition to open questions highlighted throughout the proposal, we want to take a look at the system’s properties according to L2BEAT’s criteria as well as when comparing it to Celo as it is today.

Analyzing this design against L2BEAT’s risk criteria:

  • State Validation: in development; once it has landed on OP, we plan to modify their state validation mechanism. Note that the consequences of this are different than for OP, since we plan to use an off-chain DA layer.
  • Data Availability: off-chain with EigenDA, combined with on-chain DA Certificates. EigenDA is secured by ETH restakers under the hood, and Proof of Custody makes it possible to slash DA nodes that are not actually storing the data.
  • Upgradeability: planned to be upgradeable, since we will be following the OP Stack.
  • Sequencer Failure: users can force transactions to be included in the L2 by depositing these transactions on L1. As with OP Stack, there is a delay as long as the sequencing window. Note that since Celo L2 would operate with a decentralized sequencer, L1 deposits would only be necessary if a third of the 110 elected (and independent) sequencers failed.
  • Proposer Failure: cannot withdraw. Initially at least, we will follow the OP Stack which has this property. In the future, we can revisit including a mechanism that allows anyone to propose a state root after a set period of proposer inactivity (as Arbitrum does).

Comparing the Celo L2 proposal to Celo today:

  • Transaction fees: should not increase significantly, though more research is needed to understand what this will be specifically when using EigenDA (since this has not landed in production yet).
  • Finality: 1-block finality is still supported by Celo-level security. Once DA Certificates posted to Ethereum are finalized, there is additional economic security (from EigenDA) backing those blocks.
  • Security: Celo will be able to leverage the security of ETH staked in EigenDA. Note that since EigenDA is an opt-in service, we will need to re-evaluate the specific security of the system once we better understand EigenDA and EigenLayer usage. That said, there is initial excitement around EigenLayer and we are hopeful that this will be a great way to improve Celo security while strengthening Ethereum alignment.
  • Bridging: better bridging between Ethereum and Celo should be enabled by this proposal. Note that withdrawals (Celo → Ethereum) relies on state root proposals and the fraud proof system.
32 Likes