# Taiko Preconf Gatway Design ## Overview The following diagram illustrates the interaction of a preconfer with the taiko network and the underlying L1. ```mermaid sequenceDiagram participant User participant Taiko Network participant Preconfer participant L1 Contracts Preconfer->>L1 Contracts:(1) Register loop User->>Taiko Network:(2) tx User->>Taiko Network:(2) tx User->>Taiko Network:(2) tx Preconfer->>Taiko Network:(3) Fetch head Taiko Network->>Preconfer:(3) head Preconfer->>Taiko Network:(3) Fetch txs Taiko Network->>Preconfer:(3) txs Preconfer->>Preconfer:(3) Build L2 block Preconfer->>Preconfer:(3) Signs L2 block Preconfer->>Taiko Network:(3) Signed L2 block Taiko Network->>Taiko Network:(4) Execute L2 block Taiko Network->>User:(4) Latest preconfed state end Preconfer->>L1 Contracts:(5) Propose batch ``` ### Taiko Client: - Provides access to Taiko network, in particular it - provides access to the current L2 head - publishes preconfed L2 blocks to the preconf P2P network ### Preconfer: - L2 block building - L1 inclusion of the L2 blocks ### L1 Contracts (Taiko): - registration and selection of preconfer - batch submission of L2 transactions ## Preconfer Taiko provides L1 contracts that handle preconfer registration and selection, as well as the proposing of batches by preconfers. The main part to implement is the building of L2 blocks, according to the Taiko spec, as well as optimization of the L1 inclusion strategy. ### Preconfer selection Taiko provides a contract [PreconfWhitelist.sol](https://github.com/taikoxyz/taiko-mono/blob/main/packages/protocol/contracts/layer1/preconf/impl/PreconfWhitelist.sol) that allows preconfers to register and pseudo-randomly selects one for the next epoch (the seed is the previous epoch start time so this selection is deterministic in each epoch). This is accessible through ``` function getOperatorForNextEpoch() external view returns (address); ``` ### L2 block building L2 blocks should be published exactly every __L2_BLOCK_TIME_MS__ (=T/N) at the start of the L2 block. Basic block building steps: - fetch L2 head from Taiko Client - fetch txs from L2 mempool (through [taiko-geth](https://github.com/taikoxyz/taiko-geth) (taikoAuth_txPoolContentWithMinTip); if txs are empty, block can be skipped) - create L2 block from txs - add anchor transaction as first tx of the block - publish L2 block, signature to Taiko Client For details about the L2 block requirements, anchor transactions and the data that needs to be submitted to the L1 contracts, see https://github.com/taikoxyz/taiko-mono/blob/main/packages/protocol/docs/how_taiko_proves_blocks.md. #### To check: - Publication at exact timestamps is non-trivial. Similar to the handoff window (described below), the preconfer needs some time buffer to build, sign and publish the latest L2 block, after the last tx for that block arrived and before the next block starts. Double check exactness requirements with Taiko. - baseFee: specs mention calculation of baseFee. It can be retrieved from the L1 block header. Clarify if/why it should be computed. - check if Taiko supports gossiping of txs that will be included in the next L2 block. - check with Taiko if there are docs for the Taiko Client API and taiko-geth API. ### L1 inclusion Taiko provides a contract [PreconfRouter.sol](https://github.com/taikoxyz/taiko-mono/blob/main/packages/protocol/contracts/layer1/preconf/impl/PreconfRouter.sol) that provides an interface for batch submission of L2 blocks through ``` function proposeBatch(bytes calldata _params, bytes calldata _txList ) external returns (ITaikoInbox.BatchInfo memory info_, ITaikoInbox.BatchMetadata memory meta_); ``` It rejects transactions that are not provided by the currently assigned preconfer. The current epochs preconfer needs to publish all preconfed blocks to the L1 to not get slashed. This includes potentially unpublished L2 blocks that were preconfed by the previous preconfer(s). There are different options to submit batches to the L1: - Submit all preconfed L2 blocks in one batch as soon as the handoff window starts. - Submit preconfed L2 blocks as soon as their combined size exceeds a threshold. - Submit preconfed L2 blocks when a certain number of blobs has been filled (not applicable without replacing some Taiko components (L1 contracts) as Taiko doesn't use blobs yet, should come in the future) #### Synchronization: - __HANDOFF_WINDOW__: In order to get a high chance of an the preconfed L2-blocks get included in the L1, a handover window (here defined wrt slots) is required at the end of an epoch. During these slots, the preconfers should successfully submit the preconfed L2 blocks to the L1. New transactions are preconfed by the preconfer for the next block. - __HANDOFF_START_BUFFER__: When the preconfer changes, the new preconfer needs to know the latest preconfed L2 block. The handover start buffer is a short period of time at the beginning of each handover window that allows the last L2 block to propagate through the P2P network and be processed by the next epochs preconfer. This doesn't provide a strict guarantee that the next preconfer knows about the latest block when it starts preconfing. #### To check: - The Taiko preconf design does not consider the option to have block proposers as preconfer. Check with them if this is by design. - How to deal with the case that a preconfer didn't see the latest L2 block when it starts preconfing? Specs mention "Edge Cases" section that doesn't exist:) ### Slashing - The preconfer can be slashed for faults. This is handled by Taiko, currently using a whitelisting approach with restaking protocols. ## Open questions/challenges: - **Guaranteed inclusion in the L1 is not fully solved yet** (not relevant for current design, but might become interesting for proposers that are preconfing): - Nondeterministic edge cases for proposer lookahead (EIP-7917) - **Scaling**: see https://github.com/gattaca-com/based-op/blob/main/docs/docs/scaling.md - gossiping can be problematic and needs to be measured