Week 1 repo: https://github.com/zku-cohort-4/week1
Note
Fork the above repo onto your own Github and run git submodule update --init --recursive
to pull all submodules. Group your coding assignment submission into a single commit. Link the commit to the submission text box. All word answers should go into a single PDF file to be uploaded here.
Part 1 Theoretical background of zk-SNARKs and zk-STARKS
- Explain in 2-4 sentences why SNARK requires a trusted setup while STARK doesn’t.
- Name two more differences between SNARK and STARK proofs.
Circom is perhaps the single most important tool we will be using throughout this course. Let’s get familiar with it!
-
Follow the instructions on Circom 2 Documentation to install circom (2.0.3 or above) and snarkjs@latest on your machine (Windows users are recommended to install via WSL). Read through the rest of the documentation to learn about the syntax of the circom language. You might also find this tutorial and this tutorial useful.
-
Fork the
Week 1
repo and go into the Q2 directory. Install all the node dependencies. In thecontracts/circuits
folder, you will findHelloWorld.circom
. Run the bash scriptscripts/compile-HelloWorld.sh
to compile the circuit. Answer the following questions (word answers should go into the PDF file):-
What does the circuit in
HelloWorld.circom
do? -
Lines 7-12 of
compile-HelloWorld.sh
download a file calledpowersOfTau28_hez_final_10.ptau
for Phase 1 trusted setup. Read more about how this is generated here, here, and here. What is a Powers of Tau ceremony? Explain why this is important in the setup of zk-SNARK applications. -
Line 24 of
compile-HelloWorld.sh
makes a random entropy contribution as a Phase 2 trusted setup. How are Phase 1 and Phase 2 trusted setup ceremonies different from each other?`
-
-
In this question, you will learn about an important restriction on circom circuits:
-
In the empty
scripts/compile-Multiplier3-groth16.sh
, create a script to compilecontracts/circuits/Multiplier3.circom
and create a verifier contract modeling aftercompile-HelloWorld.sh
. -
Try to run
compile-Multiplier3-groth16.sh
. You should encounter anerror[T3001]
with the circuit as is. Explain what the error means and how it arises. -
Modify
Multiplier3.circom
to perform a multiplication of three input signals under the restrictions of circom.
-
-
In the empty
scripts/compile-Multiplier3-plonk.sh
, create a script to compilecircuit/Multiplier3.circom
using PLONK in snarkjs. Add a_plonk
suffix to the build folder and the output contract to distinguish the two sets of output.-
You will encounter an error
zkey file is not groth16
if you just changesnarkjs groth16 setup
tosnarkjs plonk setup
. Resolve this error and answer the following question - How is the process of compiling with PLONK different from compiling with Groth16? -
What are the practical differences between Groth16 and PLONK? Hint: compare and contrast the resulted contracts and running time of unit tests (see Q5 below) from the two protocols.
-
-
So far we have not tested our circuit yet. While you can verify your circuit in the terminal using
snarkjs groth16 fullprove
, you can also do so directly in a Node.js script. We will practice doing so by creating some unit tests to try out our verifier contract(s):-
Running
npx hardhat test
will prompt an errorHH606
. Before we can test our verifier contracts with hardhat, we must modify the solidity version. Inscripts/bump-solidity.js
, we have already written the regular expressions to modifyHelloWorldVerifier.sol
. Add script tobump-solidity.js
to do the same for your new contract forMultiplier3
. -
You can now perform the unit tests for
HelloWorldVerifier
by runningnpm run test
. Add inline comments to explain what each line intest/test.js
is doing. -
In
test/test.js
, add the unit tests forMultiplier3
for both the Groth16 and PLONK versions. Include a screenshot of all the tests (forHelloWorld, Multiplier3 with Groth16
, andMultiplier3 with PLONK
) passing in your PDF file.
-
Though it will be nice if we write entirely innovative circuits for every project we create, we should also utilize existing circuit libraries to help us. In this question, you will be learning about two such libraries that you can import to create more complicated circuits. To start, go into the Q3
directory in Week 1
repo and run npm install
in each project folder to install the dependencies.
-
circomlib is the official library of circuit templates released by iden3, the creator of Circom. One important template included is
comparators.circom
, which implements value comparisons between two numbers. The following questions will cover the use of this template in our own circuits:-
contracts/circuits/LessThan10.circom
implements a circuit that verifies an input is less than 10 using theLessThan
template. Study how the template is used in this circuit. What does the 32 in Line 9 stand for? -
What are the possible outputs for the
LessThan
template and what do they mean respectively? (If you cannot figure this out by reading the code alone, feel free to compile the circuit and test with different input values.) -
Proving a number is within a range without revealing the actual number could be useful in applications like proving our income when applying for a credit card. In
contracts/circuits/RangeProof.circom
, create a template (not circuit, so don’t addcomponent main = ...
) that usesGreaterEqThan
andLessEqThan
to perform a range proof.
-
-
circomlib-matrix is a library covering basic matrix operations, modeled after circomlib, and created by our very own mentor Cathie. Matrix operations can be useful in puzzles (e.g. zkPuzzles, zkGames), image processing (e.g zkPhoto), and machine learning (e.g. zk-mnist, zk-ml). Let’s take a look at matrix operations in action in a Sudoku circuit in the zkPuzzles repo.
-
In
projects/zkPuzzles/circuits
, modify Lines 20-23 ofsudoku.circom
so that it implements the check on the inputs to be between 0 and 9 (inclusive) using yourRangeProof
template from 1.3. -
You can run
npm run test:fullProof
while inside thezkPuzzles
directory to test your modified circuit. You are expected to encounter an error. Record the error, resolve it by modifyingproject/zkPuzzles/scripts/compile-circuits.sh
, and explain why it has occurred and what you did to solve the error. -
Copy your modified
sudoku.circom
intocontracts/circuits/sudokuModified.circom
for submission, so you don’t have to commit the submodule.
-
-
[bonus] Matrix operations could also be used to verify that someone knows a solution to a system of (linear) equations without revealing the solution itself. In
bonus/SystemOfEquations.circom
, implement a general circuit that verifies an inputx
solves the system of equationsAx=b
, whereA
andb
are also signal inputs. Then runnpm run test
to prove that the solution to the following system of equations isx=15, y=17, z=19
.
x + y + z = 51
x + 2y + 3z = 106
2x - y + z = 32
-
[bonus] Apart from the standard
circomlib
library andcircomlib-matrix
library that performs matrix operations, what other libraries do you think could be created to help foster the growth of ZK applications?
Further resources: