owned this note
owned this note
Published
Linked with GitHub
---
marp: true
title: "Taipei ZK Workshop: Programming ZKPs: From Zero to Hero"
paginate: true
_paginate: false
---
## Taipei ZK Workshop
- Second session: Intro to programming (11-13)
- Stop for exercises twice
- Short break in middle
Note:
---
## Programming ZKPs: From Zero to Hero

Based on [Programming ZKPs: From Zero to Hero](https://zkintro.com/articles/programming-zkps-from-zero-to-hero)
---
## Programming ZKPs: From Zero to Hero
- Zebras: stripes for camouflage in a herd
- Humans: group pseudonyms (Publius, Bourbaki)
- Digital: prove membership without revealing which member
Note:
- Motivates group signatures.
---
## Programming ZKPs: From Zero to Hero
- Circom + Groth16 focus
- Goal: hands-on coding & proof generation
- Edit-Build-Run cycle; work iteratively
Note:
- Emphasize iterative flow: build → prove → verify.
- Setup env etc, then improve
---
## Proving you sent a message

Note:
- Signature scheme, proving msg
- Grok code and why, able to support group sigs
---
## Pre-requisites (1.1)
- Software engineer; OK with command line
- Familiarity with digital signatures, public-key cryptography, hash functions
- Previous session intro to ZK
---
## Recap of ZKPs (1.2)
- Zero Knowledge: prove correctness, hide data
- Succinctness: small proofs, no matter complexity
- Circom: a DSL for constraints
- Groth16: proving system needing a trusted setup
Note:
- If needed, see “A Friendly Intro to Zero Knowledge.”
- Assume everyone in previous session
- Blockchain state transition, digital id, sudoku...
---
## Overview (2)
1. Write circuit (`.circom`)
2. Build → `.r1cs` + `.wasm`
3. Trusted setup → proving & verification keys
4. Generate proof (private inputs + proving key)
5. Verify proof (verification key + public data)
Note:
- We’ll do simple examples first, then build up.
---
## Preparation (2.1)
- See https://github.com/oskarth/zkintro-tutorial
- Pre-reqs: rust, just, npm
- ZKP tools: circom, snarkjs, just tasks
- Alternative: https://zkrepl.dev
Note:
See README, recommend installing but not comf zkrepl
Better mental model; also see book
Feel free to do now or wait for break
---
## First iteration (3)
- Equivalent of "Hello World"
- Program to prove knowledge of two secret numbers
- without revealing secret numbers
- E.g. $3 \cdot 11 = 33$
Note:
- Stepping stone towards digital signatures
- Think of secret numbers as private keys, product public
- Diff way of thinking
---
## Write a special program (3.1)
(example1)
```
pragma circom 2.0.0;
template Multiplier2 () {
signal input a;
signal input b;
signal output c;
c <== a * b;
}
component main = Multiplier2();
```
- `a`, `b`: private; `c`: public
Note:
- “Hello World” of Circom; line by line
- Minimal circuit; set of constraints
---
## Constraints (3.2)
- How do constraints work?
- In Sudoku: number between 1..9, not a single constraint
- Circom: Express using equality `===` constraints, e.g. `a * b === c`
- Under hood: polynomials
Note:
- More to be aware of, more fundamental operations
- (constants/add/mul, check equality)
---
## Constraints (3.2)

Note:
- Illustrated here
- Under hood, polynomials, fundamental operations
---
## Building our circuit (3.3)
- `just build example1` → produces `.r1cs` + `.wasm`
- thin wrapper around `circom`
Note:
- Solution; also Circom docs
- `.r1cs` describes constraints; `.wasm` used for the witness generation (WebAssembly)
- New way of doing things
---
## Building our circuit (3.3)
Output:
```shell
template instances: 1
non-linear constraints: 1
linear constraints: 0
public inputs: 0
private inputs: 2
public outputs: 1
wires: 4
labels: 4
Written successfully: example/target/example1.r1cs
Written successfully: example/target/example1_js/example1.wasm
```
Note:
- 2 priv 1 pub 1 non-linear
---
## Building our circuit (3.3)

---
## Trusted setup (3.4)
- `just trusted_setup example1` → single-participant ceremony
- Generates Common Reference String (CRS)
- Consists of proving & verification keys
- Needed for proving and verifying; not a "private key"
Note:
- Preprocessing; create cryptographic secret
---
## Trusted setup (3.4)


---
## Trusted setup (3.4)
- In production: N participants, trust $\frac{1}{n}$
- Different ZKP systems different properties
- Groth16 two phases: phase1 and phase2 (circuit specific)
Note:
- Groth16 small proofs so two trusted setups
- Most modern universal or single trusted setup
---
## Generate proof (Example 1) (3.5)
- `input.json`: `{"a":"3","b":"11"}`
- `just generate_proof example1` → outputs proof + public `["33"]`
Note:
- Demonstrates privacy (hiding `a`,`b`) + succinctness (small proof).
---
## Proof output (3.5)
```json
{
"pi_a": ["15932[...]3948", "66284[...]7222", "1"],
"pi_b": [
["17667[...]0525", "13094[...]1600"],
["12020[...]5738", "10182[...]7650"],
["1", "0"]
],
"pi_c": ["18501[...]3969", "13175[...]3552", "1"],
"protocol": "groth16",
"curve": "bn128"
}
```
Note:
- Details not important, these are EC elemn
- Short concise proof regardless; succinctness
---
## Visualization (3.5)

Note:
- Summarizes the pipeline in one diagram.
---
## Verify proof (3.6)
- `just verify_proof example1` → checks correctness
- If we tamper the output to `34`, verification fails
---
## Visualization (3.7)

---
## Exercises (Example 1) (3.7)
- What are two key properties of ZKPs and what mean?
- Role of prover and what input needed? Verifier?
- What does `c <== a * b;` do?
- Why a trusted setup? How use artifacts?
- (Coding) Generate & verify a proof in `example1`.
Note:
- Group discussion after we cover all examples.
---
## Code & Break
- Break up into smaller groups
- Run setup and solve exercises above (15-20m)
- Then take brief break (10-15m)
---
(Break)
---
## Second iteration (4)
- Integer factorization
- Prime factorization: hard (multiplication: easy)
- Big problem with current approach right now, what is it?
Note:
Just integer factorization but related
---
## Second iteration (4)
- Change input to be "1" and "33"
- Want constraint neither `a=1` or `b=1`
- How to add this? Can't just write `!=`
- How to express "something is not?"
Note:
- Different paradigm, not intuitive
---
## Updating our circuit (4.1)
- Idea: Use `IsZero()` template (in stdlib)
- Truth table:
```
| in | out |
| --- | --- |
| 0 | 1 |
| n | 0 |
```
---
## Updating our circuit (4.1)
```
include "circomlib/circuits/comparators.circom";
...
component isZeroCheck = IsZero();
isZeroCheck.in <== (a - 1) * (b - 1);
isZeroCheck.out === 0;
```
- Forces `a,b ≠ 1`
Note:
- Classic Circom trick to encode “≠ 1.”
- See example2; npm project around
---
## Build & Setup (Example 2) (4.1-4.2)
- Update circuit, then:
- `just build example2`
- `just trusted_setup_phase2 example2` (reuse .ptau)
- `just generate_proof example2` / `just verify_proof example2`
- `1 * 33` fails → better constraints
Note:
- Re-running phase2 each time we alter circuit.
---
## Re-running our trusted setup (4.2)


Note:
- First generic; shared with some capacity for constraints
- Groth16 need circuit-specific, annoying; modern ZKPs don't have this
---
## Testing our changes (4.3)
- `just generate_proof example2`
- `just verify_proof example2`
- Changing `input.json` to be `1 * 33` fails
Note:
---
## Complete flow diagram (4.4)

Note:
- Gone through twice, hopefully starting to make sense
- Let's make our circuit more useful
---
## Third iteration (5)
- Proven know product of two secret values
- not very useful
- Useful: digitial signature scheme
- prove you wrote a specific message
- Usually implememented with public-key crypto
---
## Digital signatures (5.1)
- Key generation
- Signing
- Signature verification
---
## Trapdoor function (5.1)

---
## Digital signatures (5.1)
- Public key crypto (implemented with ECC)
- We don't want:

- Want to write program, generate and verify proof
Note:
- Not clever math
---
## Hash functions and commitments (5.2)
- Hash functions: e.g. SHA256
- Commitments:
- Commit and reveal
- Two properties: hiding and binding
Note:
- Use these simpler tools; common primitive
- Meatgrinder; not a trapdoor
---
## Lockbox (5.1)

Note:
Can't change after fact, give key to friend
---
## Digital signature scheme (5.1)
- Key generation: hash(secret) to create commitment
- Signing: Hash secret with message
- Verification: Verify proof using commitment, message, signature (public output)
---
## Pseudocode (5.1)
```python
identity_secret # private
identity_commitment = hash(secret)
signature = hash(secret, message)
```
Note:
- Qs: Why ZKP? why not public key crypto?
- Programmable; easier to extend logic here
- Mimics public-key logic but purely via ZK constraints
---
## Back to the code (5.3)
`just generate_identity`
```shell
identity_secret: 43047[...]2270
identity_commitment: 21618[...]0684
```
Note:
- Big random number
- What hash function? using Poseidon
---
## Poseidon: ZK-Friendly Hash (5.3)
- SHA-256 is large in constraints
- Poseidon = fewer multiplications, faster to prove
- Example:
```
component hasher = Poseidon(2);
hasher.inputs[0] <== identity_secret
hasher.inputs[1] <== message;
signature <== hasher.out;
```
Note:
- Big difference in performance vs. standard crypto hashes.
- Has to do with operating on binary diff arch
---
## Back to the code (5.3)
- New syntax:
```
component main {public [identity_commitment, message]}
= SignMessage();
```
- Input private by default, this makes it part of public output
Note:
- Input private default, now public output
---
## Signature Circuit (5.3)

Note:
- Another diagram: how signals flow in the circuit.
---
## Build & Setup (Example 3) (5.3)
- `just build example3`
- `just trusted_setup_phase2 example3`
Note:
- Public output: `[signature, identity_commitment, message]`.
---
## Testing our circuit (5.4)
- Example input:
```
{"identity_secret":"...",
"identity_commitment":"...",
"message":"42"}
```
- Then generate & verify proof as before
- Public output:
```json
["48968[...]5499", "48269[...]7915", "42"]
```
Note:
- Public output: `[signature, identity_commitment, message
- Have to quote message, numbers
- Output: sig, commitment, message
---
## Next steps (6)
- We have all tools for group signatures
- See example4, 5-10 lines of code
- Group sig: sign message, prove 1/3 people, not reveal which one
- Extensions: `n` participants, `reveal`, `deny`
- Use cases: Anonymous voting, Private membership, Sybil-resistance
Note:
- Doing this with code, not just math special case
- Not specialized cryptography, few hours
Note:
- A bit tricky, but there's one big aha moment, one line
- For loops
---
## Exercises (4.5)
6. Why do we have to run phase 2 but not phase 1 of our trusted setup for `example2`?
7. What was the main problem with the previous example and how did we fix it?
8. Code: Finish `example2` until you failed to generate a proof.
---
### Exercises (5.5)
9. Three parts of a digital signature scheme?
10. Purpose of using a "ZK-Friendly hash function" like Poseidon?
11. What are commitments? How can we use them for a digital signature scheme?
12. Why do we mark the identity commitment and message as public?
13. Why do we need the identity commitment and signature constraints?
14. Code: Finish `example3`, generate/verify proof.
---
## Exercises (6.1)
15. What do group signatures do over normal signatures? How can they be used?
---
## Problems (7)
- See booklet
- IsZero, group signatures, ZK Identity, Layer 2s
---
## Code & Break
- Break up into smaller groups
- Solve exercises above (20-30m)
---
(Coding)
---
## Conclusion (8)
- Write and modify ZKPs from scratch
- Programming environment, setup, generate and verify proofs
- Multiplier circuit, improvements -> signature scheme -> group signatures
- Mental model for ZKP dev and edit-run-debug cycle
- Easy to extend, move to different toolstack, etc
Note:
- We turned custom crypto logic into straightforward code.
---
## Conclusion (8)
- ZKPs allow for “programmable cryptography”
- No specialized math for every new use case
- Different programmming paradigm, new skill (constraints, commitments, ZK-friendly hashes)
Note:
- Encourages creative new solutions; see stdlib etc
---
## References
- **Programming ZKPs: From Zero to Hero**
<https://zkintro.com/articles/programming-zkps-from-zero-to-hero>
- Circom Docs
<https://docs.circom.io>
Note:
---
## Thank you
- Questions
- Lunch break
Note:
- Wrap-up & Q&A