forked from rdi-berkeley/zkp-mooc-lab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcircuit.circom
95 lines (81 loc) · 2.92 KB
/
circuit.circom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
pragma circom 2.0.0;
/*
* Decomposes `in` into `b` bits, given by `bits`.
* Least significant bit in `bits[0]`.
* Enforces that `in` is at most `b` bits long.
*/
template Num2Bits(b) {
signal input in;
signal output bits[b];
// First, compute the bit values
for (var i = 0; i < b; i++) {
// Use `<--` to assign to a signal without constraining it.
// While our constraints can only use multiplication/addition, our
// assignments can use any operation.
bits[i] <-- (in >> i) & 1;
}
// Now, contrain each bit to be 0 or 1.
for (var i = 0; i < b; i++) {
// Use `===` to enforce a rank-1 constraint (R1C) on signals.
bits[i] * (1 - bits[i]) === 0;
// ^--A--^ ^-----B-----^ C
//
// The linear combinations A, B, and C in this R1C.
}
// Now, construct a sum of all the bits.
// Note that var is a linear combination of signals since the `(2 ** i)` terms are constants.
var sum_of_bits = 0;
for (var i = 0; i < b; i++) {
sum_of_bits += (2 ** i) * bits[i];
}
// Constrain that `sum` is equal to the input `in`.
sum_of_bits === in;
}
// Now we look at `SmallOdd`, a circuit which features:
//
// * the use of components, or sub-circuits
// * the `<==` operator, which combines `<--` and `===`.
/*
* Enforces that `in` is an odd number less than 2 ** `b`.
*/
template SmallOdd(b) {
signal input in;
// Declare and intialize a sub-circuit;
component binaryDecomposition = Num2Bits(b);
// Use `<==` to **assign** and **constrain** simultaneously.
binaryDecomposition.in <== in;
// Constrain the least significant bit to be 1.
binaryDecomposition.bits[0] === 1;
}
// Next we look at `SmallOddFactorization`, a circuit which features:
//
// * arrays of components
// * using helper (witness) signals to express multiple multiplications
// * (or any iterator general computation)
/*
* Enforces the factorization of `product` into `n` odd factors that are each
* less than 2 ** `b`.
*/
template SmallOddFactorization(n, b) {
signal input product;
signal input factors[n];
// Constrain each factor to be small and odd.
// We're going to need `n` subcircuits for small-odd-ness.
component smallOdd[n];
for (var i = 0; i < n; i++) {
smallOdd[i] = SmallOdd(b);
smallOdd[i].in <== factors[i];
}
// Now constrain the factors to multiply to the product. Since there are
// many multiplications, we introduce helper signals to split the
// multiplications up into R1Cs.
signal partialProducts[n + 1];
partialProducts[0] <== 1;
for (var i = 0; i < n; i++) {
partialProducts[i + 1] <== partialProducts[i] * factors[i];
}
product === partialProducts[n];
}
// Finally, we set the `main` circuit for this file, which is the circuit that
// `circom` will synthesize.
component main {public [product]} = SmallOddFactorization(3, 8);