diff --git a/test/aliascheck.js b/test/aliascheck.js new file mode 100644 index 00000000..15680269 --- /dev/null +++ b/test/aliascheck.js @@ -0,0 +1,77 @@ +const chai = require("chai"); +const path = require("path"); + +const assert = chai.assert; + +const Scalar = require("ffjavascript").Scalar; +const F1Field = require("ffjavascript").F1Field; +const utils = require("ffjavascript").utils; +const q = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const F = new F1Field(q); + +const wasm_tester = require("circom_tester").wasm; + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +function getBits(v, n) { + const res = []; + for (let i=0; i { + + cir = await wasm_tester(path.join(__dirname, "circuits", "aliascheck_test.circom")); + }); + + it("Satisfy the aliastest 0", async () => { + const inp = getBits(0, 254); + await cir.calculateWitness({in: inp}, true); + }); + + it("Satisfy the aliastest 3", async () => { + const inp = getBits(3, 254); + await cir.calculateWitness({in: inp}, true); + }); + + it("Satisfy the aliastest q-1", async () => { + const inp = getBits(F.e(-1), 254); + // console.log(JSON.stringify(utils.stringifyBigInts(inp))); + await cir.calculateWitness({in: inp}, true); + }); + + it("Should not satisfy an input of q", async () => { + const inp = getBits(q, 254); + try { + await cir.calculateWitness({in: inp}, true); + assert(false); + } catch(err) { + assert(err.message.includes("Assert Failed")); + } + }); + + it("Should not satisfy all ones", async () => { + + const inp = getBits(Scalar.sub(Scalar.shl(1, 254) , 1) , 254); + try { + await cir.calculateWitness({in: inp}, true); + assert(false); + } catch(err) { + assert(err.message.includes("Assert Failed")); + } + }); + +}); diff --git a/test/babyjub.js b/test/babyjub.js new file mode 100644 index 00000000..eafb0f3b --- /dev/null +++ b/test/babyjub.js @@ -0,0 +1,113 @@ +const chai = require("chai"); +const path = require("path"); + +const createBlakeHash = require("blake-hash"); +const eddsa = require("../src/eddsa.js"); +const F = require("../src/babyjub.js").F; + +const assert = chai.assert; + +const tester = require("circom").tester; +const utils = require("ffjavascript").utils; +const Scalar = require("ffjavascript").Scalar; + +describe("Baby Jub test", function () { + let circuitAdd; + let circuitTest; + let circuitPbk; + + this.timeout(100000); + + before( async() => { + circuitAdd = await tester(path.join(__dirname, "circuits", "babyadd_tester.circom")); + + circuitTest = await tester(path.join(__dirname, "circuits", "babycheck_test.circom")); + + circuitPbk = await tester(path.join(__dirname, "circuits", "babypbk_test.circom")); + }); + + it("Should add point (0,1) and (0,1)", async () => { + + const input={ + x1: F.e(0), + y1: F.e(1), + x2: F.e(0), + y2: F.e(1) + }; + + const w = await circuitAdd.calculateWitness(input, true); + + await circuitAdd.assertOut(w, {xout: F.e(0), yout: F.e(1)}); + }); + + it("Should add 2 same numbers", async () => { + + const input={ + x1: F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + y1: F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + x2: F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + y2: F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475") + }; + + const w = await circuitAdd.calculateWitness(input, true); + + await circuitAdd.assertOut(w, { + xout: F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"), + yout: F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889") + }); + + }); + + it("Should add 2 different numbers", async () => { + + const input={ + x1: F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + y1: F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + x2: F.e("16540640123574156134436876038791482806971768689494387082833631921987005038935"), + y2: F.e("20819045374670962167435360035096875258406992893633759881276124905556507972311") + }; + + const w = await circuitAdd.calculateWitness(input, true); + + await circuitAdd.assertOut(w, { + xout: F.e("7916061937171219682591368294088513039687205273691143098332585753343424131937"), + yout: F.e("14035240266687799601661095864649209771790948434046947201833777492504781204499") + }); + + }); + + it("Should check (0,1) is a valid point", async() => { + const w = await circuitTest.calculateWitness({x: 0, y:1}, true); + + await circuitTest.checkConstraints(w); + }); + + it("Should check (1,0) is an invalid point", async() => { + try { + await circuitTest.calculateWitness({x: 1, y: 0}, true); + assert(false, "Should be a valid point"); + } catch(err) { + assert(/Constraint\sdoesn't\smatch(.*)168700\s!=\s1/.test(err.message) ); + } + }); + + it("Should extract the public key from the private one", async () => { + + const rawpvk = Buffer.from("0001020304050607080900010203040506070809000102030405060708090021", "hex"); + const pvk = eddsa.pruneBuffer(createBlakeHash("blake512").update(rawpvk).digest().slice(0,32)); + const S = Scalar.shr(utils.leBuff2int(pvk), 3); + + const A = eddsa.prv2pub(rawpvk); + + const input = { + in : S + }; + + const w = await circuitPbk.calculateWitness(input, true); + + await circuitPbk.assertOut(w, {Ax : A[0], Ay: A[1]}); + + await circuitPbk.checkConstraints(w); + }); + +}); diff --git a/test/babyjub_js.js b/test/babyjub_js.js new file mode 100644 index 00000000..fb488fb5 --- /dev/null +++ b/test/babyjub_js.js @@ -0,0 +1,170 @@ +const chai = require("chai"); +const babyjub = require("../src/babyjub.js"); +const Scalar = require("ffjavascript").Scalar; + +const assert = chai.assert; + +// const bigInt = require("big-integer"); + +function buff2hex(buff) { + function i2hex(i) { + return ('0' + i.toString(16)).slice(-2); + } + return Array.from(buff).map(i2hex).join(''); +} + +describe("Baby Jub js test", function () { + + this.timeout(100000); + + it("Should add point (0,1) and (0,1)", () => { + + const p1 = [ + babyjub.F.e(0), + babyjub.F.e(1)]; + const p2 = [ + babyjub.F.e(0), + babyjub.F.e(1) + ]; + + const out = babyjub.addPoint(p1, p2); + assert(babyjub.F.eq(out[0], babyjub.F.zero)); + assert(babyjub.F.eq(out[1], babyjub.F.one)); + }); + + it("Should base be 8*generator", () => { + let res; + res = babyjub.addPoint(babyjub.Generator, babyjub.Generator); + res = babyjub.addPoint(res, res); + res = babyjub.addPoint(res, res); + + assert(babyjub.F.eq(res[0], babyjub.Base8[0])); + assert(babyjub.F.eq(res[1], babyjub.Base8[1])); + }); + + it("Should add 2 same numbers", () => { + + const p1 = [ + babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ]; + const p2 = [ + babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ]; + + const out = babyjub.addPoint(p1, p2); + assert(babyjub.F.eq(out[0], babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"))); + assert(babyjub.F.eq(out[1], babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"))); + }); + + it("Should add 2 different numbers", () => { + + const p1 = [ + babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ]; + const p2 = [ + babyjub.F.e("16540640123574156134436876038791482806971768689494387082833631921987005038935"), + babyjub.F.e("20819045374670962167435360035096875258406992893633759881276124905556507972311"), + ]; + + const out = babyjub.addPoint(p1, p2); + assert(babyjub.F.eq(out[0], babyjub.F.e("7916061937171219682591368294088513039687205273691143098332585753343424131937"))); + assert(babyjub.F.eq(out[1], babyjub.F.e("14035240266687799601661095864649209771790948434046947201833777492504781204499"))); + + }); + + it("should mulPointEscalar 0", () => { + const p = [ + babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ]; + + const r = babyjub.mulPointEscalar(p, 3); + let r2 = babyjub.addPoint(p, p); + r2 = babyjub.addPoint(r2, p); + assert.equal(r2[0].toString(), r[0].toString()); + assert.equal(r2[1].toString(), r[1].toString()); + assert.equal(r[0].toString(), "19372461775513343691590086534037741906533799473648040012278229434133483800898"); + assert.equal(r[1].toString(), "9458658722007214007257525444427903161243386465067105737478306991484593958249"); + }); + + it("should mulPointEscalar 1", () => { + const p = [ + babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ]; + + const r = babyjub.mulPointEscalar(p, Scalar.fromString("14035240266687799601661095864649209771790948434046947201833777492504781204499")); + assert.equal(r[0].toString(), "17070357974431721403481313912716834497662307308519659060910483826664480189605"); + assert.equal(r[1].toString(), "4014745322800118607127020275658861516666525056516280575712425373174125159339"); + }); + + it("should mulPointEscalar 2", () => { + const p = [ + babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"), + babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"), + ]; + + const r = babyjub.mulPointEscalar(p, Scalar.fromString("20819045374670962167435360035096875258406992893633759881276124905556507972311")); + assert.equal(r[0].toString(), "13563888653650925984868671744672725781658357821216877865297235725727006259983"); + assert.equal(r[1].toString(), "8442587202676550862664528699803615547505326611544120184665036919364004251662"); + }); + + it("should inCurve 1", () => { + const p = [ + babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ]; + assert(babyjub.inCurve(p)); + }); + + it("should inCurve 2", () => { + const p = [ + babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"), + babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"), + ]; + assert(babyjub.inCurve(p)); + }); + + it("should inSubgroup 1", () => { + const p = [ + babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ]; + assert(babyjub.inSubgroup(p)); + }); + + it("should inSubgroup 2", () => { + const p = [ + babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"), + babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"), + ]; + assert(babyjub.inSubgroup(p)); + }); + + it("should packPoint - unpackPoint 1", () => { + const p = [ + babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"), + babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ]; + const buf = babyjub.packPoint(p); + assert.equal(buff2hex(buf), "53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85"); + const p2 = babyjub.unpackPoint(buf); + assert.equal(p2[0].toString(), "17777552123799933955779906779655732241715742912184938656739573121738514868268"); + assert.equal(p2[1].toString(), "2626589144620713026669568689430873010625803728049924121243784502389097019475"); + }); + + it("should packPoint - unpackPoint 2", () => { + const p = [ + babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"), + babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"), + ]; + const buf = babyjub.packPoint(p); + assert.equal(buff2hex(buf), "e114eb17eddf794f063a68fecac515e3620e131976108555735c8b0773929709"); + const p2 = babyjub.unpackPoint(buf); + assert.equal(p2[0].toString(), "6890855772600357754907169075114257697580319025794532037257385534741338397365"); + assert.equal(p2[1].toString(), "4338620300185947561074059802482547481416142213883829469920100239455078257889"); + }); +}); diff --git a/test/binsub.js b/test/binsub.js new file mode 100644 index 00000000..7f238fe9 --- /dev/null +++ b/test/binsub.js @@ -0,0 +1,52 @@ +const path = require("path"); + +const Scalar = require("ffjavascript").Scalar; +const tester = require("circom").tester; + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +async function checkSub(_a,_b, circuit) { + let a=Scalar.e(_a); + let b=Scalar.e(_b); + if (Scalar.lt(a, 0)) a = Scalar.add(a, Scalar.shl(1, 16)); + if (Scalar.lt(b, 0)) b = Scalar.add(b, Scalar.shl(1, 16)); + const w = await circuit.calculateWitness({a: a, b: b}, true); + + let res = Scalar.sub(a, b); + if (Scalar.lt(res, 0)) res = Scalar.add(res, Scalar.shl(1, 16)); + + await circuit.assertOut(w, {out: res}); +} + +describe("BinSub test", function () { + + this.timeout(100000); + + let circuit; + before( async() => { + circuit = await tester(path.join(__dirname, "circuits", "binsub_test.circom")); + }); + + it("Should check variuos ege cases", async () => { + await checkSub(0,0, circuit); + await checkSub(1,0, circuit); + await checkSub(-1,0, circuit); + await checkSub(2,1, circuit); + await checkSub(2,2, circuit); + await checkSub(2,3, circuit); + await checkSub(2,-1, circuit); + await checkSub(2,-2, circuit); + await checkSub(2,-3, circuit); + await checkSub(-2,-3, circuit); + await checkSub(-2,-2, circuit); + await checkSub(-2,-1, circuit); + await checkSub(-2,0, circuit); + await checkSub(-2,1, circuit); + await checkSub(-2,2, circuit); + await checkSub(-2,3, circuit); + }); + + +}); diff --git a/test/binsum.js b/test/binsum.js new file mode 100644 index 00000000..601baa99 --- /dev/null +++ b/test/binsum.js @@ -0,0 +1,39 @@ +const chai = require("chai"); +const path = require("path"); + +const tester = require("circom").tester; + +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const assert = chai.assert; + +describe("Binary sum test", function () { + this.timeout(100000000); + + it("Should create a constant circuit", async () => { + const circuit = await tester(path.join(__dirname, "circuits", "constants_test.circom")); + await circuit.loadConstraints(); + + assert.equal(circuit.nVars, 2); + assert.equal(circuit.constraints.length, 1); + + const witness = await circuit.calculateWitness({ "in": Fr.toString(Fr.e("0xd807aa98"))}, true); + + assert(Fr.eq(Fr.e(witness[0]),Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]),Fr.e("0xd807aa98"))); + }); + it("Should create a sum circuit", async () => { + const circuit = await tester(path.join(__dirname, "circuits", "sum_test.circom")); + await circuit.loadConstraints(); + + assert.equal(circuit.constraints.length, 97); // 32 (in1) + 32(in2) + 32(out) + 1 (carry) + + const witness = await circuit.calculateWitness({ "a": "111", "b": "222" }, true); + + assert(Fr.eq(Fr.e(witness[0]),Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]),Fr.e("333"))); + }); +}); diff --git a/test/circuits/aliascheck_test.circom b/test/circuits/aliascheck_test.circom new file mode 100644 index 00000000..942b77c8 --- /dev/null +++ b/test/circuits/aliascheck_test.circom @@ -0,0 +1,4 @@ +pragma circom 2.0.0; +include "../../circuits/aliascheck.circom"; + +component main = AliasCheck(); diff --git a/test/circuits/babyadd_tester.circom b/test/circuits/babyadd_tester.circom new file mode 100644 index 00000000..18c9d8c6 --- /dev/null +++ b/test/circuits/babyadd_tester.circom @@ -0,0 +1,4 @@ +pragma circom 2.0.0; +include "../../circuits/babyjub.circom"; + +component main = BabyAdd(); diff --git a/test/circuits/babycheck_test.circom b/test/circuits/babycheck_test.circom new file mode 100644 index 00000000..bdcdc699 --- /dev/null +++ b/test/circuits/babycheck_test.circom @@ -0,0 +1,4 @@ +pragma circom 2.0.0; +include "../../circuits/babyjub.circom"; + +component main = BabyCheck(); diff --git a/test/circuits/babypbk_test.circom b/test/circuits/babypbk_test.circom new file mode 100644 index 00000000..5e1f8a54 --- /dev/null +++ b/test/circuits/babypbk_test.circom @@ -0,0 +1,4 @@ +pragma circom 2.0.0; +include "../../circuits/babyjub.circom"; + +component main = BabyPbk(); diff --git a/test/circuits/binsub_test.circom b/test/circuits/binsub_test.circom new file mode 100644 index 00000000..33cd1a48 --- /dev/null +++ b/test/circuits/binsub_test.circom @@ -0,0 +1,33 @@ +pragma circom 2.0.0; + +include "../../circuits/bitify.circom"; +include "../../circuits/binsub.circom"; + +template A() { + signal input a; //private + signal input b; + signal output out; + + var i; + + component n2ba = Num2Bits(16); + component n2bb = Num2Bits(16); + component sub = BinSub(16); + component b2n = Bits2Num(16); + + n2ba.in <== a; + n2bb.in <== b; + + for (i=0; i<16; i++) { + sub.in[0][i] <== n2ba.out[i]; + sub.in[1][i] <== n2bb.out[i]; + } + + for (i=0; i<16; i++) { + b2n.in[i] <== sub.out[i]; + } + + out <== b2n.out; +} + +component main = A(); diff --git a/test/circuits/constants_test.circom b/test/circuits/constants_test.circom new file mode 100644 index 00000000..56ca82d0 --- /dev/null +++ b/test/circuits/constants_test.circom @@ -0,0 +1,20 @@ +pragma circom 2.0.0; + +include "../../circuits/sha256/constants.circom"; + +template A() { + signal input in; + component h0; + h0 = K(8); + + var lc = 0; + var e = 1; + for (var i=0; i<32; i++) { + lc = lc + e*h0.out[i]; + e *= 2; + } + + lc === in; +} + +component main = A(); diff --git a/test/circuits/eddsa_test.circom b/test/circuits/eddsa_test.circom new file mode 100644 index 00000000..b04ef9b3 --- /dev/null +++ b/test/circuits/eddsa_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/eddsa.circom"; + +component main = EdDSAVerifier(80); diff --git a/test/circuits/eddsamimc_test.circom b/test/circuits/eddsamimc_test.circom new file mode 100644 index 00000000..ca1a9791 --- /dev/null +++ b/test/circuits/eddsamimc_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/eddsamimc.circom"; + +component main = EdDSAMiMCVerifier(); diff --git a/test/circuits/eddsaposeidon_test.circom b/test/circuits/eddsaposeidon_test.circom new file mode 100644 index 00000000..22ee5997 --- /dev/null +++ b/test/circuits/eddsaposeidon_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/eddsaposeidon.circom"; + +component main = EdDSAPoseidonVerifier(); diff --git a/test/circuits/edwards2montgomery.circom b/test/circuits/edwards2montgomery.circom new file mode 100644 index 00000000..7fce4d73 --- /dev/null +++ b/test/circuits/edwards2montgomery.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/montgomery.circom"; + +component main = Edwards2Montgomery(); diff --git a/test/circuits/escalarmul_min_test.circom b/test/circuits/escalarmul_min_test.circom new file mode 100644 index 00000000..50ce99e4 --- /dev/null +++ b/test/circuits/escalarmul_min_test.circom @@ -0,0 +1,27 @@ +pragma circom 2.0.0; + +include "../../circuits/escalarmul.circom"; + + +template Main() { + signal input in[256]; + signal output out[2]; + + var i; + + var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203]; + + component escalarMul = EscalarMul(256, base); + + escalarMul.inp[0] <== 0; + escalarMul.inp[1] <== 1; + + for (i=0; i<256; i++) { + in[i] ==> escalarMul.in[i]; + } + + escalarMul.out[0] ==> out[0]; + escalarMul.out[1] ==> out[1]; +} + +component main = Main(); diff --git a/test/circuits/escalarmul_test.circom b/test/circuits/escalarmul_test.circom new file mode 100644 index 00000000..1988633e --- /dev/null +++ b/test/circuits/escalarmul_test.circom @@ -0,0 +1,33 @@ +pragma circom 2.0.0; + +include "../../circuits/escalarmul.circom"; +include "../../circuits/bitify.circom"; + + +template Main() { + signal input in; + signal output out[2]; + + var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, + 16950150798460657717958625567821834550301663161624707787222815936182638968203]; + + + component n2b = Num2Bits(253); + component escalarMul = EscalarMul(253, base); + + escalarMul.inp[0] <== 0; + escalarMul.inp[1] <== 1; + + var i; + + in ==> n2b.in; + + for (i=0; i<253; i++) { + n2b.out[i] ==> escalarMul.in[i]; + } + + escalarMul.out[0] ==> out[0]; + escalarMul.out[1] ==> out[1]; +} + +component main = Main(); diff --git a/test/circuits/escalarmul_test_min.circom b/test/circuits/escalarmul_test_min.circom new file mode 100644 index 00000000..422e0a81 --- /dev/null +++ b/test/circuits/escalarmul_test_min.circom @@ -0,0 +1,28 @@ +pragma circom 2.0.0; + +include "../../circuits/escalarmul.circom"; + + +template Main() { + signal input in[256]; + signal output out[2]; + + var i; + + var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, + 16950150798460657717958625567821834550301663161624707787222815936182638968203]; + + component escalarMul = EscalarMul(256, base); + + escalarMul.inp[0] <== 0; + escalarMul.inp[1] <== 1; + + for (i=0; i<256; i++) { + in[i] ==> escalarMul.in[i]; + } + + escalarMul.out[0] ==> out[0]; + escalarMul.out[1] ==> out[1]; +} + +component main = Main(); diff --git a/test/circuits/escalarmulany_test.circom b/test/circuits/escalarmulany_test.circom new file mode 100644 index 00000000..5e79bbec --- /dev/null +++ b/test/circuits/escalarmulany_test.circom @@ -0,0 +1,30 @@ +pragma circom 2.0.0; + +include "../../circuits/escalarmulany.circom"; +include "../../circuits/bitify.circom"; + +template Main() { + signal input e; + signal input p[2]; + signal output out[2]; + + component n2b = Num2Bits(253); + component escalarMulAny = EscalarMulAny(253); + + escalarMulAny.p[0] <== p[0]; + escalarMulAny.p[1] <== p[1]; + + var i; + + e ==> n2b.in; + + for (i=0; i<253; i++) { + n2b.out[i] ==> escalarMulAny.e[i]; + } + + escalarMulAny.out[0] ==> out[0]; + escalarMulAny.out[1] ==> out[1]; +} + +component main = Main(); + diff --git a/test/circuits/escalarmulfix_test.circom b/test/circuits/escalarmulfix_test.circom new file mode 100644 index 00000000..54cd7bab --- /dev/null +++ b/test/circuits/escalarmulfix_test.circom @@ -0,0 +1,31 @@ +pragma circom 2.0.0; + +include "../../circuits/escalarmulfix.circom"; +include "../../circuits/bitify.circom"; + + +template Main() { + signal input e; + signal output out[2]; + + var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, + 16950150798460657717958625567821834550301663161624707787222815936182638968203]; + + + component n2b = Num2Bits(253); + component escalarMul = EscalarMulFix(253, base); + + var i; + + e ==> n2b.in; + + for (i=0; i<253; i++) { + n2b.out[i] ==> escalarMul.e[i]; + } + + escalarMul.out[0] ==> out[0]; + escalarMul.out[1] ==> out[1]; +} + +component main = Main(); + diff --git a/test/circuits/escalarmulw4table.circom b/test/circuits/escalarmulw4table.circom new file mode 100644 index 00000000..74b43348 --- /dev/null +++ b/test/circuits/escalarmulw4table.circom @@ -0,0 +1,20 @@ +pragma circom 2.0.0; + +include "../../circuits/escalarmulw4table.circom"; + + + + +template Main() { + signal output out[16][2]; + var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, + 16950150798460657717958625567821834550301663161624707787222815936182638968203]; + + var escalarMul[16][2] = EscalarMulW4Table(base, 0); + for (var i=0; i<16; i++) { + out[i][0] <== escalarMul[i][0]; + out[i][1] <== escalarMul[i][1]; + } +} + +component main = Main(); diff --git a/test/circuits/escalarmulw4table_test.circom b/test/circuits/escalarmulw4table_test.circom new file mode 100644 index 00000000..ed2ac41e --- /dev/null +++ b/test/circuits/escalarmulw4table_test.circom @@ -0,0 +1,19 @@ +pragma circom 2.0.0; + +include "../../circuits/escalarmulw4table.circom"; + + +template Main() { + signal input in; + signal output out[16][2]; + var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, + 16950150798460657717958625567821834550301663161624707787222815936182638968203]; + + var escalarMul[16][2] = EscalarMulW4Table(base, 0); + for (var i=0; i<16; i++) { + out[i][0] <== escalarMul[i][0]*in; + out[i][1] <== escalarMul[i][1]*in; + } +} + +component main = Main(); diff --git a/test/circuits/escalarmulw4table_test3.circom b/test/circuits/escalarmulw4table_test3.circom new file mode 100644 index 00000000..14c0ee89 --- /dev/null +++ b/test/circuits/escalarmulw4table_test3.circom @@ -0,0 +1,19 @@ +pragma circom 2.0.0; + +include "../../circuits/escalarmulw4table.circom"; + + +template Main() { + signal input in; + signal output out[16][2]; + var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, + 16950150798460657717958625567821834550301663161624707787222815936182638968203]; + + var escalarMul[16][2] = EscalarMulW4Table(base, 3); + for (var i=0; i<16; i++) { + out[i][0] <== escalarMul[i][0]*in; + out[i][1] <== escalarMul[i][1]*in; + } +} + +component main = Main(); diff --git a/test/circuits/greatereqthan.circom b/test/circuits/greatereqthan.circom new file mode 100644 index 00000000..8e53f940 --- /dev/null +++ b/test/circuits/greatereqthan.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/comparators.circom"; + +component main = GreaterEqThan(32); diff --git a/test/circuits/greaterthan.circom b/test/circuits/greaterthan.circom new file mode 100644 index 00000000..d2142379 --- /dev/null +++ b/test/circuits/greaterthan.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/comparators.circom"; + +component main = GreaterThan(32); diff --git a/test/circuits/isequal.circom b/test/circuits/isequal.circom new file mode 100644 index 00000000..eb4fcc4d --- /dev/null +++ b/test/circuits/isequal.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/comparators.circom"; + +component main = IsEqual(); diff --git a/test/circuits/iszero.circom b/test/circuits/iszero.circom new file mode 100644 index 00000000..0ce848a4 --- /dev/null +++ b/test/circuits/iszero.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/comparators.circom"; + +component main = IsZero(); diff --git a/test/circuits/lesseqthan.circom b/test/circuits/lesseqthan.circom new file mode 100644 index 00000000..9b9a89b4 --- /dev/null +++ b/test/circuits/lesseqthan.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/comparators.circom"; + +component main = LessEqThan(32); diff --git a/test/circuits/lessthan.circom b/test/circuits/lessthan.circom new file mode 100644 index 00000000..78660b76 --- /dev/null +++ b/test/circuits/lessthan.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/comparators.circom"; + +component main = LessThan(32); diff --git a/test/circuits/mimc_sponge_hash_test.circom b/test/circuits/mimc_sponge_hash_test.circom new file mode 100644 index 00000000..68a8ab59 --- /dev/null +++ b/test/circuits/mimc_sponge_hash_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/mimcsponge.circom"; + +component main = MiMCSponge(2, 220, 3); diff --git a/test/circuits/mimc_sponge_test.circom b/test/circuits/mimc_sponge_test.circom new file mode 100644 index 00000000..367c6159 --- /dev/null +++ b/test/circuits/mimc_sponge_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/mimcsponge.circom"; + +component main = MiMCFeistel(220); diff --git a/test/circuits/mimc_test.circom b/test/circuits/mimc_test.circom new file mode 100644 index 00000000..2325e65e --- /dev/null +++ b/test/circuits/mimc_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/mimc.circom"; + +component main = MiMC7(91); diff --git a/test/circuits/montgomery2edwards.circom b/test/circuits/montgomery2edwards.circom new file mode 100644 index 00000000..af344a4c --- /dev/null +++ b/test/circuits/montgomery2edwards.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/montgomery.circom"; + +component main = Montgomery2Edwards(); diff --git a/test/circuits/montgomeryadd.circom b/test/circuits/montgomeryadd.circom new file mode 100644 index 00000000..8d0e73b3 --- /dev/null +++ b/test/circuits/montgomeryadd.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/montgomery.circom"; + +component main = MontgomeryAdd(); diff --git a/test/circuits/montgomerydouble.circom b/test/circuits/montgomerydouble.circom new file mode 100644 index 00000000..51909dbd --- /dev/null +++ b/test/circuits/montgomerydouble.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/montgomery.circom"; + +component main = MontgomeryDouble(); diff --git a/test/circuits/mux1_1.circom b/test/circuits/mux1_1.circom new file mode 100644 index 00000000..ff13ae22 --- /dev/null +++ b/test/circuits/mux1_1.circom @@ -0,0 +1,33 @@ +pragma circom 2.0.0; + +include "../../circuits/mux1.circom"; +include "../../circuits/bitify.circom"; + + +template Constants() { + var i; + signal output out[2]; + + out[0] <== 37; + out[1] <== 47; +} + +template Main() { + var i; + signal input selector;//private + signal output out; + + component mux = Mux1(); + component n2b = Num2Bits(1); + component cst = Constants(); + + selector ==> n2b.in; + n2b.out[0] ==> mux.s; + for (i=0; i<2; i++) { + cst.out[i] ==> mux.c[i]; + } + + mux.out ==> out; +} + +component main = Main(); diff --git a/test/circuits/mux2_1.circom b/test/circuits/mux2_1.circom new file mode 100644 index 00000000..419fe625 --- /dev/null +++ b/test/circuits/mux2_1.circom @@ -0,0 +1,37 @@ +pragma circom 2.0.0; + +include "../../circuits/mux2.circom"; +include "../../circuits/bitify.circom"; + + +template Constants() { + var i; + signal output out[4]; + + out[0] <== 37; + out[1] <== 47; + out[2] <== 53; + out[3] <== 71; +} + +template Main() { + var i; + signal input selector;//private + signal output out; + + component mux = Mux2(); + component n2b = Num2Bits(2); + component cst = Constants(); + + selector ==> n2b.in; + for (i=0; i<2; i++) { + n2b.out[i] ==> mux.s[i]; + } + for (i=0; i<4; i++) { + cst.out[i] ==> mux.c[i]; + } + + mux.out ==> out; +} + +component main = Main(); diff --git a/test/circuits/mux3_1.circom b/test/circuits/mux3_1.circom new file mode 100644 index 00000000..8723c8ba --- /dev/null +++ b/test/circuits/mux3_1.circom @@ -0,0 +1,41 @@ +pragma circom 2.0.0; + +include "../../circuits/mux3.circom"; +include "../../circuits/bitify.circom"; + + +template Constants() { + var i; + signal output out[8]; + + out[0] <== 37; + out[1] <== 47; + out[2] <== 53; + out[3] <== 71; + out[4] <== 89; + out[5] <== 107; + out[6] <== 163; + out[7] <== 191; +} + +template Main() { + var i; + signal input selector;//private + signal output out; + + component mux = Mux3(); + component n2b = Num2Bits(3); + component cst = Constants(); + + selector ==> n2b.in; + for (i=0; i<3; i++) { + n2b.out[i] ==> mux.s[i]; + } + for (i=0; i<8; i++) { + cst.out[i] ==> mux.c[i]; + } + + mux.out ==> out; +} + +component main = Main(); diff --git a/test/circuits/mux4_1.circom b/test/circuits/mux4_1.circom new file mode 100644 index 00000000..c9b10dda --- /dev/null +++ b/test/circuits/mux4_1.circom @@ -0,0 +1,56 @@ +pragma circom 2.0.0; + +include "../../circuits/mux4.circom"; +include "../../circuits/bitify.circom"; + + +template Constants() { + var i; + signal output out[16]; + + out[0] <== 123; + out[1] <== 456; + out[2] <== 789; + out[3] <== 012; + out[4] <== 111; + out[5] <== 222; + out[6] <== 333; + out[7] <== 4546; + out[8] <== 134523; + out[9] <== 44356; + out[10] <== 15623; + out[11] <== 4566; + out[12] <== 1223; + out[13] <== 4546; + out[14] <== 4256; + out[15] <== 4456; + +/* + for (i=0;i<16; i++) { + out[i] <== i*2+100; + } +*/ + +} + +template Main() { + var i; + signal input selector;//private + signal output out; + + component mux = Mux4(); + component n2b = Num2Bits(4); + component cst = Constants(); + + selector ==> n2b.in; + for (i=0; i<4; i++) { + n2b.out[i] ==> mux.s[i]; + } + for (i=0; i<16; i++) { + cst.out[i] ==> mux.c[i]; + } + + mux.out ==> out; +} + +component main = Main(); diff --git a/test/circuits/pedersen2_test.circom b/test/circuits/pedersen2_test.circom new file mode 100644 index 00000000..c407d53d --- /dev/null +++ b/test/circuits/pedersen2_test.circom @@ -0,0 +1,34 @@ +pragma circom 2.0.0; + +include "../../circuits/pedersen.circom"; +include "../../circuits/bitify.circom"; + + +template Main() { + signal input in; + signal output out[2]; + + component pedersen = Pedersen(256); + + component n2b; + n2b = Num2Bits(253); + + var i; + + in ==> n2b.in; + + for (i=0; i<253; i++) { + pedersen.in[i] <== n2b.out[i]; + } + + for (i=253; i<256; i++) { + pedersen.in[i] <== 0; + } + + pedersen.out[0] ==> out[0]; + pedersen.out[1] ==> out[1]; +} + +component main = Main(); + + diff --git a/test/circuits/pedersen_test.circom b/test/circuits/pedersen_test.circom new file mode 100644 index 00000000..eba561cb --- /dev/null +++ b/test/circuits/pedersen_test.circom @@ -0,0 +1,31 @@ +pragma circom 2.0.0; + +include "../../circuits/pedersen_old.circom"; +include "../../circuits/bitify.circom"; + + +template Main() { + signal input in[2]; + signal output out[2]; + + component pedersen = Pedersen(250*2); + + component n2b[2]; + n2b[0] = Num2Bits(250); + n2b[1] = Num2Bits(250); + + var i; + + in[0] ==> n2b[0].in; + in[1] ==> n2b[1].in; + + for (i=0; i<250; i++) { + n2b[0].out[i] ==> pedersen.in[i]; + n2b[1].out[i] ==> pedersen.in[250+i]; + } + + pedersen.out[0] ==> out[0]; + pedersen.out[1] ==> out[1]; +} + +component main = Main(); diff --git a/test/circuits/pointbits_loopback.circom b/test/circuits/pointbits_loopback.circom new file mode 100644 index 00000000..cbba8fcb --- /dev/null +++ b/test/circuits/pointbits_loopback.circom @@ -0,0 +1,25 @@ +pragma circom 2.0.0; + +include "../../circuits/pointbits.circom"; + + +template Main() { + signal input in[2]; + + var i; + + component p2b = Point2Bits_Strict(); + component b2p = Bits2Point_Strict(); + + p2b.in[0] <== in[0]; + p2b.in[1] <== in[1]; + + for (i=0; i<256; i++) { + b2p.in[i] <== p2b.out[i]; + } + + b2p.out[0] === in[0]; + b2p.out[1] === in[1]; +} + +component main = Main(); diff --git a/test/circuits/poseidon3_test.circom b/test/circuits/poseidon3_test.circom new file mode 100644 index 00000000..1b06c187 --- /dev/null +++ b/test/circuits/poseidon3_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/poseidon.circom"; + +component main = Poseidon(2); diff --git a/test/circuits/poseidon6_test.circom b/test/circuits/poseidon6_test.circom new file mode 100644 index 00000000..83cd1cfb --- /dev/null +++ b/test/circuits/poseidon6_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/poseidon.circom"; + +component main = Poseidon(5); diff --git a/test/circuits/sha256_2_test.circom b/test/circuits/sha256_2_test.circom new file mode 100644 index 00000000..13a445da --- /dev/null +++ b/test/circuits/sha256_2_test.circom @@ -0,0 +1,17 @@ +pragma circom 2.0.0; + +include "../../circuits/sha256/sha256_2.circom"; + +template Main() { + signal input a; //private + signal input b; //private + signal output out; + + component sha256_2 = Sha256_2(); + + sha256_2.a <== a; + sha256_2.b <== b; + out <== sha256_2.out; +} + +component main = Main(); diff --git a/test/circuits/sha256_test448.circom b/test/circuits/sha256_test448.circom new file mode 100644 index 00000000..7a9843cd --- /dev/null +++ b/test/circuits/sha256_test448.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/sha256/sha256.circom"; + +component main = Sha256(448); diff --git a/test/circuits/sha256_test512.circom b/test/circuits/sha256_test512.circom new file mode 100644 index 00000000..06db0d39 --- /dev/null +++ b/test/circuits/sha256_test512.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/sha256/sha256.circom"; + +component main = Sha256(512); diff --git a/test/circuits/sign_test.circom b/test/circuits/sign_test.circom new file mode 100644 index 00000000..2dae52c3 --- /dev/null +++ b/test/circuits/sign_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/sign.circom"; + +component main = Sign(); diff --git a/test/circuits/smtprocessor10_test.circom b/test/circuits/smtprocessor10_test.circom new file mode 100644 index 00000000..3030054e --- /dev/null +++ b/test/circuits/smtprocessor10_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/smt/smtprocessor.circom"; + +component main = SMTProcessor(10); diff --git a/test/circuits/smtverifier10_test.circom b/test/circuits/smtverifier10_test.circom new file mode 100644 index 00000000..5b6d47a7 --- /dev/null +++ b/test/circuits/smtverifier10_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/smt/smtverifier.circom"; + +component main = SMTVerifier(10); diff --git a/test/circuits/sum_test.circom b/test/circuits/sum_test.circom new file mode 100644 index 00000000..b0be22f3 --- /dev/null +++ b/test/circuits/sum_test.circom @@ -0,0 +1,33 @@ +pragma circom 2.0.0; + +include "../../circuits/bitify.circom"; +include "../../circuits/binsum.circom"; + +template A() { + signal input a; //private + signal input b; + signal output out; + + var i; + + component n2ba = Num2Bits(32); + component n2bb = Num2Bits(32); + component sum = BinSum(32,2); + component b2n = Bits2Num(32); + + n2ba.in <== a; + n2bb.in <== b; + + for (i=0; i<32; i++) { + sum.in[0][i] <== n2ba.out[i]; + sum.in[1][i] <== n2bb.out[i]; + } + + for (i=0; i<32; i++) { + b2n.in[i] <== sum.out[i]; + } + + out <== b2n.out; +} + +component main = A(); diff --git a/test/comparators.js b/test/comparators.js new file mode 100644 index 00000000..a41bbb8f --- /dev/null +++ b/test/comparators.js @@ -0,0 +1,187 @@ +const chai = require("chai"); +const path = require("path"); +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const tester = require("circom").tester; + +const assert = chai.assert; + +describe("Comparators test", function () { + + this.timeout(100000); + + it("Should create a iszero circuit", async() => { + const circuit = await tester(path.join(__dirname, "circuits", "iszero.circom")); + + let witness; + witness = await circuit.calculateWitness({ "in": 111}, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": 0 }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + }); + it("Should create a isequal circuit", async() => { + const circuit = await tester(path.join(__dirname, "circuits", "isequal.circom")); + + let witness; + witness = await circuit.calculateWitness({ "in": [111,222] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + + witness = await circuit.calculateWitness({ "in": [444,444] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + }); + it("Should create a comparison lessthan", async() => { + const circuit = await tester(path.join(__dirname, "circuits", "lessthan.circom")); + + let witness; + witness = await circuit.calculateWitness({ "in": [333,444] }), true; + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in":[1,1] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [661, 660] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [0, 1] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [0, 444] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [1, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [555, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [0, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + }); + it("Should create a comparison lesseqthan", async() => { + + const circuit = await tester(path.join(__dirname, "circuits", "lesseqthan.circom")); + + let witness; + witness = await circuit.calculateWitness({ "in": [333,444] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in":[1,1] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [661, 660] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [0, 1] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [0, 444] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [1, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [555, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [0, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + }); + it("Should create a comparison greaterthan", async() => { + + const circuit = await tester(path.join(__dirname, "circuits", "greaterthan.circom")); + + let witness; + witness = await circuit.calculateWitness({ "in": [333,444] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in":[1,1] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [661, 660] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [0, 1] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [0, 444] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [1, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [555, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [0, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + }); + it("Should create a comparison greatereqthan", async() => { + const circuit = await tester(path.join(__dirname, "circuits", "greatereqthan.circom")); + + let witness; + witness = await circuit.calculateWitness({ "in": [333,444] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in":[1,1] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [661, 660] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [0, 1] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [0, 444] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(0))); + + witness = await circuit.calculateWitness({ "in": [1, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [555, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + + witness = await circuit.calculateWitness({ "in": [0, 0] }, true); + assert(Fr.eq(Fr.e(witness[0]), Fr.e(1))); + assert(Fr.eq(Fr.e(witness[1]), Fr.e(1))); + }); +}); diff --git a/test/eddsa.js b/test/eddsa.js new file mode 100644 index 00000000..4a9554b4 --- /dev/null +++ b/test/eddsa.js @@ -0,0 +1,71 @@ +const chai = require("chai"); +const path = require("path"); + +const tester = require("circom").tester; + +const eddsa = require("../src/eddsa.js"); +const babyJub = require("../src/babyjub.js"); + +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const assert = chai.assert; + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +function buffer2bits(Fr, buff) { + const res = []; + for (let i=0; i>j)&1) { + res.push(Fr.toString(Fr.one)); + } else { + res.push(Fr.toString(Fr.zero)); + } + } + } + return res; +} + + +describe("EdDSA test", function () { + let circuit; + + this.timeout(100000); + + before( async () => { + circuit = await tester(path.join(__dirname, "circuits", "eddsa_test.circom")); + }); + + it("Sign a single 10 bytes from 0 to 9", async () => { + const msg = Buffer.from("00010203040506070809", "hex"); + +// const prvKey = crypto.randomBytes(32); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + const pPubKey = babyJub.packPoint(pubKey); + + const signature = eddsa.sign(prvKey, msg); + + const pSignature = eddsa.packSignature(signature); + const uSignature = eddsa.unpackSignature(pSignature); + + assert(eddsa.verify(msg, uSignature, pubKey)); + + const msgBits = buffer2bits(Fr, msg); + const r8Bits = buffer2bits(Fr, pSignature.slice(0, 32)); + const sBits = buffer2bits(Fr, pSignature.slice(32, 64)); + const aBits = buffer2bits(Fr, pPubKey); + + const w = await circuit.calculateWitness({A: aBits, R8: r8Bits, S: sBits, msg: msgBits}, true); + + await circuit.checkConstraints(w); + }); +}); diff --git a/test/eddsa_js.js b/test/eddsa_js.js new file mode 100644 index 00000000..24befd80 --- /dev/null +++ b/test/eddsa_js.js @@ -0,0 +1,88 @@ +const chai = require("chai"); + +const eddsa = require("../src/eddsa.js"); +const babyJub = require("../src/babyjub.js"); + +const assert = chai.assert; + +const utils = require("ffjavascript").utils; + +function buff2hex(buff) { + function i2hex(i) { + return ('0' + i.toString(16)).slice(-2); + } + return Array.from(buff).map(i2hex).join(''); +} + +describe("EdDSA js test", function () { + + this.timeout(100000); + + it("Sign (using Mimc7) a single 10 bytes from 0 to 9", () => { + const msgBuf = Buffer.from("00010203040506070809", "hex"); + const msg = utils.leBuff2int(msgBuf); + + // const prvKey = crypto.randomBytes(32); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + assert.equal(pubKey[0].toString(), + "13277427435165878497778222415993513565335242147425444199013288855685581939618"); + assert.equal(pubKey[1].toString(), + "13622229784656158136036771217484571176836296686641868549125388198837476602820"); + + const pPubKey = babyJub.packPoint(pubKey); + + const signature = eddsa.signMiMC(prvKey, msg); + assert.equal(signature.R8[0].toString(), + "11384336176656855268977457483345535180380036354188103142384839473266348197733"); + assert.equal(signature.R8[1].toString(), + "15383486972088797283337779941324724402501462225528836549661220478783371668959"); + assert.equal(signature.S.toString(), + "2523202440825208709475937830811065542425109372212752003460238913256192595070"); + + const pSignature = eddsa.packSignature(signature); + assert.equal(buff2hex(pSignature), ""+ + "dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+ + "7ed40dab29bf993c928e789d007387998901a24913d44fddb64b1f21fc149405"); + + const uSignature = eddsa.unpackSignature(pSignature); + assert(eddsa.verifyMiMC(msg, uSignature, pubKey)); + + }); + + it("Sign (using Poseidon) a single 10 bytes from 0 to 9", () => { + const msgBuf = Buffer.from("00010203040506070809", "hex"); + const msg = utils.leBuff2int(msgBuf); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + assert.equal(pubKey[0].toString(), + "13277427435165878497778222415993513565335242147425444199013288855685581939618"); + assert.equal(pubKey[1].toString(), + "13622229784656158136036771217484571176836296686641868549125388198837476602820"); + + const pPubKey = babyJub.packPoint(pubKey); + + const signature = eddsa.signPoseidon(prvKey, msg); + assert.equal(signature.R8[0].toString(), + "11384336176656855268977457483345535180380036354188103142384839473266348197733"); + assert.equal(signature.R8[1].toString(), + "15383486972088797283337779941324724402501462225528836549661220478783371668959"); + assert.equal(signature.S.toString(), + "1672775540645840396591609181675628451599263765380031905495115170613215233181"); + + const pSignature = eddsa.packSignature(signature); + assert.equal(buff2hex(pSignature), ""+ + "dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+ + "9d043ece562a8f82bfc0adb640c0107a7d3a27c1c7c1a6179a0da73de5c1b203"); + + const uSignature = eddsa.unpackSignature(pSignature); + assert(eddsa.verifyPoseidon(msg, uSignature, pubKey)); + + }); +}); diff --git a/test/eddsamimc.js b/test/eddsamimc.js new file mode 100644 index 00000000..df3503d2 --- /dev/null +++ b/test/eddsamimc.js @@ -0,0 +1,98 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; + +const eddsa = require("../src/eddsa.js"); +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const assert = chai.assert; + +describe("EdDSA MiMC test", function () { + let circuit; + + this.timeout(100000); + + before( async () => { + circuit = await tester(path.join(__dirname, "circuits", "eddsamimc_test.circom")); + }); + + it("Sign a single number", async () => { + const msg = Scalar.e(1234); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + const signature = eddsa.signMiMC(prvKey, msg); + + assert(eddsa.verifyMiMC(msg, signature, pubKey)); + + const w = await circuit.calculateWitness({ + enabled: 1, + Ax: pubKey[0], + Ay: pubKey[1], + R8x: signature.R8[0], + R8y: signature.R8[1], + S: signature.S, + M: msg}, true); + + + await circuit.checkConstraints(w); + + }); + + it("Detect Invalid signature", async () => { + const msg = Scalar.e(1234); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + + const signature = eddsa.signMiMC(prvKey, msg); + + assert(eddsa.verifyMiMC(msg, signature, pubKey)); + try { + const w = await circuit.calculateWitness({ + enabled: 1, + Ax: pubKey[0], + Ay: pubKey[1], + R8x: Fr.toString(Fr.add(Fr.e(signature.R8[0]), Fr.e(1))), + R8y: Fr.toString(Fr.e(signature.R8[1])), + S: signature.S, + M: msg}, true); + assert(false); + } catch(err) { + assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) ); + } + }); + + + it("Test a dissabled circuit with a bad signature", async () => { + const msg = Scalar.e(1234); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + + const signature = eddsa.signMiMC(prvKey, msg); + + assert(eddsa.verifyMiMC(msg, signature, pubKey)); + + const w = await circuit.calculateWitness({ + enabled: 0, + Ax: pubKey[0], + Ay: pubKey[1], + R8x: Fr.toString(Fr.add(Fr.e(signature.R8[0]), Fr.e(1))), + R8y: Fr.toString(Fr.e(signature.R8[1])), + S: signature.S, + M: msg}, true); + + await circuit.checkConstraints(w); + + }); +}); diff --git a/test/eddsaposeidon.js b/test/eddsaposeidon.js new file mode 100644 index 00000000..ea62272a --- /dev/null +++ b/test/eddsaposeidon.js @@ -0,0 +1,100 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; + +const eddsa = require("../src/eddsa.js"); +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const assert = chai.assert; + +describe("EdDSA Poseidon test", function () { + let circuit; + + this.timeout(100000); + + before( async () => { + circuit = await tester(path.join(__dirname, "circuits", "eddsaposeidon_test.circom")); + }); + + it("Sign a single number", async () => { + const msg = Scalar.e(1234); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + const signature = eddsa.signPoseidon(prvKey, msg); + + assert(eddsa.verifyPoseidon(msg, signature, pubKey)); + + const input = { + enabled: 1, + Ax: pubKey[0], + Ay: pubKey[1], + R8x: signature.R8[0], + R8y: signature.R8[1], + S: signature.S, + M: msg + }; + + // console.log(JSON.stringify(utils.stringifyBigInts(input))); + + const w = await circuit.calculateWitness(input, true); + + await circuit.checkConstraints(w); + }); + + it("Detect Invalid signature", async () => { + const msg = Scalar.e(1234); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + + const signature = eddsa.signPoseidon(prvKey, msg); + + assert(eddsa.verifyPoseidon(msg, signature, pubKey)); + try { + await circuit.calculateWitness({ + enabled: 1, + Ax: pubKey[0], + Ay: pubKey[1], + R8x: Fr.toString(Fr.add(Fr.e(signature.R8[0]), Fr.e(1))), + R8y: signature.R8[1], + S: signature.S, + M: msg}, true); + assert(false); + } catch(err) { + assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) ); + } + }); + + + it("Test a dissabled circuit with a bad signature", async () => { + const msg = Scalar.e(1234); + + const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); + + const pubKey = eddsa.prv2pub(prvKey); + + + const signature = eddsa.signPoseidon(prvKey, msg); + + assert(eddsa.verifyPoseidon(msg, signature, pubKey)); + + const w = await circuit.calculateWitness({ + enabled: 0, + Ax: pubKey[0], + Ay: pubKey[1], + R8x: Fr.toString(Fr.add(Fr.e(signature.R8[0]), Fr.e(1))), + R8y: signature.R8[1], + S: signature.S, + M: msg}, true); + + await circuit.checkConstraints(w); + }); +}); diff --git a/test/escalarmul.js b/test/escalarmul.js new file mode 100644 index 00000000..b059c9e6 --- /dev/null +++ b/test/escalarmul.js @@ -0,0 +1,117 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; +const babyJub = require("../src/babyjub.js"); + +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const assert = chai.assert; + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +describe("Exponentioation test", function () { + this.timeout(100000); + + it("Should generate the Exponentiation table in k=0", async () => { + + const circuit = await tester(path.join(__dirname, "circuits", "escalarmulw4table_test.circom")); + + const w = await circuit.calculateWitness({in: 1}); + + await circuit.checkConstraints(w); + + let g = [ + Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"), + Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203") + ]; + + let dbl= [Fr.e("0"), Fr.e("1")]; + + const expectedOut = []; + + for (let i=0; i<16; i++) { + + expectedOut.push(dbl); + dbl = babyJub.addPoint(dbl,g); + } + + await circuit.assertOut(w, {out: expectedOut}); + + }); + + it("Should generate the Exponentiation table in k=3", async () => { + + const circuit = await tester(path.join(__dirname, "circuits", "escalarmulw4table_test3.circom")); + + const w = await circuit.calculateWitness({in: 1}); + + await circuit.checkConstraints(w); + + let g = [ + Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"), + Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203") + ]; + + for (let i=0; i<12;i++) { + g = babyJub.addPoint(g,g); + } + + let dbl= [Fr.e("0"), Fr.e("1")]; + + const expectedOut = []; + + for (let i=0; i<16; i++) { + expectedOut.push(dbl); + + dbl = babyJub.addPoint(dbl,g); + } + + await circuit.assertOut(w, {out: expectedOut}); + + }); + + it("Should exponentiate g^31", async () => { + + const circuit = await tester(path.join(__dirname, "circuits", "escalarmul_test.circom")); + + const w = await circuit.calculateWitness({"in": 31}); + + await circuit.checkConstraints(w); + + let g = [ + Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"), + Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203") + ]; + + let c = [Fr.e(0), Fr.e(1)]; + + for (let i=0; i<31;i++) { + c = babyJub.addPoint(c,g); + } + + await circuit.assertOut(w, {out: c}); + + const w2 = await circuit.calculateWitness({"in": Fr.add(Fr.shl(Fr.e(1), Fr.e(252)),Fr.one)}); + + c = [g[0], g[1]]; + for (let i=0; i<252;i++) { + c = babyJub.addPoint(c,c); + } + c = babyJub.addPoint(c,g); + + await circuit.assertOut(w2, {out: c}); + + }).timeout(10000000); + + it("Number of constrains for 256 bits", async () => { + + const circuit = await tester(path.join(__dirname, "circuits", "escalarmul_test_min.circom")); + + }).timeout(10000000); + +}); diff --git a/test/escalarmulany.js b/test/escalarmulany.js new file mode 100644 index 00000000..8cd0e639 --- /dev/null +++ b/test/escalarmulany.js @@ -0,0 +1,51 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; + +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +describe("Escalarmul test", function () { + let circuitEMulAny; + + this.timeout(100000); + + let g; + + before( async() => { + circuitEMulAny = await tester(path.join(__dirname, "circuits", "escalarmulany_test.circom")); + g = [ + Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"), + Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203") + ] + }); + + it("Should generate Same escalar mul", async () => { + + const w = await circuitEMulAny.calculateWitness({"e": 1, "p": g}); + + await circuitEMulAny.checkConstraints(w); + + await circuitEMulAny.assertOut(w, {out: g}, true); + + }); + + it("If multiply by order should return 0", async () => { + + const r = Fr.e("2736030358979909402780800718157159386076813972158567259200215660948447373041"); + const w = await circuitEMulAny.calculateWitness({"e": r, "p": g}); + + await circuitEMulAny.checkConstraints(w); + + await circuitEMulAny.assertOut(w, {out: [0,1]}, true); + + }); + +}); + diff --git a/test/escalarmulfix.js b/test/escalarmulfix.js new file mode 100644 index 00000000..f50f205b --- /dev/null +++ b/test/escalarmulfix.js @@ -0,0 +1,93 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; +const babyjub = require("../src/babyjub"); +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const assert = chai.assert; + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +describe("Escalarmul test", function () { + let circuit; + + this.timeout(100000); + + before( async() => { + circuit = await tester(path.join(__dirname, "circuits", "escalarmulfix_test.circom")); + }); + + it("Should generate Same escalar mul", async () => { + + const w = await circuit.calculateWitness({"e": 0}); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {out: [0,1]}, true); + + }); + + it("Should generate Same escalar mul", async () => { + + const w = await circuit.calculateWitness({"e": 1}, true); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {out: babyjub.Base8}); + + }); + + it("Should generate scalar mul of a specific constant", async () => { + + const s = Fr.e("2351960337287830298912035165133676222414898052661454064215017316447594616519"); + const base8 = [ + Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"), + Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203") + ]; + + const w = await circuit.calculateWitness({"e": s}, true); + + await circuit.checkConstraints(w); + + const expectedRes = babyjub.mulPointEscalar(base8, s); + + await circuit.assertOut(w, {out: expectedRes}); + + }); + + it("Should generate scalar mul of the firsts 50 elements", async () => { + + const base8 = [ + Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"), + Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203") + ]; + + for (let i=0; i<50; i++) { + const s = Fr.e(i); + + const w = await circuit.calculateWitness({"e": s}, true); + + await circuit.checkConstraints(w); + + const expectedRes = babyjub.mulPointEscalar(base8, s); + + await circuit.assertOut(w, {out: expectedRes}); + } + }); + + it("If multiply by order should return 0", async () => { + + const w = await circuit.calculateWitness({"e": babyjub.subOrder }, true); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {out: [0,1]}); + }); + +}); + diff --git a/test/helpers/printsignal.js b/test/helpers/printsignal.js new file mode 100644 index 00000000..796274d7 --- /dev/null +++ b/test/helpers/printsignal.js @@ -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); +}; diff --git a/test/helpers/sha256.js b/test/helpers/sha256.js new file mode 100644 index 00000000..ec58ee1d --- /dev/null +++ b/test/helpers/sha256.js @@ -0,0 +1,178 @@ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* SHA-256 (FIPS 180-4) implementation in JavaScript (c) Chris Veness 2002-2017 */ +/* MIT Licence */ +/* www.movable-type.co.uk/scripts/sha256.html */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +'use strict'; + + +/** + * SHA-256 hash function reference implementation. + * + * This is an annotated direct implementation of FIPS 180-4, without any optimisations. It is + * intended to aid understanding of the algorithm rather than for production use. + * + * While it could be used where performance is not critical, I would recommend using the ‘Web + * Cryptography API’ (developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest) for the browser, + * or the ‘crypto’ library (nodejs.org/api/crypto.html#crypto_class_hash) in Node.js. + * + * See csrc.nist.gov/groups/ST/toolkit/secure_hashing.html + * csrc.nist.gov/groups/ST/toolkit/examples.html + */ +class Sha256 { + + /** + * Generates SHA-256 hash of string. + * + * @param {string} msg - (Unicode) string to be hashed. + * @param {Object} [options] + * @param {string} [options.msgFormat=string] - Message format: 'string' for JavaScript string + * (gets converted to UTF-8 for hashing); 'hex-bytes' for string of hex bytes ('616263' ≡ 'abc') . + * @param {string} [options.outFormat=hex] - Output format: 'hex' for string of contiguous + * hex bytes; 'hex-w' for grouping hex bytes into groups of (4 byte / 8 character) words. + * @returns {string} Hash of msg as hex character string. + */ + static hash(msg, options) { + const defaults = { msgFormat: 'string', outFormat: 'hex' }; + const opt = Object.assign(defaults, options); + + // note use throughout this routine of 'n >>> 0' to coerce Number 'n' to unsigned 32-bit integer + + switch (opt.msgFormat) { + default: // default is to convert string to UTF-8, as SHA only deals with byte-streams + case 'string': msg = utf8Encode(msg); break; + case 'hex-bytes':msg = hexBytesToString(msg); break; // mostly for running tests + } + + // constants [§4.2.2] + const K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ]; + + // initial hash value [§5.3.3] + const H = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ]; + + // PREPROCESSING [§6.2.1] + + msg += String.fromCharCode(0x80); // add trailing '1' bit (+ 0's padding) to string [§5.1.1] + + // convert string msg into 512-bit blocks (array of 16 32-bit integers) [§5.2.1] + const l = msg.length/4 + 2; // length (in 32-bit integers) of msg + ‘1’ + appended length + const N = Math.ceil(l/16); // number of 16-integer (512-bit) blocks required to hold 'l' ints + const M = new Array(N); // message M is N×16 array of 32-bit integers + + for (let i=0; i>> 32, but since JS converts + // bitwise-op args to 32 bits, we need to simulate this by arithmetic operators + const lenHi = ((msg.length-1)*8) / Math.pow(2, 32); + const lenLo = ((msg.length-1)*8) >>> 0; + M[N-1][14] = Math.floor(lenHi); + M[N-1][15] = lenLo; + + // HASH COMPUTATION [§6.2.2] + + for (let i=0; i>> 0; + } + + // 2 - initialise working variables a, b, c, d, e, f, g, h with previous hash value + let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7]; + + // 3 - main loop (note '>>> 0' for 'addition modulo 2^32') + for (let t=0; t<64; t++) { + const T1 = h + Sha256.Σ1(e) + Sha256.Ch(e, f, g) + K[t] + W[t]; + const T2 = Sha256.Σ0(a) + Sha256.Maj(a, b, c); + h = g; + g = f; + f = e; + e = (d + T1) >>> 0; + d = c; + c = b; + b = a; + a = (T1 + T2) >>> 0; + } + + // 4 - compute the new intermediate hash value (note '>>> 0' for 'addition modulo 2^32') + H[0] = (H[0]+a) >>> 0; + H[1] = (H[1]+b) >>> 0; + H[2] = (H[2]+c) >>> 0; + H[3] = (H[3]+d) >>> 0; + H[4] = (H[4]+e) >>> 0; + H[5] = (H[5]+f) >>> 0; + H[6] = (H[6]+g) >>> 0; + H[7] = (H[7]+h) >>> 0; + } + + // convert H0..H7 to hex strings (with leading zeros) + for (let h=0; h prev + String.fromCharCode(curr), ''); + } catch (e) { // no TextEncoder available? + return unescape(encodeURIComponent(str)); // monsur.hossa.in/2012/07/20/utf-8-in-javascript.html + } + } + + function hexBytesToString(hexStr) { // convert string of hex numbers to a string of chars (eg '616263' -> 'abc'). + const str = hexStr.replace(' ', ''); // allow space-separated groups + return str=='' ? '' : str.match(/.{2}/g).map(byte => String.fromCharCode(parseInt(byte, 16))).join(''); + } + } + + + + /** + * Rotates right (circular right shift) value x by n positions [§3.2.4]. + * @private + */ + static ROTR(n, x) { + return (x >>> n) | (x << (32-n)); + } + + + /** + * Logical functions [§4.1.2]. + * @private + */ + static Σ0(x) { return Sha256.ROTR(2, x) ^ Sha256.ROTR(13, x) ^ Sha256.ROTR(22, x); } + static Σ1(x) { return Sha256.ROTR(6, x) ^ Sha256.ROTR(11, x) ^ Sha256.ROTR(25, x); } + static σ0(x) { return Sha256.ROTR(7, x) ^ Sha256.ROTR(18, x) ^ (x>>>3); } + static σ1(x) { return Sha256.ROTR(17, x) ^ Sha256.ROTR(19, x) ^ (x>>>10); } + static Ch(x, y, z) { return (x & y) ^ (~x & z); } // 'choice' + static Maj(x, y, z) { return (x & y) ^ (x & z) ^ (y & z); } // 'majority' + +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +if (typeof module != 'undefined' && module.exports) module.exports = Sha256; // ≡ export default Sha256 + diff --git a/test/mimccircuit.js b/test/mimccircuit.js new file mode 100644 index 00000000..5601811b --- /dev/null +++ b/test/mimccircuit.js @@ -0,0 +1,25 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; + +const mimcjs = require("../src/mimc7.js"); + +describe("MiMC Circuit test", function () { + let circuit; + + this.timeout(100000); + + before( async () => { + circuit = await tester(path.join(__dirname, "circuits", "mimc_test.circom")); + }); + + it("Should check constrain", async () => { + const w = await circuit.calculateWitness({x_in: 1, k: 2}, true); + + const res2 = mimcjs.hash(1,2,91); + + await circuit.assertOut(w, {out: res2}); + + await circuit.checkConstraints(w); + }); +}); diff --git a/test/mimccontract.js b/test/mimccontract.js new file mode 100644 index 00000000..9c135d5b --- /dev/null +++ b/test/mimccontract.js @@ -0,0 +1,48 @@ +const ganache = require("ganache-cli"); +const Web3 = require("web3"); +const chai = require("chai"); +const mimcGenContract = require("../src/mimc_gencontract.js"); +const mimcjs = require("../src/mimc7.js"); + + +const assert = chai.assert; +const log = (msg) => { if (process.env.MOCHA_VERBOSE) console.log(msg); }; + +const SEED = "mimc"; + +describe("MiMC Smart contract test", function () { + let testrpc; + let web3; + let mimc; + let accounts; + + this.timeout(100000); + + before(async () => { + web3 = new Web3(ganache.provider(), null, { transactionConfirmationBlocks: 1 }); + accounts = await web3.eth.getAccounts(); + }); + + it("Should deploy the contract", async () => { + const C = new web3.eth.Contract(mimcGenContract.abi); + + mimc = await C.deploy({ + data: mimcGenContract.createCode(SEED, 91), + arguments: [] + }).send({ + gas: 1500000, + gasPrice: '30000000000000', + from: accounts[0] + }).on("error", (error) => { + console.log("ERROR: "+error); + }); + }); + + it("Shold calculate the mimic correctly", async () => { + const res = await mimc.methods.MiMCpe7(1,2).call(); + const res2 = await mimcjs.hash(1,2,91); + + assert.equal(res.toString(), res2.toString()); + }); +}); + diff --git a/test/mimcspongecircuit.js b/test/mimcspongecircuit.js new file mode 100644 index 00000000..32055340 --- /dev/null +++ b/test/mimcspongecircuit.js @@ -0,0 +1,37 @@ +const path = require("path"); +const tester = require("circom").tester; + +const mimcjs = require("../src/mimcsponge.js"); + + +describe("MiMC Sponge Circuit test", function () { + let circuit; + + this.timeout(100000); + + it("Should check permutation", async () => { + + circuit = await tester(path.join(__dirname, "circuits", "mimc_sponge_test.circom")); + + const w = await circuit.calculateWitness({xL_in: 1, xR_in: 2, k: 3}); + + const out2 = mimcjs.hash(1,2,3); + + await circuit.assertOut(w, {xL_out: out2.xL, xR_out: out2.xR}); + + await circuit.checkConstraints(w); + + }); + + it("Should check hash", async () => { + circuit = await tester(path.join(__dirname, "circuits", "mimc_sponge_hash_test.circom")); + + const w = await circuit.calculateWitness({ins: [1, 2], k: 0}); + + const out2 = mimcjs.multiHash([1,2], 0, 3); + + await circuit.assertOut(w, {outs: out2}); + + await circuit.checkConstraints(w); + }); +}); diff --git a/test/mimcspongecontract.js b/test/mimcspongecontract.js new file mode 100644 index 00000000..a2e7394c --- /dev/null +++ b/test/mimcspongecontract.js @@ -0,0 +1,43 @@ +const ganache = require("ganache-cli"); +const Web3 = require("web3"); +const chai = require("chai"); +const mimcGenContract = require("../src/mimcsponge_gencontract.js"); +const mimcjs = require("../src/mimcsponge.js"); + + +const assert = chai.assert; +const log = (msg) => { if (process.env.MOCHA_VERBOSE) console.log(msg); }; + +const SEED = "mimcsponge"; + +describe("MiMC Sponge Smart contract test", () => { + let testrpc; + let web3; + let mimc; + let accounts; + + before(async () => { + web3 = new Web3(ganache.provider(), null, { transactionConfirmationBlocks: 1 }); + accounts = await web3.eth.getAccounts(); + }); + + it("Should deploy the contract", async () => { + const C = new web3.eth.Contract(mimcGenContract.abi); + + mimc = await C.deploy({ + data: mimcGenContract.createCode(SEED, 220) + }).send({ + gas: 3500000, + from: accounts[0] + }); + }); + + it("Shold calculate the mimc correctly", async () => { + const res = await mimc.methods.MiMCSponge(1,2,3).call(); + const res2 = await mimcjs.hash(1,2,3); + + assert.equal(res.xL.toString(), res2.xL.toString()); + assert.equal(res.xR.toString(), res2.xR.toString()); + }); +}); + diff --git a/test/montgomery.js b/test/montgomery.js new file mode 100644 index 00000000..49c29273 --- /dev/null +++ b/test/montgomery.js @@ -0,0 +1,95 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; +const babyJub = require("../src/babyjub.js"); +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const assert = chai.assert; + +describe("Montgomery test", function () { + let circuitE2M; + let circuitM2E; + let circuitMAdd; + let circuitMDouble; + + let g = [ + Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"), + Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203") + ]; + + let mg, mg2, g2, g3, mg3; + + this.timeout(100000); + before( async() => { + circuitE2M = await tester(path.join(__dirname, "circuits", "edwards2montgomery.circom")); + await circuitE2M.loadSymbols(); + circuitM2E = await tester(path.join(__dirname, "circuits", "montgomery2edwards.circom")); + await circuitM2E.loadSymbols(); + circuitMAdd = await tester(path.join(__dirname, "circuits", "montgomeryadd.circom")); + await circuitMAdd.loadSymbols(); + circuitMDouble = await tester(path.join(__dirname, "circuits", "montgomerydouble.circom")); + await circuitMDouble.loadSymbols(); + }); + it("Convert Edwards to Montgomery and back again", async () => { + let w, xout, yout; + + w = await circuitE2M.calculateWitness({ in: g}, true); + + xout = w[circuitE2M.symbols["main.out[0]"].varIdx]; + yout = w[circuitE2M.symbols["main.out[1]"].varIdx]; + + mg = [xout, yout]; + + w = await circuitM2E.calculateWitness({ in: [xout, yout]}, true); + + xout = w[circuitM2E.symbols["main.out[0]"].varIdx]; + yout = w[circuitM2E.symbols["main.out[1]"].varIdx]; + + assert(Fr.eq(xout, g[0])); + assert(Fr.eq(yout, g[1])); + }); + it("Should double a point", async () => { + let w, xout, yout; + + g2 = babyJub.addPoint(g,g); + + w = await circuitMDouble.calculateWitness({ in: mg}, true); + + xout = w[circuitE2M.symbols["main.out[0]"].varIdx]; + yout = w[circuitE2M.symbols["main.out[1]"].varIdx]; + + mg2 = [xout, yout]; + + w = await circuitM2E.calculateWitness({ in: mg2}, true); + + xout = w[circuitM2E.symbols["main.out[0]"].varIdx]; + yout = w[circuitM2E.symbols["main.out[1]"].varIdx]; + + + assert(Fr.eq(xout, g2[0])); + assert(Fr.eq(yout, g2[1])); + }); + it("Should add a point", async () => { + let w, xout, yout; + + g3 = babyJub.addPoint(g,g2); + + w = await circuitMAdd.calculateWitness({ in1: mg, in2: mg2}, true); + + xout = w[circuitMAdd.symbols["main.out[0]"].varIdx]; + yout = w[circuitMAdd.symbols["main.out[1]"].varIdx]; + + mg3 = [xout, yout]; + + w = await circuitM2E.calculateWitness({ in: mg3}, true); + + xout = w[circuitM2E.symbols["main.out[0]"].varIdx]; + yout = w[circuitM2E.symbols["main.out[1]"].varIdx]; + + assert(Fr.eq(xout, g3[0])); + assert(Fr.eq(yout, g3[1])); + }); +}); diff --git a/test/multiplexer.js b/test/multiplexer.js new file mode 100644 index 00000000..29e2b033 --- /dev/null +++ b/test/multiplexer.js @@ -0,0 +1,101 @@ +const path = require("path"); +const tester = require("circom").tester; +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +describe("Mux4 test", function() { + this.timeout(100000); + it("Should create a constant multiplexer 4", async () => { + + const circuit = await tester(path.join(__dirname, "circuits", "mux4_1.circom")); + + const ct16 = [ + Fr.e("123"), + Fr.e("456"), + Fr.e("789"), + Fr.e("012"), + Fr.e("111"), + Fr.e("222"), + Fr.e("333"), + Fr.e("4546"), + Fr.e("134523"), + Fr.e("44356"), + Fr.e("15623"), + Fr.e("4566"), + Fr.e("1223"), + Fr.e("4546"), + Fr.e("4256"), + Fr.e("4456") + ]; + + for (let i=0; i<16; i++) { + const w = await circuit.calculateWitness({ "selector": i }, true); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {out: ct16[i]}); + } + }); + + it("Should create a constant multiplexer 3", async () => { + + const circuit = await tester(path.join(__dirname, "circuits", "mux3_1.circom")); + + const ct8 = [ + Fr.e("37"), + Fr.e("47"), + Fr.e("53"), + Fr.e("71"), + Fr.e("89"), + Fr.e("107"), + Fr.e("163"), + Fr.e("191") + ]; + + for (let i=0; i<8; i++) { + const w = await circuit.calculateWitness({ "selector": i }, true); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {out: ct8[i]}); + } + }); + it("Should create a constant multiplexer 2", async () => { + + const circuit = await tester(path.join(__dirname, "circuits", "mux2_1.circom")); + + const ct4 = [ + Fr.e("37"), + Fr.e("47"), + Fr.e("53"), + Fr.e("71"), + ]; + + for (let i=0; i<4; i++) { + const w = await circuit.calculateWitness({ "selector": i }, true); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {out: ct4[i]}); + } + }); + it("Should create a constant multiplexer 1", async () => { + + const circuit = await tester(path.join(__dirname, "circuits", "mux1_1.circom")); + + const ct2 = [ + Fr.e("37"), + Fr.e("47"), + ]; + + for (let i=0; i<2; i++) { + const w = await circuit.calculateWitness({ "selector": i }, true); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {out: ct2[i]}); + } + }); +}); diff --git a/test/pedersen.js b/test/pedersen.js new file mode 100644 index 00000000..2002edba --- /dev/null +++ b/test/pedersen.js @@ -0,0 +1,81 @@ +const chai = require("chai"); +const path = require("path"); + +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const tester = require("circom").tester; + +const babyJub = require("../src/babyjub.js"); + +const PBASE = + [ + [Fr.e("10457101036533406547632367118273992217979173478358440826365724437999023779287"),Fr.e("19824078218392094440610104313265183977899662750282163392862422243483260492317")], + [Fr.e("2671756056509184035029146175565761955751135805354291559563293617232983272177"),Fr.e("2663205510731142763556352975002641716101654201788071096152948830924149045094")], + [Fr.e("5802099305472655231388284418920769829666717045250560929368476121199858275951"),Fr.e("5980429700218124965372158798884772646841287887664001482443826541541529227896")], + [Fr.e("7107336197374528537877327281242680114152313102022415488494307685842428166594"),Fr.e("2857869773864086953506483169737724679646433914307247183624878062391496185654")], + [Fr.e("20265828622013100949498132415626198973119240347465898028410217039057588424236"),Fr.e("1160461593266035632937973507065134938065359936056410650153315956301179689506")] + ]; + +describe("Double Pedersen test", function() { + let circuit; + this.timeout(100000); + before( async() => { + + circuit = await tester(path.join(__dirname, "circuits", "pedersen_test.circom")); + + }); + it("Should pedersen at zero", async () => { + + let w; + + w = await circuit.calculateWitness({ in: ["0", "0"]}, true); + + await circuit.assertOut(w, {out: [0,1]}); + + }); + it("Should pedersen at one first generator", async () => { + let w; + + w = await circuit.calculateWitness({ in: ["1", "0"]}, true); + + await circuit.assertOut(w, {out: PBASE[0]}); + + }); + it("Should pedersen at one second generator", async () => { + let w; + + w = await circuit.calculateWitness({ in: ["0", "1"]}, true); + + await circuit.assertOut(w, {out: PBASE[1]}); + + }); + it("Should pedersen at mixed generators", async () => { + let w; + w = await circuit.calculateWitness({ in: ["3", "7"]}, true); + + const r = babyJub.addPoint( + babyJub.mulPointEscalar(PBASE[0], 3), + babyJub.mulPointEscalar(PBASE[1], 7) + ); + + await circuit.assertOut(w, {out: r}); + + }); + it("Should pedersen all ones", async () => { + let w; + + const allOnes = Fr.sub(Fr.shl(Fr.e("1"), Fr.e(250)), Fr.e("1")); + w = await circuit.calculateWitness({ in: [allOnes, allOnes]}, true); + + + const r2 = babyJub.addPoint( + babyJub.mulPointEscalar(PBASE[0], allOnes), + babyJub.mulPointEscalar(PBASE[1], allOnes) + ); + + await circuit.assertOut(w, {out: r2}); + }); +}); diff --git a/test/pedersen2.js b/test/pedersen2.js new file mode 100644 index 00000000..f017b6b0 --- /dev/null +++ b/test/pedersen2.js @@ -0,0 +1,53 @@ +const path = require("path"); + +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const tester = require("circom").tester; + +const babyJub = require("../src/babyjub.js"); +const pedersen = require("../src/pedersenHash.js"); + + +describe("Pedersen test", function() { + let circuit; + this.timeout(100000); + before( async() => { + + circuit = await tester(path.join(__dirname, "circuits", "pedersen2_test.circom")); + }); + it("Should pedersen at zero", async () => { + + let w; + + w = await circuit.calculateWitness({ in: 0}, true); + + const b = Buffer.alloc(32); + + const h = pedersen.hash(b); + const hP = babyJub.unpackPoint(h); + + await circuit.assertOut(w, {out: hP}); + + }); + it("Should pedersen with 253 ones", async () => { + + let w; + + const n = Fr.sub(Fr.shl(Fr.one, Fr.e(253)), Fr.one); + + w = await circuit.calculateWitness({ in: n}, true); + + const b = Buffer.alloc(32); + for (let i=0; i<31; i++) b[i] = 0xFF; + b[31] = 0x1F; + + const h = pedersen.hash(b); + const hP = babyJub.unpackPoint(h); + + await circuit.assertOut(w, {out: hP}); + + }); +}); diff --git a/test/point2bits.js b/test/point2bits.js new file mode 100644 index 00000000..f0697a18 --- /dev/null +++ b/test/point2bits.js @@ -0,0 +1,23 @@ +const path = require("path"); +const tester = require("circom").tester; + +const babyJub = require("../src/babyjub.js"); + + +describe("Point 2 bits test", function() { + let circuit; + this.timeout(100000); + before( async() => { + circuit = await tester(path.join(__dirname, "circuits", "pointbits_loopback.circom")); + }); + it("Should do the both convertions for 8Base", async () => { + const w = await circuit.calculateWitness({ in: babyJub.Base8}, true); + + await circuit.checkConstraints(w); + }); + it("Should do the both convertions for Zero point", async () => { + const w = await circuit.calculateWitness({ in: [0, 1]}, true); + + await circuit.checkConstraints(w); + }); +}); diff --git a/test/poseidoncircuit.js b/test/poseidoncircuit.js new file mode 100644 index 00000000..ede13b1b --- /dev/null +++ b/test/poseidoncircuit.js @@ -0,0 +1,60 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; + +const poseidon = require("../src/poseidon.js"); + +const assert = chai.assert; + +describe("Poseidon Circuit test", function () { + let circuit6; + let circuit3; + + this.timeout(100000); + + before( async () => { + circuit6 = await tester(path.join(__dirname, "circuits", "poseidon6_test.circom")); + circuit3 = await tester(path.join(__dirname, "circuits", "poseidon3_test.circom")); + }); + + it("Should check constrain of hash([1, 2]) t=6", async () => { + const w = await circuit6.calculateWitness({inputs: [1, 2, 0,0,0]}, true); + + const res2 = poseidon([1,2,0,0,0]); + + assert.equal("1018317224307729531995786483840663576608797660851238720571059489595066344487", res2.toString()); + await circuit6.assertOut(w, {out : res2}); + await circuit6.checkConstraints(w); + }); + + it("Should check constrain of hash([3, 4]) t=6", async () => { + const w = await circuit6.calculateWitness({inputs: [3, 4,5,10,23]}); + + const res2 = poseidon([3, 4,5,10,23]); + + assert.equal("13034429309846638789535561449942021891039729847501137143363028890275222221409", res2.toString()); + await circuit6.assertOut(w, {out : res2}); + await circuit6.checkConstraints(w); + }); + + + it("Should check constrain of hash([1, 2]) t=3", async () => { + const w = await circuit3.calculateWitness({inputs: [1, 2]}); + + const res2 = poseidon([1,2]); + + assert.equal("7853200120776062878684798364095072458815029376092732009249414926327459813530", res2.toString()); + await circuit3.assertOut(w, {out : res2}); + await circuit3.checkConstraints(w); + }); + + it("Should check constrain of hash([3, 4]) t=3", async () => { + const w = await circuit3.calculateWitness({inputs: [3, 4]}); + + const res2 = poseidon([3, 4]); + + assert.equal("14763215145315200506921711489642608356394854266165572616578112107564877678998", res2.toString()); + await circuit3.assertOut(w, {out : res2}); + await circuit3.checkConstraints(w); + }); +}); diff --git a/test/poseidoncontract.js b/test/poseidoncontract.js new file mode 100644 index 00000000..f53638de --- /dev/null +++ b/test/poseidoncontract.js @@ -0,0 +1,65 @@ +const ganache = require("ganache-cli"); +const Web3 = require("web3"); +const chai = require("chai"); +const poseidonGenContract = require("../src/poseidon_gencontract.js"); +const poseidon = require("../src/poseidon.js"); + +const assert = chai.assert; +const log = (msg) => { if (process.env.MOCHA_VERBOSE) console.log(msg); }; + +describe("Poseidon Smart contract test", function () { + let testrpc; + let web3; + let poseidon6; + let poseidon3; + let accounts; + this.timeout(100000); + + before(async () => { + web3 = new Web3(ganache.provider(), null, { transactionConfirmationBlocks: 1 }); + accounts = await web3.eth.getAccounts(); + }); + + it("Should deploy the contract", async () => { + const C6 = new web3.eth.Contract(poseidonGenContract.generateABI(5)); + const C3 = new web3.eth.Contract(poseidonGenContract.generateABI(2)); + + poseidon6 = await C6.deploy({ + data: poseidonGenContract.createCode(5) + }).send({ + gas: 5000000, + from: accounts[0] + }); + poseidon3 = await C3.deploy({ + data: poseidonGenContract.createCode(2) + }).send({ + gas: 5000000, + from: accounts[0] + }); + }); + + it("Should calculate the poseidon correctly t=6", async () => { + + const res = await poseidon6.methods.poseidon([1,2, 0, 0, 0]).call(); + + // console.log("Cir: " + bigInt(res.toString(16)).toString(16)); + + const res2 = poseidon([1,2, 0, 0, 0]); + // console.log("Ref: " + bigInt(res2).toString(16)); + + assert.equal(res.toString(), res2.toString()); + }); + it("Should calculate the poseidon correctly t=3", async () => { + + const res = await poseidon3.methods.poseidon([1,2]).call(); + + // console.log("Cir: " + bigInt(res.toString(16)).toString(16)); + + const res2 = poseidon([1,2]); + // console.log("Ref: " + bigInt(res2).toString(16)); + + assert.equal(res.toString(), res2.toString()); + }); + +}); + diff --git a/test/poseidonjs.js b/test/poseidonjs.js new file mode 100644 index 00000000..96e5e65c --- /dev/null +++ b/test/poseidonjs.js @@ -0,0 +1,15 @@ +const chai = require("chai"); +const assert = chai.assert; + +const poseidon = require("../src/poseidon.js"); + +describe("Poseidon Circuit test", function () { + it("Should check constrain reference implementation poseidonperm_x5_254_3", async () => { + const res2 = poseidon([1,2]); + assert.equal("115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a", res2.toString(16)); + }); + it("Should check constrain reference implementation poseidonperm_x5_254_5", async () => { + const res2 = poseidon([1,2,3,4]); + assert.equal("299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465", res2.toString(16)); + }); +}); diff --git a/test/sha256.js b/test/sha256.js new file mode 100644 index 00000000..2490fd96 --- /dev/null +++ b/test/sha256.js @@ -0,0 +1,118 @@ +const chai = require("chai"); +const path = require("path"); +const crypto = require("crypto"); +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const assert = chai.assert; + +const sha256 = require("./helpers/sha256"); + +const tester = require("circom").tester; + +// const printSignal = require("./helpers/printsignal"); + + +function buffer2bitArray(b) { + const res = []; + for (let i=0; i> (7-j) &1)); + } + } + return res; +} + +function bitArray2buffer(a) { + const len = Math.floor((a.length -1 )/8)+1; + const b = new Buffer.alloc(len); + + for (let i=0; i { + const b = new Buffer.alloc(64); + for (let i=0; i<64; i++) { + b[i] = i+1; + } + const a = buffer2bitArray(b); + const b2 = bitArray2buffer(a); + + assert.equal(b.toString("hex"), b2.toString("hex"), true); + }); + + it("Should calculate a hash of 1 compressor", async () => { + const cir = await tester(path.join(__dirname, "circuits", "sha256_2_test.circom")); + + const witness = await cir.calculateWitness({ "a": "1", "b": "2" }, true); + + const b = new Buffer.alloc(54); + b[26] = 1; + b[53] = 2; + + const hash = crypto.createHash("sha256") + .update(b) + .digest("hex"); + const r = "0x" + hash.slice(10); + + const hash2 = sha256.hash(b.toString("hex"), {msgFormat: "hex-bytes"}); + + assert.equal(hash, hash2); + + assert(Fr.eq(witness[1], Fr.e(r))); + }).timeout(1000000); + + it("Should calculate a hash of 2 compressor", async () => { + const cir = await tester(path.join(__dirname, "circuits", "sha256_test512.circom")); + + const b = new Buffer.alloc(64); + for (let i=0; i<64; i++) { + b[i] = i+1; + } + + const hash = crypto.createHash("sha256") + .update(b) + .digest("hex"); + + const arrIn = buffer2bitArray(b); + const witness = await cir.calculateWitness({ "in": arrIn }, true); + + const arrOut = witness.slice(1, 257); + const hash2 = bitArray2buffer(arrOut).toString("hex"); + + assert.equal(hash, hash2); + + }).timeout(1000000); + it ("Should calculate a hash of 2 compressor", async () => { + const cir = await tester(path.join(__dirname, "circuits", "sha256_test448.circom")); + + const testStr = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + + const b = Buffer.from(testStr, "utf8"); + + const hash = crypto.createHash("sha256") + .update(b) + .digest("hex"); + + const arrIn = buffer2bitArray(b); + + const witness = await cir.calculateWitness({ "in": arrIn }, true); + + const arrOut = witness.slice(1, 257); + const hash2 = bitArray2buffer(arrOut).toString("hex"); + + assert.equal(hash, hash2); + }); + +}); diff --git a/test/sign.js b/test/sign.js new file mode 100644 index 00000000..9bb38a5d --- /dev/null +++ b/test/sign.js @@ -0,0 +1,82 @@ +const path = require("path"); +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); +const tester = require("circom").tester; + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +function getBits(v, n) { + const res = []; + for (let i=0; i { + circuit = await tester(path.join(__dirname, "circuits", "sign_test.circom")); + }); + + it("Sign of 0", async () => { + const inp = getBits(Scalar.e(0), 254); + const w = await circuit.calculateWitness({in: inp}, true); + + await circuit.assertOut(w, {sign: 0}); + }); + + it("Sign of 3", async () => { + const inp = getBits(Scalar.e(3), 254); + const w = await circuit.calculateWitness({in: inp}, true); + + await circuit.assertOut(w, {sign: 0}); + }); + + it("Sign of q/2", async () => { + const inp = getBits(Scalar.shr(q, 1), 254); + const w = await circuit.calculateWitness({in: inp}, true); + + await circuit.assertOut(w, {sign: 0}); + }); + + it("Sign of q/2+1", async () => { + const inp = getBits(Scalar.add(Scalar.shr(q, 1), 1) , 254); + const w = await circuit.calculateWitness({in: inp}, true); + + await circuit.assertOut(w, {sign: 1}); + }); + + it("Sign of q-1", async () => { + const inp = getBits(Scalar.sub(q, 1), 254); + const w = await circuit.calculateWitness({in: inp}, true); + + await circuit.assertOut(w, {sign: 1}); + }); + + it("Sign of q", async () => { + const inp = getBits(q, 254); + const w = await circuit.calculateWitness({in: inp}, true); + + await circuit.assertOut(w, {sign: 1}); + }); + + it("Sign of all ones", async () => { + const inp = getBits(Scalar.sub(Scalar.shl(1,254),1), 254); + const w = await circuit.calculateWitness({in: inp}, true); + + await circuit.assertOut(w, {sign: 1}); + }); +}); diff --git a/test/smtjs.js b/test/smtjs.js new file mode 100644 index 00000000..ac7655a6 --- /dev/null +++ b/test/smtjs.js @@ -0,0 +1,176 @@ +const chai = require("chai"); + +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const smt = require("../src/smt.js"); + +const assert = chai.assert; + +describe("SMT Javascript test", function () { + this.timeout(100000); + before( async () => { + }); + + it("Should insert 2 elements and empty them", async () => { + const tree = await smt.newMemEmptyTrie(); + const key1 = Fr.e(111); + const value1 = Fr.e(222); + const key2 = Fr.e(333); + const value2 = Fr.e(444); + + await tree.insert(key1,value1); + await tree.insert(key2,value2); + await tree.delete(key2); + await tree.delete(key1); + + assert(Fr.isZero(tree.root)); + }); + + it("Should insert 3 elements in dferent order and should be the same", async () => { + const keys = [Fr.e(8), Fr.e(9), Fr.e(32)]; + const values = [Fr.e(88), Fr.e(99), Fr.e(3232)]; + const tree1 = await smt.newMemEmptyTrie(); + const tree2 = await smt.newMemEmptyTrie(); + const tree3 = await smt.newMemEmptyTrie(); + const tree4 = await smt.newMemEmptyTrie(); + const tree5 = await smt.newMemEmptyTrie(); + const tree6 = await smt.newMemEmptyTrie(); + + await tree1.insert(keys[0],values[0]); + await tree1.insert(keys[1],values[1]); + await tree1.insert(keys[2],values[2]); + + await tree2.insert(keys[0],values[0]); + await tree2.insert(keys[2],values[2]); + await tree2.insert(keys[1],values[1]); + + await tree3.insert(keys[1],values[1]); + await tree3.insert(keys[0],values[0]); + await tree3.insert(keys[2],values[2]); + + await tree4.insert(keys[1],values[1]); + await tree4.insert(keys[2],values[2]); + await tree4.insert(keys[0],values[0]); + + await tree5.insert(keys[2],values[2]); + await tree5.insert(keys[0],values[0]); + await tree5.insert(keys[1],values[1]); + + await tree6.insert(keys[2],values[2]); + await tree6.insert(keys[1],values[1]); + await tree6.insert(keys[0],values[0]); + + assert(Fr.eq(tree1.root, tree2.root)); + assert(Fr.eq(tree2.root, tree3.root)); + assert(Fr.eq(tree3.root, tree4.root)); + assert(Fr.eq(tree4.root, tree5.root)); + assert(Fr.eq(tree5.root, tree6.root)); + + assert.equal(Object.keys(tree1.db.nodes).length, Object.keys(tree2.db.nodes).length); + assert.equal(Object.keys(tree2.db.nodes).length, Object.keys(tree3.db.nodes).length); + assert.equal(Object.keys(tree3.db.nodes).length, Object.keys(tree4.db.nodes).length); + assert.equal(Object.keys(tree4.db.nodes).length, Object.keys(tree5.db.nodes).length); + assert.equal(Object.keys(tree5.db.nodes).length, Object.keys(tree6.db.nodes).length); + + await tree1.delete(keys[0]); + await tree1.delete(keys[1]); + await tree2.delete(keys[1]); + await tree2.delete(keys[0]); + assert(Fr.eq(tree1.root, tree2.root)); + + await tree3.delete(keys[0]); + await tree3.delete(keys[2]); + await tree4.delete(keys[2]); + await tree4.delete(keys[0]); + assert(Fr.eq(tree3.root, tree4.root)); + + await tree5.delete(keys[1]); + await tree5.delete(keys[2]); + await tree6.delete(keys[2]); + await tree6.delete(keys[1]); + assert(Fr.eq(tree5.root, tree6.root)); + + await tree1.delete(keys[2]); + await tree2.delete(keys[2]); + await tree3.delete(keys[1]); + await tree4.delete(keys[1]); + await tree5.delete(keys[0]); + await tree6.delete(keys[0]); + + assert(Fr.isZero(tree1.root)); + assert(Fr.isZero(tree2.root)); + assert(Fr.isZero(tree3.root)); + assert(Fr.isZero(tree4.root)); + assert(Fr.isZero(tree5.root)); + assert(Fr.isZero(tree6.root)); + + assert.equal(Object.keys(tree1.db.nodes).length, 0); + assert.equal(Object.keys(tree2.db.nodes).length, 0); + assert.equal(Object.keys(tree3.db.nodes).length, 0); + assert.equal(Object.keys(tree4.db.nodes).length, 0); + assert.equal(Object.keys(tree5.db.nodes).length, 0); + assert.equal(Object.keys(tree6.db.nodes).length, 0); + }); + + it("Insert and remove 100 numbers randomly", async () => { + function perm(a) { + const arr = a.slice(); + const rArr = []; + for (let i=0; i { + const tree1 = await smt.newMemEmptyTrie(); + const tree2 = await smt.newMemEmptyTrie(); + + await tree1.insert(8,88); + await tree1.insert(9,99,); + await tree1.insert(32,3232); + + await tree2.insert(8,888); + await tree2.insert(9,999); + await tree2.insert(32,323232); + + await tree1.update(8, 888); + await tree1.update(9, 999); + await tree1.update(32, 323232); + + assert(Fr.eq(tree1.root, tree2.root)); + }); + + it("Should test update with same key-value", async () => { + const tree1 = await smt.newMemEmptyTrie(); + + await tree1.insert(8,88); + await tree1.update(8,88); + + const res = await tree1.db.get(tree1.root); + assert.notEqual(res, undefined); + }); +}); diff --git a/test/smtprocessor.js b/test/smtprocessor.js new file mode 100644 index 00000000..54198160 --- /dev/null +++ b/test/smtprocessor.js @@ -0,0 +1,211 @@ +const chai = require("chai"); +const path = require("path"); +const tester = require("circom").tester; +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const smt = require("../src/smt.js"); + +const assert = chai.assert; + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +async function testInsert(tree, key, value, circuit ) { + + const res = await tree.insert(key,value); + let siblings = res.siblings; + while (siblings.length<10) siblings.push(Fr.e(0)); + + const w = await circuit.calculateWitness({ + fnc: [1,0], + oldRoot: res.oldRoot, + siblings: siblings, + oldKey: res.isOld0 ? 0 : res.oldKey, + oldValue: res.isOld0 ? 0 : res.oldValue, + isOld0: res.isOld0 ? 1 : 0, + newKey: key, + newValue: value + }, true); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {newRoot: res.newRoot}); + +} + +async function testDelete(tree, key, circuit) { + const res = await tree.delete(key); + let siblings = res.siblings; + while (siblings.length<10) siblings.push(Fr.e(0)); + + const w = await circuit.calculateWitness({ + fnc: [1,1], + oldRoot: res.oldRoot, + siblings: siblings, + oldKey: res.isOld0 ? 0 : res.oldKey, + oldValue: res.isOld0 ? 0 : res.oldValue, + isOld0: res.isOld0 ? 1 : 0, + newKey: res.delKey, + newValue: res.delValue + }, true); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {newRoot: res.newRoot}); +} + +async function testUpdate(tree, key, newValue, circuit) { + const res = await tree.update(key, newValue); + let siblings = res.siblings; + while (siblings.length<10) siblings.push(Fr.e(0)); + + const w = await circuit.calculateWitness({ + fnc: [0,1], + oldRoot: res.oldRoot, + siblings: siblings, + oldKey: res.oldKey, + oldValue: res.oldValue, + isOld0: 0, + newKey: res.newKey, + newValue: res.newValue + }); + + await circuit.checkConstraints(w); + + await circuit.assertOut(w, {newRoot: res.newRoot}); +} + + +describe("SMT Processor test", function () { + let circuit; + let tree; + + this.timeout(10000000); + + before( async () => { + circuit = await tester(path.join(__dirname, "circuits", "smtprocessor10_test.circom")); + await circuit.loadSymbols(); + + tree = await smt.newMemEmptyTrie(); + }); + + it("Should verify an insert to an empty tree", async () => { + const key = Fr.e(111); + const value = Fr.e(222); + + await testInsert(tree, key, value, circuit); + }); + + it("It should add another element", async () => { + const key = Fr.e(333); + const value = Fr.e(444); + + await testInsert(tree, key, value, circuit); + }); + + it("Should remove an element", async () => { + await testDelete(tree, 111, circuit); + await testDelete(tree, 333, circuit); + }); + + it("Should test convination of adding and removing 3 elements", async () => { + const keys = [Fr.e(8), Fr.e(9), Fr.e(32)]; + const values = [Fr.e(88), Fr.e(99), Fr.e(3232)]; + const tree1 = await smt.newMemEmptyTrie(); + const tree2 = await smt.newMemEmptyTrie(); + const tree3 = await smt.newMemEmptyTrie(); + const tree4 = await smt.newMemEmptyTrie(); + const tree5 = await smt.newMemEmptyTrie(); + const tree6 = await smt.newMemEmptyTrie(); + + await testInsert(tree1,keys[0],values[0], circuit); + await testInsert(tree1,keys[1],values[1], circuit); + await testInsert(tree1,keys[2],values[2], circuit); + + await testInsert(tree2,keys[0],values[0], circuit); + await testInsert(tree2,keys[2],values[2], circuit); + await testInsert(tree2,keys[1],values[1], circuit); + + await testInsert(tree3,keys[1],values[1], circuit); + await testInsert(tree3,keys[0],values[0], circuit); + await testInsert(tree3,keys[2],values[2], circuit); + + await testInsert(tree4,keys[1],values[1], circuit); + await testInsert(tree4,keys[2],values[2], circuit); + await testInsert(tree4,keys[0],values[0], circuit); + + await testInsert(tree5,keys[2],values[2], circuit); + await testInsert(tree5,keys[0],values[0], circuit); + await testInsert(tree5,keys[1],values[1], circuit); + + await testInsert(tree6,keys[2],values[2], circuit); + await testInsert(tree6,keys[1],values[1], circuit); + await testInsert(tree6,keys[0],values[0], circuit); + + + await testDelete(tree1, keys[0], circuit); + await testDelete(tree1, keys[1], circuit); + await testDelete(tree2, keys[1], circuit); + await testDelete(tree2, keys[0], circuit); + + await testDelete(tree3, keys[0], circuit); + await testDelete(tree3, keys[2], circuit); + await testDelete(tree4, keys[2], circuit); + await testDelete(tree4, keys[0], circuit); + + + await testDelete(tree5, keys[1], circuit); + await testDelete(tree5, keys[2], circuit); + await testDelete(tree6, keys[2], circuit); + await testDelete(tree6, keys[1], circuit); + + await testDelete(tree1, keys[2], circuit); + await testDelete(tree2, keys[2], circuit); + await testDelete(tree3, keys[1], circuit); + await testDelete(tree4, keys[1], circuit); + await testDelete(tree5, keys[0], circuit); + await testDelete(tree6, keys[0], circuit); + }); + + it("Should match a NOp with random vals", async () => { + let siblings = []; + while (siblings.length<10) siblings.push(Fr.e(88)); + const w = await circuit.calculateWitness({ + fnc: [0,0], + oldRoot: 11, + siblings: siblings, + oldKey: 33, + oldValue: 44, + isOld0: 55, + newKey: 66, + newValue: 77 + }); + + const root1 = w[circuit.symbols["main.oldRoot"].varIdx]; + const root2 = w[circuit.symbols["main.newRoot"].varIdx]; + + await circuit.checkConstraints(w); + + assert(Fr.eq(root1, root2)); + }); + it("Should update an element", async () => { + const tree1 = await smt.newMemEmptyTrie(); + const tree2 = await smt.newMemEmptyTrie(); + + await testInsert(tree1,8,88, circuit); + await testInsert(tree1,9,99, circuit); + await testInsert(tree1,32,3232, circuit); + + await testInsert(tree2,8,888, circuit); + await testInsert(tree2,9,999, circuit); + await testInsert(tree2,32,323232, circuit); + + await testUpdate(tree1, 8, 888, circuit); + await testUpdate(tree1, 9, 999, circuit); + await testUpdate(tree1, 32, 323232, circuit); + }); +}); diff --git a/test/smtverifier.js b/test/smtverifier.js new file mode 100644 index 00000000..4b27e9a0 --- /dev/null +++ b/test/smtverifier.js @@ -0,0 +1,139 @@ +const chai = require("chai"); +const path = require("path"); +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); +const tester = require("circom").tester; + +const smt = require("../src/smt.js"); + +const assert = chai.assert; + +function print(circuit, w, s) { + console.log(s + ": " + w[circuit.getSignalIdx(s)]); +} + +async function testInclusion(tree, key, circuit) { + + const res = await tree.find(key); + + assert(res.found); + let siblings = res.siblings; + while (siblings.length<10) siblings.push(Fr.e(0)); + + const w = await circuit.calculateWitness({ + enabled: 1, + fnc: 0, + root: tree.root, + siblings: siblings, + oldKey: 0, + oldValue: 0, + isOld0: 0, + key: key, + value: res.foundValue + }, true); + + await circuit.checkConstraints(w); + +} + +async function testExclusion(tree, key, circuit) { + const res = await tree.find(key); + + assert(!res.found); + let siblings = res.siblings; + while (siblings.length<10) siblings.push(Fr.e(0)); + + const w = await circuit.calculateWitness({ + enabled: 1, + fnc: 1, + root: tree.root, + siblings: siblings, + oldKey: res.isOld0 ? 0 : res.notFoundKey, + oldValue: res.isOld0 ? 0 : res.notFoundValue, + isOld0: res.isOld0 ? 1 : 0, + key: key, + value: 0 + }); + + await circuit.checkConstraints(w); + +} + +describe("SMT Verifier test", function () { + let circuit; + let tree; + + this.timeout(100000); + + before( async () => { + circuit = await tester(path.join(__dirname, "circuits", "smtverifier10_test.circom")); + + tree = await smt.newMemEmptyTrie(); + await tree.insert(7,77); + await tree.insert(8,88); + await tree.insert(32,3232); + }); + + it("Check inclussion in a tree of 3", async () => { + await testInclusion(tree, 7, circuit); + await testInclusion(tree, 8, circuit); + await testInclusion(tree, 32, circuit); + }); + + it("Check exclussion in a tree of 3", async () => { + await testExclusion(tree, 0, circuit); + await testExclusion(tree, 6, circuit); + await testExclusion(tree, 9, circuit); + await testExclusion(tree, 33, circuit); + await testExclusion(tree, 31, circuit); + await testExclusion(tree, 16, circuit); + await testExclusion(tree, 64, circuit); + }); + + it("Check not enabled accepts any thing", async () => { + let siblings = []; + for (let i=0; i<10; i++) siblings.push(i); + + const w = await circuit.calculateWitness({ + enabled: 0, + fnc: 0, + root: 1, + siblings: siblings, + oldKey: 22, + oldValue: 33, + isOld0: 0, + key: 44, + value: 0 + }); + + + await circuit.checkConstraints(w); + }); + + it("Check inclussion Adria case", async () => { + const e1_hi= Fr.e("17124152697573569611556136390143205198134245887034837071647643529178599000839"); + const e1_hv= Fr.e("19650379996168153643111744440707177573540245771926102415571667548153444658179"); + + const e2ok_hi= Fr.e("16498254692537945203721083102154618658340563351558973077349594629411025251262"); + const e2ok_hv= Fr.e("19650379996168153643111744440707177573540245771926102415571667548153444658179"); + + const e2fail_hi= Fr.e("17195092312975762537892237130737365903429674363577646686847513978084990105579"); + const e2fail_hv= Fr.e("19650379996168153643111744440707177573540245771926102415571667548153444658179"); + + const tree1 = await smt.newMemEmptyTrie(); + await tree1.insert(e1_hi,e1_hv); + await tree1.insert(e2ok_hi,e2ok_hv); + + await testInclusion(tree1, e2ok_hi, circuit); + + const tree2 = await smt.newMemEmptyTrie(); + await tree2.insert(e1_hi,e1_hv); + await tree2.insert(e2fail_hi,e2fail_hv); + + await testInclusion(tree2, e2fail_hi, circuit); + }); + + +});