There are two parts to a Taiko node, which are connected over the engine API:
taiko-geth
taiko-client
Taiko geth
The taiko-geth (opens in a new tab) repo is a fork of go-ethereum (opens in a new tab) with some changes according to Taiko protocol, it serves as a L2 execution engine, which needs to be coupled to a consensus client (in Taiko network, this will be the taiko client's driver software), like L1 ethereum execution engines, it will listen to new L2 transactions broadcasted in the L2 network, executes them in EVM, and holds the latest state and database of all current L2 data.
Taiko client
The compiled binary bin/taiko-client
is the main entrypoint which includes three sub-commands:
driver
: keep the L2 execution engine's chain in sync with theTaikoL1
contract, by directing the L2 execution engine (opens in a new tab).proposer
: propose new transactions from the L2 execution engine's transaction pool to theTaikoL1
contract.prover
: request ZK proofs from the zkEVM, and send transactions to prove the proposed blocks are valid or invalid.
Driver
Taiko client's driver software serves as an L2 consensus client. It will listen for new L2 blocks from the Taiko layer 1 protocol contract, then direct the connected L2 execution engine to insert them into its local chain through the Engine API.
Engine API
Driver directs a L2 execution engine to insert new blocks or reorg the local chain through the Engine API (opens in a new tab).
Chain synchronization process
NOTE: The Taiko protocol allows a block's timestamp to be equal to its parent block's timestamp, which differs from the original Ethereum protocol. So it's fine that there are two
TaikoL1.proposeBlock
transactions included in one L1 block.
Driver will inform the L2 execution engine Taiko protocol contract's latest verified L2 head, and try to let it catch up the latest verified L2 block through P2P at first. Driver will monitor the execution engine's sync progress, if it is not able to make any new sync progress in a period of time, driver will switch to insert the verified blocks to its local chain through the Engine API one by one.
After the L2 execution engine catches up the latest verified L2 head, driver will subscribe to TaikoL1.BlockProposed
events, and when a new pending block is proposed:
- Get the corresponding
TaikoL1.proposeBlock
L1 transaction. - Decode the txList and block metadata from the transaction's calldata.
- Check whether the txList is valid based on the rules defined in Taiko protocol.
If the txList is valid:
- Assemble a deterministic
TaikoL2.anchor
transaction based on the rules defined in the protocol, and put it as the first transaction in the proposed txList. - Use this txList and the decoded block metadata to assemble a deterministic L2 block.
- Direct L2 execution engine to insert this assembled block and set it as the current canonical chain's head via the Engine API.
If the txList is invalid:
- Create a
TaikoL2.invalidateBlock
transaction and then assemble a L2 block only including this transaction. - Direct the L2 execution engine to insert this block, but does not set it as the chain's head via the Engine API.
NOTE: For more detailed information about: block metadata, please see
5.2.2 Block Metadata
in the white paper.
NOTE: For more detailed information about txList validation rules, please see
5.3.1 Validation
in the white paper.
NOTE: For more detailed information about the
TaikoL2.anchor
transaction and proposed block's determination, please see5.4.1 Construction of Anchor Transactions
in the white paper.
Proposer
Taiko client's proposer software will fetch pending transactions in a L2 execution engine's mempool intervally, then try to propose them to the Taiko layer 1 protocol contract.
Proposing strategy
Since tokenomics have not been fully implemented in the Taiko protocol, the current proposing strategy is simply based on time interval.
Proposing process
Proposing a block involves a few steps:
- Fetch the pending transactions from the L2 execution engine through the
txpool_content
RPC method. - If there are too many pending transactions in the L2 execution engine, split them into several smaller txLists. This is because the Taiko protocol restricts the max size of each proposed txList.
- Commit hashes of the txLists by sending
TaikoL1.commitBlock
transactions to L1. - Wait for
TaikoData.Config.commitConfirmations
(currently0
) L1 blocks confirmations. - Propose all splitted txLists by sending
TaikoL1.proposeBlock
transactions.
Prover
Proving strategy
Since tokenomics have not been fully implemented in the Taiko protocol, the prover software currently proves all proposed blocks.
Proving process
When a new block is proposed:
- Get the
TaikoL1.proposeBlock
L1 transaction calldata, decode it, and validate the txList. Just like what thedriver
software does. - Wait until the corresponding block is inserted by the L2 execution engine's
driver
software. - Generate a ZK proof for that block asynchronously.
If the proposed block has a valid txList:
- Generate the merkel proof of the block's
TaikoL2.anchor
transaction to prove its existence in theblock.txRoot
's MPT (opens in a new tab), and also this transaction receipt's merkel proof in theblock.receiptRoot
's MPT from the L2 execution engine. - Submit the
TaikoL2.anchor
transaction's RLP encoded bytes, its receipt's RLP encoded bytes, generated merkel proofs, and ZK proof to prove this block valid, by sending aTaikoL1.proveBlock
transaction.
If the proposed block has an invalid txList:
- Generate the merkel proof of the block's
TaikoL2.invalidateBlock
transaction receipt to prove its existence in theblock.receiptRoot
's MPT from the L2 execution engine. - Submit the
TaikoL2.invalidateBlock
transaction receipt's RLP encoded bytes, generated merkel proof, and ZK proof to prove this block invalid, by sending aTaikoL1.proveBlockInvalid
transaction.
NOTE: For more information about why we need these merkel proofs when proving, please see
5.5 Proving Blocks
in the white paper.