ZK stands for Zero-Knowledge or Zero Knowledge Proofs. It's the idea that you can prove you know something without giving that something away.
Let's say you want to prove that you're over 18 but don't want to give away your birthdate. You can use Zero Knowledge Proofs to do this.
Alice is color-blind and sees Blue and Red as the same shade. Bob is not color blind.
Bob tries to convince Alice that two sheets of paper are different colors (red and blue), but Alice doesn't believe him. So, Bob uses a simple Zero Knowledge proof:
- Bob places the red piece of paper in Alice's right hand and tells her this is red.
- Bob places the blue piece of paper in Alice's left hand and tells her this is blue.
- Alice places her hands behind her back, with paper in each, without Bob seeing. She swaps them over any number of times she likes, keeping track of how many times she swaps to know which paper was originally in each hand.
- Periodically, she presents the papers to Bob, one in each hand, and asks him which is red and which is blue.
- Each time Bob guesses correctly, Alice is more confident that Bob is correct when he says which is red and which is blue.
This is an interactive Zero Knowledge proof since the prover (Bob), and the verifier (Alice) interact with each other at each step (when Alice presents the papers to Bob).
Crucially, when we talk about zk-SNARKS, we speak about Non-Interactive proofs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge). These use fancy math, cryptography, and a "trusted setup" to avoid being interactive at each step. In other words, it enables the prover to generate a one-time single proof. And the verifier can verify that proof without periodically interacting with the prover.
Simply put, the verifier can be a Solidity smart contract that can verify a proof that is generated by a prover off-chain (or from another chain, or whatever).
By writing ZK circuits, which are sort of "proof generators".
We can write a ZK circuit that proves you are over the age of 18. You feed your birthday into the circuit; it spits out a proof that doesn't contain any underlying information but proves that the fact is correct.
We write circuits in this repo in a language called circom
.
Then, using a package called snarkjs
, we can use this circuit to generate a Solidity smart contract verifier specifically for that circuit!
Example flow: Generate the proof off-chain, and submit on-chain to the verifier. If verified, the contract can take action/open some doors/mint some tokens/etc.
This is a raw manual version of the following steps:
- Compiling the circuit using circom
- Long-winded trusted setup using Groth-16 and Powers of Tau
- Generating the proof
- Verifying the proof locally
- Generating a smart contract verifier
- Generating raw call to the verifier contract to copy-paste into a Remix call
This is pretty long-winded and you can get a bit lost in the low-level weeds here, but it does a good job of going through what's required at a low-level to work with SNARKs.
If you want to get straight into learning how to engineer circuits in a repo using hardhat, check out number 2...
This is a simplified version of the many manual steps above, integrated into a hardhat project, using the same circuit.
It has a hardhat test file that tests the constraints of the circuit.
A hardhat project with quadratic equation provers. Prove that you know the root of an equation without revealing it.