Writing My First ZK Circuit with Circom
-
#ZK
#零知識證明
#Cryptography
#密碼學
#Ethereum
#以太坊
#How-To
#教學

The crypto market is down bad right now 📉. But honestly? The bear market is my favourite time to learn. No FOMO, no Twitter noise. Just me, my laptop, and a very long reading list.
I have been talking about zero-knowledge proofs for a while now (see my earlier posts on the STARK prover). This time I actually wrote one from scratch instead of just reading about it.
Why Circom?
I started with Circom because it targets Solidity developers and the tooling around it (snarkjs) is well-documented. There are other options like Noir or Halo2, but Circom felt the most approachable as a starting point.
The mental model that finally clicked for me: a ZK circuit is like a function where you prove you know the inputs that produce a given output, without revealing those inputs. The verifier learns nothing about your private inputs — only that they satisfy the constraints.
My First Circuit
I started with the classic example: prove that you know two numbers a and b that multiply together to give a public value c. Sounds simple, but seeing it work end-to-end made everything concrete.
pragma circom 2.0.0;
template Multiply() {
signal input a;
signal input b;
signal output c;
c <== a * b;
}
component main = Multiply();
After compiling with Circom, running through snarkjs to generate the proving and verification keys, and finally deploying the Solidity verifier contract on a testnet — it worked. The verifier confirmed my proof without knowing what a and b were.
It’s honestly a bit magical the first time you see it. 🤯
What Tripped Me Up
The hardest part was understanding the difference between signals and variables in Circom. Signals are constrained (they form part of your circuit), variables are not. If you mix them up, you get subtle bugs that compile fine but produce incorrect proofs.
Also, the trusted setup phase with snarkjs requires downloading some relatively large files (the Powers of Tau ceremony output). The documentation does warn you but I still sat there wondering why my internet was being hammered.
What’s Next
I want to build something actually useful with this — probably a simple private voting circuit. Also planning to explore Noir from Aztec, which has a Rust-like syntax and might feel more natural given my background with Rust.
ZK is hard, but it’s the kind of hard that feels worth it.