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