Tests added and Comparators
jump to
@@ -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; +}
@@ -17,6 +17,9 @@ 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];@@ -43,3 +46,27 @@ }
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; +}
@@ -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 @@ along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ include "sha256compression.circom"; -include "bitify.circom" +include "../bitify.circom" template Sha256_2() { signal input a;
@@ -20,7 +20,7 @@
include "constants.circom"; include "t1.circom"; include "t2.circom"; -include "binsum.circom"; +include "../binsum.circom"; include "sigmaplus.circom"; template Sha256compression() {
@@ -17,7 +17,7 @@ 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 "../binsum.circom" include "sigma.circom" template SigmaPlus() {
@@ -17,7 +17,7 @@ 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 "../binsum.circom"; include "sigma.circom"; include "ch.circom";
@@ -17,7 +17,7 @@ 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 "../binsum.circom"; include "sigma.circom"; include "maj.circom"
@@ -98,6 +98,8 @@ } else if (ast.op == ">=") {
return execGte(ctx, ast); } else if (ast.op == "==") { return execEq(ctx, ast); + } else if (ast.op == "!=") { + return execNeq(ctx, ast); } else if (ast.op == "?") { return execTerCon(ctx, ast); } else {@@ -677,6 +679,20 @@ if (!a.value || !b.value) return { type: "NUMBER" };
return { type: "NUMBER", value: a.value.eq(b.value) ? bigInt(1) : bigInt(0) + }; +} + +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) }; }
@@ -83,6 +83,8 @@ } else if (ast.op == ">=") {
return genGte(ctx, ast); } else if (ast.op == "==") { return genEq(ctx, ast); + } else if (ast.op == "!=") { + return genNeq(ctx, ast); } else if (ast.op == "?") { return genTerCon(ctx, ast); } else {@@ -314,7 +316,9 @@ sels.push(gen(ctx, ast.selectors[i]));
if (ctx.error) return; } - + if (!v) { + return error(ctx, ast, "Invalid left operand"); + } if (v.type == "VARIABLE") { return `ctx.getVar("${ast.name}",[${sels.join(",")}])`; } else if (v.type == "SIGNAL") {@@ -530,7 +534,15 @@ 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})) ? 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) {
@@ -0,0 +1,4 @@
+ +include "../../circuits/comparators.circom"; + +component main = IsEqual();
@@ -0,0 +1,5 @@
+ + +include "../../circuits/comparators.circom"; + +component main = IsZero();
@@ -0,0 +1,4 @@
+ +include "../../circuits/comparators.circom"; + +component main = LessThan(32);
@@ -1,5 +1,5 @@
-include "../../circuits/sha256/bitify.circom" -include "../../circuits/sha256/binsum.circom" +include "../../circuits/bitify.circom" +include "../../circuits/binsum.circom" template A() { signal private input a;
@@ -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))); + }); +});
@@ -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); +};
@@ -8,51 +8,11 @@
const assert = chai.assert; const sha256 = require("./helpers/sha256"); -const bigInt = require("big-integer"); - -function hexBits(cir, witness, sig, nBits) { - let v = bigInt(0); - for (let i=nBits-1; i>=0; i--) { - v = v.shiftLeft(1); - const name = sig+"["+i+"]"; - const idx = cir.getSignalIdx(name); - const vbit = bigInt(witness[idx].toString()); - if (vbit.equals(bigInt(1))) { - v = v.add(bigInt(1)); - } else if (vbit.equals(bigInt(0))) { - v; - } else { - console.log("Not Binary: "+name); - } - } - return v.toString(16); -} - -describe("SHA256 test", () => { - it("Should create a constant circuit", async () => { - const cirDef = await compiler(path.join(__dirname, "circuits", "constants_test.circom")); - assert.equal(cirDef.nVars, 2); - - const circuit = new snarkjs.Circuit(cirDef); - - const witness = circuit.calculateWitness({ "in": "0xd807aa98" }); - - assert(witness[0].equals(snarkjs.bigInt(1))); - assert(witness[1].equals(snarkjs.bigInt("0xd807aa98"))); - }); - it("Should create a sum circuit", async () => { - - const cirDef = await compiler(path.join(__dirname, "circuits", "sum_test.circom")); - assert.equal(cirDef.nVars, 101); +// const printSignal = require("./helpers/printsignal"); - 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"))); - }); +describe("SHA256 test", () => { it("Should calculate a hash", async () => { const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_2_test.circom")); const circuit = new snarkjs.Circuit(cirDef);
@@ -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"))); + }); +});