From d04eff6c0d5f80149addb031cf15eba8c8e8e09d Mon Sep 17 00:00:00 2001 From: Jordi Baylina Date: Wed, 18 Sep 2019 17:43:14 +0200 Subject: [PATCH] Optimize optimization and fix out<==in --- src/compiler.js | 167 +++++++++++++++++++++++++------------ src/exec.js | 25 ++++-- test/cases.js | 5 ++ test/circuits/circuit.json | 75 +++++++++++++++++ test/circuits/inout.circom | 18 ++++ 5 files changed, 233 insertions(+), 57 deletions(-) create mode 100644 test/circuits/circuit.json create mode 100644 test/circuits/inout.circom diff --git a/src/compiler.js b/src/compiler.js index 0b53ade..91052c0 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -226,71 +226,134 @@ function reduceConstants(ctx) { } function reduceConstrains(ctx) { - const newConstraints = []; - for (let i=0; i0) { + let nextPossibleConstraints = {}; + for (let i in possibleConstraints) { + if (!ctx.constraints[i]) continue; + const c = ctx.constraints[i]; + + // Swap a and b if b has more variables. + if (Object.keys(c.b).length > Object.keys(c.a).length) { + const aux = c.a; + c.a=c.b; + c.b=aux; + } - // Swap a and b if b has more variables. - if (Object.keys(c.b).length > Object.keys(c.a).length) { - const aux = c.a; - c.a=c.b; - c.b=aux; - } + // Mov to C if possible. + if (isConstant(c.a)) { + const ct = {type: "NUMBER", value: c.a.values["one"]}; + c.c = lc.add(lc.mul(c.b, ct), c.c); + c.a = { type: "LINEARCOMBINATION", values: {} }; + c.b = { type: "LINEARCOMBINATION", values: {} }; + } + if (isConstant(c.b)) { + const ct = {type: "NUMBER", value: c.b.values["one"]}; + c.c = lc.add(lc.mul(c.a, ct), c.c); + c.a = { type: "LINEARCOMBINATION", values: {} }; + c.b = { type: "LINEARCOMBINATION", values: {} }; + } + + if (lc.isZero(c.a) || lc.isZero(c.b)) { + const isolatedSignal = getFirstInternalSignal(ctx, c.c); + if (isolatedSignal) { + + let lSignal = ctx.signals[isolatedSignal]; + while (lSignal.equivalence) { + lSignal = ctx.signals[lSignal.equivalence]; + } - // Mov to C if possible. - if (isConstant(c.a)) { - const ct = {type: "NUMBER", value: c.a.values["one"]}; - c.c = lc.add(lc.mul(c.b, ct), c.c); - c.a = { type: "LINEARCOMBINATION", values: {} }; - c.b = { type: "LINEARCOMBINATION", values: {} }; - } - if (isConstant(c.b)) { - const ct = {type: "NUMBER", value: c.b.values["one"]}; - c.c = lc.add(lc.mul(c.a, ct), c.c); - c.a = { type: "LINEARCOMBINATION", values: {} }; - c.b = { type: "LINEARCOMBINATION", values: {} }; - } - if (lc.isZero(c.a) || lc.isZero(c.b)) { - const isolatedSignal = getFirstInternalSignal(ctx, c.c); - if (isolatedSignal) { - const isolatedSignalEquivalence = { - type: "LINEARCOMBINATION", - values: {} - }; - const invCoef = c.c.values[isolatedSignal].modInv(__P__); - for (const s in c.c.values) { - if (s != isolatedSignal) { - const v = __P__.minus(c.c.values[s]).times(invCoef).mod(__P__); - if (!v.isZero()) { - isolatedSignalEquivalence.values[s] = v; + const isolatedSignalEquivalence = { + type: "LINEARCOMBINATION", + values: {} + }; + const invCoef = c.c.values[isolatedSignal].modInv(__P__); + for (const s in c.c.values) { + if (s != isolatedSignal) { + const v = __P__.minus(c.c.values[s]).times(invCoef).mod(__P__); + if (!v.isZero()) { + isolatedSignalEquivalence.values[s] = v; + } } } - } - for (let j=0; j { assert(witness[1].equals(bigInt(37))); assert(witness[2].equals(bigInt(6))); }); + it("Should compile a code with compute", async () => { + const cirDef = await compiler(path.join(__dirname, "circuits", "inout.circom")); + + assert.equal(cirDef.constraints.length, 1); + }); }); diff --git a/test/circuits/circuit.json b/test/circuits/circuit.json new file mode 100644 index 0000000..c0636c4 --- /dev/null +++ b/test/circuits/circuit.json @@ -0,0 +1,75 @@ +{ + "mainCode": "{\n}\n", + "signalName2Idx": { + "one": 0, + "main.in": 2, + "main.out": 1, + "main.internal.in": 2, + "main.internal.out": 2 + }, + "components": [ + { + "name": "main", + "params": {}, + "template": "InOut", + "inputSignals": 1 + }, + { + "name": "main.internal", + "params": {}, + "template": "Internal", + "inputSignals": 1 + } + ], + "componentName2Idx": { + "main": 0, + "main.internal": 1 + }, + "signals": [ + { + "names": [ + "one" + ], + "triggerComponents": [] + }, + { + "names": [ + "main.out" + ], + "triggerComponents": [] + }, + { + "names": [ + "main.in", + "main.internal.in", + "main.internal.out" + ], + "triggerComponents": [ + 0, + 1 + ] + } + ], + "constraints": [ + [ + {}, + {}, + { + "1": "21888242871839275222246405745257275088548364400416034343698204186575808495616", + "2": "1" + } + ] + ], + "templates": { + "Internal": "function(ctx) {\n ctx.setSignal(\"out\", [], ctx.getSignal(\"in\", []));\n}\n", + "InOut": "function(ctx) {\n ctx.setPin(\"internal\", [], \"in\", [], ctx.getSignal(\"in\", []));\n ctx.setSignal(\"out\", [], ctx.getPin(\"internal\", [], \"out\", []));\n}\n" + }, + "functions": {}, + "nPrvInputs": 0, + "nPubInputs": 1, + "nInputs": 1, + "nOutputs": 1, + "nVars": 3, + "nConstants": 0, + "nSignals": 3 +} \ No newline at end of file diff --git a/test/circuits/inout.circom b/test/circuits/inout.circom new file mode 100644 index 0000000..cf42e36 --- /dev/null +++ b/test/circuits/inout.circom @@ -0,0 +1,18 @@ +template Internal() { + signal input in; + signal output out; + + out <== in; +} + +template InOut() { + signal input in; + signal output out; + + component internal = Internal(); + + internal.in <== in; + internal.out ==> out; +} + +component main = InOut();