mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 03:06:42 +01:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dcfb9ab8b4 | ||
|
|
bfdf17fd89 | ||
|
|
9d0b27a7e8 | ||
|
|
4d79038fd8 | ||
|
|
95755c4afe | ||
|
|
afc60ec033 | ||
|
|
77393e2d0c | ||
|
|
2db08a0a34 | ||
|
|
23255de508 | ||
|
|
7c03ae4033 | ||
|
|
5e58584a01 | ||
|
|
cb9a5b536e | ||
|
|
70c88be334 | ||
|
|
25759e53cd | ||
|
|
4fa0c79e26 | ||
|
|
e685392523 | ||
|
|
e81c4f1331 | ||
|
|
483c9c0c26 | ||
|
|
eb1834833d | ||
|
|
49a6120eeb |
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
include "comparators.circom";
|
||||||
|
|
||||||
|
|
||||||
template Num2Bits(n) {
|
template Num2Bits(n) {
|
||||||
signal input in;
|
signal input in;
|
||||||
signal output out[n];
|
signal output out[n];
|
||||||
@@ -43,3 +46,27 @@ template Bits2Num(n) {
|
|||||||
|
|
||||||
lc1 ==> out;
|
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;
|
||||||
|
}
|
||||||
55
circuits/comparators.circom
Normal file
55
circuits/comparators.circom
Normal 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;
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
include "sha256compression.circom";
|
include "sha256compression.circom";
|
||||||
include "bitify.circom"
|
include "../bitify.circom"
|
||||||
|
|
||||||
template Sha256_2() {
|
template Sha256_2() {
|
||||||
signal input a;
|
signal input a;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
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() {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
include "binsum.circom"
|
include "../binsum.circom"
|
||||||
include "sigma.circom"
|
include "sigma.circom"
|
||||||
|
|
||||||
template SigmaPlus() {
|
template SigmaPlus() {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
include "binsum.circom";
|
include "../binsum.circom";
|
||||||
include "sigma.circom";
|
include "sigma.circom";
|
||||||
include "ch.circom";
|
include "ch.circom";
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
include "binsum.circom";
|
include "../binsum.circom";
|
||||||
include "sigma.circom";
|
include "sigma.circom";
|
||||||
include "maj.circom"
|
include "maj.circom"
|
||||||
|
|
||||||
|
|||||||
35
cli.js
35
cli.js
@@ -30,12 +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")
|
||||||
.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
|
||||||
@@ -43,14 +42,34 @@ 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);
|
|
||||||
|
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";
|
||||||
|
|
||||||
compiler(fullFileName).then( (cir) => {
|
compiler(fullFileName).then( (cir) => {
|
||||||
fs.writeFileSync(argv.output, 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}`);
|
if (err.pos) {
|
||||||
console.error(JSON.stringify(err.ast, null, 1));
|
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
11
package-lock.json
generated
11
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circom",
|
"name": "circom",
|
||||||
"version": "0.0.10",
|
"version": "0.0.19",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1469,14 +1469,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"snarkjs": {
|
"snarkjs": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.3.tgz",
|
||||||
"integrity": "sha512-i+OOKwATef3/oUleae9FHt/qACPYH1M5gjQkdYYkyRYqScIuZHCmNSf6Q5RWJT5hmOkTEor+T2C5qwKSrzzGSg==",
|
"integrity": "sha512-z5HhuNt019ZzNzUztETK31rpjRRSz3Uzy8TjGgSROf+9ZT9i6dbdWkjTC3fh5o9H+R/2+hcR+7IKAmpIR56V+A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.35",
|
"big-integer": "^1.6.35",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"eslint": "^5.3.0"
|
"eslint": "^5.3.0",
|
||||||
|
"yargs": "^12.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": {
|
"ajv": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circom",
|
"name": "circom",
|
||||||
"version": "0.0.10",
|
"version": "0.0.19",
|
||||||
"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.3"
|
"snarkjs": "0.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
60
src/exec.js
60
src/exec.js
@@ -98,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 {
|
||||||
@@ -545,15 +547,17 @@ function execFor(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;
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,12 +565,14 @@ 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 +580,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,6 +688,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]);
|
||||||
|
|||||||
@@ -83,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 {
|
||||||
@@ -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;
|
||||||
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 +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") {
|
||||||
@@ -526,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) {
|
||||||
|
|||||||
14
test/cases.js
Normal file
14
test/cases.js
Normal 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"));
|
||||||
|
});
|
||||||
|
});
|
||||||
4
test/circuits/isequal.circom
Normal file
4
test/circuits/isequal.circom
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
include "../../circuits/comparators.circom";
|
||||||
|
|
||||||
|
component main = IsEqual();
|
||||||
5
test/circuits/iszero.circom
Normal file
5
test/circuits/iszero.circom
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
include "../../circuits/comparators.circom";
|
||||||
|
|
||||||
|
component main = IsZero();
|
||||||
4
test/circuits/lessthan.circom
Normal file
4
test/circuits/lessthan.circom
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
include "../../circuits/comparators.circom";
|
||||||
|
|
||||||
|
component main = LessThan(32);
|
||||||
@@ -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;
|
||||||
|
|||||||
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();
|
||||||
77
test/comparators.js
Normal file
77
test/comparators.js
Normal 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)));
|
||||||
|
});
|
||||||
|
});
|
||||||
22
test/helpers/printsignal.js
Normal file
22
test/helpers/printsignal.js
Normal 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);
|
||||||
|
};
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"a": "111",
|
|
||||||
"b": "222"
|
|
||||||
}
|
|
||||||
@@ -8,51 +8,11 @@ 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 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 () => {
|
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 snarkjs.Circuit(cirDef);
|
const circuit = new snarkjs.Circuit(cirDef);
|
||||||
|
|||||||
35
test/sum.js
Normal file
35
test/sum.js
Normal 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")));
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user