Integrated with asm and tested

This commit is contained in:
Jordi Baylina
2020-01-23 07:20:58 +07:00
parent e11e6768e4
commit f6092e3944
22 changed files with 6410 additions and 152 deletions

View File

@@ -35,6 +35,11 @@ function buildC(ctx) {
ctx.codes_sizes = [];
ctx.definedSizes = {};
ctx.addSizes = addSizes;
ctx.constants = [];
ctx.constantsMap = {};
ctx.addConstant = addConstant;
ctx.addConstant(bigInt.zero);
ctx.addConstant(bigInt.one);
const entryTables = buildEntryTables(ctx);
ctx.globalNames = ctx.uniqueNames;
@@ -45,6 +50,7 @@ function buildC(ctx) {
const headder = buildHeader(ctx);
const sizes = buildSizes(ctx);
const constants = buildConstants(ctx);
const mapIsInput = buildMapIsInput(ctx);
const wit2Sig = buildWit2Sig(ctx);
const circuitVar = buildCircuitVar(ctx);
@@ -52,6 +58,7 @@ function buildC(ctx) {
return "" +
headder + "\n" +
sizes + "\n" +
constants + "\n" +
entryTables + "\n" +
functions + "\n" +
code + "\n" +
@@ -244,6 +251,69 @@ function buildSizes(ctx) {
ctx.codes_sizes.join("\n");
}
function buildConstants(ctx) {
const n64 = Math.floor((ctx.field.p.bitLength() - 1) / 64)+1;
const R = bigInt.one.shiftLeft(n64*64);
const lines = [];
lines.push("// Constants");
lines.push(`FrElement _constants[${ctx.constants.length}] = {`);
for (let i=0; i<ctx.constants.length; i++) {
lines.push((i>0 ? "," : " ") + "{" + number2Code(ctx.constants[i]) + "}");
}
lines.push("};");
return lines.join("\n");
function number2Code(n) {
if (n.lt(bigInt("80000000", 16)) ) {
return addShortMontgomeryPositive(n);
}
if (n.geq(ctx.field.p.minus(bigInt("80000000", 16))) ) {
return addShortMontgomeryNegative(n);
}
return addLongMontgomery(n);
function addShortMontgomeryPositive(a) {
return `${a.toString()}, 0x40000000, { ${getLongString(toMontgomery(a))} }`;
}
function addShortMontgomeryNegative(a) {
const b = a.minus(ctx.field.p);
return `${b.toString()}, 0x40000000, { ${getLongString(toMontgomery(a))} }`;
}
function addLongMontgomery(a) {
return `0, 0xC0000000, { ${getLongString(toMontgomery(a))} }`;
}
function getLongString(a) {
let r = bigInt(a);
let S = "";
let i = 0;
while (!r.isZero()) {
if (S!= "") S = S+",";
S += "0x" + r.and(bigInt("FFFFFFFFFFFFFFFF", 16)).toString(16) + "LL";
i++;
r = r.shiftRight(64);
}
while (i<n64) {
if (S!= "") S = S+",";
S += "0LL";
i++;
}
return S;
}
function toMontgomery(a) {
return a.times(R).mod(ctx.field.p);
}
}
}
function buildMapIsInput(ctx) {
const arr = [];
@@ -338,6 +408,7 @@ function buildCircuitVar() {
" _wit2sig,\n"+
" _components,\n"+
" _mapIsInput,\n"+
" _constants,\n" +
" __P__\n" +
"};\n";
}
@@ -370,6 +441,16 @@ function addSizes(_sizes) {
return labelName;
}
function addConstant(c) {
c = bigInt(c);
const s = c.toString();
if (typeof (this.constantsMap[s]) !== "undefined") return this.constantsMap[s];
const newId = this.constants.length;
this.constants.push(c);
this.constantsMap[s] = newId;
return newId;
}
function buildFunction(name, paramValues) {
const ctx = this;
const {h, instanceDef} = hashFunctionCall(ctx, name, paramValues);
@@ -409,7 +490,7 @@ function buildFunction(name, paramValues) {
for (let i=0; i<ctx.functions[name].params.length; i++) {
if (paramValues[i].used) {
paramsStr += `,PBigInt ${ctx.functions[name].params[i]}`;
paramsStr += `,PFrElement ${ctx.functions[name].params[i]}`;
const idRef = ctx.refs.length;
ctx.refs.push({
type: "BIGINT",
@@ -444,11 +525,12 @@ function buildFunction(name, paramValues) {
"/*\n" +
instanceDef +
"\n*/\n" +
`void ${name}_${h}(Circom_CalcWit *ctx, PBigInt __retValue ${paramsStr}) {`;
`void ${name}_${h}(Circom_CalcWit *ctx, PFrElement __retValue ${paramsStr}) {`;
code += utils.ident(ctx.codeHeader);
code += utils.ident(ctx.code);
code += utils.ident("returnFunc:\n");
code += utils.ident(ctx.codeFooter);
code += utils.ident(";\n");
code += "}\n";
res.returnSizes = ctx.returnSizes;
ctx.functionCodes.push(code);

View File

@@ -43,8 +43,7 @@ function instantiateRef(ctx, refId, initValue) {
if (!v.sizes) v.sizes = [1,0];
if (v.type=="BIGINT") {
ctx.codeHeader += `PBigInt ${v.label} = ctx->allocBigInts(${v.sizes[0]});\n`;
ctx.codeFooter += `ctx->freeBigInts(${v.label}, ${v.sizes[0]});\n`;
ctx.codeHeader += `FrElement ${v.label}[${v.sizes[0]}];\n`;
} else if (v.type=="INT") {
ctx.codeHeader += `int ${v.label};\n`;
} else if (v.type=="SIZES") {
@@ -55,8 +54,8 @@ function instantiateRef(ctx, refId, initValue) {
if (v.type == "BIGINT") {
for (let i=0; i<initValue.length; i++) {
if (utils.isDefined(initValue[i])) {
const c = `mpz_set_str(${v.label}[${i}], "${initValue[i].toString(10)}", 10);\n`;
ctx.code += c;
const idConstant = ctx.addConstant(initValue[i]);
ctx.code += `Fr_copy(&(${v.label}[${i}]), ctx->circuit->constants +${idConstant});\n`;
}
}
}
@@ -67,12 +66,11 @@ function instantiateConstant(ctx, value) {
const sizes = utils.accSizes(utils.extractSizes(value));
const flatedValue = utils.flatArray(value);
const label = ctx.getUniqueName("_const");
ctx.codeHeader += `PBigInt ${label};\n`;
ctx.codeHeader += `${label} = ctx->allocBigInts(${sizes[0]});\n`;
ctx.codeHeader += `FrElement ${label}[${sizes[0]}];\n`;
for (let i=0; i<flatedValue.length; i++) {
ctx.codeHeader += `mpz_set_str(${label}[${i}], "${flatedValue[i].toString(10)}", 10);\n`;
const idConstant = ctx.addConstant(flatedValue[i]);
ctx.codeHeader += `Fr_copy(&(${label}[${i}]), ctx->circuit->constants +${idConstant});\n`;
}
ctx.codeFooter += `ctx->freeBigInts(${label}, ${sizes[0]});\n`;
const refId = ctx.refs.length;
ctx.refs.push({
type: "BIGINT",
@@ -392,7 +390,7 @@ function genGetOffset(ctx, refOffset, vSizes, sels) {
if (rStr != "") rStr += " + ";
if (iIdx.used) {
rStr += `ctx->field->toInt(${iIdx.label})`;
rStr += `Fr_toInt(${iIdx.label})`;
} else {
rStr += iIdx.value[0].toString();
}
@@ -451,14 +449,14 @@ function genVariable(ctx, ast) {
const refRes = newRef(ctx, "BIGINT", "_v", null, v.sizes.slice(l));
const res = ctx.refs[refRes];
res.used = true;
ctx.codeHeader += `PBigInt ${res.label};\n`;
ctx.codeHeader += `PFrElement ${res.label};\n`;
ctx.code += `${res.label} = ${v.label} + ${offset.label};\n`;
return refRes;
} else if ((offset.value[0])||(l>0)) {
const refRes = newRef(ctx, "BIGINT", "_v", null, v.sizes.slice(l));
const res = ctx.refs[refRes];
res.used = true;
ctx.codeHeader += `PBigInt ${res.label};\n`;
ctx.codeHeader += `PFrElement ${res.label};\n`;
ctx.code += `${res.label} = ${v.label} + ${offset.value[0]};\n`;
return refRes;
} else {
@@ -470,7 +468,7 @@ function genVariable(ctx, ast) {
const resRef = newRef(ctx, "BIGINT", "_v", null, v.sizes.slice(l));
const res = ctx.refs[resRef];
res.used = true;
ctx.codeHeader += `PBigInt ${res.label};\n`;
ctx.codeHeader += `PFrElement ${res.label};\n`;
ctx.code += `${res.label} = ${v.label} + ${offset.label};\n`;
return resRef;
} else {
@@ -685,12 +683,12 @@ function genVarAssignment(ctx, ast, lRef, sels, rRef) {
if (instantiated) {
if (offset.used) {
ctx.code += `ctx->field->copyn(${left.label} + ${offset.label}, ${right.label}, ${right.sizes[0]});\n`;
ctx.code += `Fr_copyn(${left.label} + ${offset.label}, ${right.label}, ${right.sizes[0]});\n`;
} else {
if (offset.value[0]>0) {
ctx.code += `ctx->field->copyn(${left.label} + ${offset.value[0]}, ${right.label}, ${right.sizes[0]});\n`;
ctx.code += `Fr_copyn(${left.label} + ${offset.value[0]}, ${right.label}, ${right.sizes[0]});\n`;
} else {
ctx.code += `ctx->field->copyn(${left.label}, ${right.label}, ${right.sizes[0]});\n`;
ctx.code += `Fr_copyn(${left.label}, ${right.label}, ${right.sizes[0]});\n`;
}
}
} else {
@@ -783,7 +781,7 @@ function genArray(ctx, ast) {
for (let i=0; i<ast.values.length; i++) {
const v = ctx.refs[refs[i]];
const r = ctx.refs[rRef];
ctx.code += `ctx->field->copyn(${r.label}+${i*subSizes[0]}, ${v.label}, ${subSizes[0]});\n`;
ctx.code += `Fr_copyn(${r.label}+${i*subSizes[0]}, ${v.label}, ${subSizes[0]});\n`;
}
return rRef;
} else {
@@ -883,7 +881,7 @@ function genLoop(ctx, ast) {
instantiateRef(ctx, condVarRef);
ctx.code +=
`${condVar.label} = ctx->field->isTrue(${cond.label});\n` +
`${condVar.label} = Fr_isTrue(${cond.label});\n` +
`while (${condVar.label}) {\n`;
} else {
if (!utils.isDefined(cond.value)) return ctx.throwError(ast, "condition value not assigned");
@@ -924,7 +922,7 @@ function genLoop(ctx, ast) {
instantiateRef(ctx, condVarRef);
ctx.code +=
`${condVar.label} = ctx->field->isTrue(${cond2.label});\n` +
`${condVar.label} = Fr_isTrue(${cond2.label});\n` +
`while (${condVar.label}) {\n`;
} else {
ctx.code = oldCode + ctx.code;
@@ -935,7 +933,7 @@ function genLoop(ctx, ast) {
oldCode +
utils.ident(
ctx.code +
`${condVar.label} = ctx->field->isTrue(${cond2.label});\n`);
`${condVar.label} = Fr_isTrue(${cond2.label});\n`);
end=true;
}
}
@@ -960,7 +958,7 @@ function genIf(ctx, ast) {
if (cond.used) {
enterConditionalCode(ctx, ast);
ctx.code += `if (ctx->field->isTrue(${cond.label})) {\n`;
ctx.code += `if (Fr_isTrue(${cond.label})) {\n`;
const oldCode = ctx.code;
ctx.code = "";
@@ -1007,7 +1005,7 @@ function genReturn(ctx, ast) {
instantiateRef(ctx, vRef, v.value);
}
if (v.used) {
ctx.code += `ctx->field->copyn(__retValue, ${v.label}, ${v.sizes[0]});\n`;
ctx.code += `Fr_copyn(__retValue, ${v.label}, ${v.sizes[0]});\n`;
} else {
if (!utils.isDefined(v.value)) return ctx.throwError(ast, "Returning an unknown value");
if (!utils.isDefined(ctx.returnValue)) {
@@ -1051,7 +1049,7 @@ function genOpOp(ctx, ast, op, lr) {
const res = ctx.refs[resRef];
if (veval.used) {
instantiateRef(ctx, resRef);
ctx.code += `ctx->field->${op}(${res.label}, ${veval.label}, &(ctx->field->one));\n`;
ctx.code += `Fr_${op}(${res.label}, ${veval.label}, ctx->circuit->constants + ${ctx.addConstant(bigInt.one)});\n`;
} else {
res.value = [ctx.field[op](veval.value[0], bigInt(1))];
}
@@ -1097,7 +1095,7 @@ function genOp(ctx, ast, op, nOps) {
rRef = newRef(ctx, "BIGINT", "_tmp");
instantiateRef(ctx, rRef);
const r = ctx.refs[rRef];
let c = `ctx->field->${op}(${r.label}`;
let c = `Fr_${op}(${r.label}`;
for (let i=0; i<nOps; i++) {
c+=`,${vals[i].label}`;
}
@@ -1126,8 +1124,8 @@ function genTerCon(ctx, ast) {
const rLabel = ctx.getUniqueName("_ter");
ctx.codeHeader += `PBigInt ${rLabel};\n`;
ctx.code += `if (ctx->field->isTrue(${cond.label})) {\n`;
ctx.codeHeader += `PFrElement ${rLabel};\n`;
ctx.code += `if (Fr_isTrue(${cond.label})) {\n`;
oldCode = ctx.code;
ctx.code = "";

View File

@@ -23,6 +23,8 @@ async function c_tester(circomFile, _options) {
const dir = await tmp.dir({prefix: "circom_", unsafeCleanup: true });
// console.log(dir.path);
const baseName = path.basename(circomFile, ".circom");
const options = Object.assign({}, _options);
@@ -40,7 +42,8 @@ async function c_tester(circomFile, _options) {
` ${path.join(cdir, "main.cpp")}` +
` ${path.join(cdir, "calcwit.cpp")}` +
` ${path.join(cdir, "utils.cpp")}` +
` ${path.join(cdir, "zqfield.cpp")}` +
` ${path.join(cdir, "fr.c")}` +
` ${path.join(cdir, "fr.o")}` +
` ${path.join(dir.path, baseName + ".cpp")} ` +
` -o ${path.join(dir.path, baseName)}` +
` -I ${cdir}` +