Compare commits

..

25 Commits

Author SHA1 Message Date
Jordi Baylina
d35d438107 0.0.20 2018-11-11 19:50:40 +01:00
Jordi Baylina
5b45bafaac Array params in templates 2018-11-11 19:50:26 +01:00
Jordi Baylina
dcfb9ab8b4 0.0.19 2018-10-29 07:09:54 +01:00
Jordi Baylina
bfdf17fd89 Fix undefined if 2018-10-29 07:09:28 +01:00
Jordi Baylina
9d0b27a7e8 Tests added and Comparators 2018-10-26 17:34:02 +02:00
Jordi Baylina
4d79038fd8 0.0.18 2018-10-25 17:04:13 +02:00
Jordi Baylina
95755c4afe remove more memory 2018-10-25 17:04:01 +02:00
Jordi Baylina
afc60ec033 0.0.17 2018-10-25 10:25:39 +02:00
Jordi Baylina
77393e2d0c Increase memory in cli.js 2018-10-25 10:25:32 +02:00
Jordi Baylina
2db08a0a34 0.0.16 2018-10-25 09:44:34 +02:00
Jordi Baylina
23255de508 deps 2018-10-25 09:44:14 +02:00
Jordi Baylina
7c03ae4033 0.0.15 2018-10-24 20:28:08 +02:00
Jordi Baylina
5e58584a01 Verbose and error if main is not defined 2018-10-24 20:27:34 +02:00
Jordi Baylina
cb9a5b536e 0.0.14 2018-10-24 20:06:09 +02:00
Jordi Baylina
70c88be334 One and only one file compilation at a time 2018-10-24 20:05:50 +02:00
Jordi Baylina
25759e53cd 0.0.13 2018-10-24 20:00:07 +02:00
Jordi Baylina
4fa0c79e26 If without else 2018-10-24 19:59:50 +02:00
Jordi Baylina
e685392523 Fix title in readme 2018-10-23 08:06:23 +02:00
Jordi Baylina
e81c4f1331 0.0.12 2018-10-22 08:36:49 +02:00
Jordi Baylina
483c9c0c26 deps 2018-10-22 08:36:43 +02:00
Jordi Baylina
eb1834833d 0.0.11 2018-10-22 07:00:00 +02:00
Jordi Baylina
49a6120eeb Cli parameters standarized to C 2018-10-22 06:59:47 +02:00
Jordi Baylina
b91eb93389 0.0.10 2018-10-21 20:31:43 +02:00
Jordi Baylina
01e0f97239 Dependencies 2018-10-21 20:31:32 +02:00
Jordi Baylina
99a7489fa2 Some fixes and new version 2018-10-21 19:44:19 +02:00
46 changed files with 1053 additions and 2912 deletions

View File

@@ -1,4 +1,4 @@
# Circon # Circom
Circon is a language designed to write arithmetic circuits that can be used in zero knowledge proofs. Circon is a language designed to write arithmetic circuits that can be used in zero knowledge proofs.

View File

