Zero-knowledge proofs (ZKPs) are cryptographic methods that allow one party (the prover) to prove to another party (the verifier) that a statement is true without revealing any additional information beyond the validity of the statement itself. This tutorial will guide you through creating your first ZK circuit using Circom, one of the most popular languages for writing ZK circuits.
Before we begin, make sure you have the following installed:
Node.js (v14 or higher)
npm (Node Package Manager)
Git
npm install -g circom snarkjs
mkdir my-first-zk-circuit
cd my-first-zk-circuit
npm init -y
A ZK circuit is a program that defines a computational problem that can be proven without revealing the inputs. Think of it as a mathematical function that:
Takes some inputs (private and public)
Performs computations
Produces outputs that can be verified
Signals: These are the inputs and outputs of your circuit
Private signals: Known only to the prover
Public signals: Known to both prover and verifier
Constraints: These are the mathematical relationships that must be satisfied
They define the valid computations in your circuit
They ensure the prover is following the rules
Let's create a simple circuit that proves knowledge of a number that, when multiplied by itself, equals a given public number. This is a basic example that demonstrates the core concepts.
multiplier.circom
:pragma circom 2.0.0;
template Multiplier() {
// Declaration of signals
signal private input a;
signal public output b;
// Constraints
b <== a * a;
}
component main = Multiplier();
Let's break down this circuit:
pragma circom 2.0.0;
- Specifies the Circom version
template Multiplier()
- Defines our circuit template
signal private input a;
- Declares a private input signal
signal public output b;
- Declares a public output signal
b <== a * a;
- Defines the constraint (b must equal a squared)
circom multiplier.circom --r1cs --wasm --sym
snarkjs powersoftau new bn128 12 pot12_0000.ptau -v
snarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="First contribution" -v
snarkjs powersoftau prepare phase2 pot12_0001.ptau pot12_final.ptau -v
snarkjs groth16 setup multiplier.r1cs pot12_final.ptau multiplier_0000.zkey
snarkjs zkey contribute multiplier_0000.zkey multiplier_0001.zkey --name="First contribution" -v
snarkjs zkey export verificationkey multiplier_0001.zkey verification_key.json
input.json
:{
"a": 5
}
snarkjs groth16 prove multiplier_0001.zkey witness.wtns proof.json public.json
snarkjs groth16 verify verification_key.json public.json proof.json
Let's break down what we just did:
Circuit Definition: We created a circuit that proves knowledge of a number that, when squared, equals a given output.
Compilation: The circuit was compiled into a format that can be used to generate and verify proofs.
Trusted Setup: We performed a trusted setup to generate the proving and verification keys.
Proof Generation: We generated a proof that we know a number (5) that, when squared, equals 25.
Verification: We verified that the proof is valid without revealing the original number.
Security:
Always keep private inputs secure
Use appropriate bit lengths for your signals
Be careful with arithmetic overflow
Performance:
Minimize the number of constraints
Use efficient circuit designs
Consider the trade-off between circuit size and security
Testing:
Test your circuit with various inputs
Include edge cases
Verify the constraints work as expected
Arithmetic Overflow: Always consider the maximum values your signals can take
Incorrect Constraints: Double-check your mathematical relationships
Inefficient Designs: Keep your circuits as simple as possible
Security Assumptions: Don't make assumptions about the security of your inputs
Now that you've created your first ZK circuit, here are some suggestions for further learning:
Try creating more complex circuits
Learn about different proving systems (Groth16, PLONK, etc.)
Explore optimization techniques
Study real-world applications of ZK proofs
Join the ZK community and contribute to open-source projects
Congratulations! You've created your first ZK circuit. This is just the beginning of your journey into the world of zero-knowledge proofs. Remember that ZK technology is still evolving, and there's always more to learn. Keep experimenting, building, and contributing to the community.
Happy coding!