Skip to main content

Circom Workshop 1

Description​

In this session, we introduce the Circom tool stack and how to write basic circuits.

πŸ”‘ zk-SNARKs allow you to generate a proof that some arithmetic function ff evaluates to an output y given a list of values W=[w1,…,wn]W=[w_1,…,w_n], which is called a witness. A circuit is uniquely defined by a series of arithmetic constraints which ensure that the function f was computed correctly.

zk-SNARK proofs are useful because they allow a verifier to verify that ff was correctly computed without needing to know all of the witness or having to check all the constraints. A valid proof (i.e. one that the verifier accepts) means that the witness has satisfied all of circuit’s constraints. This is why it is important to construct your circuit to exactly reflect function ff.

The property of zero-knowledge follows from the fact that the prover can hide information in the witness from the verifier. The property of succinctness follows from the fact that all the constraints are combined using cryptographic magic such that the verifier only needs to actually check a few constraints.

Pre-Session Reading/Setup​

Take a look at the circom docs: https://docs.circom.io/

https://docs.google.com/presentation/d/1ri-jMmRx1l6-yjYHTVJy6ar3G5zq4k0chnLiOwdol0o/edit?usp=sharing

Check-in Questions​

(1) Constraint Forms: In the Circom circuit’s computation trace, there are input values, intermediate values, and an OUT value. Why do we need to create intermediate values in the computation trace between inputs and OUT?

(2) Circom Syntax: What’s the difference between using β€˜<—’ and β€˜<==’ in circom?

(3) Example Circom Code: What does the following Circom code do?

template Example() {
signal input in[2];
signal output out;

component isz = IsZero(); // checks if an input is 0
in[1] - in[0] ==> isz.in;

isz.out ==> out;
}
Sample Answers

(1) Constraint Forms: SNARK constraints can only take two inputs and are modeled in the equation form β€˜a = b + c’ (addition) or β€˜a = b * c’ (multiplication). Thus, we need intermediate values to store computations starting from the inputs, two variables at a time.

(2) Circom Syntax: β€˜<—’ is used to define a witness value. β€˜<==’ is used to define a witness value and imply an assert statement for the values on the left and right.

(3) Example Circom Code: Checks if two values are equal to one another. Feel free to play around with circuits more using https://zkrepl.dev/!

Learning Group 1 lecture video and slides for reference.