SPV on Ethereum layer2
Author: Eric from @OrbiterResearch
1. Basic Concept
Create a Simple Payment Verification (SPV) on (or off-chain) Ethereum layer2, and verify it on Ethereum Mainnet to prove the transaction exists.
2. What is Ethereum Layer2
Layer 2 (L2) is a collective term to describe a specific set of Ethereum scaling solutions. Layer 2 is a separate blockchain that extends Ethereum and inherits the security guarantees of Ethereum. (From ethereum.org)
3. Optimistic Rollups
3.1 Optimism
As we know, Optimism is an “Optimistic Rollup” Layer2, which is describing a blockchain that it’s consensus mechanism and security takes advantage of Ethereum instead of providing their own. So all the transactions that happen on the optimistic will be Rollup to Ethereum.
On Optimism, every tx will be sent to “sequencer”, which provides the following services:
● Providing instant transaction confirmations and state updates.
● Constructing and executing L2 blocks.
● Submitting user transactions to L1.
These pending txs are periodically submitted in large batches(with some basic compression) to Ethereum for finalization. All Batches are stored in a contract on Ethereum called CTC(CanonicalTransactionChain). So technically this CTC forms the Optimism blockchain.
When the tx batch has been submitted to Ethereum(or an individual wallet sends a tx directly from CTC Contract’s enqueue method), the CTC contract will emit a “TransactionEnqueued” Event, “sequencer” has an “ indexer” service that monitors this event to update L2 tx state.
After the tx’s data has been submitted to Ethereum, the sequencer’s other service “batch-submitter” will periodically submitted these tx’s (block’s because every tx has a block) stateRoot in a larger batches to Ethereum to prove a tx is on-chain. These batches are stored in a contract on Ethereum called SCC(State Commitment Chain). The SCC contains a list of state roots, which, in the optimistic case, correspond to the result of applying each transaction in the CTC against the previous state.
After that, the Fault proofs can work. Because there isn’t any direct proof of the validity of stateRoot, any stateRoot can be challenged by “fault-proof”. If the stateRoot is successfully challenged, then it is removed from the StateCommitmentChain to eventually be replaced by another proposed stateRoot. A successful challenge does not roll back Optimism itself, only the published stateRoot about the state of the chain. The ordering of transactions and the state of Optimism are unchanged by a fault-proof challenge.
3.2 Arbitrum
The basic concept of the Arbitrum rollup strategy is almost the same as optimism. But the implementation is different. One difference is Arbitrum only has one chain data on mainnet called Sequencer InBox, because Arbitrum sequencer only submits the L2 confirmed tx to L1, that means Sequencer Inbox contract plays both CTC and SCC roles. The other difference is the “Fault proofs” part. Optimism’s Fault proofs process totally relies on EVM, but Arbitrum puts most of the process off-chain and only verifies the assertion on-chain.
4. ZK Rollups
4.1 zkSync
In ZK rollups there is no “fault-proofs” part, the batch of transactions is verified directly on the Ethereum network. After the verification passes, the batch of transactions is considered final like any other Ethereum transaction. With any batch of off-chain transactions, the ZK rollup operator generates a proof of validity for this batch. Once the proof is generated, it is submitted to Ethereum to make the roll-up batch final. In zkSync, this is done via a SNARK, succinct non-interactive argument of knowledge.
4.2 StarkNet
The difference with zkSync is StarkNet produces STARK proofs, the zero-knowledge scalable transparent argument of knowledge.
5. How to verify a layer2 tx hash on Ethereum Mainnet
ZK Rollups: Because zkSync 2.0 and StarkNet are still in the early alpha\baby alpha stage, their rollup data protocol format details are still not open source, so we discuss optimistic rollups first.
5.1 Use the rollup on-chain data
5.1.1 Optimism
Now we know how Optimism Rollup Works, let’s take a closer look so that we can find out how to verify an optimism tx on Ethereum in a simple way.
There is a transaction whose txHash is 0xa219a0fbca39a3544e8e66423b7cce51efdac0059f208c362c234656605d3131
We can get txinfo from RPC:
then use block hash to get block info from RPC:
Now we know the block’s stateRoot hash is 0x93678ea5b8325e72fe9345f0c33bfa3aa2d888ecc5b645505f6ad1757f7a16ea
It is necessary to build a full node to obtain the batch tx of SCC through the Tx of L2:0xf37ea02a03a6ad4424c1f0b4b9d669a9577d9b5427fa4fe992dfd43556729c0b
we can find the stateroot is in the arg “ _batch” array to call the appendStateBatch function
the batch index is 34692 and we can find the MPT root hash of these batches of stateroot from the SCC storage contract “get” function
SCC storage contract:0xb0ddff09c4019e31960de11bd845e836078e8ebe
So the proof scheme is:
Step 1:
Step 1.
tx hash
0xa219a0fbca39a3544e8e66423b7cce51efdac0059f208c362c234656605d3131
=>
block stateRoot
0x93678ea5b8325e72fe9345f0c33bfa3aa2d888ecc5b645505f6ad1757f7a16ea
First is to replay the tx and generate a new stateRoot for comparison
We can do this based on optimism’s fraud-prover services
As part of the OVM2.0 upgrade, Optimism temporarily prohibits the use of failure-proof mechanisms. We can follow progress at https://github.com/ethereum-optimism/cannon/
and we can verify it on-chain based on the OVM verification contract
https://github.com/ethereum-optimism/optimism/tree/8d67991aba584c1703692ea46273ea8a 1ef45f56/packages/contracts/contracts/optimistic-ethereum/OVM/verification
Step 2:
Step 2.
block stateRoot
0x93678ea5b8325e72fe9345f0c33bfa3aa2d888ecc5b645505f6ad1757f7a16ea
=>
SCC batch index root hash
0xcc43dec03a7928fdff64d14d9bffc9f9c01bd8c112bbb7b8648d38273c2c2445
Step 2 is simple, we just need to rebuild the statebatch’s MPT and get the proof to verify on-chain
5.1.2 Arbitrum
Arbitrum is using Interactive fraud proofs so that we can’t verify txs on-chain.
So on-chain verification is not universal, we need off-chain solutions.
5.2 Use the roll up off-chain data and verify on-chain
5.2.1 Basic concept
The RollUps’s basic common is to submit the tx data (in a certain form) to the mainnet:
Arbitrum: https://etherscan.io/tx/0x2fdff8d93621dc8d77c87f565d6f83f823ac989f86574afe8ad7abe74adbb2c4
Optimism:
https://etherscan.io/tx/0x2af907902032f5af7bce2a09e0e07d077a5fe7f952a23ae380f8c450ceebcfaa
zkSync:
https://goerli.etherscan.io/tx/0x98202afdf37d85b17b2bf286489ce7c8f03d2509391f759330d70df6ffe31017
StarkNet:
https://etherscan.io/tx/0x83cee9310c4fb41dd7d4f72fcca03abf4e5d7db889638038cd2a6acc731caa7b
5.2.2 Practice
So what we need to do is:
1. Transform the tx info into rollup’s format metadata => txmetadataformat
2. verify the “txmetadataformat” is include the rollup l1-submissionTx inputData => l1-submissionTx inputData
3. use the “ rollupinputdata” and the transaction info to rebuild l1-txhash
4. verify l1-txhash is in block l1-txroot
5. use the l1-txroot with prevblock’s info and other blockinfo to rebuild blockhash
6. generate the calculation process proof and verify it with the blockhash on-chain
It seems like this is the solution. However, we still have some problems to solve.
1.What’s the best way to generate and verify the proof?
zkSNARKs are the most widely used zero-knowledge protocols, it has many toolkits compatible with Ethereum.
ToolKits candidates:
We may need the browser-compatible features, so maybe zokrates(zokrates’ backend also used bellman) or snarkjs are the better options.
Typical on-chain verifier gas cost:
Zokrates: 275k
snarkjs: 290k ~ 600k
2. How to read the blockhash before the latest 256 blocks. 256 blocks means we can only read block hashes within about one hour, that’s not enough.
Luckily, the architecture of Ethereum makes it possible to verify the authenticity of previous data naturally. Each block’s header data is included in the Keccak hash calculation that describes the next block. Similar to a Merkle Tree, this means the current block hash is a commitment to all previous blocks. Therefore, as long as we can link up all of our historic blocks using successive hashing and have the final block match up with the current Ethereum state, we know that all the historic data is correct.
But the history data is huge, we can’t do this all on-chain. Luckily we have Zero-knowledge proof tech that can make this happen. We can use zkSNARK to construct our Merkle Tree to guarantee that the original data has the blockchain property and results in the stated Merkle root. Then we can “connect” the last block in our proof to a recent block that is still accessible from EVM, by showing the recent block was created by hashing the data from our block. Thereby proving that the Merkle Tree was created from our preceding block data. We are making several trees of fixed size. This makes Merkle proofs shorter and makes it easier to work with as a zk-SNARK, both of these keeping gas costs under control for users.
Here is what we need to do:
1. We have to make all the historic block hashes into several Merkle Trees, and submit them on-chain.
2. We have to run a server running 24/7 building zk-SNARK proofs and submitting them on-chain once every x block (maybe every day).
3. To those blocks that are less than one day and more than 256 blocks can just make a hash chain from the desired block to a block recent enough to be accessible from the EVM. And issue their proof as a zk-SNARK of a small Merkle Tree of block headers and their inclusion in that tree.
RoadMap
● Week 46 2022
○ Circuit Build: Optimism implements route verification
● Week 47 2022
○ Circuit Build: Arbitrum Proof Verification
● Week 48–49 2022
○ Circuit Build: Zksync 1.0 Transaction Info => Rollback Transaction Info inputData
● Week 50 2022
○ Circuit Build: Arbitrum & Zksync 1.0 SVP testnet alpha
● Week 51–52 2022
○ Circuit Build: Use zkSNARKS to build L2 historical block Merkel Tree, and write off-chain clients to generate Merkel Tree-RootHash regularly
○ Circuit Build: Write a proof contract, provide the function of submitting rootHash and verification data, and verify the validity of L2 transactions
● Week 53
○ Other Layer2s