@@ -1,3 +1,22 @@
/*
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 Binary Sum

72
circuits/bitify.circom Normal file
View File

@@ -0,0 +1,72 @@
/*
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 "comparators.circom";
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;
}
template Num2BitsNeg(n) {
signal input in;
signal output out[n];
var lc1=0;
component isZero;
isZero = IsZero();
var neg = n == 0 ? 0 : 2**n - in;
for (var i = 0; i<n; i++) {
out[i] <-- (neg >> i) & 1;
out[i] * (out[i] -1 ) === 0;
lc1 += out[i] * 2**i;
}
in ==> isZero.in;
lc1 + isZero.out * 2**n === 2**n - in;
}

View File

@@ -0,0 +1,55 @@
include "bitify.circom";
include "binsum.circom";
template IsZero() {
signal input in;
signal output out;
signal inv;
inv <-- in!=0 ? 1/in : 0;
out <== -in*inv +1;
in*out === 0;
}
template IsEqual() {
signal input in[2];
signal output out;
component isz = IsZero();
in[1] - in[0] ==> isz.in;
isz.out ==> out;
}
// N is the number of bits the input have.
// The MSF is the sign bit.
template LessThan(n) {
signal input in[2];
signal output out;
component num2Bits0;
component num2Bits1;
component adder;
adder = BinSum(n, 2);
num2Bits0 = Num2Bits(n);
num2Bits1 = Num2BitsNeg(n);
in[0] ==> num2Bits0.in;
in[1] ==> num2Bits1.in;
var i;
for (i=0;i<n;i++) {
num2Bits0.out[i] ==> adder.in[0][i];
num2Bits1.out[i] ==> adder.in[1][i];
}
adder.out[n-1] ==> out;
}

View File

@@ -1,3 +1,21 @@
/*
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() { template XOR() {
signal input a; signal input a;

View File

@@ -1,3 +1,22 @@
/*
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
// <-- Assignation without constraint // <-- Assignation without constraint
// === Constraint // === Constraint

View File

@@ -1,28 +0,0 @@
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;
}

View File

@@ -1,3 +1,22 @@
/*
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 /* Ch
000 0 000 0

View File

@@ -1,4 +1,21 @@
/*
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) { template H(x) {
signal output out[32]; signal output out[32];

View File

@@ -1,49 +0,0 @@
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;
}

View File

@@ -1,3 +1,22 @@
/*
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"; include "sha256_2.jaz";
template Main() { template Main() {

View File

@@ -1,3 +1,22 @@
/*
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 /* Maj function for sha256
out = a&b ^ a&c ^ b&c => out = a&b ^ a&c ^ b&c =>

View File

@@ -1,4 +1,21 @@
/*
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) { template RotR(n, r) {
signal input in[n]; signal input in[n];

View File

@@ -1,6 +1,24 @@
/*
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 "sha256compression.circom";
include "bitify.circom" include "../bitify.circom"
template Sha256_2() { template Sha256_2() {
signal input a; signal input a;

View File

@@ -1,8 +1,26 @@
/*
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 "constants.circom";
include "t1.circom"; include "t1.circom";
include "t2.circom"; include "t2.circom";
include "binsum.circom"; include "../binsum.circom";
include "sigmaplus.circom"; include "sigmaplus.circom";
template Sha256compression() { template Sha256compression() {

View File

@@ -1,3 +1,21 @@
/*
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) { template ShR(n, r) {
signal input in[n]; signal input in[n];

View File

@@ -1,3 +1,22 @@
/*
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 "xor3.circom";
include "rotate.circom"; include "rotate.circom";
include "shift.circom"; include "shift.circom";

View File

@@ -1,4 +1,23 @@
include "binsum.circom" /*
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 "sigma.circom"
template SigmaPlus() { template SigmaPlus() {

View File

@@ -1,4 +1,23 @@
include "binsum.circom"; /*
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 "sigma.circom";
include "ch.circom"; include "ch.circom";

View File

@@ -1,4 +1,23 @@
include "binsum.circom"; /*
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 "sigma.circom";
include "maj.circom" include "maj.circom"

View File

@@ -1,3 +1,22 @@
/*
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 /* Xor3 function for sha256
out = a ^ b ^ c => out = a ^ b ^ c =>

View File

@@ -1,4 +1,21 @@
/*
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) { template toBin(n) {

43
cli.js
View File

@@ -3,20 +3,20 @@
/* /*
Copyright 2018 0KIMS association. Copyright 2018 0KIMS association.
This file is part of jaz (Zero Knowledge Circuit Compiler). This file is part of circom (Zero Knowledge Circuit Compiler).
jaz is a free software: you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
jaz is distributed in the hope that it will be useful, but WITHOUT circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details. License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with jaz. If not, see <https://www.gnu.org/licenses/>. along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ */
/* eslint-disable no-console */ /* eslint-disable no-console */
@@ -30,13 +30,11 @@ const version = require("./package").version;
const argv = require("yargs") const argv = require("yargs")
.version(version) .version(version)
.usage("circom -s [input source circuit file] -o [output definition circuit file]") .usage("circom [input source circuit file] -o [output definition circuit file]")
.alias("s", "source")
.alias("o", "output") .alias("o", "output")
.alias("c", "cfile")
.require(["s","o"])
.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
@@ -44,14 +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.source);
compiler(fullFileName, argv.cfile).then( (cir) => { let inputFile;
fs.writeFileSync(argv.output, JSON.stringify(cir, null, 1), "utf8"); 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";
compiler(fullFileName).then( (cir) => {
fs.writeFileSync(outName, JSON.stringify(cir, null, 1), "utf8");
process.exit(0);
}, (err) => { }, (err) => {
console.log(err); // console.log(err);
console.log(err.stack);
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}`); 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)); console.error(JSON.stringify(err.ast, null, 1));
}
process.exit(1); process.exit(1);
}); });

83
out.c
View File

@@ -1,83 +0,0 @@
// File: ../../circuits/sha256/bitify.circom
function Num2Bits(ctx)
{
ctx.setVar("lc1", [], "0");
for (ctx.setVar("i", [], "0");bigInt(ctx.getVar("i",[])).lt(bigInt(ctx.getVar("n",[]))) ? 1 : 0;(ctx.setVar("i", [], bigInt(ctx.getVar("i",[])).add(bigInt("1")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__))
{
ctx.setSignal("out", [ctx.getVar("i",[])], bigInt(bigInt(ctx.getVar("i",[])).greater(bigInt(256)) ? 0 : bigInt(ctx.getSignal("in", [])).shr(bigInt(ctx.getVar("i",[]))).and(__MASK__)).and(bigInt("1")).and(__MASK__));
ctx.assert(bigInt(ctx.getSignal("out", [ctx.getVar("i",[])])).mul(bigInt(bigInt(ctx.getSignal("out", [ctx.getVar("i",[])])).add(__P__).sub(bigInt("1")).mod(__P__))).mod(__P__), "0");
ctx.setVar("lc1", [], bigInt(ctx.getVar("lc1",[])).add(bigInt(bigInt(ctx.getSignal("out", [ctx.getVar("i",[])])).mul(bigInt(bigInt("2").modPow(bigInt(ctx.getVar("i",[])), __P__))).mod(__P__))).mod(__P__));
}
ctx.assert(ctx.getVar("lc1",[]), ctx.getSignal("in", []));
}
function Bits2Num(ctx)
{
ctx.setVar("lc1", [], "0");
for (ctx.setVar("i", [], "0");bigInt(ctx.getVar("i",[])).lt(bigInt(ctx.getVar("n",[]))) ? 1 : 0;(ctx.setVar("i", [], bigInt(ctx.getVar("i",[])).add(bigInt("1")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__))
{
ctx.setVar("lc1", [], bigInt(ctx.getVar("lc1",[])).add(bigInt(bigInt(ctx.getSignal("in", [ctx.getVar("i",[])])).mul(bigInt(bigInt("2").modPow(bigInt(ctx.getVar("i",[])), __P__))).mod(__P__))).mod(__P__));
}
ctx.setSignal("out", [], ctx.getVar("lc1",[]));
ctx.assert(ctx.getSignal("out", []), ctx.getVar("lc1",[]));
}
// File: ../../circuits/sha256/binsum.circom
function nbits(ctx) {
ctx.setVar("n", [], "1");
ctx.setVar("r", [], "0");
while (bigInt(bigInt(ctx.getVar("n",[])).add(__P__).sub(bigInt("1")).mod(__P__)).lt(bigInt(ctx.getVar("a",[]))) ? 1 : 0) {
(ctx.setVar("r", [], bigInt(ctx.getVar("r",[])).add(bigInt("1")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__);
ctx.setVar("n", [], bigInt(ctx.getVar("n",[])).mul(bigInt("2")).mod(__P__));
}
return ctx.getVar("r",[]);;
}
function BinSum(ctx)
{
ctx.setVar("nout", [], ctx.callFunction("nbits", [bigInt(bigInt(bigInt("2").modPow(bigInt(ctx.getVar("n",[])), __P__)).add(__P__).sub(bigInt("1")).mod(__P__)).mul(bigInt(ctx.getVar("ops",[]))).mod(__P__)]));
ctx.setVar("lin", [], "0");
ctx.setVar("lout", [], "0");
for (ctx.setVar("k", [], "0");bigInt(ctx.getVar("k",[])).lt(bigInt(ctx.getVar("n",[]))) ? 1 : 0;(ctx.setVar("k", [], bigInt(ctx.getVar("k",[])).add(bigInt("1")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__))
{
for (ctx.setVar("j", [], "0");bigInt(ctx.getVar("j",[])).lt(bigInt(ctx.getVar("ops",[]))) ? 1 : 0;(ctx.setVar("j", [], bigInt(ctx.getVar("j",[])).add(bigInt("1")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__))
{
ctx.setVar("lin", [], bigInt(ctx.getVar("lin",[])).add(bigInt(bigInt(ctx.getSignal("in", [ctx.getVar("j",[]),ctx.getVar("k",[])])).mul(bigInt(bigInt("2").modPow(bigInt(ctx.getVar("k",[])), __P__))).mod(__P__))).mod(__P__));
}
}
for (ctx.setVar("k", [], "0");bigInt(ctx.getVar("k",[])).lt(bigInt(ctx.getVar("nout",[]))) ? 1 : 0;(ctx.setVar("k", [], bigInt(ctx.getVar("k",[])).add(bigInt("1")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__))
{
ctx.setSignal("out", [ctx.getVar("k",[])], bigInt(bigInt(ctx.getVar("k",[])).greater(bigInt(256)) ? 0 : bigInt(ctx.getVar("lin",[])).shr(bigInt(ctx.getVar("k",[]))).and(__MASK__)).and(bigInt("1")).and(__MASK__));
ctx.assert(bigInt(ctx.getSignal("out", [ctx.getVar("k",[])])).mul(bigInt(bigInt(ctx.getSignal("out", [ctx.getVar("k",[])])).add(__P__).sub(bigInt("1")).mod(__P__))).mod(__P__), "0");
ctx.setVar("lout", [], bigInt(ctx.getVar("lout",[])).add(bigInt(bigInt(ctx.getSignal("out", [ctx.getVar("k",[])])).mul(bigInt(bigInt("2").modPow(bigInt(ctx.getVar("k",[])), __P__))).mod(__P__))).mod(__P__));
}
ctx.assert(ctx.getVar("lin",[]), ctx.getVar("lout",[]));
}
function A(ctx)
{
ctx.setPin("n2ba", [], "in", [], ctx.getSignal("a", []));
ctx.assert(ctx.getPin("n2ba", [], "in", []), ctx.getSignal("a", []));
ctx.setPin("n2bb", [], "in", [], ctx.getSignal("b", []));
ctx.assert(ctx.getPin("n2bb", [], "in", []), ctx.getSignal("b", []));
for (ctx.setVar("i", [], "0");bigInt(ctx.getVar("i",[])).lt(bigInt("32")) ? 1 : 0;(ctx.setVar("i", [], bigInt(ctx.getVar("i",[])).add(bigInt("1")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__))
{
ctx.setPin("sum", [], "in", ["0",ctx.getVar("i",[])], ctx.getPin("n2ba", [], "out", [ctx.getVar("i",[])]));
ctx.assert(ctx.getPin("sum", [], "in", ["0",ctx.getVar("i",[])]), ctx.getPin("n2ba", [], "out", [ctx.getVar("i",[])]));
ctx.setPin("sum", [], "in", ["1",ctx.getVar("i",[])], ctx.getPin("n2bb", [], "out", [ctx.getVar("i",[])]));
ctx.assert(ctx.getPin("sum", [], "in", ["1",ctx.getVar("i",[])]), ctx.getPin("n2bb", [], "out", [ctx.getVar("i",[])]));
ctx.setPin("b2n", [], "in", [ctx.getVar("i",[])], ctx.getPin("sum", [], "out", [ctx.getVar("i",[])]));
ctx.assert(ctx.getPin("b2n", [], "in", [ctx.getVar("i",[])]), ctx.getPin("sum", [], "out", [ctx.getVar("i",[])]));
}
ctx.setSignal("out", [], ctx.getPin("b2n", [], "out", []));
ctx.assert(ctx.getSignal("out", []), ctx.getPin("b2n", [], "out", []));
}

2341
out.cir

File diff suppressed because one or more lines are too long

359
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "circom", "name": "circom",
"version": "0.0.7", "version": "0.0.20",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@@ -1468,6 +1468,185 @@
"is-fullwidth-code-point": "^2.0.0" "is-fullwidth-code-point": "^2.0.0"
} }
}, },
"snarkjs": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.5.tgz",
"integrity": "sha512-4GiP60ONIitWRnC5+Gsl7nIO62fvkGN9Y9jsDWBKORZI34eNXJBrMjhCbT+0X57FS2XjY0MsR0/Qvg2cs1H0sQ==",
"dev": true,
"requires": {
"big-integer": "^1.6.35",
"chai": "^4.1.2",
"eslint": "^5.3.0",
"yargs": "^12.0.2"
},
"dependencies": {
"ajv": {
"version": "6.5.5",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz",
"integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"big-integer": {
"version": "1.6.36",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz",
"integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==",
"dev": true
},
"chardet": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"debug": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
"integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eslint": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.9.0.tgz",
"integrity": "sha512-g4KWpPdqN0nth+goDNICNXGfJF7nNnepthp46CAlJoJtC5K/cLu3NgCM3AHu1CkJ5Hzt9V0Y0PBAO6Ay/gGb+w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"ajv": "^6.5.3",
"chalk": "^2.1.0",
"cross-spawn": "^6.0.5",
"debug": "^4.0.1",
"doctrine": "^2.1.0",
"eslint-scope": "^4.0.0",
"eslint-utils": "^1.3.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^4.0.0",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^2.0.0",
"functional-red-black-tree": "^1.0.1",
"glob": "^7.1.2",
"globals": "^11.7.0",
"ignore": "^4.0.6",
"imurmurhash": "^0.1.4",
"inquirer": "^6.1.0",
"is-resolvable": "^1.1.0",
"js-yaml": "^3.12.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.5",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"path-is-inside": "^1.0.2",
"pluralize": "^7.0.0",
"progress": "^2.0.0",
"regexpp": "^2.0.1",
"require-uncached": "^1.0.3",
"semver": "^5.5.1",
"strip-ansi": "^4.0.0",
"strip-json-comments": "^2.0.1",
"table": "^5.0.2",
"text-table": "^0.2.0"
}
},
"external-editor": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
"integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
"dev": true,
"requires": {
"chardet": "^0.7.0",
"iconv-lite": "^0.4.24",
"tmp": "^0.0.33"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"inquirer": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
"integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
"dev": true,
"requires": {
"ansi-escapes": "^3.0.0",
"chalk": "^2.0.0",
"cli-cursor": "^2.1.0",
"cli-width": "^2.0.0",
"external-editor": "^3.0.0",
"figures": "^2.0.0",
"lodash": "^4.17.10",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rxjs": "^6.1.0",
"string-width": "^2.1.0",
"strip-ansi": "^4.0.0",
"through": "^2.3.6"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
},
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
"dev": true
},
"rxjs": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
"integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
}
},
"semver": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
"dev": true
},
"table": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz",
"integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==",
"dev": true,
"requires": {
"ajv": "^6.5.3",
"lodash": "^4.17.10",
"slice-ansi": "1.0.0",
"string-width": "^2.1.1"
}
}
}
},
"source-map": { "source-map": {
"version": "0.1.43", "version": "0.1.43",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
@@ -1721,184 +1900,6 @@
"requires": { "requires": {
"camelcase": "^4.1.0" "camelcase": "^4.1.0"
} }
},
"zksnark": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/zksnark/-/zksnark-0.0.11.tgz",
"integrity": "sha512-YIOk93pLvc8NDVvedB0SDM1kGjPTdTYC/sgAvc9Dm6qMSYnS7tzCr844QaUlMApFTldz7D/6xlF1l24ttTGLXw==",
"dev": true,
"requires": {
"big-integer": "^1.6.35",
"chai": "^4.1.2",
"eslint": "^5.3.0"
},
"dependencies": {
"ajv": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
"integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"big-integer": {
"version": "1.6.36",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz",
"integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==",
"dev": true
},
"chardet": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"debug": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
"integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eslint": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.7.0.tgz",
"integrity": "sha512-zYCeFQahsxffGl87U2aJ7DPyH8CbWgxBC213Y8+TCanhUTf2gEvfq3EKpHmEcozTLyPmGe9LZdMAwC/CpJBM5A==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"ajv": "^6.5.3",
"chalk": "^2.1.0",
"cross-spawn": "^6.0.5",
"debug": "^4.0.1",
"doctrine": "^2.1.0",
"eslint-scope": "^4.0.0",
"eslint-utils": "^1.3.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^4.0.0",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^2.0.0",
"functional-red-black-tree": "^1.0.1",
"glob": "^7.1.2",
"globals": "^11.7.0",
"ignore": "^4.0.6",
"imurmurhash": "^0.1.4",
"inquirer": "^6.1.0",
"is-resolvable": "^1.1.0",
"js-yaml": "^3.12.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.5",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"path-is-inside": "^1.0.2",
"pluralize": "^7.0.0",
"progress": "^2.0.0",
"regexpp": "^2.0.1",
"require-uncached": "^1.0.3",
"semver": "^5.5.1",
"strip-ansi": "^4.0.0",
"strip-json-comments": "^2.0.1",
"table": "^5.0.2",
"text-table": "^0.2.0"
}
},
"external-editor": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
"integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
"dev": true,
"requires": {
"chardet": "^0.7.0",
"iconv-lite": "^0.4.24",
"tmp": "^0.0.33"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"inquirer": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
"integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
"dev": true,
"requires": {
"ansi-escapes": "^3.0.0",
"chalk": "^2.0.0",
"cli-cursor": "^2.1.0",
"cli-width": "^2.0.0",
"external-editor": "^3.0.0",
"figures": "^2.0.0",
"lodash": "^4.17.10",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rxjs": "^6.1.0",
"string-width": "^2.1.0",
"strip-ansi": "^4.0.0",
"through": "^2.3.6"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
},
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
"dev": true
},
"rxjs": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
"integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
}
},
"semver": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
"dev": true
},
"table": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz",
"integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==",
"dev": true,
"requires": {
"ajv": "^6.5.3",
"lodash": "^4.17.10",
"slice-ansi": "1.0.0",
"string-width": "^2.1.1"
}
}
}
} }
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "circom", "name": "circom",
"version": "0.0.7", "version": "0.0.20",
"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",
"zksnark": "0.0.11" "snarkjs": "0.1.6"
} }
} }

View File

@@ -1,3 +1,22 @@
/*
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/>.
*/
/* description: Construct AST for jaz language. */ /* description: Construct AST for jaz language. */
/* lexical grammar */ /* lexical grammar */

View File

@@ -1,20 +1,20 @@
/* /*
Copyright 2018 0KIMS association. Copyright 2018 0KIMS association.
This file is part of jaz (Zero Knowledge Circuit Compiler). This file is part of circom (Zero Knowledge Circuit Compiler).
jaz is a free software: you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
jaz is distributed in the hope that it will be useful, but WITHOUT circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details. License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with jaz. If not, see <https://www.gnu.org/licenses/>. along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ */
const fs = require("fs"); const fs = require("fs");
@@ -23,20 +23,17 @@ const bigInt = require("big-integer");
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const __MASK__ = new bigInt(2).pow(253).minus(1); const __MASK__ = new bigInt(2).pow(253).minus(1);
const assert = require("assert"); const assert = require("assert");
const genCode = require("./gencode"); const gen = require("./gencode");
const exec = require("./exec"); const exec = require("./exec");
const lc = require("./lcalgebra"); const lc = require("./lcalgebra");
const util = require("util");
const fs_writeFile = util.promisify(fs.writeFile)
module.exports = compile; 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, cFile) { async function compile(srcFile) {
const fullFileName = srcFile; const fullFileName = srcFile;
const fullFilePath = path.dirname(fullFileName); const fullFilePath = path.dirname(fullFileName);
@@ -65,8 +62,13 @@ async function compile(srcFile, cFile) {
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);
@@ -85,13 +87,9 @@ async function compile(srcFile, cFile) {
ctx.scopes = [{}]; ctx.scopes = [{}];
const mainCode = genCode(ctx,ast); const mainCode = gen(ctx,ast);
if (ctx.error) throw(ctx.error); if (ctx.error) throw(ctx.error);
if (cFile) {
await fs_writeFile(cFile, mainCode);
}
const def = buildCircuitDef(ctx, mainCode); const def = buildCircuitDef(ctx, mainCode);
return def; return def;
@@ -261,11 +259,11 @@ function reduceConstrains(ctx) {
} }
} }
for (let j=0; j<ctx.constraints.length; j++ ) { for (let j=0; j<newConstraints.length; j++) {
const c2 = ctx.constraints[j]; newConstraints[j] = lc.substitute(newConstraints[j], isolatedSignal, isolatedSignalEquivalence);
if (i!=j) {
lc.substitute(c2, isolatedSignal, isolatedSignalEquivalence);
} }
for (let j=i+1; j<ctx.constraints.length; j++ ) {
ctx.constraints[j] = lc.substitute(ctx.constraints[j], isolatedSignal, isolatedSignalEquivalence);
} }
c.a={ type: "LINEARCOMBINATION", values: {} }; c.a={ type: "LINEARCOMBINATION", values: {} };
c.b={ type: "LINEARCOMBINATION", values: {} }; c.b={ type: "LINEARCOMBINATION", values: {} };
@@ -406,9 +404,4 @@ function buildConstraints(ctx) {
} }
function generateCCode(ctx) {
}

View File

@@ -1,20 +1,20 @@
/* /*
Copyright 2018 0KIMS association. Copyright 2018 0KIMS association.
This file is part of jaz (Zero Knowledge Circuit Compiler). This file is part of circom (Zero Knowledge Circuit Compiler).
jaz is a free software: you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
jaz is distributed in the hope that it will be useful, but WITHOUT circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details. License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with jaz. If not, see <https://www.gnu.org/licenses/>. along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ */
const path = require("path"); const path = require("path");
@@ -78,6 +78,8 @@ 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 == "/") {
return execDiv(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 == "&") {
@@ -96,6 +98,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 {
@@ -176,7 +180,7 @@ function setScope(ctx, name, selectors, value) {
function setScopeArray(a, sels) { function setScopeArray(a, sels) {
if (sels.length == 1) { if (sels.length == 1) {
a[sels[0]] = value; a[sels[0].value] = value;
} else { } else {
setScopeArray(a[sels[0]], sels.slice(1)); setScopeArray(a[sels[0]], sels.slice(1));
} }
@@ -314,8 +318,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");
@@ -326,6 +329,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,11 +363,8 @@ function execInstantiateComponet(ctx, vr, fn) {
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;
@@ -386,8 +395,7 @@ function execFunctionCall(ctx, ast) {
const v = exec(ctx, ast.params[i]); const v = exec(ctx, ast.params[i]);
if (ctx.error) return; if (ctx.error) return;
if (v.type != "NUMBER") return error(ctx, ast.params[i], "expected a number"); paramValues.push(v);
paramValues.push( v.value);
} }
if (ast.params.length != paramValues.length) error(ctx, ast, "Invalid Number of parameters"); if (ast.params.length != paramValues.length) error(ctx, ast, "Invalid Number of parameters");
@@ -401,10 +409,7 @@ function execFunctionCall(ctx, ast) {
const scope = {}; const scope = {};
for (let i=0; i< fnc.params.length; i++) { for (let i=0; i< fnc.params.length; i++) {
scope[fnc.params[i]] = { scope[fnc.params[i]] = paramValues[i];
type: "NUMBER",
value: paramValues[i]
};
} }
ctx.fileName = fnc.fileName; ctx.fileName = fnc.fileName;
@@ -507,6 +512,14 @@ function execVariable(ctx, ast) {
if (ctx.error) return; if (ctx.error) return;
if (!v) return error(ctx, ast, "Variable not defined"); if (!v) return error(ctx, ast, "Variable not defined");
// If the signal has an assigned value (constant) just return the constant
if ((v.type == "SIGNAL") && (ctx.signals[v.fullName].value)) {
return {
type: "NUMBER",
value: ctx.signals[v.fullName].value
};
}
let res; let res;
res=v; res=v;
return res; return res;
@@ -539,6 +552,7 @@ function execFor(ctx, ast) {
let v = exec(ctx, ast.condition); let v = exec(ctx, ast.condition);
if (ctx.error) return; if (ctx.error) return;
if (typeof v.value != "undefined") {
while ((v.value.neq(0))&&(!ctx.returnValue)) { while ((v.value.neq(0))&&(!ctx.returnValue)) {
exec(ctx, ast.body); exec(ctx, ast.body);
if (ctx.error) return; if (ctx.error) return;
@@ -550,11 +564,13 @@ function execFor(ctx, ast) {
if (ctx.error) return; if (ctx.error) return;
} }
} }
}
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;
if (typeof v.value != "undefined") {
while ((v.value.neq(0))&&(!ctx.returnValue)) { while ((v.value.neq(0))&&(!ctx.returnValue)) {
exec(ctx, ast.body); exec(ctx, ast.body);
if (ctx.error) return; if (ctx.error) return;
@@ -563,19 +579,24 @@ function execWhile(ctx, ast) {
if (ctx.error) return; if (ctx.error) return;
} }
} }
}
function execIf(ctx, ast) { 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 (typeof v.value != "undefined") {
if ((v.value.neq(0))&&(!ctx.returnValue)) { if ((v.value.neq(0))&&(!ctx.returnValue)) {
exec(ctx, ast.then); exec(ctx, ast.then);
if (ctx.error) return; if (ctx.error) return;
} else { } else {
if (ast.else) {
exec(ctx, ast.else); exec(ctx, ast.else);
if (ctx.error) return; if (ctx.error) return;
} }
} }
}
}
function execVarAssignement(ctx, ast) { function execVarAssignement(ctx, ast) {
@@ -672,6 +693,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]);
@@ -746,6 +781,21 @@ function execExp(ctx, ast) {
}; };
} }
function execDiv(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.times(b.value.modInv(__P__)).mod(__P__)
};
}
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;

View File

@@ -1,25 +1,25 @@
/* /*
Copyright 2018 0KIMS association. Copyright 2018 0KIMS association.
This file is part of jaz (Zero Knowledge Circuit Compiler). This file is part of circom (Zero Knowledge Circuit Compiler).
jaz is a free software: you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
jaz is distributed in the hope that it will be useful, but WITHOUT circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details. License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with jaz. If not, see <https://www.gnu.org/licenses/>. along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ */
const bigInt = require("big-integer"); const bigInt = require("big-integer");
module.exports = genCode; module.exports = gen;
function ident(text) { function ident(text) {
let lines = text.split("\n"); let lines = text.split("\n");
@@ -65,6 +65,8 @@ function gen(ctx, ast) {
return genPlusPlusLeft(ctx, ast); return genPlusPlusLeft(ctx, ast);
} else if (ast.op == "**") { } else if (ast.op == "**") {
return genExp(ctx, ast); return genExp(ctx, ast);
} else if (ast.op == "/") {
return genDiv(ctx, ast);
} else if (ast.op == "&") { } else if (ast.op == "&") {
return genBAnd(ctx, ast); return genBAnd(ctx, ast);
} else if (ast.op == "<<") { } else if (ast.op == "<<") {
@@ -81,6 +83,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 {
@@ -170,9 +174,8 @@ function genBlock(ctx, ast) {
return "{\n"+ident(body)+"}\n"; return "{\n"+ident(body)+"}\n";
} }
function genTemplateDef(ctx, ast) { function genTemplateDef(ctx, ast) {
let S = `function ${ast.name}(ctx)\n`; let S = "function(ctx) ";
const newScope = {}; const newScope = {};
for (let i=0; i< ast.params.length; i++) { for (let i=0; i< ast.params.length; i++) {
@@ -181,7 +184,6 @@ function genTemplateDef(ctx, ast) {
ctx.scopes.push(newScope); ctx.scopes.push(newScope);
S += genBlock(ctx, ast.block); S += genBlock(ctx, ast.block);
S += "\n";
ctx.scopes.pop(); ctx.scopes.pop();
// const scope = ctx.scopes[ctx.scopes.length-1]; // const scope = ctx.scopes[ctx.scopes.length-1];
@@ -192,11 +194,11 @@ function genTemplateDef(ctx, ast) {
}; };
ctx.templates[ast.name] = S; ctx.templates[ast.name] = S;
return S; return "";
} }
function genFunctionDef(ctx, ast) { function genFunctionDef(ctx, ast) {
let S = `function ${ast.name}(ctx) `; let S = "function(ctx) ";
const newScope = {}; const newScope = {};
const params = []; const params = [];
@@ -218,7 +220,7 @@ function genFunctionDef(ctx, ast) {
ctx.functions[ast.name] = S; ctx.functions[ast.name] = S;
ctx.functionParams[ast.name] = params; ctx.functionParams[ast.name] = params;
return S; return "";
} }
function genFor(ctx, ast) { function genFor(ctx, ast) {
@@ -230,7 +232,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;
return `for (${init};${condition};${step})\n${body}\n`; return `for (${init};${condition};${step}) { \n${body}\n }\n`;
} }
function genWhile(ctx, ast) { function genWhile(ctx, ast) {
@@ -238,7 +240,7 @@ function genWhile(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;
return `while (${condition}) ${body}\n`; return `while (${condition}) {\n${body}\n}\n`;
} }
function genIf(ctx, ast) { function genIf(ctx, ast) {
@@ -246,9 +248,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;
if (ast.else) {
const elseBody = gen(ctx, ast.else); const elseBody = gen(ctx, ast.else);
if (ctx.error) return; if (ctx.error) return;
return `if (${condition}) ${thenBody} else ${elseBody}\n`; return `if (${condition}) {\n${thenBody}\n} else {\n${elseBody}\n}\n`;
} else {
return `if (${condition}) {\n${thenBody}\n}\n`;
}
} }
@@ -310,7 +316,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") {
@@ -440,6 +448,15 @@ function genSub(ctx, ast) {
return `bigInt(${a}).add(__P__).sub(bigInt(${b})).mod(__P__)`; return `bigInt(${a}).add(__P__).sub(bigInt(${b})).mod(__P__)`;
} }
function genDiv(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}).mul( bigInt(${b}).inverse(__P__) ).mod(__P__)`;
}
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;
@@ -517,7 +534,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) {
@@ -537,21 +562,7 @@ function genTerCon(ctx, ast) {
} }
function genInclude(ctx, ast) { function genInclude(ctx, ast) {
let body = genCode(ctx, ast.block); return ast.block ? gen(ctx, ast.block) : "";
return `// File: ${ast.file}\n` +body+"\n";
}
function genCode(ctx, ast) {
let body = "";
for (let i=0; i<ast.statements.length; i++) {
const l = gen(ctx, ast.statements[i]);
if (ctx.error) return;
if (l) {
body += l;
if (body[body.length-1] != "\n") body += ";\n";
}
}
return body;
} }
function genArray(ctx, ast) { function genArray(ctx, ast) {

View File

@@ -1,20 +1,20 @@
/* /*
Copyright 2018 0KIMS association. Copyright 2018 0KIMS association.
This file is part of jaz (Zero Knowledge Circuit Compiler). This file is part of circom (Zero Knowledge Circuit Compiler).
jaz is a free software: you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
jaz is distributed in the hope that it will be useful, but WITHOUT circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details. License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with jaz. If not, see <https://www.gnu.org/licenses/>. along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ */
/* /*
@@ -434,59 +434,73 @@ function toString(a, ctx) {
function canonize(ctx, a) { function canonize(ctx, a) {
if (a.type == "LINEARCOMBINATION") { if (a.type == "LINEARCOMBINATION") {
const res = clone(a);
for (let k in a.values) { for (let k in a.values) {
let s = k; let s = k;
while (ctx.signals[s].equivalence) s= ctx.signals[s].equivalence; while (ctx.signals[s].equivalence) s= ctx.signals[s].equivalence;
if ((typeof(ctx.signals[s].value) != "undefined")&&(k != "one")) { if ((typeof(ctx.signals[s].value) != "undefined")&&(k != "one")) {
const v = a.values[k].times(ctx.signals[s].value).mod(__P__); const v = res.values[k].times(ctx.signals[s].value).mod(__P__);
if (!a.values["one"]) { if (!res.values["one"]) {
a.values["one"]=v; res.values["one"]=v;
} else { } else {
a.values["one"]= a.values["one"].add(v).mod(__P__); res.values["one"]= res.values["one"].add(v).mod(__P__);
} }
delete a.values[k]; delete res.values[k];
} else if (s != k) { } else if (s != k) {
if (!a.values[s]) { if (!res.values[s]) {
a.values[s]=bigInt(a.values[k]); res.values[s]=bigInt(res.values[k]);
} else { } else {
a.values[s]= a.values[s].add(a.values[k]).mod(__P__); res.values[s]= res.values[s].add(res.values[k]).mod(__P__);
} }
delete a.values[k]; delete res.values[k];
} }
} }
for (let k in a.values) { for (let k in res.values) {
if (a.values[k].isZero()) delete a.values[k]; if (res.values[k].isZero()) delete res.values[k];
} }
return a; return res;
} else if (a.type == "QEQ") { } else if (a.type == "QEQ") {
a.a = canonize(ctx, a.a); const res = {
a.b = canonize(ctx, a.b); type: "QEQ",
a.c = canonize(ctx, a.c); a: canonize(ctx, a.a),
} b: canonize(ctx, a.b),
c: canonize(ctx, a.c)
};
return res;
} else {
return a; return a;
} }
}
function substitute(where, signal, equivalence) { function substitute(where, signal, equivalence) {
if (equivalence.type != "LINEARCOMBINATION") throw new Error("Equivalence must be a Linear Combination"); if (equivalence.type != "LINEARCOMBINATION") throw new Error("Equivalence must be a Linear Combination");
if (where.type == "LINEARCOMBINATION") { if (where.type == "LINEARCOMBINATION") {
if (!where.values[signal] || where.values[signal].isZero()) return where; if (!where.values[signal] || where.values[signal].isZero()) return where;
const coef = where.values[signal]; const res=clone(where);
const coef = res.values[signal];
for (let k in equivalence.values) { for (let k in equivalence.values) {
if (k != signal) { if (k != signal) {
const v = coef.times(equivalence.values[k]).mod(__P__); const v = coef.times(equivalence.values[k]).mod(__P__);
if (!where.values[k]) { if (!res.values[k]) {
where.values[k]=v; res.values[k]=v;
} else { } else {
where.values[k]= where.values[k].add(v).mod(__P__); res.values[k]= res.values[k].add(v).mod(__P__);
} }
if (where.values[k].isZero()) delete where.values[k]; if (res.values[k].isZero()) delete res.values[k];
} }
} }
delete where.values[signal]; delete res.values[signal];
return res;
} else if (where.type == "QEQ") { } else if (where.type == "QEQ") {
substitute(where.a, signal, equivalence); const res = {
substitute(where.b, signal, equivalence); type: "QEQ",
substitute(where.c, signal, equivalence); a: substitute(where.a, signal, equivalence),
b: substitute(where.b, signal, equivalence),
c: substitute(where.c, signal, equivalence)
};
return res;
} else {
return where;
} }
} }

14
test/cases.js Normal file
View File

@@ -0,0 +1,14 @@
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;
describe("Sum test", () => {
it("Should compile a code with an undefined if", async() => {
await compiler(path.join(__dirname, "circuits", "undefinedif.circom"));
});
});

View File

@@ -0,0 +1,4 @@
include "../../circuits/comparators.circom";
component main = IsEqual();

View File

@@ -0,0 +1,5 @@
include "../../circuits/comparators.circom";
component main = IsZero();

View File

@@ -0,0 +1,4 @@
include "../../circuits/comparators.circom";
component main = LessThan(32);

View File

@@ -1,5 +1,5 @@
include "../../circuits/sha256/bitify.circom" include "../../circuits/bitify.circom"
include "../../circuits/sha256/binsum.circom" include "../../circuits/binsum.circom"
template A() { template A() {
signal private input a; signal private input a;

View 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();

77
test/comparators.js Normal file
View File

@@ -0,0 +1,77 @@
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;
describe("Sum test", () => {
it("Should create a iszero circuit", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "iszero.circom"));
const circuit = new snarkjs.Circuit(cirDef);
let witness;
witness = circuit.calculateWitness({ "in": 111});
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = circuit.calculateWitness({ "in": 0 });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
});
it("Should create a isequal circuit", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "isequal.circom"));
const circuit = new snarkjs.Circuit(cirDef);
let witness;
witness = circuit.calculateWitness({ "in[0]": "111", "in[1]": "222" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = circuit.calculateWitness({ "in[0]": "444", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
});
it("Should create a comparison", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "lessthan.circom"));
const circuit = new snarkjs.Circuit(cirDef);
let witness;
witness = circuit.calculateWitness({ "in[0]": "333", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = circuit.calculateWitness({ "in[0]": "661", "in[1]": "660" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = circuit.calculateWitness({ "in[0]": "555", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
});
});

View File

@@ -0,0 +1,22 @@
const snarkjs = require("snarkjs");
const bigInt = snarkjs.bigInt;
module.exports = 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);
};

View File

@@ -1,4 +0,0 @@
{
"a": "111",
"b": "222"
}

View File

@@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const zkSnark = require("zksnark"); const snarkjs = require("snarkjs");
const crypto = require("crypto"); const crypto = require("crypto");
const compiler = require("../index.js"); const compiler = require("../index.js");
@@ -8,54 +8,14 @@ const compiler = require("../index.js");
const assert = chai.assert; const assert = chai.assert;
const sha256 = require("./helpers/sha256"); const sha256 = require("./helpers/sha256");
const bigInt = require("big-integer");
function hexBits(cir, witness, sig, nBits) { // const printSignal = require("./helpers/printsignal");
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", () => { 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 zkSnark.Circuit(cirDef);
const witness = circuit.calculateWitness({ "in": "0xd807aa98" });
assert(witness[0].equals(zkSnark.bigInt(1)));
assert(witness[1].equals(zkSnark.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 zkSnark.Circuit(cirDef);
const witness = circuit.calculateWitness({ "a": "111", "b": "222" });
assert(witness[0].equals(zkSnark.bigInt(1)));
assert(witness[1].equals(zkSnark.bigInt("333")));
});
it("Should calculate a hash", async () => { it("Should calculate a hash", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_2_test.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_2_test.circom"));
const circuit = new zkSnark.Circuit(cirDef); const circuit = new snarkjs.Circuit(cirDef);
console.log("Vars: "+circuit.nVars); console.log("Vars: "+circuit.nVars);
console.log("Constraints: "+circuit.nConstraints); console.log("Constraints: "+circuit.nConstraints);
@@ -75,7 +35,7 @@ describe("SHA256 test", () => {
assert.equal(hash, hash2); assert.equal(hash, hash2);
assert(witness[1].equals(zkSnark.bigInt(r))); assert(witness[1].equals(snarkjs.bigInt(r)));
}).timeout(1000000); }).timeout(1000000);

35
test/sum.js Normal file
View File

@@ -0,0 +1,35 @@
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;
describe("Sum 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")));
});
});

View File

@@ -1,36 +0,0 @@
class Value {
}
class Var : Value {
}
class Ctx {
char *currentComponent;
Var getParam(char *);
Var getSignal(char *, ...);
Var newVar(char *);
}
void Num2Bits::Num2Bits(ctx) {
Var n = ctx.getParam("n");
Var in = ctx.getSignal("in");
Var out = ctx.getSignal("out");
(Var lc1 = ctx.newVar()) = _0x0;
for ((Var i = ctx.newVar()) = _0x0 ; i<n; i++ ) {
out[i] = (in >> i) & _0x1;
assert(out[i]*(out[i] - _0x1), _0x0);
lc1 += out[i] * (2**i);
}
assert(lc1, in);
}

View File