Skip to content
This repository was archived by the owner on Aug 1, 2025. It is now read-only.

Commit dde42d0

Browse files
committed
feat: improve zksnark wording
1 parent 9a51d6c commit dde42d0

File tree

1 file changed

+96
-101
lines changed

1 file changed

+96
-101
lines changed
Lines changed: 96 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,187 +1,182 @@
1-
# Verify ZK proofs
1+
# Verify ZK Proofs on Starknet
22

3-
This example shows how to verify SNARK proofs on Starknet.
3+
This example shows how to verify SNARK proofs on Starknet using a practical example of a token minting system that requires proof of knowledge of a secret.
44

5-
**zk-SNARKs** (Zero-Knowledge Succinct Non-Interactive Arguments of Knowledge) are cryptographic proofs that allow one party (the prover) to prove to another party (the verifier) that they know a specific piece of information (ex: a solution to a computational problem) without revealing the information itself.
5+
## ZK-SNARKs
66

7-
## Key Properties
7+
**zk-SNARKs** (Zero-Knowledge Succinct Non-Interactive Arguments of Knowledge) are cryptographic proofs that enable one party (the *prover*) to demonstrate knowledge of specific information to another party (the *verifier*) without revealing the information itself.
88

9-
- **Zero-Knowledge (privacy)**: zk-SNARKs ensure that the inputs to a computation remain private while proving correctness. In other words, the proof does not disclose any information beyond the validity of the statement.
10-
- **Succinctness**: zk-SNARKs proofs size is small, regardless of the complexity of the statement, with the verification being computationally much cheaper than proof generation. It can be used to verify lots of computation in a much cheaper way than re-doing the computation, allowing for scalability for example.
11-
- **Non-Interactivity**: Once generated, the proofs require no further communication between the prover and verifier, reducing complexity in decentralized environments.
12-
- **Integrity**: Verifiers are guaranteed the correctness of the computation without having to re-execute it.
9+
- **Zero-Knowledge (Privacy)**: Ensures computation inputs remain private while proving correctness. The proof only reveals the statement's validity, not the underlying data.
10+
- **Succinctness**: Proofs remain small regardless of statement complexity, with verification being computationally cheaper than proof generation. This enables efficient verification of large computations.
11+
- **Non-Interactivity**: Proofs require no further communication between prover and verifier after generation, ideal for decentralized environments.
12+
- **Integrity**: Guarantees computation correctness without requiring re-execution.
1313

14-
## Examples of Use Cases
14+
### Common Use Cases
1515

16-
- **Identity Verification**
17-
Prove attributes like age, nationality, or membership without revealing the actual details. Instead of scanning the user's ID card or passport for example, online platforms could verify users' eligibility trustlessly without accessing nor storing sensitive data.
16+
- **Identity Verification**: Prove attributes (age, nationality, membership) without revealing actual details. Enables trustless verification without storing sensitive data.
17+
- **Scalable Rollups**: Bundle multiple transaction proofs into a single proof, eliminating the need for re-execution.
18+
- **Proof of Reserves**: Demonstrate sufficient funds for service eligibility without disclosing actual balances.
1819

19-
- **Scalable Rollups (Layer 2 Solutions)**
20-
Zk proofs could be used to prove the validity and correct computation of multiple transactions execution into a single proof, eliminating the need to re-execute them to verify. zk-Rollups on Ethereum, like Starknet, leverage zk-STARKs to improve transaction throughput while reducing costs. This enables efficient and scalable off-chain computation with secure on-chain verification.
20+
## Example: Proof of Secret with Replay Attack Protection
2121

22-
- **Proof of Reserves**
23-
Prove you have above enough money, without disclosing actual account balances, to be eligible to apply to a certain service (loan, etc).
22+
This example shows how to implement a token minting system where users can mint tokens by proving knowledge of a secret password without revealing it. The system includes protection against replay attacks, ensuring each proof is unique to its generator.
2423

25-
# Use Case Example: proof of secret (resistant to replay attacks)
24+
We will use the following:
25+
- **Circom**: Domain-specific language for defining arithmetic circuits, the foundation of zk-SNARKs.
26+
- **Groth16**: A pairing-based zk-SNARK system that provides the mathematical framework for proof generation and verification.
27+
- **Snarkjs**: JavaScript library for generating and verifying zk-SNARK proofs.
28+
- **Garaga**: Enables efficient elliptic curve operations on Starknet, including Groth16 smart contract verifier generation.
2629

27-
This specific use case is about granting access to tokens after having proven you a know secret without actually revealing it. In this example, any user can mint free tokens if they submit a valid proof unique to them to a specific contract. The proof needs to have been generated by the user submitting it, copy-pasting a proof from another user will not work. (More about it later)
30+
### 1. Circuit Definition
2831

