circom/TUTORIAL.md
TUTORIAL.mdRaw
1# circom and snarkjs tutorial
2
3This tutorial will guide you in creating your first Zero Knowledge zkSnark circuit. It will navegate across the various techniques to write circuits and it will show you how to create proofs and verify them off-chain and on-chain on Ethereum.
4
5## 1. Installing the tools
6
7
8### 1.1 Pre-requisites
9
10If you don't have it installed yet, you need to install `Node.js` in your laptop.
11
12Last stable version of `Node.js` (Or 8.12.0) works just fine. But if you install the latest current version `Node.js` (10.12.0) you will see significant performance increase. This is because last versions of node includes Big Integer Libraries nativelly. The `snarkjs` library makes use of this feature if available, and this improves the performance x10 (!).
13
14
15### 1.2 Install **circom** and **snarkjs**
16
17Just run:
18
19```sh
20npm install -g circom
21npm install -g snarkjs
22```
23
24
25## 2. Working with a circuit
26
27Let's create a circuit that tries to prove that you are able to factor a number!
28
29### 2.1 Create a circuit in a new directory
30
311. Create an empty directory called `factor` where you will put all the files that you will use in this tutorial.
32```
33mkdir factor
34cd factor
35```
36
37
38> In a real circuit, you will probably want to create a `git` repository with a `circuits` directory and a `test` directory with all your tests, and the needed scripts to build all the circuits.
39
402. Create a new file named `circuit.circom` with the following content:
41
42```
43template Multiplier() {
44 signal private input a;
45 signal private input b;
46 signal output c;
47
48 c <== a*b;
49}
50
51component main = Multiplier();
52```
53
54This circuit has 2 private input signals named `a` and `b` and one output named `c`.
55
56The only thing that the circuit does is forcing the signal `c` to be the value of `a*b`
57
58After declaring the `Multiplier` template, we instantiate it with a component named`main`.
59
60Note: When compiling a circuit a component named `main` must always exist.
61
62### 2.2 Compile the circuit
63
64We are now ready to compile the circuit. Run the following command:
65
66```sh
67circom circuit.circom -o circuit.json
68
69// Which is equivalent to "circom circuit.circom -o circuit.json"
70```
71
72to compile the circuit to a file named `circuit.json`
73
74
75## 3. Taking the compiled circuit to *snarkjs*
76
77Now that the circuit is compiled, we will continue with `snarkjs`.
78Please note that you can always access the help of `snarkjs` by typing:
79
80```sh
81snarkjs --help
82```
83
84### 3.1 View information and stats regarding a circuit
85
86To show general statistics of this circuit, you can run:
87
88```sh
89snarkjs info -c circuit.json
90```
91
92You can also print the constraints of the circuit by running:
93
94```sh
95snarkjs printconstraints -c circuit.json
96```
97
98
99### 3.2 Setting up using *snarkjs*
100
101
102Ok, let's run a setup for our circuit:
103
104```sh
105snarkjs setup
106```
107
108> By default `snarkjs` will look for and use `circuit.json`. You can always specify a different circuit file by adding `-c <circuit JSON file name>`
109
110The output of the setup will in the form of 2 files: `proving_key.json` and `verification_key.json`
111
112### 3.3. Calculating a witness
113
114Before creating any proof, we need to calculate all the signals of the circuit that match (all) the constrains of the circuit.
115
116`snarkjs` calculates these for you. You need to provide a file with the inputs and it will execute the circuit and calculate all the intermediate signals and the output. This set of signals is the *witness*.
117
118The zero knowledge proofs prove that you know a set of signals (witness) that match all the constraints but without revealing any of the signals except the public inputs plus the outputs.
119
120For example, Imagine that you want to prove that you are able to factor 33 that means that you know two numbers `a` and `b` that when you multiply them, it results in 33.
121
122> Of course you can always use one and the same number as `a` and `b`. We will deal with this problem later.
123
124
125So you want to prove that you know 3 and 11.
126
127Let's create a file named `input.json`
128
129```json
130{"a": 3, "b": 11}
131```
132
133And now let's calculate the witness:
134
135```sh
136snarkjs calculatewitness
137```
138
139You may want to take a look at `witness.json` file with all the signals.
140
141### Create the proof
142
143Now that we have the witness generated, we can create the proof.
144
145```sh
146snarkjs proof
147```
148
149This command will use the `prooving_key.json` and the `witness.json` files by default to generate `proof.json` and `public.json`
150
151The `proof.json` file will contain the actual proof. And the `public.json` file will contain just the values of the public inputs and the outputs.
152
153
154### Verifying the proof
155
156To verify the proof run:
157
158```sh
159snarkjs verify
160```
161
162This command will use `verification_key.json`, `proof.json` and `public.json` to verify that is valid.
163
164Here we are veifying that we know a witness that the public inputs and the outputs matches the ones in the `public.json` file.
165
166
167If the proof is ok, you will see an `OK` in the screen or `INVALID` otherwise.
168
169
170### Generate the solidity verifier
171
172```sh
173snarkjs generateverifier
174```
175
176This command will take the `verification_key.json` and generate a solidity code in `verifier.sol` file.
177
178You can take the code in `verifier.sol` and cut and paste in remix.
179
180This code contains two contracts: Pairings and Verifier. You just need to deploy the `Verifier` contract.
181
182> You may want to use a test net like Rinkeby, Kovan or Ropsten. You can also use the Javascript VM, but in some browsers, the verification takes long and it may hang the page.
183
184
185### Verifying the proof on-chain
186
187The verifier contract deployed in the last step has a `view` function called `verifyProof`.
188
189This function will return true if the proof and the inputs are valid.
190
191To facilitiate the call, you can use snarkjs to generate the parameters of the call by typing:
192
193```sh
194snarkjs generatecall
195```
196
197Just cut and paste the output to the parameters field of the `verifyProof` method in Remix.
198
199If every thing works ok, this method should return true.
200
201If you just change any bit in the parameters, you can check that the result will be false.
202
203
204## Bonus track
205
206We can fix the circuit to not accept one as any of the values by adding some extra constraints.
207
208Here the trick is that we use the property that 0 has no inverse. so `(a-1)` should not have an inverse.
209
210that means that `(a-1)*inv = 1` will be inpossible to match if `a` is one.
211
212We just calculate inv by `1/(a-1)`
213
214So let's modify the circuit:
215
216```
217template Multiplier() {
218 signal private input a;
219 signal private input b;
220 signal output c;
221 signal inva;
222 signal invb;
223
224 inva <-- 1/(a-1);
225 (a-1)*inva === 1;
226
227 invb <-- 1/(b-1);
228 (b-1)*invb === 1;
229
230 c <== a*b;
231}
232
233component main = Multiplier();
234```
235
236A nice thing of circom language is that you can split a <== into two independent acions: <-- and ===
237
238The <-- and --> operators Just assign a value to a signal without creating any constraints.
239
240The === operator just adds a constraint without assigning any value to any signal.
241
242The circuit has also another problem and it's that the operation works in Zr, so we need to guarantee too that the multiplication does not overflow. This can be done by binarizing the inputs and checking the ranges, but we will reserve it for future tutorials.
243
244
245## Where to go from here.
246
247You may want to read the [README](https://github.com/iden3/circom) to learn more features about circom.
248
249You can also check a a library with many basic circuits lib binaritzations, comparators, eddsa, hashes, merkle trees etc [here](https://github.com/iden3/circomlib) (Work in progress).
250
251
252Or a exponentiation in the Baby Jub curve [here](https://github.com/iden3/circomlib) (Work in progress).
253
254
255# Final note
256
257There is nothing worst for a dev than working with a buggy compiler. This is a very early stage of the compiler, so there are many bugs and lots of works needs to be done. Please have it present if you are doing anything serious with it.
258
259And please contact us for any isue you have. In general, a github issue with a small piece of code with the bug is very worthy!.
260
261Enjoy zero knowledge proving!
262
263
264
265
266
267