mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 11:16:42 +01:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45c9735a18 | ||
|
|
81da4747da | ||
|
|
394ce29fb2 | ||
|
|
47be0369e1 | ||
|
|
1965dd7f78 | ||
|
|
145a3eefeb | ||
|
|
38fa024745 | ||
|
|
5020d3f4ee | ||
|
|
ed63f08aeb | ||
|
|
c2a54e9187 | ||
|
|
d35d438107 | ||
|
|
5b45bafaac | ||
|
|
3f99f4eb53 | ||
|
|
dcfb9ab8b4 | ||
|
|
bfdf17fd89 | ||
|
|
9d0b27a7e8 | ||
|
|
4d79038fd8 | ||
|
|
95755c4afe | ||
|
|
afc60ec033 | ||
|
|
77393e2d0c | ||
|
|
2db08a0a34 | ||
|
|
23255de508 | ||
|
|
7c03ae4033 | ||
|
|
5e58584a01 | ||
|
|
cb9a5b536e | ||
|
|
70c88be334 | ||
|
|
25759e53cd | ||
|
|
4fa0c79e26 | ||
|
|
e685392523 |
23
README.md
23
README.md
@@ -1,12 +1,16 @@
|
|||||||
# Circon
|
# Circom
|
||||||
|
|
||||||
Circon is a language designed to write arithmetic circuits that can be used in zero knowledge proofs.
|
Circom is a language designed to write arithmetic circuits that can be used in zero knowledge proofs.
|
||||||
|
|
||||||
In particular, it is designed to work in [zksnarks JavaScript library](https://github.com/iden3/zksnark).
|
In particular, it is designed to work in [zksnarks JavaScript library](https://github.com/iden3/zksnark).
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Tutorial
|
||||||
|
|
||||||
|
A good starting point [is this tutorial](https://iden3.io/blog/circom-and-snarkjs-tutorial2.html)
|
||||||
|
|
||||||
### First circuit
|
### First circuit
|
||||||
|
|
||||||
Creation of a circuit. This is an example of a NAND door:
|
Creation of a circuit. This is an example of a NAND door:
|
||||||
@@ -25,7 +29,7 @@ template NAND() {
|
|||||||
component main = NAND();
|
component main = NAND();
|
||||||
```
|
```
|
||||||
|
|
||||||
The language uses mainly JavaScript/C syntax together with 5 extra operators to define the constraints:
|
The language uses mainly JavaScript/C syntax together with 5 extra operators to define the following constraints:
|
||||||
|
|
||||||
`<==` , `==>` : These two operators are used to connect signals and at the same time imply a constraint.
|
`<==` , `==>` : These two operators are used to connect signals and at the same time imply a constraint.
|
||||||
|
|
||||||
@@ -39,7 +43,7 @@ In the above example, both inputs are forced to be binary by adding the constrai
|
|||||||
|
|
||||||
### Compilation the circuit
|
### Compilation the circuit
|
||||||
|
|
||||||
First of all, the compiler must be installed typing:
|
First of all, the compiler must be installed by typing:
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install -g circom
|
npm install -g circom
|
||||||
@@ -48,7 +52,7 @@ npm install -g circom
|
|||||||
The circuit is compiled with the following command:
|
The circuit is compiled with the following command:
|
||||||
|
|
||||||
```
|
```
|
||||||
circom -s mycircuit.circom -o mycircuit.json
|
circom mycircuit.circom -o mycircuit.json
|
||||||
```
|
```
|
||||||
|
|
||||||
The resulting output ( `mycircuit.json` ) can be used in the [zksnarks JavaScript library](https://github.com/iden3/zksnark).
|
The resulting output ( `mycircuit.json` ) can be used in the [zksnarks JavaScript library](https://github.com/iden3/zksnark).
|
||||||
@@ -91,7 +95,7 @@ in === out[0]*2**0 + out[1]*2**1 + out[2]*2**2 + ... + out[n-1]*2**(n-1)
|
|||||||
```
|
```
|
||||||
|
|
||||||
We do this by using a variable `lc1` and adding each signal multiplied by its coefficient.
|
We do this by using a variable `lc1` and adding each signal multiplied by its coefficient.
|
||||||
This variable does not hold a value in compilation time, but it holds a linear combination and it is used in the last constraint:
|
This variable does not hold a value at compilation time, but it holds a linear combination and it is used in the last constraint:
|
||||||
|
|
||||||
```
|
```
|
||||||
lc1 === in;
|
lc1 === in;
|
||||||
@@ -254,9 +258,14 @@ component main = Adder();
|
|||||||
In this example we have shown how to design a top-down circuit with many subcircuits and how to connect them together. One can also see that auxiliary functions to do specific computations can be created.
|
In this example we have shown how to design a top-down circuit with many subcircuits and how to connect them together. One can also see that auxiliary functions to do specific computations can be created.
|
||||||
|
|
||||||
|
|
||||||
|
### More examples.
|
||||||
|
|
||||||
|
You can find more examples in this library of basic circits [circomlib](https://github.com/iden3/circomlib)
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Circon is part of the iden3 project copyright 2018 0KIMS association and published with GPL-3 license. Please check the COPYING file for more details.
|
Circom is part of the iden3 project copyright 2018 0KIMS association and published with GPL-3 license. Please check the COPYING file for more details.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
44
circuit.json
Normal file
44
circuit.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"mainCode": "{\n}\n",
|
||||||
|
"signalName2Idx": {
|
||||||
|
"one": 0,
|
||||||
|
"main.out": 1
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "main",
|
||||||
|
"params": {},
|
||||||
|
"template": "A",
|
||||||
|
"inputSignals": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"componentName2Idx": {
|
||||||
|
"main": 0
|
||||||
|
},
|
||||||
|
"signals": [
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"one"
|
||||||
|
],
|
||||||
|
"triggerComponents": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"main.out"
|
||||||
|
],
|
||||||
|
"triggerComponents": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"constraints": [],
|
||||||
|
"templates": {
|
||||||
|
"A": "function(ctx) {\n ctx.setSignal(\"out\", [], \"3\");\n ctx.assert(ctx.getSignal(\"out\", []), \"3\");\n}\n"
|
||||||
|
},
|
||||||
|
"functions": {},
|
||||||
|
"nPrvInputs": 0,
|
||||||
|
"nPubInputs": 0,
|
||||||
|
"nInputs": 0,
|
||||||
|
"nOutputs": 0,
|
||||||
|
"nVars": 1,
|
||||||
|
"nConstants": 1,
|
||||||
|
"nSignals": 2
|
||||||
|
}
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template XOR() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== a + b - 2*a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template AND() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template OR() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== a + b - a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template NOT() {
|
|
||||||
signal input in;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== 1 + in - 2*in;
|
|
||||||
}
|
|
||||||
|
|
||||||
template NAND() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== 1 - a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template NOR() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== a*b + 1 - a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// --> Assignation without constraint
|
|
||||||
// <-- Assignation without constraint
|
|
||||||
// === Constraint
|
|
||||||
// <== Assignation with constraint
|
|
||||||
// ==> Assignation with constraint
|
|
||||||
// All variables are members of the field F[p]
|
|
||||||
// https://github.com/zcash-hackworks/sapling-crypto
|
|
||||||
// https://github.com/ebfull/bellman
|
|
||||||
|
|
||||||
/*
|
|
||||||
function log2(a) {
|
|
||||||
if (a==0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let n = 1;
|
|
||||||
let r = 1;
|
|
||||||
while (n<a) {
|
|
||||||
r++;
|
|
||||||
n *= 2;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
template EscalarProduct(w) {
|
|
||||||
signal input in1[w];
|
|
||||||
signal input in2[w];
|
|
||||||
signal output out;
|
|
||||||
signal aux[w];
|
|
||||||
var lc = 0;
|
|
||||||
for (var i=0; i<w; i++) {
|
|
||||||
aux[i] <== in1[i]*in2[i];
|
|
||||||
lc = lc + aux[i];
|
|
||||||
}
|
|
||||||
out <== lc;
|
|
||||||
}
|
|
||||||
|
|
||||||
template Decoder(w) {
|
|
||||||
signal input inp;
|
|
||||||
signal output out[w];
|
|
||||||
signal output success;
|
|
||||||
var lc=0;
|
|
||||||
|
|
||||||
for (var i=0; i<w; i++) {
|
|
||||||
out[i] <-- (inp == i) ? 1 : 0;
|
|
||||||
out[i] * (inp-i) === 0;
|
|
||||||
lc = lc + out[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
lc ==> success;
|
|
||||||
success * (success -1) === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template Multiplexor(wIn, nIn) {
|
|
||||||
signal input inp[nIn][wIn];
|
|
||||||
signal input sel;
|
|
||||||
signal output out[wIn];
|
|
||||||
component Decoder(nIn) dec;
|
|
||||||
component EscalarProduct(nIn) ep[wIn];
|
|
||||||
sel ==> dec.inp;
|
|
||||||
for (var j=0; j<wIn; j++) {
|
|
||||||
for (var k=0; k<nIn; k++) {
|
|
||||||
inp[k][j] ==> ep[j].in1[k];
|
|
||||||
dec.out[k] ==> ep[j].in2[k];
|
|
||||||
}
|
|
||||||
ep[j].out ==> out[j];
|
|
||||||
}
|
|
||||||
dec.success === 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
component Multiplexor(8,3) main;
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Binary Sum
|
|
||||||
==========
|
|
||||||
|
|
||||||
This component creates a binary sum componet of ops operands and n bits each operand.
|
|
||||||
|
|
||||||
e is Number of carries: Depends on the number of operands in the input.
|
|
||||||
|
|
||||||
Main Constraint:
|
|
||||||
in[0][0] * 2^0 + in[0][1] * 2^1 + ..... + in[0][n-1] * 2^(n-1) +
|
|
||||||
+ in[1][0] * 2^0 + in[1][1] * 2^1 + ..... + in[1][n-1] * 2^(n-1) +
|
|
||||||
+ ..
|
|
||||||
+ in[ops-1][0] * 2^0 + in[ops-1][1] * 2^1 + ..... + in[ops-1][n-1] * 2^(n-1) +
|
|
||||||
===
|
|
||||||
out[0] * 2^0 + out[1] * 2^1 + + out[n+e-1] *2(n+e-1)
|
|
||||||
|
|
||||||
To waranty binary outputs:
|
|
||||||
|
|
||||||
out[0] * (out[0] - 1) === 0
|
|
||||||
out[1] * (out[0] - 1) === 0
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.
|
|
||||||
out[n+e-1] * (out[n+e-1] - 1) == 0
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
This function calculates the number of extra bits in the output to do the full sum.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function nbits(a) {
|
|
||||||
var n = 1;
|
|
||||||
var r = 0;
|
|
||||||
while (n-1<a) {
|
|
||||||
r++;
|
|
||||||
n *= 2;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template BinSum(n, ops) {
|
|
||||||
var nout = nbits((2**n -1)*ops);
|
|
||||||
signal input in[ops][n];
|
|
||||||
signal output out[nout];
|
|
||||||
|
|
||||||
var lin = 0;
|
|
||||||
var lout = 0;
|
|
||||||
|
|
||||||
var k;
|
|
||||||
var j;
|
|
||||||
|
|
||||||
for (k=0; k<n; k++) {
|
|
||||||
for (j=0; j<ops; j++) {
|
|
||||||
lin += in[j][k] * 2**k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k=0; k<nout; k++) {
|
|
||||||
out[k] <-- (lin >> k) & 1;
|
|
||||||
|
|
||||||
// Ensure out is binary
|
|
||||||
out[k] * (out[k] - 1) === 0;
|
|
||||||
|
|
||||||
lout += out[k] * 2**k;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the sum;
|
|
||||||
|
|
||||||
lin === lout;
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template Num2Bits(n) {
|
|
||||||
signal input in;
|
|
||||||
signal output out[n];
|
|
||||||
var lc1=0;
|
|
||||||
|
|
||||||
for (var i = 0; i<n; i++) {
|
|
||||||
out[i] <-- (in >> i) & 1;
|
|
||||||
out[i] * (out[i] -1 ) === 0;
|
|
||||||
lc1 += out[i] * 2**i;
|
|
||||||
}
|
|
||||||
|
|
||||||
lc1 === in;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template Bits2Num(n) {
|
|
||||||
signal input in[n];
|
|
||||||
signal output out;
|
|
||||||
var lc1=0;
|
|
||||||
|
|
||||||
for (var i = 0; i<n; i++) {
|
|
||||||
lc1 += in[i] * 2**i;
|
|
||||||
}
|
|
||||||
|
|
||||||
lc1 ==> out;
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Ch
|
|
||||||
|
|
||||||
000 0
|
|
||||||
001 1
|
|
||||||
010 0
|
|
||||||
011 1
|
|
||||||
100 0
|
|
||||||
101 0
|
|
||||||
110 1
|
|
||||||
111 1
|
|
||||||
|
|
||||||
out = a&b ^ (!a)&c =>
|
|
||||||
|
|
||||||
out = a*(b-c) + c
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
template Ch(n) {
|
|
||||||
signal input a[n];
|
|
||||||
signal input b[n];
|
|
||||||
signal input c[n];
|
|
||||||
signal output out[n];
|
|
||||||
|
|
||||||
for (var k=0; k<n; k++) {
|
|
||||||
out[k] <== a[k] * (b[k]-c[k]) + c[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template H(x) {
|
|
||||||
signal output out[32];
|
|
||||||
var c = [0x6a09e667,
|
|
||||||
0xbb67ae85,
|
|
||||||
0x3c6ef372,
|
|
||||||
0xa54ff53a,
|
|
||||||
0x510e527f,
|
|
||||||
0x9b05688c,
|
|
||||||
0x1f83d9ab,
|
|
||||||
0x5be0cd19];
|
|
||||||
|
|
||||||
for (var i=0; i<32; i++) {
|
|
||||||
out[i] <== (c[x] >> i) & 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template K(x) {
|
|
||||||
signal output out[32];
|
|
||||||
var c = [
|
|
||||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
||||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
||||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
||||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
||||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
||||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
||||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
||||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
||||||
];
|
|
||||||
|
|
||||||
for (var i=0; i<32; i++) {
|
|
||||||
out[i] <== (c[x] >> i) & 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template XOR() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== a + b - 2*a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template AND() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template OR() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== a + b - a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template NOT() {
|
|
||||||
signal input in;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== 1 + in - 2*in;
|
|
||||||
}
|
|
||||||
|
|
||||||
template NAND() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== 1 - a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template NOR() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
out <== a*b + 1 - a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
include "sha256_2.jaz";
|
|
||||||
|
|
||||||
template Main() {
|
|
||||||
signal private input a;
|
|
||||||
signal private input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
component sha256_2 = SHA256_2();
|
|
||||||
|
|
||||||
sha256_2.a <== a;
|
|
||||||
sha256_2.b <== a;
|
|
||||||
out <== sha256_2.out;
|
|
||||||
}
|
|
||||||
|
|
||||||
component main = Main();
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Maj function for sha256
|
|
||||||
|
|
||||||
out = a&b ^ a&c ^ b&c =>
|
|
||||||
|
|
||||||
out = a*b + a*c + b*c - 2*a*b*c =>
|
|
||||||
|
|
||||||
out = a*( b + c - 2*b*c ) + b*c =>
|
|
||||||
|
|
||||||
mid = b*c
|
|
||||||
out = a*( b + c - 2*mid ) + mid
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
template Maj(n) {
|
|
||||||
signal input a[n];
|
|
||||||
signal input b[n];
|
|
||||||
signal input c[n];
|
|
||||||
signal output out[n];
|
|
||||||
signal mid[n];
|
|
||||||
|
|
||||||
for (var k=0; k<n; k++) {
|
|
||||||
mid[k] <== b[k]*c[k];
|
|
||||||
out[k] <== a[k] * (b[k]+c[k]-2*mid[k]) + mid[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template RotR(n, r) {
|
|
||||||
signal input in[n];
|
|
||||||
signal output out[n];
|
|
||||||
|
|
||||||
for (var i=0; i<n; i++) {
|
|
||||||
out[i] <== in[ (i+r)%n ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
include "sha256compression.circom";
|
|
||||||
include "bitify.circom"
|
|
||||||
|
|
||||||
template Sha256_2() {
|
|
||||||
signal input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
component bits2num = Bits2Num(216);
|
|
||||||
component num2bits[2];
|
|
||||||
|
|
||||||
num2bits[0] = Num2Bits(216);
|
|
||||||
num2bits[1] = Num2Bits(216);
|
|
||||||
|
|
||||||
num2bits[0].in <== a;
|
|
||||||
num2bits[1].in <== b;
|
|
||||||
|
|
||||||
component sha256compression = Sha256compression() ;
|
|
||||||
|
|
||||||
var i;
|
|
||||||
|
|
||||||
for (i=0; i<216; i++) {
|
|
||||||
sha256compression.inp[i] <== num2bits[0].out[215-i];
|
|
||||||
sha256compression.inp[i+216] <== num2bits[1].out[215-i];
|
|
||||||
}
|
|
||||||
|
|
||||||
sha256compression.inp[432] <== 1;
|
|
||||||
|
|
||||||
for (i=433; i<503; i++) {
|
|
||||||
sha256compression.inp[i] <== 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sha256compression.inp[503] <== 1;
|
|
||||||
sha256compression.inp[504] <== 1;
|
|
||||||
sha256compression.inp[505] <== 0;
|
|
||||||
sha256compression.inp[506] <== 1;
|
|
||||||
sha256compression.inp[507] <== 1;
|
|
||||||
sha256compression.inp[508] <== 0;
|
|
||||||
sha256compression.inp[509] <== 0;
|
|
||||||
sha256compression.inp[510] <== 0;
|
|
||||||
sha256compression.inp[511] <== 0;
|
|
||||||
|
|
||||||
for (i=0; i<216; i++) {
|
|
||||||
bits2num.in[i] <== sha256compression.out[255-i];
|
|
||||||
}
|
|
||||||
|
|
||||||
out <== bits2num.out;
|
|
||||||
}
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
include "constants.circom";
|
|
||||||
include "t1.circom";
|
|
||||||
include "t2.circom";
|
|
||||||
include "binsum.circom";
|
|
||||||
include "sigmaplus.circom";
|
|
||||||
|
|
||||||
template Sha256compression() {
|
|
||||||
signal input inp[512];
|
|
||||||
signal output out[256];
|
|
||||||
signal a[65][32];
|
|
||||||
signal b[65][32];
|
|
||||||
signal c[65][32];
|
|
||||||
signal d[65][32];
|
|
||||||
signal e[65][32];
|
|
||||||
signal f[65][32];
|
|
||||||
signal g[65][32];
|
|
||||||
signal h[65][32];
|
|
||||||
signal w[64][32];
|
|
||||||
|
|
||||||
var i;
|
|
||||||
|
|
||||||
component sigmaPlus[48];
|
|
||||||
for (i=0; i<48; i++) sigmaPlus[i] = SigmaPlus();
|
|
||||||
|
|
||||||
component ct_k[64];
|
|
||||||
for (i=0; i<64; i++) ct_k[i] = K(i);
|
|
||||||
|
|
||||||
component ha0 = H(0);
|
|
||||||
component hb0 = H(1);
|
|
||||||
component hc0 = H(2);
|
|
||||||
component hd0 = H(3);
|
|
||||||
component he0 = H(4);
|
|
||||||
component hf0 = H(5);
|
|
||||||
component hg0 = H(6);
|
|
||||||
component hh0 = H(7);
|
|
||||||
|
|
||||||
component t1[64];
|
|
||||||
for (i=0; i<64; i++) t1[i] = T1();
|
|
||||||
|
|
||||||
component t2[64];
|
|
||||||
for (i=0; i<64; i++) t2[i] = T2();
|
|
||||||
|
|
||||||
component suma[64];
|
|
||||||
for (i=0; i<64; i++) suma[i] = BinSum(32, 2);
|
|
||||||
|
|
||||||
component sume[64];
|
|
||||||
for (i=0; i<64; i++) sume[i] = BinSum(32, 2);
|
|
||||||
|
|
||||||
component fsum[8];
|
|
||||||
for (i=0; i<8; i++) fsum[i] = BinSum(32, 2);
|
|
||||||
|
|
||||||
var k;
|
|
||||||
var t;
|
|
||||||
|
|
||||||
for (t=0; t<64; t++) {
|
|
||||||
if (t<16) {
|
|
||||||
for (k=0; k<32; k++) {
|
|
||||||
w[t][k] <== inp[t*32+31-k];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (k=0; k<32; k++) {
|
|
||||||
sigmaPlus[t-16].in2[k] <== w[t-2][k];
|
|
||||||
sigmaPlus[t-16].in7[k] <== w[t-7][k];
|
|
||||||
sigmaPlus[t-16].in15[k] <== w[t-15][k];
|
|
||||||
sigmaPlus[t-16].in16[k] <== w[t-16][k];
|
|
||||||
w[t][k] <== sigmaPlus[t-16].out[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k=0; k<32; k++ ) {
|
|
||||||
a[0][k] <== ha0.out[k]
|
|
||||||
b[0][k] <== hb0.out[k]
|
|
||||||
c[0][k] <== hc0.out[k]
|
|
||||||
d[0][k] <== hd0.out[k]
|
|
||||||
e[0][k] <== he0.out[k]
|
|
||||||
f[0][k] <== hf0.out[k]
|
|
||||||
g[0][k] <== hg0.out[k]
|
|
||||||
h[0][k] <== hh0.out[k]
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 0; t<64; t++) {
|
|
||||||
for (k=0; k<32; k++) {
|
|
||||||
t1[t].h[k] <== h[t][k];
|
|
||||||
t1[t].e[k] <== e[t][k];
|
|
||||||
t1[t].f[k] <== f[t][k];
|
|
||||||
t1[t].g[k] <== g[t][k];
|
|
||||||
t1[t].k[k] <== ct_k[t].out[k];
|
|
||||||
t1[t].w[k] <== w[t][k];
|
|
||||||
|
|
||||||
t2[t].a[k] <== a[t][k];
|
|
||||||
t2[t].b[k] <== b[t][k];
|
|
||||||
t2[t].c[k] <== c[t][k];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k=0; k<32; k++) {
|
|
||||||
sume[t].in[0][k] <== d[t][k];
|
|
||||||
sume[t].in[1][k] <== t1[t].out[k];
|
|
||||||
|
|
||||||
suma[t].in[0][k] <== t1[t].out[k];
|
|
||||||
suma[t].in[1][k] <== t2[t].out[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k=0; k<32; k++) {
|
|
||||||
h[t+1][k] <== g[t][k];
|
|
||||||
g[t+1][k] <== f[t][k];
|
|
||||||
f[t+1][k] <== e[t][k];
|
|
||||||
e[t+1][k] <== sume[t].out[k];
|
|
||||||
d[t+1][k] <== c[t][k];
|
|
||||||
c[t+1][k] <== b[t][k];
|
|
||||||
b[t+1][k] <== a[t][k];
|
|
||||||
a[t+1][k] <== suma[t].out[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k=0; k<32; k++) {
|
|
||||||
fsum[0].in[0][k] <== ha0.out[k];
|
|
||||||
fsum[0].in[1][k] <== a[64][k];
|
|
||||||
fsum[1].in[0][k] <== hb0.out[k];
|
|
||||||
fsum[1].in[1][k] <== b[64][k];
|
|
||||||
fsum[2].in[0][k] <== hc0.out[k];
|
|
||||||
fsum[2].in[1][k] <== c[64][k];
|
|
||||||
fsum[3].in[0][k] <== hd0.out[k];
|
|
||||||
fsum[3].in[1][k] <== d[64][k];
|
|
||||||
fsum[4].in[0][k] <== he0.out[k];
|
|
||||||
fsum[4].in[1][k] <== e[64][k];
|
|
||||||
fsum[5].in[0][k] <== hf0.out[k];
|
|
||||||
fsum[5].in[1][k] <== f[64][k];
|
|
||||||
fsum[6].in[0][k] <== hg0.out[k];
|
|
||||||
fsum[6].in[1][k] <== g[64][k];
|
|
||||||
fsum[7].in[0][k] <== hh0.out[k];
|
|
||||||
fsum[7].in[1][k] <== h[64][k];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k=0; k<32; k++) {
|
|
||||||
out[31-k] <== fsum[0].out[k];
|
|
||||||
out[32+31-k] <== fsum[1].out[k];
|
|
||||||
out[64+31-k] <== fsum[2].out[k];
|
|
||||||
out[96+31-k] <== fsum[3].out[k];
|
|
||||||
out[128+31-k] <== fsum[4].out[k];
|
|
||||||
out[160+31-k] <== fsum[5].out[k];
|
|
||||||
out[192+31-k] <== fsum[6].out[k];
|
|
||||||
out[224+31-k] <== fsum[7].out[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template ShR(n, r) {
|
|
||||||
signal input in[n];
|
|
||||||
signal output out[n];
|
|
||||||
|
|
||||||
for (var i=0; i<n; i++) {
|
|
||||||
if (i+r >= n) {
|
|
||||||
out[i] <== 0;
|
|
||||||
} else {
|
|
||||||
out[i] <== in[ i+r ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
include "xor3.circom";
|
|
||||||
include "rotate.circom";
|
|
||||||
include "shift.circom";
|
|
||||||
|
|
||||||
template SmallSigma(ra, rb, rc) {
|
|
||||||
signal input in[32];
|
|
||||||
signal output out[32];
|
|
||||||
|
|
||||||
component xor3 = Xor3(32);
|
|
||||||
|
|
||||||
component rota = RotR(32, ra);
|
|
||||||
component rotb = RotR(32, rb);
|
|
||||||
component shrc = ShR(32, rc);
|
|
||||||
|
|
||||||
for (var k=0; k<32; k++) {
|
|
||||||
rota.in[k] <== in[k];
|
|
||||||
rotb.in[k] <== in[k];
|
|
||||||
shrc.in[k] <== in[k];
|
|
||||||
|
|
||||||
xor3.a[k] <== rota.out[k];
|
|
||||||
xor3.b[k] <== rotb.out[k];
|
|
||||||
xor3.c[k] <== shrc.out[k];
|
|
||||||
|
|
||||||
out[k] <== xor3.out[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template BigSigma(ra, rb, rc) {
|
|
||||||
signal input in[32];
|
|
||||||
signal output out[32];
|
|
||||||
|
|
||||||
component xor3 = Xor3(32);
|
|
||||||
|
|
||||||
component rota = RotR(32, ra);
|
|
||||||
component rotb = RotR(32, rb);
|
|
||||||
component rotc = RotR(32, rc);
|
|
||||||
|
|
||||||
for (var k=0; k<32; k++) {
|
|
||||||
rota.in[k] <== in[k];
|
|
||||||
rotb.in[k] <== in[k];
|
|
||||||
rotc.in[k] <== in[k];
|
|
||||||
|
|
||||||
xor3.a[k] <== rota.out[k];
|
|
||||||
xor3.b[k] <== rotb.out[k];
|
|
||||||
xor3.c[k] <== rotc.out[k];
|
|
||||||
|
|
||||||
out[k] <== xor3.out[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
include "binsum.circom"
|
|
||||||
include "sigma.circom"
|
|
||||||
|
|
||||||
template SigmaPlus() {
|
|
||||||
signal input in2[32];
|
|
||||||
signal input in7[32];
|
|
||||||
signal input in15[32];
|
|
||||||
signal input in16[32];
|
|
||||||
signal output out[32];
|
|
||||||
|
|
||||||
component sum = BinSum(32, 4);
|
|
||||||
component sigma1 = SmallSigma(17,19,10);
|
|
||||||
component sigma0 = SmallSigma(7, 18, 3);
|
|
||||||
|
|
||||||
for (var k=0; k<32; k++) {
|
|
||||||
sigma1.in[k] <== in2[k];
|
|
||||||
sigma0.in[k] <== in15[k];
|
|
||||||
|
|
||||||
sum.in[0][k] <== sigma1.out[k];
|
|
||||||
sum.in[1][k] <== in7[k];
|
|
||||||
sum.in[2][k] <== sigma0.out[k];
|
|
||||||
sum.in[3][k] <== in16[k];
|
|
||||||
|
|
||||||
out[k] <== sum.out[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
include "binsum.circom";
|
|
||||||
include "sigma.circom";
|
|
||||||
include "ch.circom";
|
|
||||||
|
|
||||||
template T1() {
|
|
||||||
signal input h[32];
|
|
||||||
signal input e[32];
|
|
||||||
signal input f[32];
|
|
||||||
signal input g[32];
|
|
||||||
signal input k[32];
|
|
||||||
signal input w[32];
|
|
||||||
signal output out[32];
|
|
||||||
|
|
||||||
component sum = BinSum(32, 5);
|
|
||||||
component ch = Ch(32);
|
|
||||||
|
|
||||||
component bigsigma1 = BigSigma(6, 11, 25);
|
|
||||||
|
|
||||||
for (var ki=0; ki<32; ki++) {
|
|
||||||
bigsigma1.in[ki] <== e[ki];
|
|
||||||
ch.a[ki] <== e[ki];
|
|
||||||
ch.b[ki] <== f[ki];
|
|
||||||
ch.c[ki] <== g[ki]
|
|
||||||
|
|
||||||
sum.in[0][ki] <== h[ki];
|
|
||||||
sum.in[1][ki] <== bigsigma1.out[ki];
|
|
||||||
sum.in[2][ki] <== ch.out[ki];
|
|
||||||
sum.in[3][ki] <== k[ki];
|
|
||||||
sum.in[4][ki] <== w[ki];
|
|
||||||
|
|
||||||
out[ki] <== sum.out[ki];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
include "binsum.circom";
|
|
||||||
include "sigma.circom";
|
|
||||||
include "maj.circom"
|
|
||||||
|
|
||||||
template T2() {
|
|
||||||
signal input a[32];
|
|
||||||
signal input b[32];
|
|
||||||
signal input c[32];
|
|
||||||
signal output out[32];
|
|
||||||
|
|
||||||
component sum = BinSum(32, 2);
|
|
||||||
|
|
||||||
component bigsigma0 = BigSigma(2, 13, 22);
|
|
||||||
component maj = Maj(32);
|
|
||||||
|
|
||||||
for (var k=0; k<32; k++) {
|
|
||||||
|
|
||||||
bigsigma0.in[k] <== a[k];
|
|
||||||
maj.a[k] <== a[k];
|
|
||||||
maj.b[k] <== b[k];
|
|
||||||
maj.c[k] <== c[k];
|
|
||||||
|
|
||||||
sum.in[0][k] <== bigsigma0.out[k];
|
|
||||||
sum.in[1][k] <== maj.out[k];
|
|
||||||
|
|
||||||
out[k] <== sum.out[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Xor3 function for sha256
|
|
||||||
|
|
||||||
out = a ^ b ^ c =>
|
|
||||||
|
|
||||||
out = a+b+c - 2*a*b - 2*a*c - 2*b*c + 4*a*b*c =>
|
|
||||||
|
|
||||||
out = a*( 1 - 2*b - 2*c + 4*b*c ) + b + c - 2*b*c =>
|
|
||||||
|
|
||||||
mid = b*c
|
|
||||||
out = a*( 1 - 2*b -2*c + 4*mid ) + b + c - 2 * mid
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
template Xor3(n) {
|
|
||||||
signal input a[n];
|
|
||||||
signal input b[n];
|
|
||||||
signal input c[n];
|
|
||||||
signal output out[n];
|
|
||||||
signal mid[n];
|
|
||||||
|
|
||||||
for (var k=0; k<n; k++) {
|
|
||||||
mid[k] <== b[k]*c[k];
|
|
||||||
out[k] <== a[k] * (1 -2*b[k] -2*c[k] +4*mid[k]) + b[k] + c[k] -2*mid[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 0KIMS association.
|
|
||||||
|
|
||||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
|
||||||
|
|
||||||
circom is a free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
template toBin(n) {
|
|
||||||
signal input inp;
|
|
||||||
signal output out[n];
|
|
||||||
var lc1=0;
|
|
||||||
|
|
||||||
for (var i = 0; i<n; i++) {
|
|
||||||
out[i] <-- (inp >> i) & 1;
|
|
||||||
out[i] * (out[i] -1 ) === 0;
|
|
||||||
lc1 += out[i] * 2**i;
|
|
||||||
}
|
|
||||||
|
|
||||||
lc1 === inp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
component toBin(3) main;
|
|
||||||
29
cli.js
29
cli.js
@@ -34,6 +34,7 @@ const argv = require("yargs")
|
|||||||
.alias("o", "output")
|
.alias("o", "output")
|
||||||
.help("h")
|
.help("h")
|
||||||
.alias("h", "help")
|
.alias("h", "help")
|
||||||
|
.alias("v", "verbose")
|
||||||
.epilogue(`Copyright (C) 2018 0kims association
|
.epilogue(`Copyright (C) 2018 0kims association
|
||||||
This program comes with ABSOLUTELY NO WARRANTY;
|
This program comes with ABSOLUTELY NO WARRANTY;
|
||||||
This is free software, and you are welcome to redistribute it
|
This is free software, and you are welcome to redistribute it
|
||||||
@@ -41,15 +42,35 @@ const argv = require("yargs")
|
|||||||
repo directory at https://github.com/iden3/circom `)
|
repo directory at https://github.com/iden3/circom `)
|
||||||
.argv;
|
.argv;
|
||||||
|
|
||||||
const fullFileName = path.resolve(process.cwd(), argv._[0]);
|
|
||||||
|
let inputFile;
|
||||||
|
if (argv._.length == 0) {
|
||||||
|
inputFile = "circuit.circom";
|
||||||
|
} else if (argv._.length == 1) {
|
||||||
|
inputFile = argv._[0];
|
||||||
|
} else {
|
||||||
|
console.log("Only one circuit at a time is permited");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullFileName = path.resolve(process.cwd(), inputFile);
|
||||||
const outName = argv.output ? argv.output : "circuit.json";
|
const outName = argv.output ? argv.output : "circuit.json";
|
||||||
|
|
||||||
compiler(fullFileName).then( (cir) => {
|
compiler(fullFileName).then( (cir) => {
|
||||||
fs.writeFileSync(outName, JSON.stringify(cir, null, 1), "utf8");
|
fs.writeFileSync(outName, JSON.stringify(cir, null, 1), "utf8");
|
||||||
|
process.exit(0);
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
console.log(err);
|
// console.log(err);
|
||||||
console.error(`ERROR at ${err.errFile}:${err.pos.first_line},${err.pos.first_column}-${err.pos.last_line},${err.pos.last_column} ${err.errStr}`);
|
console.log(err.stack);
|
||||||
console.error(JSON.stringify(err.ast, null, 1));
|
if (err.pos) {
|
||||||
|
console.error(`ERROR at ${err.errFile}:${err.pos.first_line},${err.pos.first_column}-${err.pos.last_line},${err.pos.last_column} ${err.errStr}`);
|
||||||
|
} else {
|
||||||
|
console.log(err.message);
|
||||||
|
if (argv.verbose) console.log(err.stack);
|
||||||
|
}
|
||||||
|
if (err.ast) {
|
||||||
|
console.error(JSON.stringify(err.ast, null, 1));
|
||||||
|
}
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
125
package-lock.json
generated
125
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circom",
|
"name": "circom",
|
||||||
"version": "0.0.12",
|
"version": "0.0.23",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -137,6 +137,12 @@
|
|||||||
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"astral-regex": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"babel-code-frame": {
|
"babel-code-frame": {
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||||
@@ -1469,9 +1475,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"snarkjs": {
|
"snarkjs": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.7.tgz",
|
||||||
"integrity": "sha512-z5HhuNt019ZzNzUztETK31rpjRRSz3Uzy8TjGgSROf+9ZT9i6dbdWkjTC3fh5o9H+R/2+hcR+7IKAmpIR56V+A==",
|
"integrity": "sha512-S7un4ESi5vjE4pVt50kPEraiP9Bt5ZfNfMiqnUE+zvRyBPa/dX4vU3osAyOxp/RbBUi+MofNRdrES2TO/DET1g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.35",
|
"big-integer": "^1.6.35",
|
||||||
@@ -1480,10 +1486,22 @@
|
|||||||
"yargs": "^12.0.2"
|
"yargs": "^12.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"acorn": {
|
||||||
|
"version": "6.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz",
|
||||||
|
"integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"acorn-jsx": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "6.5.4",
|
"version": "6.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz",
|
||||||
"integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
|
"integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^2.0.1",
|
"fast-deep-equal": "^2.0.1",
|
||||||
@@ -1492,10 +1510,25 @@
|
|||||||
"uri-js": "^4.2.2"
|
"uri-js": "^4.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ansi-regex": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"big-integer": {
|
"big-integer": {
|
||||||
"version": "1.6.36",
|
"version": "1.6.40",
|
||||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz",
|
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.40.tgz",
|
||||||
"integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==",
|
"integrity": "sha512-CjhtJp0BViLzP1ZkEnoywjgtFQXS2pomKjAJtIISTCnuHILkLcAXLdFLG/nxsHc4s9kJfc+82Xpg8WNyhfACzQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chardet": {
|
"chardet": {
|
||||||
@@ -1514,9 +1547,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint": {
|
"eslint": {
|
||||||
"version": "5.7.0",
|
"version": "5.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.10.0.tgz",
|
||||||
"integrity": "sha512-zYCeFQahsxffGl87U2aJ7DPyH8CbWgxBC213Y8+TCanhUTf2gEvfq3EKpHmEcozTLyPmGe9LZdMAwC/CpJBM5A==",
|
"integrity": "sha512-HpqzC+BHULKlnPwWae9MaVZ5AXJKpkxCVXQHrFaRw3hbDj26V/9ArYM4Rr/SQ8pi6qUPLXSSXC4RBJlyq2Z2OQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/code-frame": "^7.0.0",
|
"@babel/code-frame": "^7.0.0",
|
||||||
@@ -1528,7 +1561,7 @@
|
|||||||
"eslint-scope": "^4.0.0",
|
"eslint-scope": "^4.0.0",
|
||||||
"eslint-utils": "^1.3.1",
|
"eslint-utils": "^1.3.1",
|
||||||
"eslint-visitor-keys": "^1.0.0",
|
"eslint-visitor-keys": "^1.0.0",
|
||||||
"espree": "^4.0.0",
|
"espree": "^5.0.0",
|
||||||
"esquery": "^1.0.1",
|
"esquery": "^1.0.1",
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2",
|
||||||
"file-entry-cache": "^2.0.0",
|
"file-entry-cache": "^2.0.0",
|
||||||
@@ -1538,7 +1571,6 @@
|
|||||||
"ignore": "^4.0.6",
|
"ignore": "^4.0.6",
|
||||||
"imurmurhash": "^0.1.4",
|
"imurmurhash": "^0.1.4",
|
||||||
"inquirer": "^6.1.0",
|
"inquirer": "^6.1.0",
|
||||||
"is-resolvable": "^1.1.0",
|
|
||||||
"js-yaml": "^3.12.0",
|
"js-yaml": "^3.12.0",
|
||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"levn": "^0.3.0",
|
"levn": "^0.3.0",
|
||||||
@@ -1559,6 +1591,17 @@
|
|||||||
"text-table": "^0.2.0"
|
"text-table": "^0.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"espree": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/espree/-/espree-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"acorn": "^6.0.2",
|
||||||
|
"acorn-jsx": "^5.0.0",
|
||||||
|
"eslint-visitor-keys": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"external-editor": {
|
"external-editor": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
|
||||||
@@ -1586,9 +1629,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"inquirer": {
|
"inquirer": {
|
||||||
"version": "6.2.0",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz",
|
||||||
"integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
|
"integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-escapes": "^3.0.0",
|
"ansi-escapes": "^3.0.0",
|
||||||
@@ -1602,8 +1645,19 @@
|
|||||||
"run-async": "^2.2.0",
|
"run-async": "^2.2.0",
|
||||||
"rxjs": "^6.1.0",
|
"rxjs": "^6.1.0",
|
||||||
"string-width": "^2.1.0",
|
"string-width": "^2.1.0",
|
||||||
"strip-ansi": "^4.0.0",
|
"strip-ansi": "^5.0.0",
|
||||||
"through": "^2.3.6"
|
"through": "^2.3.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"strip-ansi": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-regex": "^4.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
@@ -1633,16 +1687,35 @@
|
|||||||
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
|
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"table": {
|
"slice-ansi": {
|
||||||
"version": "5.1.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.0.0.tgz",
|
||||||
"integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==",
|
"integrity": "sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^6.5.3",
|
"ansi-styles": "^3.2.0",
|
||||||
"lodash": "^4.17.10",
|
"astral-regex": "^1.0.0",
|
||||||
"slice-ansi": "1.0.0",
|
"is-fullwidth-code-point": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/table/-/table-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "^6.6.1",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
|
"slice-ansi": "2.0.0",
|
||||||
"string-width": "^2.1.1"
|
"string-width": "^2.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||||
|
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circom",
|
"name": "circom",
|
||||||
"version": "0.0.12",
|
"version": "0.0.23",
|
||||||
"description": "Language to generate logic circuits",
|
"description": "Language to generate logic circuits",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
@@ -38,6 +38,6 @@
|
|||||||
"eslint": "^5.0.1",
|
"eslint": "^5.0.1",
|
||||||
"eslint-plugin-mocha": "^5.0.0",
|
"eslint-plugin-mocha": "^5.0.0",
|
||||||
"jison": "^0.4.18",
|
"jison": "^0.4.18",
|
||||||
"snarkjs": "0.1.4"
|
"snarkjs": "0.1.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ include { return 'include'; }
|
|||||||
\- { return '-'; }
|
\- { return '-'; }
|
||||||
\* { return '*'; }
|
\* { return '*'; }
|
||||||
\/ { return '/'; }
|
\/ { return '/'; }
|
||||||
|
\\ { return '\\'; }
|
||||||
\% { return '%'; }
|
\% { return '%'; }
|
||||||
\^ { return '^'; }
|
\^ { return '^'; }
|
||||||
\& { return '&'; }
|
\& { return '&'; }
|
||||||
@@ -118,7 +119,7 @@ include { return 'include'; }
|
|||||||
%left '<<' '>>'
|
%left '<<' '>>'
|
||||||
|
|
||||||
%left '+' '-'
|
%left '+' '-'
|
||||||
%left '*' '/' '%'
|
%left '*' '/' '\\' '%'
|
||||||
%left '**'
|
%left '**'
|
||||||
%right '++' '--' UMINUS UPLUS '!' '~'
|
%right '++' '--' UMINUS UPLUS '!' '~'
|
||||||
%left '.'
|
%left '.'
|
||||||
@@ -627,7 +628,7 @@ e7
|
|||||||
{
|
{
|
||||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||||
let v = $3.value.greater(256) ? 256 : $3.value.value;
|
let v = $3.value.greater(256) ? 256 : $3.value.value;
|
||||||
$$ = {t1ype: "NUMBER", value: $1.value.shiftRight(v).and(__MASK__) };
|
$$ = {type: "NUMBER", value: $1.value.shiftRight(v).and(__MASK__) };
|
||||||
} else {
|
} else {
|
||||||
$$ = { type: "OP", op: ">>", values: [$1, $3] };
|
$$ = { type: "OP", op: ">>", values: [$1, $3] };
|
||||||
}
|
}
|
||||||
@@ -684,6 +685,15 @@ e5
|
|||||||
}
|
}
|
||||||
setLines($$, @1, @3);
|
setLines($$, @1, @3);
|
||||||
}
|
}
|
||||||
|
| e5 '\\' e4
|
||||||
|
{
|
||||||
|
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||||
|
$$ = { type: "NUMBER", value: ($1.value.divide($3.value)) };
|
||||||
|
} else {
|
||||||
|
$$ = { type: "OP", op: "\\", values: [$1, $3] };
|
||||||
|
}
|
||||||
|
setLines($$, @1, @3);
|
||||||
|
}
|
||||||
| e5 '%' e4
|
| e5 '%' e4
|
||||||
{
|
{
|
||||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||||
|
|||||||
144
parser/jaz.js
144
parser/jaz.js
File diff suppressed because one or more lines are too long
@@ -31,7 +31,7 @@ module.exports = compile;
|
|||||||
|
|
||||||
const parser = require("../parser/jaz.js").parser;
|
const parser = require("../parser/jaz.js").parser;
|
||||||
|
|
||||||
const timeout = ms => new Promise(res => setTimeout(res, ms))
|
const timeout = ms => new Promise(res => setTimeout(res, ms));
|
||||||
|
|
||||||
async function compile(srcFile) {
|
async function compile(srcFile) {
|
||||||
const fullFileName = srcFile;
|
const fullFileName = srcFile;
|
||||||
@@ -62,8 +62,13 @@ async function compile(srcFile) {
|
|||||||
fileName: fullFileName
|
fileName: fullFileName
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
exec(ctx, ast);
|
exec(ctx, ast);
|
||||||
|
|
||||||
|
if (!ctx.components["main"]) {
|
||||||
|
throw new Error("A main component must be defined");
|
||||||
|
}
|
||||||
|
|
||||||
classifySignals(ctx);
|
classifySignals(ctx);
|
||||||
reduceConstants(ctx);
|
reduceConstants(ctx);
|
||||||
|
|
||||||
|
|||||||
159
src/exec.js
159
src/exec.js
@@ -78,12 +78,22 @@ function exec(ctx, ast) {
|
|||||||
return execPlusPlusRight(ctx, ast);
|
return execPlusPlusRight(ctx, ast);
|
||||||
} else if (ast.op == "PLUSPLUSLEFT") {
|
} else if (ast.op == "PLUSPLUSLEFT") {
|
||||||
return execPlusPlusLeft(ctx, ast);
|
return execPlusPlusLeft(ctx, ast);
|
||||||
|
} else if (ast.op == "MINUSMINUSRIGHT") {
|
||||||
|
return execMinusMinusRight(ctx, ast);
|
||||||
|
} else if (ast.op == "MINUSMINUSLEFT") {
|
||||||
|
return execMinusMinusLeft(ctx, ast);
|
||||||
} else if (ast.op == "/") {
|
} else if (ast.op == "/") {
|
||||||
return execDiv(ctx, ast);
|
return execDiv(ctx, ast);
|
||||||
|
} else if (ast.op == "\\") {
|
||||||
|
return execIDiv(ctx, ast);
|
||||||
} else if (ast.op == "**") {
|
} else if (ast.op == "**") {
|
||||||
return execExp(ctx, ast);
|
return execExp(ctx, ast);
|
||||||
} else if (ast.op == "&") {
|
} else if (ast.op == "&") {
|
||||||
return execBAnd(ctx, ast);
|
return execBAnd(ctx, ast);
|
||||||
|
} else if (ast.op == "&&") {
|
||||||
|
return execAnd(ctx, ast);
|
||||||
|
} else if (ast.op == "||") {
|
||||||
|
return execOr(ctx, ast);
|
||||||
} else if (ast.op == "<<") {
|
} else if (ast.op == "<<") {
|
||||||
return execShl(ctx, ast);
|
return execShl(ctx, ast);
|
||||||
} else if (ast.op == ">>") {
|
} else if (ast.op == ">>") {
|
||||||
@@ -98,6 +108,8 @@ function exec(ctx, ast) {
|
|||||||
return execGte(ctx, ast);
|
return execGte(ctx, ast);
|
||||||
} else if (ast.op == "==") {
|
} else if (ast.op == "==") {
|
||||||
return execEq(ctx, ast);
|
return execEq(ctx, ast);
|
||||||
|
} else if (ast.op == "!=") {
|
||||||
|
return execNeq(ctx, ast);
|
||||||
} else if (ast.op == "?") {
|
} else if (ast.op == "?") {
|
||||||
return execTerCon(ctx, ast);
|
return execTerCon(ctx, ast);
|
||||||
} else {
|
} else {
|
||||||
@@ -150,7 +162,8 @@ function error(ctx, ast, errStr) {
|
|||||||
},
|
},
|
||||||
errStr: errStr,
|
errStr: errStr,
|
||||||
errFile: ctx.fileName,
|
errFile: ctx.fileName,
|
||||||
ast: ast
|
ast: ast,
|
||||||
|
message: errStr
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,8 +329,7 @@ function execInstantiateComponet(ctx, vr, fn) {
|
|||||||
const v = exec(ctx, fn.params[i]);
|
const v = exec(ctx, fn.params[i]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
if (v.type != "NUMBER") return error(ctx, fn.params[i], "expected a number");
|
paramValues.push(v);
|
||||||
paramValues.push( v.value);
|
|
||||||
}
|
}
|
||||||
if (template.params.length != paramValues.length) error(ctx, fn, "Invalid Number of parameters");
|
if (template.params.length != paramValues.length) error(ctx, fn, "Invalid Number of parameters");
|
||||||
|
|
||||||
@@ -328,6 +340,15 @@ function execInstantiateComponet(ctx, vr, fn) {
|
|||||||
instantiateComponent(vv);
|
instantiateComponent(vv);
|
||||||
|
|
||||||
function instantiateComponent(varVal) {
|
function instantiateComponent(varVal) {
|
||||||
|
|
||||||
|
function extractValue(v) {
|
||||||
|
if (Array.isArray(v)) {
|
||||||
|
return v.map(extractValue);
|
||||||
|
} else {
|
||||||
|
return v.value.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(varVal)) {
|
if (Array.isArray(varVal)) {
|
||||||
for (let i =0; i<varVal.length; i++) {
|
for (let i =0; i<varVal.length; i++) {
|
||||||
instantiateComponent(varVal[i]);
|
instantiateComponent(varVal[i]);
|
||||||
@@ -351,13 +372,12 @@ function execInstantiateComponet(ctx, vr, fn) {
|
|||||||
|
|
||||||
ctx.scopes = oldScopes.slice(0, scopeLevel+1);
|
ctx.scopes = oldScopes.slice(0, scopeLevel+1);
|
||||||
|
|
||||||
|
if (template.params.length != paramValues.length) return error(ctx, fn, "Invalid number of parameters: " + templateName);
|
||||||
|
|
||||||
const scope = {};
|
const scope = {};
|
||||||
for (let i=0; i< template.params.length; i++) {
|
for (let i=0; i< template.params.length; i++) {
|
||||||
scope[template.params[i]] = {
|
scope[template.params[i]] = paramValues[i];
|
||||||
type: "NUMBER",
|
ctx.components[ctx.currentComponent].params[template.params[i]] = extractValue(paramValues[i]);
|
||||||
value: paramValues[i]
|
|
||||||
};
|
|
||||||
ctx.components[ctx.currentComponent].params[template.params[i]] = paramValues[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.components[ctx.currentComponent].template = templateName;
|
ctx.components[ctx.currentComponent].template = templateName;
|
||||||
@@ -539,34 +559,41 @@ function execPin(ctx, ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function execFor(ctx, ast) {
|
function execFor(ctx, ast) {
|
||||||
|
|
||||||
|
ctx.scopes.push({});
|
||||||
exec(ctx, ast.init);
|
exec(ctx, ast.init);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
let v = exec(ctx, ast.condition);
|
let v = exec(ctx, ast.condition);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
while ((v.value.neq(0))&&(!ctx.returnValue)) {
|
if (typeof v.value != "undefined") {
|
||||||
exec(ctx, ast.body);
|
while ((v.value.neq(0))&&(!ctx.returnValue)) {
|
||||||
if (ctx.error) return;
|
exec(ctx, ast.body);
|
||||||
|
if (ctx.error) return;
|
||||||
|
|
||||||
exec(ctx, ast.step);
|
exec(ctx, ast.step);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
v = exec(ctx, ast.condition);
|
v = exec(ctx, ast.condition);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ctx.scopes.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
function execWhile(ctx, ast) {
|
function execWhile(ctx, ast) {
|
||||||
let v = exec(ctx, ast.condition);
|
let v = exec(ctx, ast.condition);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
while ((v.value.neq(0))&&(!ctx.returnValue)) {
|
if (typeof v.value != "undefined") {
|
||||||
exec(ctx, ast.body);
|
while ((v.value.neq(0))&&(!ctx.returnValue)) {
|
||||||
if (ctx.error) return;
|
exec(ctx, ast.body);
|
||||||
|
if (ctx.error) return;
|
||||||
|
|
||||||
v = exec(ctx, ast.condition);
|
v = exec(ctx, ast.condition);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,12 +601,16 @@ function execIf(ctx, ast) {
|
|||||||
let v = exec(ctx, ast.condition);
|
let v = exec(ctx, ast.condition);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
if ((v.value.neq(0))&&(!ctx.returnValue)) {
|
if (typeof v.value != "undefined") {
|
||||||
exec(ctx, ast.then);
|
if ((v.value.neq(0))&&(!ctx.returnValue)) {
|
||||||
if (ctx.error) return;
|
exec(ctx, ast.then);
|
||||||
} else {
|
if (ctx.error) return;
|
||||||
exec(ctx, ast.else);
|
} else {
|
||||||
if (ctx.error) return;
|
if (ast.else) {
|
||||||
|
exec(ctx, ast.else);
|
||||||
|
if (ctx.error) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,6 +629,8 @@ function execVarAssignement(ctx, ast) {
|
|||||||
if ((typeof(num) != "object")||(num == null)) return error(ctx, ast, "Variable not defined");
|
if ((typeof(num) != "object")||(num == null)) return error(ctx, ast, "Variable not defined");
|
||||||
|
|
||||||
if (num.type == "COMPONENT") return execInstantiateComponet(ctx, v, ast.values[1]);
|
if (num.type == "COMPONENT") return execInstantiateComponet(ctx, v, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
// if (num.type == "SIGNAL") return error(ctx, ast, "Cannot assign to a signal with `=` use <-- or <== ops");
|
||||||
|
|
||||||
const res = exec(ctx, ast.values[1]);
|
const res = exec(ctx, ast.values[1]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -678,6 +711,20 @@ function execEq(ctx, ast) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execNeq(ctx, ast) {
|
||||||
|
const a = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (a.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
const b = exec(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (b.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
if (!a.value || !b.value) return { type: "NUMBER" };
|
||||||
|
return {
|
||||||
|
type: "NUMBER",
|
||||||
|
value: a.value.eq(b.value) ? bigInt(0) : bigInt(1)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function execBAnd(ctx, ast) {
|
function execBAnd(ctx, ast) {
|
||||||
const a = exec(ctx, ast.values[0]);
|
const a = exec(ctx, ast.values[0]);
|
||||||
@@ -693,6 +740,34 @@ function execBAnd(ctx, ast) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execAnd(ctx, ast) {
|
||||||
|
const a = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (a.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
const b = exec(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (b.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
if (!a.value || !b.value) return { type: "NUMBER" };
|
||||||
|
return {
|
||||||
|
type: "NUMBER",
|
||||||
|
value: (a.value.neq(0) && a.value.neq(0)) ? bigInt(1) : bigInt(0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function execOr(ctx, ast) {
|
||||||
|
const a = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (a.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
const b = exec(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (b.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
if (!a.value || !b.value) return { type: "NUMBER" };
|
||||||
|
return {
|
||||||
|
type: "NUMBER",
|
||||||
|
value: (a.value.neq(0) || a.value.neq(0)) ? bigInt(1) : bigInt(0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function execShl(ctx, ast) {
|
function execShl(ctx, ast) {
|
||||||
const a = exec(ctx, ast.values[0]);
|
const a = exec(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -767,6 +842,21 @@ function execDiv(ctx, ast) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execIDiv(ctx, ast) {
|
||||||
|
const a = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (a.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
const b = exec(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (b.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
if (!a.value || !b.value) return { type: "NUMBER" };
|
||||||
|
if (b.value.isZero()) return error(ctx, ast, "Division by zero");
|
||||||
|
return {
|
||||||
|
type: "NUMBER",
|
||||||
|
value: a.value.divide(b.value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function execAdd(ctx, ast) {
|
function execAdd(ctx, ast) {
|
||||||
const a = exec(ctx, ast.values[0]);
|
const a = exec(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -843,6 +933,23 @@ function execPlusPlusLeft(ctx, ast) {
|
|||||||
return resAfter;
|
return resAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execMinusMinusRight(ctx, ast) {
|
||||||
|
const resBefore = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
const resAfter = execSub(ctx,{ values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}] } );
|
||||||
|
if (ctx.error) return;
|
||||||
|
execVarAssignement(ctx, { values: [ast.values[0], resAfter] });
|
||||||
|
return resBefore;
|
||||||
|
}
|
||||||
|
|
||||||
|
function execMinusMinusLeft(ctx, ast) {
|
||||||
|
if (ctx.error) return;
|
||||||
|
const resAfter = execSub(ctx,{ values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}] } );
|
||||||
|
if (ctx.error) return;
|
||||||
|
execVarAssignement(ctx, { values: [ast.values[0], resAfter] });
|
||||||
|
return resAfter;
|
||||||
|
}
|
||||||
|
|
||||||
function execTerCon(ctx, ast) {
|
function execTerCon(ctx, ast) {
|
||||||
const cond = exec(ctx, ast.values[0]);
|
const cond = exec(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|||||||
70
src/genOptCode.js
Normal file
70
src/genOptCode.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
|
||||||
|
module.exports = genOpt;
|
||||||
|
|
||||||
|
|
||||||
|
function genOpt(ctx, ast) {
|
||||||
|
if (ast.type == "OP") {
|
||||||
|
if (ast.op == "=") {
|
||||||
|
return genOptVarAssignement(ctx, ast);
|
||||||
|
} else {
|
||||||
|
error(ctx, ast, "GENOPT -> Invalid operation: " + ast.op);
|
||||||
|
}
|
||||||
|
} else if (ast.type == "TEMPLATEDEF") {
|
||||||
|
return genOptTemplateDef(ctx, ast);
|
||||||
|
} else {
|
||||||
|
error(ctx, ast, "GENOPT -> Invalid AST node type: " + ast.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(ctx, ast, errStr) {
|
||||||
|
ctx.error = {
|
||||||
|
pos: {
|
||||||
|
first_line: ast.first_line,
|
||||||
|
first_column: ast.first_column,
|
||||||
|
last_line: ast.last_line,
|
||||||
|
last_column: ast.last_column
|
||||||
|
},
|
||||||
|
errStr: errStr,
|
||||||
|
errFile: ctx.fileName,
|
||||||
|
ast: ast
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function genOptTemplateDef(ctx, ast) {
|
||||||
|
if (ctx.templates[ast.name]) {
|
||||||
|
return error(ctx, ast, "Template name already exists: "+ast.name);
|
||||||
|
}
|
||||||
|
ctx.templates[ast.name] = {
|
||||||
|
type: "TEMPLATE",
|
||||||
|
params: ast.params,
|
||||||
|
block: ast.block,
|
||||||
|
fileName: ctx.fileName,
|
||||||
|
filePath: ctx.filePath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function genOptVarAssignement(ctx, ast) {
|
||||||
|
let varName;
|
||||||
|
if (ast.values[0].type == "DECLARE") {
|
||||||
|
varName = genOptCode(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
} else {
|
||||||
|
varName = ast.values[0];
|
||||||
|
}
|
||||||
|
const varContent = getScope(ctx, varName.name, varName.selectors);
|
||||||
|
if (ctx.error) return;
|
||||||
|
|
||||||
|
if ((typeof(varContent) != "object")||(varContent == null)) return error(ctx, ast, "Variable not defined");
|
||||||
|
|
||||||
|
if (varContent.type == "COMPONENT") return genOptInstantiateComponet(ctx, varName, ast.values[1]);
|
||||||
|
if (varContent.type == "SIGNAL") return error(ctx, ast, "Cannot assig to a signal with `=` use <-- or <== ops");
|
||||||
|
|
||||||
|
const res = genOpt(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
|
||||||
|
setScope(ctx, varName.name, varName.selectors, res);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
@@ -63,12 +63,22 @@ function gen(ctx, ast) {
|
|||||||
return genPlusPlusRight(ctx, ast);
|
return genPlusPlusRight(ctx, ast);
|
||||||
} else if (ast.op == "PLUSPLUSLEFT") {
|
} else if (ast.op == "PLUSPLUSLEFT") {
|
||||||
return genPlusPlusLeft(ctx, ast);
|
return genPlusPlusLeft(ctx, ast);
|
||||||
|
} else if (ast.op == "MINUSMINUSRIGHT") {
|
||||||
|
return genMinusMinusRight(ctx, ast);
|
||||||
|
} else if (ast.op == "MINUSMINUSLEFT") {
|
||||||
|
return genMinusMinusLeft(ctx, ast);
|
||||||
} else if (ast.op == "**") {
|
} else if (ast.op == "**") {
|
||||||
return genExp(ctx, ast);
|
return genExp(ctx, ast);
|
||||||
} else if (ast.op == "/") {
|
} else if (ast.op == "/") {
|
||||||
return genDiv(ctx, ast);
|
return genDiv(ctx, ast);
|
||||||
|
} else if (ast.op == "\\") {
|
||||||
|
return genIDiv(ctx, ast);
|
||||||
} else if (ast.op == "&") {
|
} else if (ast.op == "&") {
|
||||||
return genBAnd(ctx, ast);
|
return genBAnd(ctx, ast);
|
||||||
|
} else if (ast.op == "&&") {
|
||||||
|
return genAnd(ctx, ast);
|
||||||
|
} else if (ast.op == "||") {
|
||||||
|
return genOr(ctx, ast);
|
||||||
} else if (ast.op == "<<") {
|
} else if (ast.op == "<<") {
|
||||||
return genShl(ctx, ast);
|
return genShl(ctx, ast);
|
||||||
} else if (ast.op == ">>") {
|
} else if (ast.op == ">>") {
|
||||||
@@ -83,6 +93,8 @@ function gen(ctx, ast) {
|
|||||||
return genGte(ctx, ast);
|
return genGte(ctx, ast);
|
||||||
} else if (ast.op == "==") {
|
} else if (ast.op == "==") {
|
||||||
return genEq(ctx, ast);
|
return genEq(ctx, ast);
|
||||||
|
} else if (ast.op == "!=") {
|
||||||
|
return genNeq(ctx, ast);
|
||||||
} else if (ast.op == "?") {
|
} else if (ast.op == "?") {
|
||||||
return genTerCon(ctx, ast);
|
return genTerCon(ctx, ast);
|
||||||
} else {
|
} else {
|
||||||
@@ -135,7 +147,8 @@ function error(ctx, ast, errStr) {
|
|||||||
last_column: ast.last_column
|
last_column: ast.last_column
|
||||||
},
|
},
|
||||||
errStr: errStr,
|
errStr: errStr,
|
||||||
ast: ast
|
ast: ast,
|
||||||
|
message: errStr
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +235,7 @@ function genFunctionDef(ctx, ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function genFor(ctx, ast) {
|
function genFor(ctx, ast) {
|
||||||
|
ctx.scopes.push({});
|
||||||
const init = gen(ctx, ast.init);
|
const init = gen(ctx, ast.init);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
const condition = gen(ctx, ast.condition);
|
const condition = gen(ctx, ast.condition);
|
||||||
@@ -230,6 +244,7 @@ function genFor(ctx, ast) {
|
|||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
const body = gen(ctx, ast.body);
|
const body = gen(ctx, ast.body);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
ctx.scopes.pop();
|
||||||
return `for (${init};${condition};${step}) { \n${body}\n }\n`;
|
return `for (${init};${condition};${step}) { \n${body}\n }\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,9 +261,13 @@ function genIf(ctx, ast) {
|
|||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
const thenBody = gen(ctx, ast.then);
|
const thenBody = gen(ctx, ast.then);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
const elseBody = gen(ctx, ast.else);
|
if (ast.else) {
|
||||||
if (ctx.error) return;
|
const elseBody = gen(ctx, ast.else);
|
||||||
return `if (${condition}) {\n${thenBody}\n} else {\n${elseBody}\n}\n`;
|
if (ctx.error) return;
|
||||||
|
return `if (${condition}) {\n${thenBody}\n} else {\n${elseBody}\n}\n`;
|
||||||
|
} else {
|
||||||
|
return `if (${condition}) {\n${thenBody}\n}\n`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -310,7 +329,9 @@ function genVariable(ctx, ast) {
|
|||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!v) {
|
||||||
|
return error(ctx, ast, "Invalid left operand");
|
||||||
|
}
|
||||||
if (v.type == "VARIABLE") {
|
if (v.type == "VARIABLE") {
|
||||||
return `ctx.getVar("${ast.name}",[${sels.join(",")}])`;
|
return `ctx.getVar("${ast.name}",[${sels.join(",")}])`;
|
||||||
} else if (v.type == "SIGNAL") {
|
} else if (v.type == "SIGNAL") {
|
||||||
@@ -416,6 +437,14 @@ function genPlusPlusLeft(ctx, ast) {
|
|||||||
return genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "+", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]});
|
return genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "+", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function genMinusMinusRight(ctx, ast) {
|
||||||
|
return `(${genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "-", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]})}).add(__P__).sub(bigInt(1)).mod(__P__)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function genMinusMinusLeft(ctx, ast) {
|
||||||
|
return genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "-", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]});
|
||||||
|
}
|
||||||
|
|
||||||
function genAdd(ctx, ast) {
|
function genAdd(ctx, ast) {
|
||||||
const a = gen(ctx, ast.values[0]);
|
const a = gen(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -449,6 +478,15 @@ function genDiv(ctx, ast) {
|
|||||||
return `bigInt(${a}).mul( bigInt(${b}).inverse(__P__) ).mod(__P__)`;
|
return `bigInt(${a}).mul( bigInt(${b}).inverse(__P__) ).mod(__P__)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function genIDiv(ctx, ast) {
|
||||||
|
const a = gen(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
const b = gen(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
|
||||||
|
return `bigInt(${a}).div( bigInt(${b}))`;
|
||||||
|
}
|
||||||
|
|
||||||
function genExp(ctx, ast) {
|
function genExp(ctx, ast) {
|
||||||
const a = gen(ctx, ast.values[0]);
|
const a = gen(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -465,6 +503,22 @@ function genBAnd(ctx, ast) {
|
|||||||
return `bigInt(${a}).and(bigInt(${b})).and(__MASK__)`;
|
return `bigInt(${a}).and(bigInt(${b})).and(__MASK__)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function genAnd(ctx, ast) {
|
||||||
|
const a = gen(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
const b = gen(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
return `((bigInt(${a}).neq(bigInt(0)) && bigInt(${b}).neq(bigInt(0))) ? bigInt(1) : bigInt(0))`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function genOr(ctx, ast) {
|
||||||
|
const a = gen(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
const b = gen(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
return `((bigInt(${a}).neq(bigInt(0)) || bigInt(${b}).neq(bigInt(0))) ? bigInt(1) : bigInt(0))`;
|
||||||
|
}
|
||||||
|
|
||||||
function genShl(ctx, ast) {
|
function genShl(ctx, ast) {
|
||||||
const a = gen(ctx, ast.values[0]);
|
const a = gen(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -526,7 +580,15 @@ function genEq(ctx, ast) {
|
|||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
const b = gen(ctx, ast.values[1]);
|
const b = gen(ctx, ast.values[1]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
return `bigInt(${a}).eq(bigInt(${b})) ? 1 : 0`;
|
return `(bigInt(${a}).eq(bigInt(${b})) ? 1 : 0)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function genNeq(ctx, ast) {
|
||||||
|
const a = gen(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
const b = gen(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
return `(bigInt(${a}).eq(bigInt(${b})) ? 0 : 1)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function genUMinus(ctx, ast) {
|
function genUMinus(ctx, ast) {
|
||||||
|
|||||||
52
test/cases.js
Normal file
52
test/cases.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
const chai = require("chai");
|
||||||
|
const path = require("path");
|
||||||
|
const snarkjs = require("snarkjs");
|
||||||
|
|
||||||
|
const bigInt = snarkjs.bigInt;
|
||||||
|
|
||||||
|
const compiler = require("../index.js");
|
||||||
|
|
||||||
|
const assert = chai.assert;
|
||||||
|
|
||||||
|
async function assertThrowsAsync(fn, regExp) {
|
||||||
|
let f = () => {};
|
||||||
|
try {
|
||||||
|
await fn();
|
||||||
|
} catch(e) {
|
||||||
|
f = () => { throw e; };
|
||||||
|
} finally {
|
||||||
|
assert.throws(f, regExp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("Sum test", () => {
|
||||||
|
it("Should compile a code with an undefined if", async () => {
|
||||||
|
await compiler(path.join(__dirname, "circuits", "undefinedif.circom"));
|
||||||
|
});
|
||||||
|
it("Should compile a code with vars inside a for", async () => {
|
||||||
|
const cirDef = await compiler(path.join(__dirname, "circuits", "forvariables.circom"));
|
||||||
|
|
||||||
|
const circuit = new snarkjs.Circuit(cirDef);
|
||||||
|
|
||||||
|
const witness = circuit.calculateWitness({ "in": 111});
|
||||||
|
assert(witness[0].equals(bigInt(1)));
|
||||||
|
assert(witness[1].equals(bigInt(114)));
|
||||||
|
assert(witness[2].equals(bigInt(111)));
|
||||||
|
|
||||||
|
});
|
||||||
|
it("Should compile a code with an undefined if", async () => {
|
||||||
|
const cirDef = await compiler(path.join(__dirname, "circuits", "mixvarsignal.circom"));
|
||||||
|
|
||||||
|
const circuit = new snarkjs.Circuit(cirDef);
|
||||||
|
|
||||||
|
const witness = circuit.calculateWitness({ "i": 111});
|
||||||
|
assert(witness[0].equals(bigInt(1)));
|
||||||
|
assert(witness[1].equals(bigInt(111)));
|
||||||
|
assert(witness[2].equals(bigInt(111)));
|
||||||
|
});
|
||||||
|
// it("Should assign signal ERROR", async () => {
|
||||||
|
// await assertThrowsAsync(async () => {
|
||||||
|
// await compiler(path.join(__dirname, "circuits", "assignsignal.circom"));
|
||||||
|
// }, /Cannot assign to a signal .*/);
|
||||||
|
// });
|
||||||
|
});
|
||||||
7
test/circuits/assignsignal.circom
Normal file
7
test/circuits/assignsignal.circom
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
template A() {
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
out = 3; // This is an error that compile should detect
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = A();
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
include "../../circuits/sha256/constants.circom"
|
|
||||||
|
|
||||||
template A() {
|
|
||||||
signal input in;
|
|
||||||
component h0;
|
|
||||||
h0 = K(8);
|
|
||||||
|
|
||||||
var lc = 0;
|
|
||||||
var e = 1;
|
|
||||||
for (var i=0; i<32; i++) {
|
|
||||||
lc = lc + e*h0.out[i];
|
|
||||||
e *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
lc === in;
|
|
||||||
}
|
|
||||||
|
|
||||||
component main = A();
|
|
||||||
12
test/circuits/declareandistantiate.circom
Normal file
12
test/circuits/declareandistantiate.circom
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template A() {
|
||||||
|
signal a;
|
||||||
|
}
|
||||||
|
|
||||||
|
template B() {
|
||||||
|
component a[2] = A();
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = B();
|
||||||
19
test/circuits/forvariables.circom
Normal file
19
test/circuits/forvariables.circom
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
template A() {
|
||||||
|
signal input in;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
var acc = 0;
|
||||||
|
for (var i=0; i<3; i++) {
|
||||||
|
if (i==1) {
|
||||||
|
var accIn = 0;
|
||||||
|
for (var j=0; j<3; j++) {
|
||||||
|
accIn= accIn+1;
|
||||||
|
}
|
||||||
|
acc = acc + accIn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out <== in + acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = A();
|
||||||
14
test/circuits/mixvarsignal.circom
Normal file
14
test/circuits/mixvarsignal.circom
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
template X() {
|
||||||
|
signal input i;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
var r = 0;
|
||||||
|
for (var n=0; n<i; n++) {
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i === r;
|
||||||
|
out <== r;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = X();
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +0,0 @@
|
|||||||
include "../../circuits/sha256/sha256_2.circom";
|
|
||||||
|
|
||||||
template Main() {
|
|
||||||
signal private input a;
|
|
||||||
signal private input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
component sha256_2 = Sha256_2();
|
|
||||||
|
|
||||||
sha256_2.a <== a;
|
|
||||||
sha256_2.b <== b;
|
|
||||||
out <== sha256_2.out;
|
|
||||||
}
|
|
||||||
|
|
||||||
component main = Main();
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
include "../../circuits/sha256/bitify.circom"
|
|
||||||
include "../../circuits/sha256/binsum.circom"
|
|
||||||
|
|
||||||
template A() {
|
|
||||||
signal private input a;
|
|
||||||
signal input b;
|
|
||||||
signal output out;
|
|
||||||
|
|
||||||
component n2ba = Num2Bits(32);
|
|
||||||
component n2bb = Num2Bits(32);
|
|
||||||
component sum = BinSum(32,2);
|
|
||||||
component b2n = Bits2Num(32);
|
|
||||||
|
|
||||||
n2ba.in <== a;
|
|
||||||
n2bb.in <== b;
|
|
||||||
|
|
||||||
for (var i=0; i<32; i++) {
|
|
||||||
sum.in[0][i] <== n2ba.out[i];
|
|
||||||
sum.in[1][i] <== n2bb.out[i];
|
|
||||||
b2n.in[i] <== sum.out[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
out <== b2n.out;
|
|
||||||
}
|
|
||||||
|
|
||||||
component main = A();
|
|
||||||
14
test/circuits/undefinedif.circom
Normal file
14
test/circuits/undefinedif.circom
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
template X() {
|
||||||
|
signal input i;
|
||||||
|
signal input j;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
out <-- i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out <-- j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = X();
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
/* SHA-256 (FIPS 180-4) implementation in JavaScript (c) Chris Veness 2002-2017 */
|
|
||||||
/* MIT Licence */
|
|
||||||
/* www.movable-type.co.uk/scripts/sha256.html */
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SHA-256 hash function reference implementation.
|
|
||||||
*
|
|
||||||
* This is an annotated direct implementation of FIPS 180-4, without any optimisations. It is
|
|
||||||
* intended to aid understanding of the algorithm rather than for production use.
|
|
||||||
*
|
|
||||||
* While it could be used where performance is not critical, I would recommend using the ‘Web
|
|
||||||
* Cryptography API’ (developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest) for the browser,
|
|
||||||
* or the ‘crypto’ library (nodejs.org/api/crypto.html#crypto_class_hash) in Node.js.
|
|
||||||
*
|
|
||||||
* See csrc.nist.gov/groups/ST/toolkit/secure_hashing.html
|
|
||||||
* csrc.nist.gov/groups/ST/toolkit/examples.html
|
|
||||||
*/
|
|
||||||
class Sha256 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates SHA-256 hash of string.
|
|
||||||
*
|
|
||||||
* @param {string} msg - (Unicode) string to be hashed.
|
|
||||||
* @param {Object} [options]
|
|
||||||
* @param {string} [options.msgFormat=string] - Message format: 'string' for JavaScript string
|
|
||||||
* (gets converted to UTF-8 for hashing); 'hex-bytes' for string of hex bytes ('616263' ≡ 'abc') .
|
|
||||||
* @param {string} [options.outFormat=hex] - Output format: 'hex' for string of contiguous
|
|
||||||
* hex bytes; 'hex-w' for grouping hex bytes into groups of (4 byte / 8 character) words.
|
|
||||||
* @returns {string} Hash of msg as hex character string.
|
|
||||||
*/
|
|
||||||
static hash(msg, options) {
|
|
||||||
const defaults = { msgFormat: 'string', outFormat: 'hex' };
|
|
||||||
const opt = Object.assign(defaults, options);
|
|
||||||
|
|
||||||
// note use throughout this routine of 'n >>> 0' to coerce Number 'n' to unsigned 32-bit integer
|
|
||||||
|
|
||||||
switch (opt.msgFormat) {
|
|
||||||
default: // default is to convert string to UTF-8, as SHA only deals with byte-streams
|
|
||||||
case 'string': msg = utf8Encode(msg); break;
|
|
||||||
case 'hex-bytes':msg = hexBytesToString(msg); break; // mostly for running tests
|
|
||||||
}
|
|
||||||
|
|
||||||
// constants [§4.2.2]
|
|
||||||
const K = [
|
|
||||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
||||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
||||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
||||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
||||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
||||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
||||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
||||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ];
|
|
||||||
|
|
||||||
// initial hash value [§5.3.3]
|
|
||||||
const H = [
|
|
||||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ];
|
|
||||||
|
|
||||||
// PREPROCESSING [§6.2.1]
|
|
||||||
|
|
||||||
msg += String.fromCharCode(0x80); // add trailing '1' bit (+ 0's padding) to string [§5.1.1]
|
|
||||||
|
|
||||||
// convert string msg into 512-bit blocks (array of 16 32-bit integers) [§5.2.1]
|
|
||||||
const l = msg.length/4 + 2; // length (in 32-bit integers) of msg + ‘1’ + appended length
|
|
||||||
const N = Math.ceil(l/16); // number of 16-integer (512-bit) blocks required to hold 'l' ints
|
|
||||||
const M = new Array(N); // message M is N×16 array of 32-bit integers
|
|
||||||
|
|
||||||
for (let i=0; i<N; i++) {
|
|
||||||
M[i] = new Array(16);
|
|
||||||
for (let j=0; j<16; j++) { // encode 4 chars per integer (64 per block), big-endian encoding
|
|
||||||
M[i][j] = (msg.charCodeAt(i*64+j*4+0)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16)
|
|
||||||
| (msg.charCodeAt(i*64+j*4+2)<< 8) | (msg.charCodeAt(i*64+j*4+3)<< 0);
|
|
||||||
} // note running off the end of msg is ok 'cos bitwise ops on NaN return 0
|
|
||||||
}
|
|
||||||
// add length (in bits) into final pair of 32-bit integers (big-endian) [§5.1.1]
|
|
||||||
// note: most significant word would be (len-1)*8 >>> 32, but since JS converts
|
|
||||||
// bitwise-op args to 32 bits, we need to simulate this by arithmetic operators
|
|
||||||
const lenHi = ((msg.length-1)*8) / Math.pow(2, 32);
|
|
||||||
const lenLo = ((msg.length-1)*8) >>> 0;
|
|
||||||
M[N-1][14] = Math.floor(lenHi);
|
|
||||||
M[N-1][15] = lenLo;
|
|
||||||
|
|
||||||
// HASH COMPUTATION [§6.2.2]
|
|
||||||
|
|
||||||
for (let i=0; i<N; i++) {
|
|
||||||
const W = new Array(64);
|
|
||||||
|
|
||||||
// 1 - prepare message schedule 'W'
|
|
||||||
for (let t=0; t<16; t++) W[t] = M[i][t];
|
|
||||||
for (let t=16; t<64; t++) {
|
|
||||||
W[t] = (Sha256.σ1(W[t-2]) + W[t-7] + Sha256.σ0(W[t-15]) + W[t-16]) >>> 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 - initialise working variables a, b, c, d, e, f, g, h with previous hash value
|
|
||||||
let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];
|
|
||||||
|
|
||||||
// 3 - main loop (note '>>> 0' for 'addition modulo 2^32')
|
|
||||||
for (let t=0; t<64; t++) {
|
|
||||||
const T1 = h + Sha256.Σ1(e) + Sha256.Ch(e, f, g) + K[t] + W[t];
|
|
||||||
const T2 = Sha256.Σ0(a) + Sha256.Maj(a, b, c);
|
|
||||||
h = g;
|
|
||||||
g = f;
|
|
||||||
f = e;
|
|
||||||
e = (d + T1) >>> 0;
|
|
||||||
d = c;
|
|
||||||
c = b;
|
|
||||||
b = a;
|
|
||||||
a = (T1 + T2) >>> 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4 - compute the new intermediate hash value (note '>>> 0' for 'addition modulo 2^32')
|
|
||||||
H[0] = (H[0]+a) >>> 0;
|
|
||||||
H[1] = (H[1]+b) >>> 0;
|
|
||||||
H[2] = (H[2]+c) >>> 0;
|
|
||||||
H[3] = (H[3]+d) >>> 0;
|
|
||||||
H[4] = (H[4]+e) >>> 0;
|
|
||||||
H[5] = (H[5]+f) >>> 0;
|
|
||||||
H[6] = (H[6]+g) >>> 0;
|
|
||||||
H[7] = (H[7]+h) >>> 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert H0..H7 to hex strings (with leading zeros)
|
|
||||||
for (let h=0; h<H.length; h++) H[h] = ('00000000'+H[h].toString(16)).slice(-8);
|
|
||||||
|
|
||||||
// concatenate H0..H7, with separator if required
|
|
||||||
const separator = opt.outFormat=='hex-w' ? ' ' : '';
|
|
||||||
|
|
||||||
return H.join(separator);
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
function utf8Encode(str) {
|
|
||||||
try {
|
|
||||||
return new TextEncoder().encode(str, 'utf-8').reduce((prev, curr) => prev + String.fromCharCode(curr), '');
|
|
||||||
} catch (e) { // no TextEncoder available?
|
|
||||||
return unescape(encodeURIComponent(str)); // monsur.hossa.in/2012/07/20/utf-8-in-javascript.html
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function hexBytesToString(hexStr) { // convert string of hex numbers to a string of chars (eg '616263' -> 'abc').
|
|
||||||
const str = hexStr.replace(' ', ''); // allow space-separated groups
|
|
||||||
return str=='' ? '' : str.match(/.{2}/g).map(byte => String.fromCharCode(parseInt(byte, 16))).join('');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rotates right (circular right shift) value x by n positions [§3.2.4].
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
static ROTR(n, x) {
|
|
||||||
return (x >>> n) | (x << (32-n));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logical functions [§4.1.2].
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
static Σ0(x) { return Sha256.ROTR(2, x) ^ Sha256.ROTR(13, x) ^ Sha256.ROTR(22, x); }
|
|
||||||
static Σ1(x) { return Sha256.ROTR(6, x) ^ Sha256.ROTR(11, x) ^ Sha256.ROTR(25, x); }
|
|
||||||
static σ0(x) { return Sha256.ROTR(7, x) ^ Sha256.ROTR(18, x) ^ (x>>>3); }
|
|
||||||
static σ1(x) { return Sha256.ROTR(17, x) ^ Sha256.ROTR(19, x) ^ (x>>>10); }
|
|
||||||
static Ch(x, y, z) { return (x & y) ^ (~x & z); } // 'choice'
|
|
||||||
static Maj(x, y, z) { return (x & y) ^ (x & z) ^ (y & z); } // 'majority'
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
if (typeof module != 'undefined' && module.exports) module.exports = Sha256; // ≡ export default Sha256
|
|
||||||
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"a": "111",
|
|
||||||
"b": "222"
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
const chai = require("chai");
|
|
||||||
const path = require("path");
|
|
||||||
const snarkjs = require("snarkjs");
|
|
||||||
const crypto = require("crypto");
|
|
||||||
|
|
||||||
const compiler = require("../index.js");
|
|
||||||
|
|
||||||
const assert = chai.assert;
|
|
||||||
|
|
||||||
const sha256 = require("./helpers/sha256");
|
|
||||||
const bigInt = require("big-integer");
|
|
||||||
|
|
||||||
function hexBits(cir, witness, sig, nBits) {
|
|
||||||
let v = bigInt(0);
|
|
||||||
for (let i=nBits-1; i>=0; i--) {
|
|
||||||
v = v.shiftLeft(1);
|
|
||||||
const name = sig+"["+i+"]";
|
|
||||||
const idx = cir.getSignalIdx(name);
|
|
||||||
const vbit = bigInt(witness[idx].toString());
|
|
||||||
if (vbit.equals(bigInt(1))) {
|
|
||||||
v = v.add(bigInt(1));
|
|
||||||
} else if (vbit.equals(bigInt(0))) {
|
|
||||||
v;
|
|
||||||
} else {
|
|
||||||
console.log("Not Binary: "+name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v.toString(16);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("SHA256 test", () => {
|
|
||||||
it("Should create a constant circuit", async () => {
|
|
||||||
|
|
||||||
const cirDef = await compiler(path.join(__dirname, "circuits", "constants_test.circom"));
|
|
||||||
assert.equal(cirDef.nVars, 2);
|
|
||||||
|
|
||||||
const circuit = new snarkjs.Circuit(cirDef);
|
|
||||||
|
|
||||||
const witness = circuit.calculateWitness({ "in": "0xd807aa98" });
|
|
||||||
|
|
||||||
assert(witness[0].equals(snarkjs.bigInt(1)));
|
|
||||||
assert(witness[1].equals(snarkjs.bigInt("0xd807aa98")));
|
|
||||||
});
|
|
||||||
it("Should create a sum circuit", async () => {
|
|
||||||
|
|
||||||
const cirDef = await compiler(path.join(__dirname, "circuits", "sum_test.circom"));
|
|
||||||
assert.equal(cirDef.nVars, 101);
|
|
||||||
|
|
||||||
const circuit = new snarkjs.Circuit(cirDef);
|
|
||||||
|
|
||||||
const witness = circuit.calculateWitness({ "a": "111", "b": "222" });
|
|
||||||
|
|
||||||
assert(witness[0].equals(snarkjs.bigInt(1)));
|
|
||||||
assert(witness[1].equals(snarkjs.bigInt("333")));
|
|
||||||
});
|
|
||||||
it("Should calculate a hash", async () => {
|
|
||||||
const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_2_test.circom"));
|
|
||||||
const circuit = new snarkjs.Circuit(cirDef);
|
|
||||||
|
|
||||||
console.log("Vars: "+circuit.nVars);
|
|
||||||
console.log("Constraints: "+circuit.nConstraints);
|
|
||||||
|
|
||||||
const witness = circuit.calculateWitness({ "a": "1", "b": "2" });
|
|
||||||
|
|
||||||
const b = new Buffer.alloc(54);
|
|
||||||
b[26] = 1;
|
|
||||||
b[53] = 2;
|
|
||||||
|
|
||||||
const hash = crypto.createHash("sha256")
|
|
||||||
.update(b)
|
|
||||||
.digest("hex");
|
|
||||||
const r = "0x" + hash.slice(10);
|
|
||||||
|
|
||||||
const hash2 = sha256.hash(b.toString("hex"), {msgFormat: "hex-bytes"});
|
|
||||||
|
|
||||||
assert.equal(hash, hash2);
|
|
||||||
|
|
||||||
assert(witness[1].equals(snarkjs.bigInt(r)));
|
|
||||||
}).timeout(1000000);
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user