32+
Create a circuit that:
33+
- Takes 3 inputs:
34+
- User address (public)
35+
- Password hash (public)
36+
- Password in plain text (private)
37+
- Computes the hash of the plain text password
38+
- Compares it with the public hash
39+
- Generates a user-specific proof to prevent replay attacks
2940

30-
## Stack used: Circom, Groth16, Snarkjs, Garaga
31-
32-
- **Circom**: A domain-specific language for defining arithmetic circuits, which are the foundation of zk-SNARKs. These circuits describe the computation to be proven in a zk-SNARK.
33-
34-
- **Groth16**: Groth16 is a famous pairing-based zk-SNARK system. In other words, it is a cryptographic protocol, or more precisely a proving scheme for zk-SNARKs. It defines the mathematical framework and the core logic for generating and verifying zk-SNARK proofs. Its principal function is to allow a prover to validate the accuracy of a statement to a verifier, without revealing any additional data. A distinct feature of Groth16 is its succinctness; the proofs generated are concise, occupying minimal storage and transmission space.
35-
36-
- **Snarkjs**: A JavaScript library acting as an implementation layer of proving systems by providing tools and utilities for generating and verifying zk-SNARK proofs. It currently supports 3 proving systems: Groth16, PLONK, and FFLONK. It integrates with the circom compiler used for compiling circom circuits.
37-
38-
- **Garaga**: Garaga enables efficient elliptic curve operations on Starknet. Among them, one that was particularly useful for this use case, was the Groth16 smart contract verifiers generator. This functionality helps in generating verifier contracts allowing on-chain proof verification. Instead of verifying locally using snarkjs, Garaga allows the proof verification directly on-chain by anyone.
39-
40-
## How it works:
41-
42-
In this section, the example workflow is explained. As this repository consists of examples, each command is briefly explained to give a gist of it. If you wish to learn about those, please refer to the documentation of those technologies:
43-
- [Circom](https://docs.circom.io/)
44-
- [Snarkjs](https://github.com/iden3/snarkjs)
45-
- [Garaga](https://garaga.gitbook.io/garaga)
46-
47-
1. Write a circuit using `Circom` that will correspond to the program you are proving. In the circuit, you can set constraints (aka assertions) that the program needs to respect. Otherwise, the proof generation will fail.
48-
49-
- 1.1. Circuit
50-
51-
```circom
41+
```solidity
5242
// [!include ~/listings/advanced-concepts/verify_proofs/src/circuit/circuit.circom]
5343
```
5444

55-
This circuit takes 3 inputs:
56-
- user address (public)
57-
- password hash (public)
58-
- password in plain text (private)
45+
### 2. Circuit Compilation
5946

6047
The circuit computes the hash of the plain text password and compares the result to the publicly known hash of the password. This equality assertion is one of the constraints set by the circuit. The rest of the code is to generate a proof unique to the user to avoid replay attacks (more about it later).
6148

62-
- 1.2. Circuit inputs
63-
64-
```json
65-
// [!include ~/listings/advanced-concepts/verify_proofs/src/circuit/input.json]
66-
```
67-
> In my example, the secret password is 2468. You should input the same user address with which you will submit your proof to the ZkERC20Token to mint free tokens.
68-
69-
2. Compile the circuit (in binary and web assembly formats)
70-
7149
```bash [Terminal]
7250
mkdir target
73-
circom src/circuit/circuit.circom -l node_modules --r1cs --wasm --output target
51+
circom src/circuit/circuit.circom -l node_modules --r1cs --wasm --output target
7452
```
7553

76-
3. Trusted setup -- phase 1 (independent of the circuit)
54+
### 3. Trusted Setup
7755

78-
> The **trusted setup** is a phase in the zk-SNARK protocol where cryptographic parameters, known as a **proving key** and a **verification key**, are generated. These keys are essential for the prover to create proofs and for the verifier to validate them.
56+
The **trusted setup** is a phase in the zk-SNARK protocol where cryptographic parameters, known as a *proving key* and a *verification key*, are generated. These keys are essential for the prover to create proofs and for the verifier to validate them.
7957

80-
- 3.1. Start a new `powers of tau` ceremony
81-
```bash [Terminal]
82-
mkdir target/ptau && cd target/ptau
83-
snarkjs powersoftau new bn128 12 pot12_0000.ptau -v
84-
```
58+
#### Phase 1: "Powers of Tau" Ceremony
8559

86-
- 3.2. Contribute to phase 1 of ceremony
60+
:::info
61+
A trusted setup ceremony is a collaborative process where multiple participants contribute randomness to create the cryptographic parameters for a proof system (the proving and verification keys), with the goal to provide additional security. You can provide additional contributions if you wish to do so.
62+
:::
8763

88-
> A trusted setup ceremony is a collaborative process where multiple participants contribute randomness to create the cryptographic parameters for a zk-SNARK system (the proving and verification keys), with the goal to provide additional security. You can therefore provide additional contributions if you wish to do so.
64+
- Initialize powers of tau ceremony:
8965

9066
```bash [Terminal]
91-
snarkjs powersoftau contribute pot12_0000.ptau pot12.ptau --name="My contribution to part 1" -v -e="some random text for the contribution to part 1"
67+
mkdir target/ptau && cd target/ptau
68+
snarkjs powersoftau new bn128 12 pot12_0000.ptau -v
9269
```
9370

94-
4. Trusted setup -- phase 2 (circuit dependent)
71+
```bash [Terminal]
72+
snarkjs powersoftau contribute pot12_0000.ptau pot12.ptau --name="My contribution to part 1" -v -e="some random text for the contribution to part 1"
73+
```
9574

96-
- 4.1. Finalize ptau file
75+
#### Phase 2: Circuit Dependent
76+
77+
- Finalize ptau file:
9778

9879
```bash [Terminal]
99-
snarkjs powersoftau prepare phase2 pot12.ptau pot12_final.ptau -v
80+
snarkjs powersoftau prepare phase2 pot12.ptau pot12_final.ptau -v
10081
```
10182

102-
- 4.2. Generate a zkey file
83+
- Generate a zkey file:
10384

10485
```bash [Terminal]
105-
cd ..
106-
snarkjs groth16 setup circuit.r1cs ptau/pot12_final.ptau circuit_0000.zkey
86+
cd ..
87+
snarkjs groth16 setup circuit.r1cs ptau/pot12_final.ptau circuit_0000.zkey
10788
```
10889

109-
- 4.3. Contribute to phase 2
90+
- Contribute to Phase 2:
11091

11192
```bash [Terminal]
112-
snarkjs zkey contribute circuit_0000.zkey circuit_0001.zkey --name="My contribution to part 2" -v -e="some random text for the contribution to part 2"
93+
snarkjs zkey contribute circuit_0000.zkey circuit_0001.zkey --name="My contribution to part 2" -v -e="some random text for the contribution to part 2"
11394
```
114-
After 4.3., we have our proving key (`circuit_0001.zkey`) that we will use, along with the compiled circuit and the input to the circuit, to generate proofs.
11595

116-
- 4.4. Export verification key
96+
We now have our proving key (`circuit_0001.zkey{:md}`) that we will use, along with the compiled circuit and the input to the circuit, to generate proofs.
97+
98+
- Export verification key:
11799

118100
```bash [Terminal]
119-
snarkjs zkey export verificationkey circuit_0001.zkey circuit_verification_key.json
101+
snarkjs zkey export verificationkey circuit_0001.zkey circuit_verification_key.json
120102
```
121-
After 4.4., we have our verification key (`circuit_verification_key.json`) that we will use, along with the generated proof and its outputs, to verify proofs.
122103

123-
5. Proof Generation
104+
We have our verification key (`circuit_verification_key.json{:md}`) that we will use, along with the generated proof and its outputs, to verify proofs.
105+
106+
### 4. Proof Generation
124107

125-
- 5.1. Generate witness
108+
#### Generate witness
126109

127110
The **witness** refers to the private input and intermediate values that the prover knows and uses to generate the proof. The intermediate values correspond to the values computed during the circuit execution. These are also part of the witness and are necessary for proving the correctness of the computation. In short, the witness is a complete set of values that satisfies the constraints defined by the zk-SNARK circuit.
128111

129112
```bash [Terminal]
130-
node circuit_js/generate_witness.js circuit_js/circuit.wasm ../src/circuit/input.json witness.wtns
113+
node circuit_js/generate_witness.js circuit_js/circuit.wasm ../src/circuit/input.json witness.wtns
131114
```
132115

133-
- 5.2 Generate proof
116+
#### Generate proof
134117

135118
```bash [Terminal]
136-
snarkjs groth16 prove circuit_0001.zkey witness.wtns proof.json public.json
119+
snarkjs groth16 prove circuit_0001.zkey witness.wtns proof.json public.json
137120
```
138121

139-
> To generate a proof, 3 information are needed:
140-
> - compiled circuit
141-
> - circuit inputs
142-
> - proving key
122+
:::note
123+
To generate a proof, 3 information are needed:
124+
- compiled circuit
125+
- circuit inputs
126+
- proving key
143127

144-
> To verify a proof, 3 information are also needed:
145-
> - proof
146-
> - circuit outputs (obtained when generating proof)
147-
> - verification key
128+
To verify a proof, 3 information are also needed:
129+
- proof
130+
- circuit outputs (obtained when generating proof)
131+
- verification key
132+
:::
148133

149-
150-
- 6. Generate verifier contract
134+
### 5. Generate verifier contract
151135

152136
```bash [Terminal]
153-
garaga gen --system groth16 --vk circuit_verification_key.json
137+
garaga gen --system groth16 --vk circuit_verification_key.json
154138
```
155139

156-
This above command will generate a cairo project with the verifier contract, with the main endpoint `verify_groth16_proof_[curve_name]`.
140+
This above command will generate a cairo project with the verifier contract, with the main endpoint `verify_groth16_proof_[curve_name]{:md}`.
157141

158-
> Garaga also provides some command utilities to deploy it on-chain. Else, you can deploy it like any other contract (using starkli or sncast for example).
142+
:::info
143+
Garaga also provides some command utilities to deploy it on-chain. Else, you can deploy it like any other contract (using starkli or sncast for example).
144+
:::
159145

160146
Here is the generated starknet contract:
161147

162148
```cairo
163149
// [!include ~/listings/advanced-concepts/verify_proofs/src/verifier/groth16_verifier.cairo]
164150
```
165151

166-
7. Generate calldata & call on-chain verifier contract
152+
### 6. Generate calldata & call on-chain verifier contract
167153

168-
This step is useful for generating calldata from the proof & circuit execution outputs, which can then be sent to the verifier contract to verify the proof on-chain. In this example, there is an intermediary contract, ZkERC20Token, which will itself call the verifier contract (more about it below).
154+
This step is useful for generating calldata from the proof & circuit execution outputs, which can then be sent to the verifier contract to verify the proof on-chain. In this example, there is an intermediary contract, `ZkERC20Token`, which will itself call the verifier contract (more about it below).
169155

170156
```bash [Terminal]
171-
garaga calldata --system groth16 --vk circuit_verification_key.json --proof proof.json --public-inputs public.json --format starkli | xargs starkli invoke --account ~/.starkli-wallets/deployer/account.json --keystore ~/.starkli-wallets/deployer/keystore.json --network sepolia --watch 0x00375cf5081763e1f2a7ed5e28d4253c6135243385f432492dda00861ec5e58f mint_with_proof
157+
garaga calldata --system groth16 --vk circuit_verification_key.json --proof proof.json --public-inputs public.json --format starkli | xargs starkli invoke --account ~/.starkli-wallets/deployer/account.json --keystore ~/.starkli-wallets/deployer/keystore.json --network sepolia --watch 0x00375cf5081763e1f2a7ed5e28d4253c6135243385f432492dda00861ec5e58f mint_with_proof
172158
```
173159

174-
> Garaga also provides some command utilities to call the verifier contract directly abstracting the calldata generation part, simplifying the above command.
160+
:::info
161+
Garaga also provides some command utilities to call the verifier contract directly abstracting the calldata generation part, simplifying the above command.
162+
:::
175163

176-
8. ZkERC20Token contract
164+
### 7. `ZkERC20Token` contract
177165

178-
This contract allows anyone to mint free tokens if they know a secret password (2468). You can submit your proof calldata to this contract, which will itself call the generated verifier contract. If the proof verification passes and the proof is indeed unique to you (ie, you generated it yourself), you can receive the free tokens. Otherwise, the endpoint execution will revert. You can mint free tokens only once per user.
166+
This contract allows anyone to mint free tokens if they know a secret password (`2468`). You can submit your proof calldata to this contract, which will itself call the generated verifier contract. If the proof verification passes and the proof is indeed unique to you (ie, you generated it yourself), you can receive the free tokens. Otherwise, the endpoint execution will revert. You can mint free tokens only once per user.
179167

180-
Here is the address of this contract (on Sepolia testnet) : 0x00375cf5081763e1f2a7ed5e28d4253c6135243385f432492dda00861ec5e58f
168+
The final contract allows users to mint tokens by submitting a valid proof of knowledge of the secret password (`2468`). Each user can mint tokens only once.
181169

182-
Here is the code of this ZkERC20Token contract :
170+
Contract Address (Sepolia testnet): `0x00375cf5081763e1f2a7ed5e28d4253c6135243385f432492dda00861ec5e58f{:md}`
183171

184172
```cairo
185173
// [!include ~/listings/advanced-concepts/verify_proofs/src/contract.cairo]
186174
```
187175

176+
:::info
177+
For more detailed information about the technologies used, refer to:
178+
- [Circom Documentation](https://docs.circom.io/)
179+
- [Snarkjs GitHub](https://github.com/iden3/snarkjs)
180+
- [Garaga Documentation](https://garaga.gitbook.io/garaga)
181+
:::
182+

0 commit comments

Comments
 (0)