The problem zk-sunade solves
There is a considerable cost associated with verifying zk proofs on the EVM. Arbitrum Stylus allows writing smart contracts in Rust, hence we wrote a groth16 verifier contract in Rust and deployed it on the Stylus testnet.
Challenges we ran into
- Initially, we were very ambitious and wanted to verify zkEVM circuits written in Halo2. However, we quickly ran into the issue that everyone else ran into, i.e. the bytecode size limit as it was taking about 190 kb after compression. So we understood that importing any rust crate is not going to work and we have to write as much code we can to be able to optimize on the bytecode size.
- So we thought of writing the halo2 verifier code by hand but that's a lot for a weekend hackathon. So we reduced the scope to writing groth16 verifier. One of the most popular privacy application TornadoCash uses the groth16 zk scheme and its verifier is written in Solidity. We rewrote the verifier in Rust.
- We found that our groth16 verifier exceeded the bytecode size limit! It was a very scary situation but then we tried to figure out multiple tricks to optimize the bytecode size.
- It was very difficult to test our code and debug issues in our implementation since we cannot use frameworks like Foundry or Hardhat or anything else. We had to continuously send transactions to the live stylus testnet and wait for our tx to work.
- Since there aren't any tools that display error stack trace or display execution trace similar to tenderly, it was very difficult to pinpoint bugs in our implementation and we spent a lot of time binary searching in our code.
- We also found that some AbiEncoderV2 features are not implemented in stylus SDK yet.
Eventually, we made it work.