arnaucube
arnaucube/circomPublic Self-hosted repository
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
 70to compile the circuit to a file named `circuit.json`
 71
 72
 73## 3. Taking the compiled circuit to *snarkjs*
 74
 75Now that the circuit is compiled, we will continue with `snarkjs`.
 76Please note that you can always access the help of `snarkjs` by typing:
 77
 78```sh
 79snarkjs --help 
 80```
 81
 82### 3.1 View information and stats regarding a circuit
 83
 84To show general statistics of this circuit, you can run:
 85
 86```sh
 87snarkjs info -c circuit.json
 88```
 89
 90You can also print the constraints of the circuit by running:
 91
 92```sh
 93snarkjs printconstraints -c circuit.json
 94```
 95
 96
 97### 3.2 Setting up using *snarkjs*
 98
 99
100Ok, let's run a setup for our circuit:
101
102```sh
103snarkjs setup 
104```
105
106> 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>`
107
108The output of the setup will in the form of 2 files: `proving_key.json` and `verification_key.json`
109
110### 3.3. Calculating a witness
111
112Before creating any proof, we need to calculate all the signals of the circuit that match (all) the constrains of the circuit.
113
114`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*.
115
116The 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.
117
118For 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. 
119
120> Of course you can always use one and the same number as `a` and `b`.  We  will deal with this problem later.
121
122
123So you want to prove that you know 3 and 11.
124
125Let's create a file named `input.json`
126
127```json
128{"a": 3, "b": 11}
129```
130
131And now let's calculate the witness:
132
133```sh
134snarkjs calculatewitness
135```
136
137You may want to take a look at `witness.json` file with all the signals.
138
139### Create the proof
140
141Now that we have the witness generated, we can create the proof.
142
143```sh
144snarkjs proof
145```
146
147This command will use the `prooving_key.json` and the `witness.json` files by default to generate `proof.json` and `public.json`
148
149The `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.
150
151
152### Verifying the proof
153
154To verify the proof run:
155
156```sh
157snarkjs verify
158```
159
160This command will use `verification_key.json`, `proof.json` and `public.json` to verify that is valid.
161
162Here we are veifying that we know a witness that the public inputs and the outputs matches the ones in the `public.json` file.
163
164
165If the proof is ok, you will see an `OK` in the screen or `INVALID` otherwise.
166
167
168### Generate the solidity verifier
169
170```sh
171snarkjs generateverifier
172```
173
174This command will take the `verification_key.json` and generate a solidity code in `verifier.sol` file.
175
176You can take the code in `verifier.sol` and cut and paste in remix.
177
178This code contains two contracts: Pairings and Verifier.  You just need to deploy the `Verifier` contract.
179
180> 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.
181
182
183### Verifying the proof on-chain
184
185The verifier contract deployed in the last step has a `view` function called `verifyProof`.
186
187This function will return true if the proof and the inputs are valid.
188
189To facilitiate the call, you can use snarkjs to generate the parameters of the call by typing:
190
191```sh
192snarkjs generatecall
193```
194
195Just cut and paste the output to the parameters field of the `verifyProof` method in Remix.
196
197If every thing works ok, this method should return true.
198
199If you just change any bit in the parameters, you can check that the result will be false.
200
201
202## Bonus track
203
204We can fix the circuit to not accept one as any of the values by adding some extra constraints.
205
206Here the trick is that we use the property that 0 has no inverse.  so `(a-1)` should not have an inverse.
207
208that means that `(a-1)*inv = 1` will be inpossible to match if `a` is one.
209
210We just calculate inv by `1/(a-1)`
211
212So let's modify the circuit:
213
214```
215template Multiplier() {
216    signal private input a;
217    signal private input b;
218    signal output c;
219    signal inva;
220    signal invb;
221    
222    inva <-- 1/(a-1);
223    (a-1)*inva === 1;
224    
225    invb <-- 1/(b-1);
226    (b-1)*invb === 1;    
227    
228    c <== a*b;
229}
230
231component main = Multiplier();
232```
233
234A nice thing of circom language is that you can split a <== into two independent acions: <-- and === 
235
236The <-- and --> operators Just assign a value to a signal without creating any constraints.
237
238The === operator just adds a constraint without assigning any value to any signal.
239
240The 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.
241
242
243## Where to go from here.
244
245You may want to read the [README](https://github.com/iden3/circom)  to learn more features about circom.
246
247You 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).
248
249
250Or a exponentiation in the Baby Jub curve [here](https://github.com/iden3/circomlib) (Work in progress).
251
252
253# Final note
254
255There 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.
256
257And 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!.
258
259Enjoy zero knowledge proving!
260
261
262
263
264
265