We all know Layer 2s batch transactions together and send a single transaction back to Ethereum.
But what *actually* gets posted to L1?
I followed a transaction all the way from being submitted on Polygon zkEVM through to being part of a ZK proof on L1.
Here's what I learned:
The full flow of transactions can be broken down into 5 steps:
1/ Submitting
2/ Executing
3/ Batching
4/ Sequencing
5/ Aggregating
(1/25)
1/ Submitting
On the zkEVM, transactions go through almost instantly.
I built a demo application last week showcasing how quickly the state is updated from the user's POV on the Polygon zkEVM.
(2/25)
From the user's perspective, interacting with the zkEVM looks and feels exactly the same as Ethereum with cheaper fees and faster transaction speeds.
Users submit transactions via a JSON-RPC interface (typically through wallets like 🦊) where they go into a pending pool.
(3/25)
2/ Executing
After being submitted, the transactions are stored in a pending transactions pool, where they await the sequencer's selection for either execution or discard based on a few validity checks.
Once executed, the L2 state is updated almost instantly.
(4/25)
Under the hood, the sequencer is executing or discarding each transaction, and broadcasting this information to each zkEVM node.
For every transaction except bridging to L1, this is all the user needs to care about; the transaction is executed & the state is updated.
(5/25)
However, as we explored in this previous thread, bridging funds back to L1 requires those batches of transactions to be proved using ZK-proofs like a ZK SNARK on Ethereum.
This is where the next three steps (batching, sequencing, aggregating) come into play.
(6/25)
3/ Batching
To batch transactions together, they're concatenated into one bytes value.
On the L1 PolygonZkEVM smart contract, a "BatchData" struct is defined, containing a "transactions" field of type bytes.
(7/25)
The transactions are encoded using RLP (Recursive-Length Prefix) serialization and can be either EIP-155 (Simple replay attack protection) or pre-EIP-155 transactions.
The other properties contain the time the batch was created and a Merkle tree about L1-L2 transfers.
(8/25)
Each transaction goes through RLP serialization and is converted into bytes which are then concatenated together into the transactions field of the BatchData struct, along with the other metadata properties.
Multiple of these batches gets created for one transaction.
(9/25)
4/ Sequencing
Once these batches are created, they're ready to be sent to L1 for sequencing.
The PolygonZkEVM smart contract has a function called "sequenceBatches", which is called with the batches we just saw created as an argument.
(10/25)
Let's inspect a real transaction as an example.
In the screenshot below, we can see the sequencer calling the PolygonZkEVM smart contract on Ethereum L1, by providing the batches it prepared as an argument to the "sequenceBatches" function.
(11/25)
This particular transaction provided the function with 52 batches of transactions as we can see in the input data.
The max number of batches is actually defined in the contract, currently set at 1000 in the _MAX_VERIFY_BATCHES constant.
(12/25)
Each batch provided also contains the concatenated, RLP-serialized transactions in the transactions field of the BatchData struct.
The maximum it can take is also defined in the contract, currently set at 120000 in the _MAX_TRANSACTIONS_BYTE_LENGTH constant.
(13/25)
The sequenceBatches function iterates over each batch and ensures they are valid, before updating the virtual state on the L1 smart contract inside a mapping called "sequencedBatches".
(14/25)
The batches are now sequenced and the transactions are said to be in the "virtual state".
We'll explore what that means shortly, but here's a quick update to our diagram to see what the trusted sequencer is doing under the hood.
(15/25)
In the zkEVM, there are three (or four, if you include the pending state) states a transaction can be in:
1/ Trusted: State is updated on L2.
2/ Virtual: Batches are sequenced on L1.
3/ Consolidated: ZK Proof is posted on L1.
(16/25)
So far we've explored every step of the process up until the batches have been sequenced on L1 by the PolygonZkEVM smart contract. So we're currently in a virtual state.
But in order to bridge funds back to L1, a validity proof needs to be posted on L1 first.
(17/25)
5/ Aggregating
Finally, the trusted aggregator takes the sequenced batches and provides them to the zkProver to generate a ZK proof in the form of a ZK SNARK.
We explored this in another previous thread in more detail:
(18/25)
Using the FFLONK protocol, the specific trusted setup drawback that typically comes with SNARKs is avoided.
More details from Jordi are below:
(19/25)
The end result is the aggregator receives a ZK proof that is succinct enough that it can be stored on the Ethereum L1. A simplified diagram of this flow is below:
(20/25)
Once the aggregator has the proof, it calls another function on the PolygonZkEVM smart contract called "verifyBatchesTrustedAggregator", providing the proof it just received as an argument, among other parameters.
(21/25)
We can inspect another real transaction on Ethereum to see this in action.
Below, we can see the trusted aggregator calling the PolygonZkEVM Smart contract on Ethereum, providing the ZK proof as an argument to the "verifyBatchesTrustedAggregator" function:
(22/25)
Within this function, another smart contract, "rollupVerifier", has a function called "verifyProof" that gets called.
It is provided with the proof and an inputSnark; which is a cryptographic representation of all the L2 transactions of a specific L2 State transition.
(23/25)
Finally, the state of the L1 smart contract is updated again.
If the proof is valid, various states are updated like the global exit root and the "batchNumToStateRoot" mapping containing the consolidated L2 state roots:
We've now reached the final consolidated state!
(24/25)
In this particular example, the posting and verification of this ZK proof cost around ~350K gas:
(25/25)
I've also posted the full blog post covering this in more detail, linked below:
https://t.co/eGsEb0hOpTblog.jarrodwatts.com/how-polygon-zk…
That's everything I learned.
If you enjoyed this kind of technical content:
- Sharing the thread helps me out a lot with engagement
- Follow me for more threads!
Share this Scrolly Tale with your friends.
A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.