arnaucube
arnaucube/circomPublic Self-hosted repository
circom/README.md
README.mdRaw
  1# circon
  2
  3Circon is a language designed to write aritmetic circuits to be used in zero knowlage proof.
  4
  5Concretly it is designed to work in convination with [zksnarks javascript library](https://github.com/iden3/zksnark)
  6
  7
  8## Usage
  9
 10### First circuit
 11
 12Create a circuit. This is a simple example for a NAND door:
 13
 14```
 15template NAND() {
 16    signal private input a;
 17    signal input b;
 18    signal output out;
 19
 20    out <== 1 - a*b;
 21    a*(a-1) === 0;
 22    b*(b-1) === 0;
 23}
 24
 25component main = NAND();
 26```
 27
 28The language is mainly a javascript/c syntax but with extra 5 operators in order to define the constrains:
 29
 30`<==` , `==>`  This operator is used to connect signals. This operator also implies a constrain.
 31
 32As you can see in the example above, `out` is assigned a value and a constrain is also generated.  The assigned value must be of the form a*b+c where a,b and c are linear convinations of the signals.
 33
 34`<--` , `-->` This operators assign values to a signals but does not generate any constrain. This allow to assign any value to a signal including extrange operations like shifhts, modules, divisiones, etc.  Generally this operator goes together wit a `===` operator in order to force the constrain.
 35
 36`===` This operator defines a constrain. The constrain must be simplificable to the form a*b+c=0 where a,b and c are linear convinations.
 37
 38In the example above, we force the two inputs to be binary by adding the constrain `a*(a-1)===0` and `b*(b-1) === 0`
 39
 40### Compile the circui
 41
 42To compile the circuit, you first install the compiler:
 43
 44```
 45npm install -g circom
 46````
 47
 48Then just run
 49
 50```
 51circom -s mycircuit.circom -o mycircuit.json
 52```
 53
 54The resulting output ( `mycircuit.json` ) can be used with the [zksnarks javascript library](https://github.com/iden3/zksnark)
 55
 56In that library you will be able to do the trusted setup, create the proofs and verify them.
 57
 58### Number to binary
 59
 60In many situations, we have to convert an input to it's binary representation.  We would write a circuit this way:
 61
 62```
 63template Num2Bits(n) {
 64    signal input in;
 65    signal output out[n];
 66    var lc1=0;
 67
 68    for (var i = 0; i<n; i++) {
 69        out[i] <-- (in >> i) & 1;
 70        out[i] * (out[i] -1 ) === 0;
 71        lc1 += out[i] * 2**i;
 72    }
 73
 74    lc1 === in;
 75}
 76
 77component main = Num2Bits(8)
 78```
 79
 80The first thing we observe in this example is that templates can have parameters. This allows to create libraries with templates that generate circuits in a parametric ways. In this case, we are using a circuit with an output of 8 signals, but you can instantiate easily any circuit with any number of outputs.
 81
 82Then we define the inputs and the outputs. We see that we can work with arrays. The program allows multidimension arrays for signals and variables.
 83
 84Then we need to assign the values to the different signals. In this case, we assign the value without the constrain by using the shift and & operators:
 85`out[i] <-- (in >> i) & 1;`
 86
 87But we need to define also the constrains.  In this case there is a big constrain of the form:
 88
 89```
 90in === out[0]*2**0  + out[1]*2**1 + out[2]*2**2  ....
 91```
 92
 93We do this by using a variable `lc1` and adding each signal multiplied by his coefficient.
 94
 95This variable does not hold a value in compilation time, but it holds a linear combination.  and it is used in the last constrain:
 96
 97```
 98lc1 === in;
 99```
100
101Finally we also have to force each output to be binary.
102
103We do this by adding this constrain for each output:
104
105```
106out[i] * (out[i] -1 ) === 0;
107```
108
109### A Binary adder.
110Lets now create a 32bits adder.
111
112The strategy will be to first convert the number to binary, do the addition in the binary space and then finally convert it back to a number.
113
114We could do it directly by adding a simple constrain where out === in1 + in2, but if we do this the operation will not be module 2**32 but `r` where r is the range of the elliptic curve. In the case of regular zkSnarks typically is some prime number close to 2**253
115
116With this example we also demostrate the normal patter of binarize a number, work in binary (reguular electronic circuit), and then convert the result back to a number.
117
118To do this, we will create 3 files named: `bitify.circom` `binsum.circom` and `sum_test.circom`
119
120bitify.circom:
121```
122template Num2Bits(n) {
123    signal input in;
124    signal output out[n];
125    var lc1=0;
126
127    for (var i = 0; i<n; i++) {
128        out[i] <-- (in >> i) & 1;
129        out[i] * (out[i] -1 ) === 0;
130        lc1 += out[i] * 2**i;
131    }
132
133    lc1 === in;
134
135}
136
137template Bits2Num(n) {
138    signal input in[n];
139    signal output out;
140    var lc1=0;
141
142    for (var i = 0; i<n; i++) {
143        lc1 += in[i] * 2**i;
144    }
145
146    lc1 ==> out;
147}
148
149```
150
151binsum.circom
152```
153/*
154
155Binary Sum
156==========
157
158This component creates a binary sum componet of ops operands and n bits each operand.
159
160e is Number of carries: Depends on the number of operands in the input.
161
162Main Constrain:
163   in[0][0]     * 2^0  +  in[0][1]     * 2^1  + ..... + in[0][n-1]    * 2^(n-1)  +
164 + in[1][0]     * 2^0  +  in[1][1]     * 2^1  + ..... + in[1][n-1]    * 2^(n-1)  +
165 + ..
166 + in[ops-1][0] * 2^0  +  in[ops-1][1] * 2^1  + ..... + in[ops-1][n-1] * 2^(n-1)  +
167 ===
168   out[0] * 2^0  + out[1] * 2^1 +   + out[n+e-1] *2(n+e-1)
169
170To waranty binary outputs:
171
172    out[0]     * (out[0] - 1) === 0
173    out[1]     * (out[0] - 1) === 0
174    .
175    .
176    .
177    out[n+e-1] * (out[n+e-1] - 1) == 0
178
179 */
180
181
182/*
183    This function calculates the number of extra bits in the output to do the full sum.
184 */
185
186function nbits(a) {
187    var n = 1;
188    var r = 0;
189    while (n-1<a) {
190        r++;
191        n *= 2;
192    }
193    return r;
194}
195
196
197template BinSum(n, ops) {
198    var nout = nbits((2**n -1)*ops);
199    signal input in[ops][n];
200    signal output out[nout];
201
202    var lin = 0;
203    var lout = 0;
204
205    var k;
206    var j;
207
208    for (k=0; k<n; k++) {
209        for (j=0; j<ops; j++) {
210            lin += in[j][k] * 2**k;
211        }
212    }
213
214    for (k=0; k<nout; k++) {
215        out[k] <-- (lin >> k) & 1;
216
217        // Ensure out is binary
218        out[k] * (out[k] - 1) === 0;
219
220        lout += out[k] * 2**k;
221    }
222
223    // Ensure the sum;
224
225    lin === lout;
226}
227```
228
229sumtest.circom:
230```
231include "bitify.circom"
232include "binsum.circom"
233
234template Adder() {
235    signal private input a;
236    signal input b;
237    signal output out;
238
239    component n2ba = Num2Bits(32);
240    component n2bb = Num2Bits(32);
241    component sum = BinSum(32,2);
242    component b2n = Bits2Num(32);
243
244    n2ba.in <== a;
245    n2bb.in <== b;
246
247    for (var i=0; i<32; i++) {
248        sum.in[0][i] <== n2ba.out[i];
249        sum.in[1][i] <== n2bb.out[i];
250        b2n.in[i] <== sum.out[i];
251    }
252
253    out <== b2n.out;
254}
255
256component main = Adder();
257```
258
259In this example we can see how we can design a top dow circuit with many subcircuits and how we connect them together.
260
261We also see the option to create auxilary functions to do specific computations.
262
263
264## License
265
266circon is part of the iden3 project copyright 2018 0kims association and published with GPL-3 license, please check the COPYING file for more details.
267
268
269