Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doc: Add registry description to design doc #123

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
60 changes: 50 additions & 10 deletions Docs/design-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ end
- Provide the latest preconfed state to users.
- (3)~(5) is repeated 4 times until the end of the slot.
- (6) L1 proposer submits the preconfirmed L2 blocks to the L1 Taiko inbox contract.
- Since proposers do not build blocks in the current PBS pipeline, they will use inclusion lists to force the builder to include the L2 blocks in the L1 block. More on this is in [Appendix: MEV-Boost Modification for Forced Inclusion List](https://www.notion.so/Appendix-MEV-Boost-Modification-for-Forced-Inclusion-List-685e9b4e89eb43b48c5b172c220be7a7?pvs=21) .
- Since proposers do not build blocks in the current PBS pipeline, they will use inclusion lists to force the builder to include the L2 blocks in the L1 block. More on this is in [Appendix: MEV-Boost Modification for Forced Inclusion List](#Appendix-MEV-Boost-Modification-for-Forced-Inclusion-List) .
- (7) A disputer, who can be anyone, submits fraud proofs if the preconfed block published in (4) contradicts the L2 blocks submitted in (6).

# Components

The PoC will be implemented as an [EigenLayer AVS](https://www.eigenlayer.xyz/ecosystem?category=Rollup%2CAVS%2COperator). Two main components are involved: the *AVS smart contracts* and the *AVS operator node*.

In this section, we will explore what each of these components does at a high level. Further details on how these components interact will be covered in the following [Implementation](https://www.notion.so/Implementation-1debf554210242cd9880d7c7e5e16282?pvs=21) section.
In this section, we will explore what each of these components does at a high level. Further details on how these components interact will be covered in the following [Implementation](#Implementation) section.

### **AVS smart contracts**

Expand All @@ -99,7 +99,7 @@ They will be responsible for:

# Implementation

In this section, we will outline how the PoC will implement each step in the [The Seven Steps for Preconfirmations](https://www.notion.so/The-Seven-Steps-for-Preconfirmations-fb88cdf993c24e60b931f20568f9cde5?pvs=21).
In this section, we will outline how the PoC will implement each step in the [The Seven Steps for Preconfirmations](#The-Seven-Steps-for-Preconfirmations).

## Step 1: Registration

Expand Down Expand Up @@ -139,6 +139,8 @@ end
- Note: Since the slasher contract has [not yet been implemented](https://github.com/Layr-Labs/eigenlayer-contracts/blob/a888a1cd1479438dda4b138245a69177b125a973/src/contracts/core/Slasher.sol#L14) in EigenLayer, we will implement our own mock contract for the PoC.
- (4) The operator registers as a preconfer operator by calling [Registry Coordinator](https://github.com/Layr-Labs/eigenlayer-middleware/blob/mainnet/docs/RegistryCoordinator.md) Eigenlayer middleware.

More detailed design considerations around the registry can be found in [Appendix: Registry Design](#Appendix-Registry-Design).

## Step 2: Election

The AVS contract (`PreconfTaskManager`) elects a single preconfer from the set of registered validators for a given slot. There are two cases to consider:
Expand Down Expand Up @@ -170,7 +172,7 @@ p(p): Preconfer
p(n): Non-preconfer
```

The preconfer that submitted the lookahead is slashed if the lookahead is wrong, which can be proven after the invalid preconfer’s slot passes. Details on the slashing conditions are explained in the [Step 7: Slashing](https://www.notion.so/Step-7-Slashing-bb151c894bb54c47b8d220f3f7055720?pvs=21) section.
The preconfer that submitted the lookahead is slashed if the lookahead is wrong, which can be proven after the invalid preconfer’s slot passes. Details on the slashing conditions are explained in the [Step 7: Slashing](#Step-7-Slashing) section.

### **Empty Lookahead**

Expand Down Expand Up @@ -282,7 +284,7 @@ Note that, as illustrated above, the AVS operator node will discard the preconfi
The preconfers will need to eventually include their preconfed L2 transactions to the L1 to avoid being slashed. There are two scenarios to consider depending on when this inclusion happens:

- **The preconfer is the proposer of the current slot**:
- In this case, the preconfirmer will submit the list of preconfirmed transactions to the L1 builders via forced inclusion lists in MEV-Boost. Since the current version of MEV-Boost does not support forced inclusion lists, we will implement our own fork of MEV-Boost to add this functionality. More details on this fork can be found in [Appendix: MEV-Boost Modification for Forced Inclusion List](https://www.notion.so/Appendix-MEV-Boost-Modification-for-Forced-Inclusion-List-685e9b4e89eb43b48c5b172c220be7a7?pvs=21)
- In this case, the preconfirmer will submit the list of preconfirmed transactions to the L1 builders via forced inclusion lists in MEV-Boost. Since the current version of MEV-Boost does not support forced inclusion lists, we will implement our own fork of MEV-Boost to add this functionality. More details on this fork can be found in [Appendix: MEV-Boost Modification for Forced Inclusion List](#Appendix-MEV-Boost-Modification-for-Forced-Inclusion-List)
- **The preconfer is not the proposer of the current slot**:
- In this case, the preconfer will submit the list of preconfirmed transactions via the L1 mempool.

Expand Down Expand Up @@ -331,15 +333,15 @@ end
- (4) If the sender is the first preconfer of the epoch, verify the `lookahead` (e.g. it is not empty) and update the contract’s view of the lookahead.
- (5) Process the block and submit the L2 txs to the [TaikoL1 contract](https://github.com/taikoxyz/taiko-mono/blob/ef3d7d5c32e0687e273d149bc7ba1da5642fb9ba/packages/protocol/contracts/L1/TaikoL1.sol#L74).
- (6) TaikoL1 contract checks if the sender is `PreconfTaskManager`, and aborts if not.
- (7) If the L2 block is accepted by the TaikoL1 contract, store the `(blockId => proposer, txListHash)` mapping within the `PreconfTaskManager` contract. This mapping will be used in the [Incorrect Preconfirmation Slashing](https://www.notion.so/Incorrect-Preconfirmation-Slashing-5fe36e637eb54ced88d7a43b8b6c83c4?pvs=21) below.
- (7) If the L2 block is accepted by the TaikoL1 contract, store the `(blockId => proposer, txListHash)` mapping within the `PreconfTaskManager` contract. This mapping will be used in the [Incorrect Preconfirmation Slashing](#Incorrect-Preconfirmation-Slashing) below.

## Step 7: Slashing

The preconfer will be slashed if they equivocate during their preconfirmation duties. There are two kinds of slashing in the PoC:

- **Incorrect Preconfirmation Slashing**: Slashes when the preconfirmed L2 block was not submitted to L1 as promised.
- Implemented as `proveIncorrectPreconfirmation(..)` function in the `PreconfTaskManager`.
- **Incorrect Lookahead Slashing:** Slashes when the preconfer [submitted](https://www.notion.so/EXT-Design-Doc-Taiko-Preconfirmation-PoC-74db78ff89df4aa8983ed1e640a05359?pvs=21) an incorrect lookahead.
- **Incorrect Lookahead Slashing:** Slashes when the preconfer submitted an incorrect lookahead.
- Implemented as `proveIncorrectLookahead(..)` function in the `PreconfTaskManager`.

For both `proveIncorrectPreconfirmation` and `proveIncorrectLookahead`, the slashing will be conducted by invoicing the `Slasher` contract of EigenLayer core via the `PreconfServiceManager` as the following:
Expand Down Expand Up @@ -376,8 +378,8 @@ Next, we will dive deep into how these slashing conditions can be implemented wi

This slashing should happen when the preconfirmed L2 block contradicts with the L2 block submitted to the L1. More concretely, slashing would happen the following two contradict each other:

- The `Preconfirmation` object published by the preconfer at [Step 4: Preconfirmation Publication](https://www.notion.so/Step-4-Preconfirmation-Publication-d6620e19f3334226a96311ed315c92d0?pvs=21)
- The `(blockId => proposer, txListHash)` mapping which is [recorded](https://www.notion.so/EXT-Design-Doc-Taiko-Preconfirmation-PoC-74db78ff89df4aa8983ed1e640a05359?pvs=21) when the L2 block is submitted to L1.
- The `Preconfirmation` object published by the preconfer at [Step 4: Preconfirmation Publication](#Step-4-Preconfirmation-Publication)
- The `(blockId => proposer, txListHash)` mapping which is [recorded](#Updated-Design-Doc-Taiko-Preconfirmation-PoC) when the L2 block is submitted to L1.

Below is a pseudo-code for this slashing condition:

Expand Down Expand Up @@ -423,7 +425,7 @@ The preconfer that submitted the lookahead is slashed if the lookahead is wrong,
- (B) Proof that the proposer change was not due to `p8'` being slashed:
- This can be done via Merkle proof of beacon head of the previous slot, proving that `slashed:false` for `p8'` ([example code](https://github.com/nerolation/slashing-proofoor/tree/main)).

Note that this setup only detects and slashes the incorrect lookahead after the fact, providing a time window during which L2 blocks from an incorrect proposer can be accepted by the Taiko inbox contract. We plan to address this issue by introducing a more robust election mechanism in a future extension ([**Better election mechanism**](https://www.notion.so/Better-election-mechanism-36472dd4639945acb6ef7dce4f20cb5e?pvs=21)).
Note that this setup only detects and slashes the incorrect lookahead after the fact, providing a time window during which L2 blocks from an incorrect proposer can be accepted by the Taiko inbox contract. We plan to address this issue by introducing a more robust election mechanism in a future extension ([**Better election mechanism**](#Future-Extensions)).

# Future Extensions

Expand Down Expand Up @@ -459,6 +461,44 @@ Another difference is the granularity of preconfs: For the devnet design, they p

We plan to publish more research on these points in the future.

# Appendix: Registry Design

In this section, we delve deeper into the registry design.

## The Key Question

In Ethereum, there are two types of cryptographic keys:

- **BLS Keys**: Used by validators to sign consensus operations like attestations and block proposals and to identify them in the proposer lookahead.
- **ECDSA Keys**: These are used to hold ETH and sign transactions on the network.

On the other hand, preconfer signatures are required in preconfirmation publication (step 4) and L1 inclusion (step 6). The question is, what key should the preconfer use to sign the signature in these steps? There are broadly two approaches.

- **Approach 1: Use BLS keys**
- Pros:
- Validators are already identified using the BLS key, so there is no need to store any additional key mapping in the preconf registry.
- Validators can leverage existing BLS key management systems within node operator infrastructures. These systems provide an additional layer of security by allowing validators to **split their BLS keys, distribute them among multiple parties, and require an n-of-m threshold for signing.**
- Cons:
- When including the preconfed transactions on L1, the transaction batch must be signed with the BLS key in addition to the ECDSA key of the overarching transaction. This is problematic in terms of cost because BLS key verification will require 220K gas in the BLS precompile in an upcoming hard fork based on internal experiments. Given that current Taiko block proposals cost around [110K gas](https://dune.com/queries/3837305/6453697), **this would more than triple the block proposal cost for Taiko blocks.**
- **Approach 2: Use ECDSA keys**
- Pros:
- When including the preconfed transactions on L1, **no additional signature is required other than the ECDSA signature of the overarching tx**.
- Cons:
- Requires managing the BLS key to ECDSA key mapping in the registration contract.
- Node operators cannot utilize their existing BLS key management systems and must set up new infrastructure for ECDSA management. Furthermore, since **ECDSA keys cannot be split like BLS keys, they cannot set up an n-of-m threshold for signing as they can for BLS**.

## Our Solution

We believe that the additional gas cost associated with BLS signatures makes Approach 1 impractical. Therefore, we have adopted Approach 2. Our registry design works as following:

- The preoconf registry internally holds a BLS key to ECDSA key mapping.
- The registration endpoint takes the validator BLS key and signature, then stores the BLS key to ECDSA (= the `msg.sender` of the registration) mapping.
- The preconfer actions (e.g., proposing L2 blocks to the inbox contract) are signed and verified using the mapped ECDSA key of the validator.

Based on hearings from node operators, this approach's biggest downside is the lack of distributed key management of ECDSA. One potential mitigation would be to allow BLS to ECDSA multi-sig mapping so node operators can operate distributed key management of the individual ECDSA keys of the multi-sig. Since the gas cost of `ECRECOVER` is [3000 gas](https://www.evm.codes/precompiled), on-chain verification of the multi-sig will be significantly lower than BLS signature checks.

You can find our registry implementation here: https://github.com/NethermindEth/Taiko-Preconf-AVS/blob/5bdb53b7e7ab4aa2284dbb4e069eac5e051f2e93/SmartContracts/src/avs/PreconfRegistry.sol

# Appendix: MEV-Boost Modification for Forced Inclusion List

The forced inclusion list functionality will work as the following:
Expand Down