mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-06 18:56:40 +01:00
Allows pass signal arrays to a function
This commit is contained in:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -208,9 +208,9 @@
|
|||||||
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
||||||
},
|
},
|
||||||
"circom_runtime": {
|
"circom_runtime": {
|
||||||
"version": "0.1.5",
|
"version": "0.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.8.tgz",
|
||||||
"integrity": "sha512-BT3d9VCrH/rBRbThDXG731JwezKyskxyE46nACO6Tt/jaorn27LDxFDORdAAjyD0RAoBt+6FpaTp3qlYSx7Pjg==",
|
"integrity": "sha512-5ZmzCyidkNPb1zZsJGRXTuWcJ6kW6+gRBtHgf2tFqTh5dUyWVVPH0Zg7AsU2ijPr1AmYZUlme0yORUZK5HrjOA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ffjavascript": "0.2.10",
|
"ffjavascript": "0.2.10",
|
||||||
"fnv-plus": "^1.3.1"
|
"fnv-plus": "^1.3.1"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"circom_runtime": "0.1.5",
|
"circom_runtime": "0.1.8",
|
||||||
"fastfile": "0.0.18",
|
"fastfile": "0.0.18",
|
||||||
"ffiasm": "0.1.1",
|
"ffiasm": "0.1.1",
|
||||||
"ffjavascript": "0.2.22",
|
"ffjavascript": "0.2.22",
|
||||||
|
|||||||
@@ -59,8 +59,9 @@ class CodeBuilderC {
|
|||||||
this.ops.push({op: "SETSIGNAL", component, signal, value});
|
this.ops.push({op: "SETSIGNAL", component, signal, value});
|
||||||
}
|
}
|
||||||
|
|
||||||
getSignal(dLabel, component, signal) {
|
getSignal(dLabel, component, signal, n) {
|
||||||
this.ops.push({op: "GETSIGNAL", dLabel, component, signal});
|
if (typeof(n) == "undefined") n=1;
|
||||||
|
this.ops.push({op: "GETSIGNAL", dLabel, component, signal, n});
|
||||||
}
|
}
|
||||||
|
|
||||||
copyN(dLabel, offset, src, n) {
|
copyN(dLabel, offset, src, n) {
|
||||||
@@ -181,7 +182,7 @@ class CodeBuilderC {
|
|||||||
} else if (o.op == "SETSIGNAL") {
|
} else if (o.op == "SETSIGNAL") {
|
||||||
code.push(`ctx->setSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${ref2src(o.value)});`);
|
code.push(`ctx->setSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${ref2src(o.value)});`);
|
||||||
} else if (o.op == "GETSIGNAL") {
|
} else if (o.op == "GETSIGNAL") {
|
||||||
code.push(`ctx->getSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${o.dLabel});`);
|
code.push(`ctx->multiGetSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${o.dLabel}, ${o.n});`);
|
||||||
} else if (o.op == "COPYN") {
|
} else if (o.op == "COPYN") {
|
||||||
const oS = ref2src(o.offset);
|
const oS = ref2src(o.offset);
|
||||||
const dLabel = (oS != "0") ? (o.dLabel + "+" + oS) : o.dLabel;
|
const dLabel = (oS != "0") ? (o.dLabel + "+" + oS) : o.dLabel;
|
||||||
|
|||||||
@@ -412,6 +412,42 @@ module.exports = function buildRuntime(module, builder) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildMultiGetSignal() {
|
||||||
|
const f = module.addFunction("multiGetSignal");
|
||||||
|
f.addParam("cIdx", "i32");
|
||||||
|
f.addParam("pR", "i32");
|
||||||
|
f.addParam("component", "i32");
|
||||||
|
f.addParam("signal", "i32");
|
||||||
|
f.addParam("n", "i32");
|
||||||
|
f.addLocal("i", "i32");
|
||||||
|
|
||||||
|
const c = f.getCodeBuilder();
|
||||||
|
|
||||||
|
f.addCode(
|
||||||
|
c.setLocal("i", c.i32_const(0)),
|
||||||
|
c.block(c.loop(
|
||||||
|
c.br_if(1, c.i32_eq(c.getLocal("i"), c.getLocal("n"))),
|
||||||
|
c.call(
|
||||||
|
"getSignal",
|
||||||
|
c.getLocal("cIdx"),
|
||||||
|
c.i32_add(
|
||||||
|
c.getLocal("pR"),
|
||||||
|
c.i32_mul(
|
||||||
|
c.getLocal("i"),
|
||||||
|
c.i32_const(builder.sizeFr)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
c.getLocal("component"),
|
||||||
|
c.i32_add(
|
||||||
|
c.getLocal("signal"),
|
||||||
|
c.getLocal("i")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))),
|
||||||
|
c.br(0)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function buildSetSignal() {
|
function buildSetSignal() {
|
||||||
const f = module.addFunction("setSignal");
|
const f = module.addFunction("setSignal");
|
||||||
@@ -847,6 +883,7 @@ module.exports = function buildRuntime(module, builder) {
|
|||||||
|
|
||||||
buildGetSignal();
|
buildGetSignal();
|
||||||
buildSetSignal();
|
buildSetSignal();
|
||||||
|
buildMultiGetSignal();
|
||||||
|
|
||||||
buildComponentStarted();
|
buildComponentStarted();
|
||||||
buildComponentFinished();
|
buildComponentFinished();
|
||||||
@@ -867,6 +904,7 @@ module.exports = function buildRuntime(module, builder) {
|
|||||||
module.exportFunction("getFrLen");
|
module.exportFunction("getFrLen");
|
||||||
module.exportFunction("getSignalOffset32");
|
module.exportFunction("getSignalOffset32");
|
||||||
module.exportFunction("setSignal");
|
module.exportFunction("setSignal");
|
||||||
|
module.exportFunction("multiGetSignal");
|
||||||
module.exportFunction("getPWitness");
|
module.exportFunction("getPWitness");
|
||||||
module.exportFunction("Fr_toInt");
|
module.exportFunction("Fr_toInt");
|
||||||
module.exportFunction("getPRawPrime");
|
module.exportFunction("getPRawPrime");
|
||||||
|
|||||||
@@ -62,8 +62,9 @@ class CodeBuilderWasm {
|
|||||||
this.ops.push({op: "SETSIGNAL", component, signal, value});
|
this.ops.push({op: "SETSIGNAL", component, signal, value});
|
||||||
}
|
}
|
||||||
|
|
||||||
getSignal(dLabel, component, signal) {
|
getSignal(dLabel, component, signal, n) {
|
||||||
this.ops.push({op: "GETSIGNAL", dLabel, component, signal});
|
if (typeof n == "undefined") n=1;
|
||||||
|
this.ops.push({op: "GETSIGNAL", dLabel, component, signal, n});
|
||||||
}
|
}
|
||||||
|
|
||||||
copyN(dLabel, offset, src, n) {
|
copyN(dLabel, offset, src, n) {
|
||||||
@@ -251,11 +252,12 @@ class CodeBuilderWasm {
|
|||||||
} else if (o.op == "GETSIGNAL") {
|
} else if (o.op == "GETSIGNAL") {
|
||||||
code.push(
|
code.push(
|
||||||
c.call(
|
c.call(
|
||||||
"getSignal",
|
"multiGetSignal",
|
||||||
c.getLocal("cIdx"),
|
c.getLocal("cIdx"),
|
||||||
this.fnBuilder._getPtr(c, o.dLabel),
|
this.fnBuilder._getPtr(c, o.dLabel),
|
||||||
this.fnBuilder._deRefInt(c, o.component),
|
this.fnBuilder._deRefInt(c, o.component),
|
||||||
this.fnBuilder._deRefInt(c, o.signal)
|
this.fnBuilder._deRefInt(c, o.signal),
|
||||||
|
c.i32_const(o.n)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else if (o.op == "COPYN") {
|
} else if (o.op == "COPYN") {
|
||||||
|
|||||||
@@ -888,7 +888,8 @@ function execOpOp(ctx, ast, op, lr) {
|
|||||||
right = {t:"N", v: ctx.F.one};
|
right = {t:"N", v: ctx.F.one};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!right) return ctx.throwError(ast, "adding a no number");
|
if (!right) return ctx.throwError(ast, "right operand is not initialized");
|
||||||
|
if (!resBefore) return ctx.throwError(ast, "left operand is not initialized");
|
||||||
|
|
||||||
const resAfter = ctx.lc[op](resBefore, right);
|
const resAfter = ctx.lc[op](resBefore, right);
|
||||||
left.v[o] = resAfter;
|
left.v[o] = resAfter;
|
||||||
|
|||||||
@@ -284,6 +284,32 @@ function genDeclareComponent(ctx, ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function genDeclareSignal(ctx, ast) {
|
function genDeclareSignal(ctx, ast) {
|
||||||
|
|
||||||
|
const v = ctx.refs[ast.refId];
|
||||||
|
|
||||||
|
let sizes;
|
||||||
|
if (ast.name.selectors.length>0) {
|
||||||
|
sizes=[];
|
||||||
|
for (let i=0; i< ast.name.selectors.length; i++) {
|
||||||
|
const sizeRef = gen(ctx, ast.name.selectors[i]);
|
||||||
|
const size = ctx.refs[sizeRef];
|
||||||
|
if (size.sizes[0] != 1) return ctx.throwError(ast, "A selector cannot be an array");
|
||||||
|
if (size.used) return ctx.throwError(ast, "Signal size variables not allowed");
|
||||||
|
sizes.push(Scalar.toNumber(size.value[0]));
|
||||||
|
}
|
||||||
|
sizes = utils.accSizes(sizes);
|
||||||
|
} else {
|
||||||
|
sizes = [1,0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!v.sizes)&&(sizes)) {
|
||||||
|
v.sizes = sizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.sizes) {
|
||||||
|
if (!utils.sameSizes(v.sizes, sizes)) return ctx.throwError(ast, "Redefined a signal with different sized");
|
||||||
|
}
|
||||||
|
|
||||||
return ast.refId;
|
return ast.refId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,12 +440,13 @@ function genVariable(ctx, ast) {
|
|||||||
vOffset = genGetSignalOffset(ctx, -1, ast.name);
|
vOffset = genGetSignalOffset(ctx, -1, ast.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resRef = newRef(ctx, "BIGINT", "_sigValue");
|
const sizes = v.sizes.slice(l);
|
||||||
|
|
||||||
|
const resRef = newRef(ctx, "BIGINT", "_sigValue", null, sizes);
|
||||||
const res = ctx.refs[resRef];
|
const res = ctx.refs[resRef];
|
||||||
instantiateRef(ctx, resRef);
|
instantiateRef(ctx, resRef);
|
||||||
ctx.codeBuilder.getSignal(res.label, ["CC"], toRefA_Int1(ctx, ast, vOffset));
|
ctx.codeBuilder.getSignal(res.label, ["CC"], toRefA_Int1(ctx, ast, vOffset), sizes[0]);
|
||||||
return resRef;
|
return resRef;
|
||||||
|
|
||||||
} else if (v.type == "BIGINT") {
|
} else if (v.type == "BIGINT") {
|
||||||
const refOffset = genGetOffset(ctx, 0, v.sizes, ast.selectors );
|
const refOffset = genGetOffset(ctx, 0, v.sizes, ast.selectors );
|
||||||
const offset = ctx.refs[refOffset];
|
const offset = ctx.refs[refOffset];
|
||||||
@@ -486,13 +513,18 @@ function genPin(ctx, ast) {
|
|||||||
vsIdx = genGetSignalOffset(ctx, vcIdx, ast.pin.name);
|
vsIdx = genGetSignalOffset(ctx, vcIdx, ast.pin.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resRef = newRef(ctx, "BIGINT", "_sigValue");
|
const l = ast.selectors ? ast.selectors.length : 0;
|
||||||
|
|
||||||
|
const sizes = [1,0]; // TODO, Treat array
|
||||||
|
|
||||||
|
const resRef = newRef(ctx, "BIGINT", "_sigValue", null, sizes);
|
||||||
const res = ctx.refs[resRef];
|
const res = ctx.refs[resRef];
|
||||||
instantiateRef(ctx, resRef);
|
instantiateRef(ctx, resRef);
|
||||||
ctx.codeBuilder.getSignal(
|
ctx.codeBuilder.getSignal(
|
||||||
res.label,
|
res.label,
|
||||||
toRefA_Int1(ctx, ast.component, vcIdx),
|
toRefA_Int1(ctx, ast.component, vcIdx),
|
||||||
toRefA_Int1(ctx, ast.pin, vsIdx)
|
toRefA_Int1(ctx, ast.pin, vsIdx),
|
||||||
|
sizes[0]
|
||||||
);
|
);
|
||||||
return resRef;
|
return resRef;
|
||||||
}
|
}
|
||||||
@@ -951,7 +983,7 @@ function genLoop(ctx, ast) {
|
|||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
const cond = ctx.refs[condRef];
|
const cond = ctx.refs[condRef];
|
||||||
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array");
|
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "genLoop: Operation cannot be done on an array");
|
||||||
|
|
||||||
if (cond.used) {
|
if (cond.used) {
|
||||||
inLoop = true;
|
inLoop = true;
|
||||||
@@ -1028,7 +1060,7 @@ function genIf(ctx, ast) {
|
|||||||
const condRef = gen(ctx, ast.condition);
|
const condRef = gen(ctx, ast.condition);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
const cond = ctx.refs[condRef];
|
const cond = ctx.refs[condRef];
|
||||||
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array");
|
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "genIf: Operation cannot be done on an array");
|
||||||
|
|
||||||
if (cond.used) {
|
if (cond.used) {
|
||||||
let thenCode, elseCode;
|
let thenCode, elseCode;
|
||||||
@@ -1148,7 +1180,12 @@ function genOp(ctx, ast, op, nOps, adjustBool) {
|
|||||||
valRefs.push(ref);
|
valRefs.push(ref);
|
||||||
vals.push(v);
|
vals.push(v);
|
||||||
|
|
||||||
if (!utils.sameSizes(v.sizes, [1,0])) return ctx.throwError(ast, "Operation cannot be done on an array");
|
if (!utils.sameSizes(v.sizes, [1,0])) {
|
||||||
|
console.log("xx");
|
||||||
|
console.log(i);
|
||||||
|
console.log(v);
|
||||||
|
return ctx.throwError(ast, "genOp2: Operation cannot be done on an array");
|
||||||
|
}
|
||||||
if ( (!v.used)
|
if ( (!v.used)
|
||||||
&&( (!utils.isDefined(v.value))
|
&&( (!utils.isDefined(v.value))
|
||||||
||(!utils.isDefined(v.value[0]))))
|
||(!utils.isDefined(v.value[0]))))
|
||||||
@@ -1184,7 +1221,7 @@ function genTerCon(ctx, ast) {
|
|||||||
const condRef = gen(ctx, ast.values[0]);
|
const condRef = gen(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
const cond = ctx.refs[condRef];
|
const cond = ctx.refs[condRef];
|
||||||
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array");
|
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "genTer: Operation cannot be done on an array");
|
||||||
|
|
||||||
if (cond.used) {
|
if (cond.used) {
|
||||||
let thenCode, elseCode;
|
let thenCode, elseCode;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ async function doTest(tester, circuit, testVectors) {
|
|||||||
describe("basic cases", function () {
|
describe("basic cases", function () {
|
||||||
this.timeout(100000);
|
this.timeout(100000);
|
||||||
|
|
||||||
for (let i=0; i<basicCases.length; i++) {
|
for (let i=0; i< basicCases.length; i++) {
|
||||||
it("c/c++ " + basicCases[i].name, async () => {
|
it("c/c++ " + basicCases[i].name, async () => {
|
||||||
await doTest(c_tester, basicCases[i].circuit, basicCases[i].tv);
|
await doTest(c_tester, basicCases[i].circuit, basicCases[i].tv);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,6 +14,17 @@
|
|||||||
}]
|
}]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "fnarray",
|
||||||
|
"circuit": "fnarray.circom",
|
||||||
|
"tv": [
|
||||||
|
[{
|
||||||
|
"in": [1, 8, 25]
|
||||||
|
}, {
|
||||||
|
"out": [2, 16, 50]
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "add",
|
"name": "add",
|
||||||
"circuit": "add.circom",
|
"circuit": "add.circom",
|
||||||
|
|||||||
21
test/circuits/fnarray.circom
Normal file
21
test/circuits/fnarray.circom
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function calc(h) {
|
||||||
|
var res[3];
|
||||||
|
for (var i=0; i<3; i++) res[i] = h[i]*2;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template Test() {
|
||||||
|
signal input in[3];
|
||||||
|
signal output out[3];
|
||||||
|
|
||||||
|
var cout[3] = calc(in);
|
||||||
|
for (var i=0; i<3; i++) out[i] <-- cout[i];
|
||||||
|
|
||||||
|
for (var i=0; i<3; i++) out[i] === in[i]*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = Test();
|
||||||
Reference in New Issue
Block a user