mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 03:06:42 +01:00
Isolate code generation to output different languages
This commit is contained in:
20
cli.js
20
cli.js
@@ -33,6 +33,7 @@ const argv = require("yargs")
|
|||||||
.usage("circom [input source circuit file] -o [output definition circuit file] -c [output c file]")
|
.usage("circom [input source circuit file] -o [output definition circuit file] -c [output c file]")
|
||||||
.alias("o", "output")
|
.alias("o", "output")
|
||||||
.alias("c", "csource")
|
.alias("c", "csource")
|
||||||
|
.alias("w", "wasm")
|
||||||
.alias("s", "sym")
|
.alias("s", "sym")
|
||||||
.alias("r", "r1cs")
|
.alias("r", "r1cs")
|
||||||
.alias("n", "newThreadTemplates")
|
.alias("n", "newThreadTemplates")
|
||||||
@@ -69,6 +70,7 @@ if (argv._.length == 0) {
|
|||||||
const fullFileName = path.resolve(process.cwd(), inputFile);
|
const fullFileName = path.resolve(process.cwd(), inputFile);
|
||||||
const fileName = path.basename(fullFileName, ".circom");
|
const fileName = path.basename(fullFileName, ".circom");
|
||||||
const cSourceName = typeof(argv.csource) === "string" ? argv.csource : fileName + ".cpp";
|
const cSourceName = typeof(argv.csource) === "string" ? argv.csource : fileName + ".cpp";
|
||||||
|
const wasmName = typeof(argv.wasm) === "string" ? argv.wasm : fileName + ".wasm";
|
||||||
const r1csName = typeof(argv.r1cs) === "string" ? argv.r1cs : fileName + ".r1cs";
|
const r1csName = typeof(argv.r1cs) === "string" ? argv.r1cs : fileName + ".r1cs";
|
||||||
const symName = typeof(argv.sym) === "string" ? argv.sym : fileName + ".sym";
|
const symName = typeof(argv.sym) === "string" ? argv.sym : fileName + ".sym";
|
||||||
|
|
||||||
@@ -78,6 +80,9 @@ options.verbose = argv.verbose || false;
|
|||||||
if (argv.csource) {
|
if (argv.csource) {
|
||||||
options.cSourceWriteStream = fs.createWriteStream(cSourceName);
|
options.cSourceWriteStream = fs.createWriteStream(cSourceName);
|
||||||
}
|
}
|
||||||
|
if (argv.wasm) {
|
||||||
|
options.wasmWriteStream = fs.createWriteStream(wasmName);
|
||||||
|
}
|
||||||
if (argv.r1cs) {
|
if (argv.r1cs) {
|
||||||
options.r1csFileName = r1csName;
|
options.r1csFileName = r1csName;
|
||||||
}
|
}
|
||||||
@@ -90,17 +95,26 @@ if (argv.newThreadTemplates) {
|
|||||||
|
|
||||||
compiler(fullFileName, options).then( () => {
|
compiler(fullFileName, options).then( () => {
|
||||||
let cSourceDone = false;
|
let cSourceDone = false;
|
||||||
|
let wasmDone = false;
|
||||||
let symDone = false;
|
let symDone = false;
|
||||||
if (options.cSourceWriteStream) {
|
if (options.cSourceWriteStream) {
|
||||||
options.cSourceWriteStream.end(() => {
|
options.cSourceWriteStream.on("finish", () => {
|
||||||
cSourceDone = true;
|
cSourceDone = true;
|
||||||
finishIfDone();
|
finishIfDone();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cSourceDone = true;
|
cSourceDone = true;
|
||||||
}
|
}
|
||||||
|
if (options.wasmWriteStream) {
|
||||||
|
options.wasmWriteStream.on("finish", () => {
|
||||||
|
wasmDone = true;
|
||||||
|
finishIfDone();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
wasmDone = true;
|
||||||
|
}
|
||||||
if (options.symWriteStream) {
|
if (options.symWriteStream) {
|
||||||
options.symWriteStream.end(() => {
|
options.symWriteStream.on("finish", () => {
|
||||||
symDone = true;
|
symDone = true;
|
||||||
finishIfDone();
|
finishIfDone();
|
||||||
});
|
});
|
||||||
@@ -108,7 +122,7 @@ compiler(fullFileName, options).then( () => {
|
|||||||
symDone = true;
|
symDone = true;
|
||||||
}
|
}
|
||||||
function finishIfDone() {
|
function finishIfDone() {
|
||||||
if ((cSourceDone)&&(symDone)) {
|
if ((cSourceDone)&&(symDone)&&(wasmDone)) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|||||||
@@ -20,67 +20,63 @@
|
|||||||
const assert = require("assert");
|
const assert = require("assert");
|
||||||
const bigInt = require("big-integer");
|
const bigInt = require("big-integer");
|
||||||
const utils = require("./utils");
|
const utils = require("./utils");
|
||||||
const gen = require("./c_gen").gen;
|
const gen = require("./gencode").gen;
|
||||||
const createRefs = require("./c_gen").createRefs;
|
const createRefs = require("./gencode").createRefs;
|
||||||
const streamFromMultiArray = require("./stream_from_multiarray");
|
|
||||||
|
|
||||||
module.exports = buildC;
|
module.exports = build;
|
||||||
|
|
||||||
|
|
||||||
function buildC(ctx) {
|
function build(ctx) {
|
||||||
ctx.definedFunctions = {};
|
ctx.definedFunctions = {};
|
||||||
ctx.functionCodes = [];
|
ctx.functionCodes = [];
|
||||||
ctx.buildFunction = buildFunction;
|
ctx.buildFunction = buildFunction;
|
||||||
ctx.code = "";
|
|
||||||
ctx.conditionalCodeHeader = "";
|
ctx.conditionalCodeHeader = "";
|
||||||
ctx.codes_sizes = [];
|
ctx.codes_sizes = [];
|
||||||
ctx.definedSizes = {};
|
ctx.definedSizes = {};
|
||||||
ctx.addSizes = addSizes;
|
ctx.addSizes = addSizes;
|
||||||
ctx.constants = [];
|
|
||||||
ctx.constantsMap = {};
|
ctx.constantsMap = {};
|
||||||
ctx.addConstant = addConstant;
|
ctx.addConstant = addConstant;
|
||||||
ctx.addConstant(bigInt.zero);
|
ctx.addConstant(bigInt.zero);
|
||||||
ctx.addConstant(bigInt.one);
|
ctx.addConstant(bigInt.one);
|
||||||
|
|
||||||
const entryTables = buildEntryTables(ctx);
|
buildHeader(ctx);
|
||||||
|
buildEntryTables(ctx);
|
||||||
ctx.globalNames = ctx.uniqueNames;
|
ctx.globalNames = ctx.uniqueNames;
|
||||||
|
|
||||||
const code = buildCode(ctx);
|
buildCode(ctx);
|
||||||
const functions = buildFuncFunctions(ctx);
|
|
||||||
const compnentsArray = buildComponentsArray(ctx);
|
|
||||||
|
|
||||||
const headder = buildHeader(ctx);
|
buildComponentsArray(ctx);
|
||||||
const sizes = buildSizes(ctx);
|
|
||||||
const constants = buildConstants(ctx);
|
buildMapIsInput(ctx);
|
||||||
const mapIsInput = buildMapIsInput(ctx);
|
buildWit2Sig(ctx);
|
||||||
const wit2Sig = buildWit2Sig(ctx);
|
|
||||||
const circuitVar = buildCircuitVar(ctx);
|
|
||||||
|
|
||||||
return streamFromMultiArray([
|
|
||||||
headder , "\n" ,
|
|
||||||
sizes , "\n" ,
|
|
||||||
constants , "\n" ,
|
|
||||||
entryTables , "\n" ,
|
|
||||||
functions , "\n" ,
|
|
||||||
code , "\n" ,
|
|
||||||
compnentsArray , "\n" ,
|
|
||||||
mapIsInput , "\n" ,
|
|
||||||
wit2Sig , "\n" ,
|
|
||||||
circuitVar
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildEntryTables(ctx) {
|
function buildEntryTables(ctx) {
|
||||||
|
|
||||||
const codes_hashMaps = [];
|
const codes_hashMaps = [];
|
||||||
const codes_componentEntries = [];
|
const codes_componentEntries = [];
|
||||||
const definedHashTables = {};
|
const definedHashMaps = {};
|
||||||
for (let i=0; i<ctx.components.length; i++) {
|
for (let i=0; i<ctx.components.length; i++) {
|
||||||
const {htName, htMap} = addHashTable(i);
|
const {htName, htMap} = addHashTable(i);
|
||||||
|
|
||||||
let code = "";
|
let code = "";
|
||||||
const componentEntriesTableName = ctx.getUniqueName("_entryTable" + ctx.components[i].template);
|
const componentEntriesTableName = ctx.getUniqueName("_entryTable" + ctx.components[i].template);
|
||||||
|
|
||||||
|
const componentEntriesTable = [];
|
||||||
|
for (let j=0; j<htMap.length; j++) {
|
||||||
|
const entry = ctx.components[i].names.o[htMap[j]];
|
||||||
|
const sizeName = ctx.addSizes(entry.sizes);
|
||||||
|
componentEntriesTable.push({
|
||||||
|
offset: entry.offset,
|
||||||
|
sizeName: sizeName,
|
||||||
|
type: entry.type
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.builder.addComponentEntriesTable(componentEntriesTableName, componentEntriesTable);
|
||||||
|
|
||||||
|
|
||||||
code += `Circom_ComponentEntry ${componentEntriesTableName}[${htMap.length}] = {\n`;
|
code += `Circom_ComponentEntry ${componentEntriesTableName}[${htMap.length}] = {\n`;
|
||||||
for (let j=0; j<htMap.length; j++) {
|
for (let j=0; j<htMap.length; j++) {
|
||||||
const entry = ctx.components[i].names.o[htMap[j]];
|
const entry = ctx.components[i].names.o[htMap[j]];
|
||||||
@@ -112,33 +108,22 @@ function buildEntryTables(ctx) {
|
|||||||
assert(keys.length<128);
|
assert(keys.length<128);
|
||||||
keys.sort((a,b) => ((a>b) ? 1 : -1));
|
keys.sort((a,b) => ((a>b) ? 1 : -1));
|
||||||
const h = utils.fnvHash(keys.join(","));
|
const h = utils.fnvHash(keys.join(","));
|
||||||
if (definedHashTables[h]) return definedHashTables[h];
|
if (definedHashMaps[h]) return definedHashMaps[h];
|
||||||
definedHashTables[h] = {};
|
definedHashMaps[h] = {};
|
||||||
definedHashTables[h].htName = ctx.getUniqueName("_ht"+ctx.components[cIdx].template);
|
definedHashMaps[h].htName = ctx.getUniqueName("_ht"+ctx.components[cIdx].template);
|
||||||
definedHashTables[h].htMap = [];
|
definedHashMaps[h].htMap = [];
|
||||||
const t = [];
|
const t = [];
|
||||||
for (let i=0; i<keys.length; i++) {
|
for (let i=0; i<keys.length; i++) {
|
||||||
definedHashTables[h].htMap[i] = keys[i];
|
definedHashMaps[h].htMap[i] = keys[i];
|
||||||
|
|
||||||
const h2 = utils.fnvHash(keys[i]);
|
const h2 = utils.fnvHash(keys[i]);
|
||||||
let pos = parseInt(h2.slice(-2), 16);
|
let pos = parseInt(h2.slice(-2), 16);
|
||||||
while (t[pos]) pos = (pos + 1) % 256;
|
while (t[pos]) pos = (pos + 1) % 256;
|
||||||
t[pos] = [h2, i];
|
t[pos] = [h2, i, keys[i]];
|
||||||
}
|
}
|
||||||
let code = `Circom_HashEntry ${definedHashTables[h].htName}[256] = {`;
|
ctx.builder.addHashMap(definedHashMaps[h].htName, t);
|
||||||
for (let i=0; i<256; i++) {
|
|
||||||
code += i>0 ? "," : "";
|
|
||||||
if (t[i]) {
|
|
||||||
code += `{0x${t[i][0]}LL, ${t[i][1]}} /* ${keys[t[i][1]]} */`;
|
|
||||||
} else {
|
|
||||||
code += "{0,0}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code += "};\n";
|
|
||||||
|
|
||||||
codes_hashMaps.push(code);
|
return definedHashMaps[h];
|
||||||
|
|
||||||
return definedHashTables[h];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,9 +140,8 @@ function buildCode(ctx) {
|
|||||||
|
|
||||||
ctx.scopes = [{}];
|
ctx.scopes = [{}];
|
||||||
ctx.conditionalCode = false;
|
ctx.conditionalCode = false;
|
||||||
ctx.code = "";
|
ctx.fnBuilder = ctx.builder.newComponentFunctionBuilder(fName, instanceDef);
|
||||||
ctx.codeHeader = "// Header\n";
|
ctx.codeBuilder = ctx.fnBuilder.newCodeBuilder();
|
||||||
ctx.codeFooter = "// Footer\n";
|
|
||||||
ctx.uniqueNames = Object.assign({},ctx.globalNames);
|
ctx.uniqueNames = Object.assign({},ctx.globalNames);
|
||||||
ctx.refs = [];
|
ctx.refs = [];
|
||||||
ctx.fileName = ctx.templates[ctx.components[i].template].fileName;
|
ctx.fileName = ctx.templates[ctx.components[i].template].fileName;
|
||||||
@@ -184,20 +168,10 @@ function buildCode(ctx) {
|
|||||||
gen(ctx, ctx.templates[ctx.components[i].template].block);
|
gen(ctx, ctx.templates[ctx.components[i].template].block);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
const S =
|
ctx.fnBuilder.setBody(ctx.codeBuilder);
|
||||||
"/*\n" +
|
|
||||||
instanceDef +
|
ctx.builder.addFunction(ctx.fnBuilder);
|
||||||
"\n*/\n" +
|
|
||||||
`void ${fName}(Circom_CalcWit *ctx, int __cIdx) {\n` +
|
|
||||||
utils.ident(
|
|
||||||
ctx.codeHeader + "\n" +
|
|
||||||
ctx.code + "\n" +
|
|
||||||
"ctx->finished(__cIdx);\n" +
|
|
||||||
ctx.codeFooter
|
|
||||||
) +
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
fnComponents.push(S);
|
|
||||||
fDefined[fName] = true;
|
fDefined[fName] = true;
|
||||||
}
|
}
|
||||||
ctx.components[i].fnName = fName;
|
ctx.components[i].fnName = fName;
|
||||||
@@ -206,172 +180,63 @@ function buildCode(ctx) {
|
|||||||
return fnComponents;
|
return fnComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildFuncFunctions(ctx) {
|
|
||||||
if (ctx.functionCodes) {
|
|
||||||
return ["// Functions\n" ,
|
|
||||||
ctx.functionCodes
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildComponentsArray(ctx) {
|
function buildComponentsArray(ctx) {
|
||||||
|
|
||||||
const ccodes = [];
|
|
||||||
ccodes.push(`Circom_Component _components[${ctx.components.length}] = {\n`);
|
|
||||||
for (let i=0; i< ctx.components.length; i++) {
|
for (let i=0; i< ctx.components.length; i++) {
|
||||||
let newThread;
|
let newThread;
|
||||||
if (ctx.newThreadTemplates) {
|
if (ctx.newThreadTemplates) {
|
||||||
if (ctx.newThreadTemplates.test(ctx.components[i].template)) {
|
if (ctx.newThreadTemplates.test(ctx.components[i].template)) {
|
||||||
newThread = "true";
|
newThread = true;
|
||||||
} else {
|
} else {
|
||||||
newThread = "false";
|
newThread = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newThread = "false";
|
newThread = false;
|
||||||
}
|
}
|
||||||
ccodes.push(i>0 ? " ," : " ");
|
ctx.builder.addComponent({
|
||||||
ccodes.push(`{${ctx.components[i].htName},${ctx.components[i].etName},${ctx.components[i].fnName}, ${ctx.components[i].nInSignals}, ${newThread}}\n`);
|
hashMapName: ctx.components[i].htName,
|
||||||
|
entryTableName: ctx.components[i].etName,
|
||||||
|
functionName: ctx.components[i].fnName,
|
||||||
|
nInSignals: ctx.components[i].nInSignals,
|
||||||
|
newThread: newThread
|
||||||
|
});
|
||||||
}
|
}
|
||||||
ccodes.push("};\n");
|
|
||||||
|
|
||||||
return [
|
|
||||||
"// Components\n" ,
|
|
||||||
ccodes , "\n"
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function buildHeader(ctx) {
|
function buildHeader(ctx) {
|
||||||
return "#include \"circom.h\"\n" +
|
ctx.builder.setHeader({
|
||||||
"#include \"calcwit.h\"\n" +
|
NSignals: ctx.signals.length,
|
||||||
`#define NSignals ${ctx.signals.length}\n` +
|
NComponents: ctx.components.length,
|
||||||
`#define NComponents ${ctx.components.length}\n` +
|
NInputs: ctx.components[ ctx.getComponentIdx("main") ].nInSignals,
|
||||||
`#define NInputs ${ctx.components[ ctx.getComponentIdx("main") ].nInSignals}\n`+
|
NOutputs: ctx.totals[ ctx.stOUTPUT ],
|
||||||
`#define NOutputs ${ctx.totals[ ctx.stOUTPUT ]}\n`+
|
NVars: ctx.totals[ctx.stONE] + ctx.totals[ctx.stOUTPUT] + ctx.totals[ctx.stPUBINPUT] + ctx.totals[ctx.stPRVINPUT] + ctx.totals[ctx.stINTERNAL],
|
||||||
`#define NVars ${ctx.totals[ctx.stONE] + ctx.totals[ctx.stOUTPUT] + ctx.totals[ctx.stPUBINPUT] + ctx.totals[ctx.stPRVINPUT] + ctx.totals[ctx.stINTERNAL]}\n` +
|
P: ctx.field.p
|
||||||
`#define __P__ "${ctx.field.p.toString()}"\n` +
|
});
|
||||||
"\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSizes(ctx) {
|
|
||||||
return [
|
|
||||||
"// Sizes\n" ,
|
|
||||||
ctx.codes_sizes
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
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\n");
|
|
||||||
lines.push(`FrElement _constants[${ctx.constants.length}] = {\n`);
|
|
||||||
for (let i=0; i<ctx.constants.length; i++) {
|
|
||||||
lines.push((i>0 ? "," : " ") + "{" + number2Code(ctx.constants[i]) + "}\n");
|
|
||||||
}
|
|
||||||
lines.push("};\n");
|
|
||||||
|
|
||||||
return lines;
|
|
||||||
|
|
||||||
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) {
|
function buildMapIsInput(ctx) {
|
||||||
const arr = [];
|
|
||||||
let line = "";
|
|
||||||
let acc = 0;
|
|
||||||
let i;
|
let i;
|
||||||
|
let map = [];
|
||||||
|
let acc = 0;
|
||||||
for (i=0; i<ctx.signals.length; i++) {
|
for (i=0; i<ctx.signals.length; i++) {
|
||||||
if (ctx.signals[i].o & ctx.IN) {
|
if (ctx.signals[i].o & ctx.IN) {
|
||||||
acc = acc | (1 << (i%32) );
|
acc = acc | (1 << (i%32) );
|
||||||
}
|
}
|
||||||
if ((i+1)%32==0) {
|
if ((i+1)%32==0) {
|
||||||
line += (i>31) ? "," : " ";
|
map.push(acc);
|
||||||
line += toHex(acc);
|
|
||||||
acc = 0;
|
acc = 0;
|
||||||
if ( (i+1) % (32*64) == 0) {
|
|
||||||
arr.push(line);
|
|
||||||
line = "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((i%32) != 0) {
|
if ((i%32) != 0) {
|
||||||
line += (i>31) ? "," : " ";
|
map.push(acc);
|
||||||
line += toHex(acc);
|
|
||||||
}
|
|
||||||
if (line != "") {
|
|
||||||
arr.push(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ["// mapIsArray\n" ,
|
ctx.builder.setMapIsInput(map);
|
||||||
`u32 _mapIsInput[${Math.floor((ctx.signals.length-1) / 32)+1}] = {\n`,
|
|
||||||
arr, "\n" ,
|
|
||||||
"};\n"
|
|
||||||
];
|
|
||||||
|
|
||||||
function toHex(number) {
|
|
||||||
if (number < 0) number = 0xFFFFFFFF + number + 1;
|
|
||||||
let S=number.toString(16).toUpperCase();
|
|
||||||
while (S.length<8) S = "0" + S;
|
|
||||||
return "0x"+S;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function buildWit2Sig(ctx) {
|
function buildWit2Sig(ctx) {
|
||||||
const codes = [];
|
|
||||||
const NVars =
|
const NVars =
|
||||||
ctx.totals[ctx.stONE] +
|
ctx.totals[ctx.stONE] +
|
||||||
ctx.totals[ctx.stOUTPUT] +
|
ctx.totals[ctx.stOUTPUT] +
|
||||||
@@ -388,46 +253,11 @@ function buildWit2Sig(ctx) {
|
|||||||
arr[outIdx] = i;
|
arr[outIdx] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
codes.push("// Signal Table\n");
|
|
||||||
codes.push(`int _wit2sig[${NVars}] = {\n`);
|
|
||||||
let code = "";
|
|
||||||
for (let i=0; i<NVars; i++) {
|
|
||||||
code += (i>0) ? ",": " ";
|
|
||||||
code += arr[i];
|
|
||||||
if ((i>0)&&(i%64 == 0)) {
|
|
||||||
if (code != "") {
|
|
||||||
codes.push(code + "\n");
|
|
||||||
} else {
|
|
||||||
codes.push(code);
|
|
||||||
}
|
|
||||||
code ="";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (code != "") codes.push(code + "\n");
|
|
||||||
codes.push("};\n");
|
|
||||||
|
|
||||||
return codes;
|
|
||||||
|
|
||||||
|
ctx.builder.setWit2Sig(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function buildCircuitVar() {
|
|
||||||
return "Circom_Circuit _circuit = {\n" +
|
|
||||||
" NSignals,\n"+
|
|
||||||
" NComponents,\n"+
|
|
||||||
" NInputs,\n"+
|
|
||||||
" NOutputs,\n"+
|
|
||||||
" NVars,\n"+
|
|
||||||
" _wit2sig,\n"+
|
|
||||||
" _components,\n"+
|
|
||||||
" _mapIsInput,\n"+
|
|
||||||
" _constants,\n" +
|
|
||||||
" __P__\n" +
|
|
||||||
"};\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function addSizes(_sizes) {
|
function addSizes(_sizes) {
|
||||||
const sizes = _sizes || [];
|
const sizes = _sizes || [];
|
||||||
@@ -443,6 +273,8 @@ function addSizes(_sizes) {
|
|||||||
|
|
||||||
const accSizes = utils.accSizes(sizes);
|
const accSizes = utils.accSizes(sizes);
|
||||||
|
|
||||||
|
this.builder.addSizes(labelName, accSizes);
|
||||||
|
|
||||||
let code = `Circom_Size ${labelName}[${accSizes.length}] = {`;
|
let code = `Circom_Size ${labelName}[${accSizes.length}] = {`;
|
||||||
for (let i=0; i<accSizes.length; i++) {
|
for (let i=0; i<accSizes.length; i++) {
|
||||||
if (i>0) code += ",";
|
if (i>0) code += ",";
|
||||||
@@ -458,10 +290,9 @@ function addConstant(c) {
|
|||||||
c = bigInt(c);
|
c = bigInt(c);
|
||||||
const s = c.toString();
|
const s = c.toString();
|
||||||
if (typeof (this.constantsMap[s]) !== "undefined") return this.constantsMap[s];
|
if (typeof (this.constantsMap[s]) !== "undefined") return this.constantsMap[s];
|
||||||
const newId = this.constants.length;
|
const cIdx = this.builder.addConstant(c);
|
||||||
this.constants.push(c);
|
this.constantsMap[s] = cIdx;
|
||||||
this.constantsMap[s] = newId;
|
return cIdx;
|
||||||
return newId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildFunction(name, paramValues) {
|
function buildFunction(name, paramValues) {
|
||||||
@@ -476,9 +307,9 @@ function buildFunction(name, paramValues) {
|
|||||||
|
|
||||||
const oldRefs = ctx.refs;
|
const oldRefs = ctx.refs;
|
||||||
const oldConditionalCode = ctx.conditionalCode;
|
const oldConditionalCode = ctx.conditionalCode;
|
||||||
const oldCode = ctx.code;
|
const oldCodeBuilder = ctx.codeBuilder;
|
||||||
const oldCodeHeader = ctx.codeHeader;
|
const oldFnBuilder = ctx.fnBuilder;
|
||||||
const oldCodeFooter = ctx.codeFooter;
|
|
||||||
const oldUniqueNames = ctx.uniqueNames;
|
const oldUniqueNames = ctx.uniqueNames;
|
||||||
const oldFileName = ctx.fileName;
|
const oldFileName = ctx.fileName;
|
||||||
const oldFilePath = ctx.oldFilePath;
|
const oldFilePath = ctx.oldFilePath;
|
||||||
@@ -489,21 +320,20 @@ function buildFunction(name, paramValues) {
|
|||||||
ctx.scopes = [{}];
|
ctx.scopes = [{}];
|
||||||
ctx.refs = [];
|
ctx.refs = [];
|
||||||
ctx.conditionalCode = false;
|
ctx.conditionalCode = false;
|
||||||
ctx.code = "";
|
ctx.fnBuilder = ctx.builder.newFunctionBuilder(`${name}_${h}`, instanceDef);
|
||||||
ctx.codeHeader = "// Header\n";
|
ctx.codeBuilder = ctx.fnBuilder.newCodeBuilder();
|
||||||
ctx.codeFooter = "// Footer\n";
|
|
||||||
ctx.uniqueNames = Object.assign({},ctx.globalNames);
|
ctx.uniqueNames = Object.assign({},ctx.globalNames);
|
||||||
ctx.returnValue = null;
|
ctx.returnValue = null;
|
||||||
ctx.returnSizes = null;
|
ctx.returnSizes = null;
|
||||||
ctx.fileName = ctx.functions[name].fileName;
|
ctx.fileName = ctx.functions[name].fileName;
|
||||||
ctx.filePath = ctx.functions[name].filePath;
|
ctx.filePath = ctx.functions[name].filePath;
|
||||||
|
|
||||||
let paramsStr = "";
|
let paramLabels = [];
|
||||||
|
|
||||||
for (let i=0; i<ctx.functions[name].params.length; i++) {
|
for (let i=0; i<ctx.functions[name].params.length; i++) {
|
||||||
|
|
||||||
if (paramValues[i].used) {
|
if (paramValues[i].used) {
|
||||||
paramsStr += `,PFrElement ${ctx.functions[name].params[i]}`;
|
paramLabels.push(ctx.functions[name].params[i]);
|
||||||
const idRef = ctx.refs.length;
|
const idRef = ctx.refs.length;
|
||||||
ctx.refs.push({
|
ctx.refs.push({
|
||||||
type: "BIGINT",
|
type: "BIGINT",
|
||||||
@@ -525,6 +355,8 @@ function buildFunction(name, paramValues) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.fnBuilder.setParams(paramLabels);
|
||||||
|
|
||||||
createRefs(ctx, ctx.functions[name].block);
|
createRefs(ctx, ctx.functions[name].block);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
@@ -533,20 +365,12 @@ function buildFunction(name, paramValues) {
|
|||||||
|
|
||||||
if (ctx.returnValue == null) {
|
if (ctx.returnValue == null) {
|
||||||
if (ctx.returnSizes == null) assert(false, `Funciont ${name} does not return any value`);
|
if (ctx.returnSizes == null) assert(false, `Funciont ${name} does not return any value`);
|
||||||
|
|
||||||
|
ctx.fnBuilder.setBody(ctx.codeBuilder);
|
||||||
|
ctx.builder.addFunction(ctx.fnBuilder);
|
||||||
|
|
||||||
res.type = "VARVAL_CONSTSIZE";
|
res.type = "VARVAL_CONSTSIZE";
|
||||||
let code =
|
|
||||||
"/*\n" +
|
|
||||||
instanceDef +
|
|
||||||
"\n*/\n" +
|
|
||||||
`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;
|
res.returnSizes = ctx.returnSizes;
|
||||||
ctx.functionCodes.push(code);
|
|
||||||
} else {
|
} else {
|
||||||
res.type = "CONSTVAL";
|
res.type = "CONSTVAL";
|
||||||
res.returnValue = ctx.returnValue;
|
res.returnValue = ctx.returnValue;
|
||||||
@@ -555,9 +379,8 @@ function buildFunction(name, paramValues) {
|
|||||||
|
|
||||||
ctx.refs = oldRefs;
|
ctx.refs = oldRefs;
|
||||||
ctx.conditionalCode = oldConditionalCode;
|
ctx.conditionalCode = oldConditionalCode;
|
||||||
ctx.code = oldCode;
|
ctx.codeBuilder = oldCodeBuilder;
|
||||||
ctx.codeHeader = oldCodeHeader;
|
ctx.fnBuilder = oldFnBuilder;
|
||||||
ctx.codeFooter = oldCodeFooter;
|
|
||||||
ctx.uniqueNames = oldUniqueNames;
|
ctx.uniqueNames = oldUniqueNames;
|
||||||
ctx.fileName = oldFileName;
|
ctx.fileName = oldFileName;
|
||||||
ctx.filePath = oldFilePath;
|
ctx.filePath = oldFilePath;
|
||||||
@@ -570,7 +393,6 @@ function buildFunction(name, paramValues) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function hashComponentCall(ctx, cIdx) {
|
function hashComponentCall(ctx, cIdx) {
|
||||||
// TODO: At the moment generate a diferent function for each instance of the component
|
// TODO: At the moment generate a diferent function for each instance of the component
|
||||||
const constParams = [];
|
const constParams = [];
|
||||||
616
src/builder_c.js
Normal file
616
src/builder_c.js
Normal file
@@ -0,0 +1,616 @@
|
|||||||
|
const streamFromMultiArray = require("./stream_from_multiarray");
|
||||||
|
const bigInt = require("big-integer");
|
||||||
|
const utils = require("./utils");
|
||||||
|
const assert = require("assert");
|
||||||
|
|
||||||
|
function ref2src(c) {
|
||||||
|
if (c[0] == "R") {
|
||||||
|
return c[1];
|
||||||
|
} else if (c[0] == "V") {
|
||||||
|
return c[1].toString();
|
||||||
|
} else if (c[0] == "C") {
|
||||||
|
return `(ctx->circuit->constants + ${c[1]})`;
|
||||||
|
} else if (c[0] == "CC") {
|
||||||
|
return "__cIdx";
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CodeBuilderC {
|
||||||
|
constructor() {
|
||||||
|
this.ops = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
addComment(comment) {
|
||||||
|
this.ops.push({op: "COMMENT", comment});
|
||||||
|
}
|
||||||
|
|
||||||
|
addBlock(block) {
|
||||||
|
this.ops.push({op: "BLOCK", block});
|
||||||
|
}
|
||||||
|
|
||||||
|
calcOffset(dLabel, offsets) {
|
||||||
|
this.ops.push({op: "CALCOFFSETS", dLabel, offsets});
|
||||||
|
}
|
||||||
|
|
||||||
|
assign(dLabel, src, sOffset) {
|
||||||
|
this.ops.push({op: "ASSIGN", dLabel, src, sOffset});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSubComponentOffset(dLabel, component, hash, hashLabel) {
|
||||||
|
this.ops.push({op: "GETSUBCOMPONENTOFFSET", dLabel, component, hash, hashLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSubComponentSizes(dLabel, component, hash, hashLabel) {
|
||||||
|
this.ops.push({op: "GETSUBCOMPONENTSIZES", dLabel, component, hash, hashLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSignalOffset(dLabel, component, hash, hashLabel) {
|
||||||
|
this.ops.push({op: "GETSIGNALOFFSET", dLabel, component, hash, hashLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSignalSizes(dLabel, component, hash, hashLabel) {
|
||||||
|
this.ops.push({op: "GETSIGNALSIZES", dLabel, component, hash, hashLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
setSignal(component, signal, value) {
|
||||||
|
this.ops.push({op: "SETSIGNAL", component, signal, value});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSignal(dLabel, component, signal) {
|
||||||
|
this.ops.push({op: "GETSIGNAL", dLabel, component, signal});
|
||||||
|
}
|
||||||
|
|
||||||
|
copyN(dLabel, offset, src, n) {
|
||||||
|
this.ops.push({op: "COPYN", dLabel, offset, src, n});
|
||||||
|
}
|
||||||
|
|
||||||
|
copyNRet(src, n) {
|
||||||
|
this.ops.push({op: "COPYNRET", src, n});
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldOp(dLabel, fOp, params) {
|
||||||
|
this.ops.push({op: "FOP", dLabel, fOp, params});
|
||||||
|
}
|
||||||
|
|
||||||
|
ret() {
|
||||||
|
this.ops.push({op: "RET"});
|
||||||
|
}
|
||||||
|
|
||||||
|
addLoop(condLabel, body) {
|
||||||
|
this.ops.push({op: "LOOP", condLabel, body});
|
||||||
|
}
|
||||||
|
|
||||||
|
addIf(condLabel, thenCode, elseCode) {
|
||||||
|
this.ops.push({op: "IF", condLabel, thenCode, elseCode});
|
||||||
|
}
|
||||||
|
|
||||||
|
fnCall(fnName, retLabel, params) {
|
||||||
|
this.ops.push({op: "FNCALL", fnName, retLabel, params});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkConstraint(a, b, strErr) {
|
||||||
|
this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
concat(cb) {
|
||||||
|
this.ops.push(...cb.ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasCode() {
|
||||||
|
for (let i=0; i<this.ops.length; i++) {
|
||||||
|
if (this.ops[i].op != "COMMENT") return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildOffset(offsets) {
|
||||||
|
let rN=0;
|
||||||
|
let S = "";
|
||||||
|
offsets.forEach((o) => {
|
||||||
|
if ((o[0][0] == "V") && (o[1][0]== "V")) {
|
||||||
|
rN += o[0][1]*o[1][1];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let f="";
|
||||||
|
if (o[0][0] == "V") {
|
||||||
|
if (o[0][1]==0) return;
|
||||||
|
f += o[0][1];
|
||||||
|
} else if (o[0][0] == "RI") {
|
||||||
|
if (o[0][1]==0) return;
|
||||||
|
f += o[0][1];
|
||||||
|
} else if (o[0][0] == "R") {
|
||||||
|
f += `Fr_toInt(${o[0][1]})`;
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
if (o[1][0] == "V") {
|
||||||
|
if (o[1][1]==0) return;
|
||||||
|
if (o[1][1]>1) {
|
||||||
|
f += "*" + o[1][1];
|
||||||
|
}
|
||||||
|
} else if (o[1][0] == "RS") {
|
||||||
|
f += `*${o[1][1]}[${o[1][2]}]`;
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
if (S!="") S+= " + ";
|
||||||
|
S += f;
|
||||||
|
});
|
||||||
|
if (rN>0) {
|
||||||
|
S = `${rN} + ${S}`;
|
||||||
|
}
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(code) {
|
||||||
|
this.ops.forEach( (o) => {
|
||||||
|
if (o.op == "COMMENT") {
|
||||||
|
code.push(`/* ${o.comment} */`);
|
||||||
|
} else if (o.op == "BLOCK") {
|
||||||
|
const codeBlock=[];
|
||||||
|
o.block.build(codeBlock);
|
||||||
|
code.push(utils.ident(codeBlock));
|
||||||
|
} else if (o.op == "CALCOFFSETS") {
|
||||||
|
code.push(`${o.dLabel} = ${this._buildOffset(o.offsets)};`);
|
||||||
|
} else if (o.op == "ASSIGN") {
|
||||||
|
const oS = ref2src(o.sOffset);
|
||||||
|
if (oS != "0") {
|
||||||
|
code.push(`${o.dLabel} = ${ref2src(o.src)} + ${oS};`);
|
||||||
|
} else {
|
||||||
|
code.push(`${o.dLabel} = ${ref2src(o.src)};`);
|
||||||
|
}
|
||||||
|
} else if (o.op == "GETSUBCOMPONENTOFFSET") {
|
||||||
|
code.push(`${o.dLabel} = ctx->getSubComponentOffset(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
|
||||||
|
} else if (o.op == "GETSUBCOMPONENTSIZES") {
|
||||||
|
code.push(`${o.dLabel} = ctx->getSubComponentSizes(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
|
||||||
|
} else if (o.op == "GETSIGNALOFFSET") {
|
||||||
|
code.push(`${o.dLabel} = ctx->getSignalOffset(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
|
||||||
|
} else if (o.op == "GETSIGNALSIZES") {
|
||||||
|
code.push(`${o.dLabel} = ctx->getSignalSizes(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
|
||||||
|
} else if (o.op == "SETSIGNAL") {
|
||||||
|
code.push(`ctx->setSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${ref2src(o.value)});`);
|
||||||
|
} else if (o.op == "GETSIGNAL") {
|
||||||
|
code.push(`ctx->getSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${o.dLabel});`);
|
||||||
|
} else if (o.op == "COPYN") {
|
||||||
|
const oS = ref2src(o.offset);
|
||||||
|
const dLabel = (oS != "0") ? (o.dLabel + "+" + oS) : o.dLabel;
|
||||||
|
code.push(`Fr_copyn(${dLabel}, ${ref2src(o.src)}, ${o.n});`);
|
||||||
|
} else if (o.op == "COPYNRET") {
|
||||||
|
code.push(`Fr_copyn(__retValue, ${ref2src(o.src)}, ${o.n});`);
|
||||||
|
} else if (o.op == "RET") {
|
||||||
|
code.push("goto returnFunc;");
|
||||||
|
} else if (o.op == "FOP") {
|
||||||
|
let paramsS = "";
|
||||||
|
for (let i=0; i<o.params.length; i++) {
|
||||||
|
if (i>0) paramsS += ", ";
|
||||||
|
paramsS += ref2src(o.params[i]);
|
||||||
|
}
|
||||||
|
code.push(`Fr_${o.fOp}(${o.dLabel}, ${paramsS});`);
|
||||||
|
} else if (o.op == "LOOP") {
|
||||||
|
code.push(`while (Fr_isTrue(${o.condLabel})) {`);
|
||||||
|
const body = [];
|
||||||
|
o.body.build(body);
|
||||||
|
code.push(utils.ident(body));
|
||||||
|
code.push("}");
|
||||||
|
} else if (o.op == "IF") {
|
||||||
|
code.push(`if (Fr_isTrue(${o.condLabel})) {`);
|
||||||
|
const thenCode = [];
|
||||||
|
o.thenCode.build(thenCode);
|
||||||
|
code.push(utils.ident(thenCode));
|
||||||
|
if (o.elseCode) {
|
||||||
|
code.push("} else {");
|
||||||
|
const elseCode = [];
|
||||||
|
o.elseCode.build(elseCode);
|
||||||
|
code.push(utils.ident(elseCode));
|
||||||
|
}
|
||||||
|
code.push("}");
|
||||||
|
} else if (o.op == "FNCALL") {
|
||||||
|
code.push(`${o.fnName}(ctx, ${o.retLabel}, ${o.params.join(",")});`);
|
||||||
|
} else if (o.op == "CHECKCONSTRAINT") {
|
||||||
|
code.push(`ctx->checkConstraint(__cIdx, ${ref2src(o.a)}, ${ref2src(o.b)}, "${o.strErr}");`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FunctionBuilderC {
|
||||||
|
|
||||||
|
constructor(name, instanceDef, type) {
|
||||||
|
this.name = name;
|
||||||
|
this.instanceDef = instanceDef;
|
||||||
|
this.type = type; // "COMPONENT" or "FUNCTIOM"
|
||||||
|
this.definedFrElements = [];
|
||||||
|
this.definedIntElements = [];
|
||||||
|
this.definedSizeElements = [];
|
||||||
|
this.definedPFrElements = [];
|
||||||
|
this.initializedElements = [];
|
||||||
|
this.initializedSignalOffset = [];
|
||||||
|
this.initializedSignalSizes = [];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
defineFrElements(dLabel, size) {
|
||||||
|
this.definedFrElements.push({dLabel, size});
|
||||||
|
}
|
||||||
|
|
||||||
|
defineIntElement(dLabel) {
|
||||||
|
this.definedIntElements.push({dLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
defineSizesElement(dLabel) {
|
||||||
|
this.definedSizeElements.push({dLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
definePFrElement(dLabel) {
|
||||||
|
this.definedPFrElements.push({dLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeFrElement(dLabel, offset, idConstant) {
|
||||||
|
this.initializedElements.push({dLabel, offset, idConstant});
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeSignalOffset(dLabel, component, hash, hashLabel) {
|
||||||
|
this.initializedSignalOffset.push({dLabel, component, hash, hashLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeSignalSizes(dLabel, component, hash, hashLabel) {
|
||||||
|
this.initializedSignalSizes.push({dLabel, component, hash, hashLabel});
|
||||||
|
}
|
||||||
|
|
||||||
|
setParams(params) {
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildHeader(code) {
|
||||||
|
this.definedFrElements.forEach( (o) => {
|
||||||
|
code.push(`FrElement ${o.dLabel}[${o.size}];`);
|
||||||
|
});
|
||||||
|
this.definedIntElements.forEach( (o) => {
|
||||||
|
code.push(`int ${o.dLabel};`);
|
||||||
|
});
|
||||||
|
this.definedSizeElements.forEach( (o) => {
|
||||||
|
code.push(`Circom_Sizes ${o.dLabel};`);
|
||||||
|
});
|
||||||
|
this.definedPFrElements.forEach( (o) => {
|
||||||
|
code.push(`PFrElement ${o.dLabel};`);
|
||||||
|
});
|
||||||
|
this.initializedElements.forEach( (o) => {
|
||||||
|
code.push(`Fr_copy(&(${o.dLabel}[${o.offset}]), ctx->circuit->constants +${o.idConstant});`);
|
||||||
|
});
|
||||||
|
this.initializedSignalOffset.forEach( (o) => {
|
||||||
|
code.push(`${o.dLabel} = ctx->getSignalOffset(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
|
||||||
|
});
|
||||||
|
this.initializedSignalSizes.forEach( (o) => {
|
||||||
|
code.push(`${o.dLabel} = ctx->getSignalSizes(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildFooter(code) {
|
||||||
|
}
|
||||||
|
|
||||||
|
newCodeBuilder() {
|
||||||
|
return new CodeBuilderC();
|
||||||
|
}
|
||||||
|
|
||||||
|
setBody(body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(code) {
|
||||||
|
code.push(
|
||||||
|
"/*",
|
||||||
|
this.instanceDef,
|
||||||
|
"*/"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.type=="COMPONENT") {
|
||||||
|
code.push(`void ${this.name}(Circom_CalcWit *ctx, int __cIdx) {`);
|
||||||
|
} else if (this.type=="FUNCTION") {
|
||||||
|
let sParams = "";
|
||||||
|
for (let i=0;i<this.params.length;i++ ) sParams += `, PFrElement ${this.params[i]}`;
|
||||||
|
code.push(`void ${this.name}(Circom_CalcWit *ctx, PFrElement __retValue ${sParams}) {`);
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnCode = [];
|
||||||
|
this._buildHeader(fnCode);
|
||||||
|
this.body.build(fnCode);
|
||||||
|
if (this.type=="COMPONENT") {
|
||||||
|
fnCode.push("ctx->finished(__cIdx);");
|
||||||
|
} else if (this.type=="FUNCTION") {
|
||||||
|
fnCode.push("returnFunc: ;");
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
this._buildFooter(fnCode);
|
||||||
|
|
||||||
|
code.push(utils.ident(fnCode));
|
||||||
|
code.push("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class BuilderC {
|
||||||
|
constructor() {
|
||||||
|
this.hashMaps={};
|
||||||
|
this.componentEntriesTables={};
|
||||||
|
this.sizes ={};
|
||||||
|
this.constants = [];
|
||||||
|
this.functions = [];
|
||||||
|
this.components = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
setHeader(header) {
|
||||||
|
this.header=header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ht is an array of 256 element that can be undefined or [Hash, Idx, KeyName] elements.
|
||||||
|
addHashMap(name, hm) {
|
||||||
|
this.hashMaps[name] = hm;
|
||||||
|
}
|
||||||
|
|
||||||
|
addComponentEntriesTable(name, cet) {
|
||||||
|
this.componentEntriesTables[name] = cet;
|
||||||
|
}
|
||||||
|
|
||||||
|
addSizes(name, accSizes) {
|
||||||
|
this.sizes[name] = accSizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
addConstant(c) {
|
||||||
|
this.constants.push(c);
|
||||||
|
return this.constants.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addFunction(fnBuilder) {
|
||||||
|
this.functions.push(fnBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
addComponent(component) {
|
||||||
|
this.components.push(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
setMapIsInput(map) {
|
||||||
|
this.mapIsInput = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
setWit2Sig(wit2sig) {
|
||||||
|
this.wit2sig = wit2sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
newComponentFunctionBuilder(name, instanceDef) {
|
||||||
|
return new FunctionBuilderC(name, instanceDef, "COMPONENT");
|
||||||
|
}
|
||||||
|
|
||||||
|
newFunctionBuilder(name, instanceDef) {
|
||||||
|
return new FunctionBuilderC(name, instanceDef, "FUNCTION");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Body functions
|
||||||
|
|
||||||
|
_buildHeader(code) {
|
||||||
|
code.push(
|
||||||
|
"#include \"circom.h\"",
|
||||||
|
"#include \"calcwit.h\"",
|
||||||
|
`#define NSignals ${this.header.NSignals}`,
|
||||||
|
`#define NComponents ${this.header.NComponents}`,
|
||||||
|
`#define NOutputs ${this.header.NOutputs}`,
|
||||||
|
`#define NInputs ${this.header.NInputs}`,
|
||||||
|
`#define NVars ${this.header.NVars}`,
|
||||||
|
`#define __P__ "${this.header.P.toString()}"`,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildHashMaps(code) {
|
||||||
|
|
||||||
|
code.push("// Hash Maps ");
|
||||||
|
for (let hmName in this.hashMaps ) {
|
||||||
|
const hm = this.hashMaps[hmName];
|
||||||
|
|
||||||
|
let c = `Circom_HashEntry ${hmName}[256] = {`;
|
||||||
|
for (let i=0; i<256; i++) {
|
||||||
|
c += i>0 ? "," : "";
|
||||||
|
if (hm[i]) {
|
||||||
|
c += `{0x${hm[i][0]}LL, ${hm[i][1]}} /* ${hm[i][2]} */`;
|
||||||
|
} else {
|
||||||
|
c += "{0,0}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c += "};";
|
||||||
|
code.push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildComponentEntriesTables(code) {
|
||||||
|
code.push("// Component Entry tables");
|
||||||
|
for (let cetName in this.componentEntriesTables) {
|
||||||
|
const cet = this.componentEntriesTables[cetName];
|
||||||
|
|
||||||
|
code.push(`Circom_ComponentEntry ${cetName}[${cet.length}] = {`);
|
||||||
|
for (let j=0; j<cet.length; j++) {
|
||||||
|
const ty = cet[j].type == "S" ? "_typeSignal" : "_typeComponent";
|
||||||
|
code.push(` ${j>0?",":" "}{${cet[j].offset},${cet[j].sizeName}, ${ty}}`);
|
||||||
|
}
|
||||||
|
code.push("};");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildSizes(code) {
|
||||||
|
code.push("// Sizes");
|
||||||
|
for (let sName in this.sizes) {
|
||||||
|
const accSizes = this.sizes[sName];
|
||||||
|
|
||||||
|
let c = `Circom_Size ${sName}[${accSizes.length}] = {`;
|
||||||
|
for (let i=0; i<accSizes.length; i++) {
|
||||||
|
if (i>0) c += ",";
|
||||||
|
c += accSizes[i];
|
||||||
|
}
|
||||||
|
c += "};";
|
||||||
|
code.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildConstants(code) {
|
||||||
|
const self = this;
|
||||||
|
const n64 = Math.floor((self.header.P.bitLength() - 1) / 64)+1;
|
||||||
|
const R = bigInt.one.shiftLeft(n64*64);
|
||||||
|
|
||||||
|
code.push("// Constants");
|
||||||
|
code.push(`FrElement _constants[${self.constants.length}] = {`);
|
||||||
|
for (let i=0; i<self.constants.length; i++) {
|
||||||
|
code.push((i>0 ? "," : " ") + "{" + number2Code(self.constants[i]) + "}");
|
||||||
|
}
|
||||||
|
code.push("};");
|
||||||
|
|
||||||
|
function number2Code(n) {
|
||||||
|
if (n.lt(bigInt("80000000", 16)) ) {
|
||||||
|
return addShortMontgomeryPositive(n);
|
||||||
|
}
|
||||||
|
if (n.geq(self.header.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(self.header.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(self.header.P);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildFunctions(code) {
|
||||||
|
for (let i=0; i<this.functions.length; i++) {
|
||||||
|
const cfb = this.functions[i];
|
||||||
|
cfb.build(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildComponents(code) {
|
||||||
|
code.push("// Components");
|
||||||
|
code.push(`Circom_Component _components[${this.components.length}] = {`);
|
||||||
|
for (let i=0; i<this.components.length; i++) {
|
||||||
|
const c = this.components[i];
|
||||||
|
const sep = i>0 ? " ," : " ";
|
||||||
|
code.push(`${sep}{${c.hashMapName}, ${c.entryTableName}, ${c.functionName}, ${c.nInSignals}, ${c.newThread}}`);
|
||||||
|
}
|
||||||
|
code.push("};");
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildMapIsInput(code) {
|
||||||
|
code.push("// mapIsInput");
|
||||||
|
code.push(`u32 _mapIsInput[${this.mapIsInput.length}] = {`);
|
||||||
|
let line = "";
|
||||||
|
for (let i=0; i<this.mapIsInput.length; i++) {
|
||||||
|
line += i>0 ? ", " : " ";
|
||||||
|
line += toHex(this.mapIsInput[i]);
|
||||||
|
if (((i+1) % 64)==0) {
|
||||||
|
code.push(" "+line);
|
||||||
|
line = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (line != "") code.push(" "+line);
|
||||||
|
code.push("};");
|
||||||
|
|
||||||
|
function toHex(number) {
|
||||||
|
if (number < 0) number = 0xFFFFFFFF + number + 1;
|
||||||
|
let S=number.toString(16).toUpperCase();
|
||||||
|
while (S.length<8) S = "0" + S;
|
||||||
|
return "0x"+S;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildWit2Sig(code) {
|
||||||
|
code.push("// Witness to Signal Table");
|
||||||
|
code.push(`int _wit2sig[${this.wit2sig.length}] = {`);
|
||||||
|
let line = "";
|
||||||
|
for (let i=0; i<this.wit2sig.length; i++) {
|
||||||
|
line += i>0 ? "," : " ";
|
||||||
|
line += this.wit2sig[i];
|
||||||
|
if (((i+1) % 64) == 0) {
|
||||||
|
code.push(" "+line);
|
||||||
|
line = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (line != "") code.push(" "+line);
|
||||||
|
code.push("};");
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildCircuitVar(code) {
|
||||||
|
|
||||||
|
code.push(
|
||||||
|
"// Circuit Variable",
|
||||||
|
"Circom_Circuit _circuit = {" ,
|
||||||
|
" NSignals,",
|
||||||
|
" NComponents,",
|
||||||
|
" NInputs,",
|
||||||
|
" NOutputs,",
|
||||||
|
" NVars,",
|
||||||
|
" _wit2sig,",
|
||||||
|
" _components,",
|
||||||
|
" _mapIsInput,",
|
||||||
|
" _constants,",
|
||||||
|
" __P__",
|
||||||
|
"};"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
build() {
|
||||||
|
const code=[];
|
||||||
|
this._buildHeader(code);
|
||||||
|
this._buildSizes(code);
|
||||||
|
this._buildConstants(code);
|
||||||
|
this._buildHashMaps(code);
|
||||||
|
this._buildComponentEntriesTables(code);
|
||||||
|
this._buildFunctions(code);
|
||||||
|
this._buildComponents(code);
|
||||||
|
this._buildMapIsInput(code);
|
||||||
|
this._buildWit2Sig(code);
|
||||||
|
this._buildCircuitVar(code);
|
||||||
|
return streamFromMultiArray(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = BuilderC;
|
||||||
28
src/builder_wasm.js
Normal file
28
src/builder_wasm.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
class BuilderWasm {
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setHeader(header) {
|
||||||
|
this.header=header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ht is an array of 256 element that can be undefined or [Hash, Idx, KeyName] elements.
|
||||||
|
addHashMap(name, ht) {
|
||||||
|
this.hashTables[name] = ht;
|
||||||
|
}
|
||||||
|
|
||||||
|
addComponentEntriesTable(name, cet) {
|
||||||
|
this.componentEntriesTables[name] = cet;
|
||||||
|
}
|
||||||
|
|
||||||
|
addSizes(name, accSizes) {
|
||||||
|
this.sizes[name] = accSizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BuilderWasm;
|
||||||
1220
src/c_gen.js
1220
src/c_gen.js
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,9 @@
|
|||||||
const bigInt = require("big-integer");
|
const bigInt = require("big-integer");
|
||||||
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||||
const sONE = 0;
|
const sONE = 0;
|
||||||
const buildC = require("./c_build");
|
const build = require("./build");
|
||||||
|
const BuilderC = require("./builder_c");
|
||||||
|
const BuilderWasm = require("./builder_wasm");
|
||||||
const constructionPhase = require("./construction_phase");
|
const constructionPhase = require("./construction_phase");
|
||||||
const Ctx = require("./ctx");
|
const Ctx = require("./ctx");
|
||||||
const ZqField = require("fflib").ZqField;
|
const ZqField = require("fflib").ZqField;
|
||||||
@@ -81,11 +83,22 @@ async function compile(srcFile, options) {
|
|||||||
throw(ctx.error);
|
throw(ctx.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (options.cSourceWriteStream) {
|
if (options.cSourceWriteStream) {
|
||||||
const cSrc = buildC(ctx);
|
ctx.builder = new BuilderC();
|
||||||
cSrc.pipe(options.cSourceWriteStream);
|
build(ctx);
|
||||||
await new Promise(fulfill => options.cSourceWriteStream.on("finish", fulfill));
|
const rdStream = ctx.builder.build();
|
||||||
|
rdStream.pipe(options.cSourceWriteStream);
|
||||||
|
|
||||||
|
// await new Promise(fulfill => options.cSourceWriteStream.on("finish", fulfill));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.wasmWriteStream) {
|
||||||
|
ctx.builder = new BuilderWasm();
|
||||||
|
build(ctx);
|
||||||
|
const rdStream = ctx.builder.build();
|
||||||
|
rdStream.pipe(options.wasmWriteStream);
|
||||||
|
|
||||||
|
// await new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill));
|
||||||
}
|
}
|
||||||
|
|
||||||
// const mainCode = gen(ctx,ast);
|
// const mainCode = gen(ctx,ast);
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
module.exports = genOpt;
|
|
||||||
|
|
||||||
|
|
||||||
function genOpt(ctx, ast) {
|
|
||||||
if (ast.type == "OP") {
|
|
||||||
if (ast.op == "=") {
|
|
||||||
return genOptVarAssignement(ctx, ast);
|
|
||||||
} else {
|
|
||||||
error(ctx, ast, "GENOPT -> Invalid operation: " + ast.op);
|
|
||||||
}
|
|
||||||
} else if (ast.type == "TEMPLATEDEF") {
|
|
||||||
return genOptTemplateDef(ctx, ast);
|
|
||||||
} else {
|
|
||||||
error(ctx, ast, "GENOPT -> Invalid AST node type: " + ast.type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function error(ctx, ast, errStr) {
|
|
||||||
ctx.error = {
|
|
||||||
pos: {
|
|
||||||
first_line: ast.first_line,
|
|
||||||
first_column: ast.first_column,
|
|
||||||
last_line: ast.last_line,
|
|
||||||
last_column: ast.last_column
|
|
||||||
},
|
|
||||||
errStr: errStr,
|
|
||||||
errFile: ctx.fileName,
|
|
||||||
ast: ast
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function genOptTemplateDef(ctx, ast) {
|
|
||||||
if (ctx.templates[ast.name]) {
|
|
||||||
return error(ctx, ast, "Template name already exists: "+ast.name);
|
|
||||||
}
|
|
||||||
ctx.templates[ast.name] = {
|
|
||||||
type: "TEMPLATE",
|
|
||||||
params: ast.params,
|
|
||||||
block: ast.block,
|
|
||||||
fileName: ctx.fileName,
|
|
||||||
filePath: ctx.filePath
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function genOptVarAssignement(ctx, ast) {
|
|
||||||
let varName;
|
|
||||||
if (ast.values[0].type == "DECLARE") {
|
|
||||||
varName = genOptCode(ctx, ast.values[0]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
} else {
|
|
||||||
varName = ast.values[0];
|
|
||||||
}
|
|
||||||
const varContent = getScope(ctx, varName.name, varName.selectors);
|
|
||||||
if (ctx.error) return;
|
|
||||||
|
|
||||||
if ((typeof(varContent) != "object")||(varContent == null)) return error(ctx, ast, "Variable not defined");
|
|
||||||
|
|
||||||
if (varContent.type == "COMPONENT") return genOptInstantiateComponet(ctx, varName, ast.values[1]);
|
|
||||||
if (varContent.type == "SIGNAL") return error(ctx, ast, "Cannot assig to a signal with `=` use <-- or <== ops");
|
|
||||||
|
|
||||||
const res = genOpt(ctx, ast.values[1]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
|
|
||||||
setScope(ctx, varName.name, varName.selectors, res);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
1571
src/gencode.js
1571
src/gencode.js
File diff suppressed because it is too large
Load Diff
@@ -8,11 +8,13 @@ module.exports = function streamFromMultiarray(ma) {
|
|||||||
|
|
||||||
rs._read = function() {
|
rs._read = function() {
|
||||||
let res;
|
let res;
|
||||||
do {
|
|
||||||
res = objFromIdx(ma, curIndex);
|
res = objFromIdx(ma, curIndex);
|
||||||
curIndex = nextIdx(curIndex);
|
curIndex = nextIdx(curIndex);
|
||||||
} while (res==="");
|
if (res!=null) {
|
||||||
rs.push(res);
|
rs.push(res + "\n");
|
||||||
|
} else {
|
||||||
|
rs.push(null);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,18 @@ module.exports.isDefined = isDefined;
|
|||||||
module.exports.accSizes2Str = accSizes2Str;
|
module.exports.accSizes2Str = accSizes2Str;
|
||||||
|
|
||||||
function ident(text) {
|
function ident(text) {
|
||||||
|
if (typeof text === "string") {
|
||||||
let lines = text.split("\n");
|
let lines = text.split("\n");
|
||||||
for (let i=0; i<lines.length; i++) {
|
for (let i=0; i<lines.length; i++) {
|
||||||
if (lines[i]) lines[i] = " "+lines[i];
|
if (lines[i]) lines[i] = " "+lines[i];
|
||||||
}
|
}
|
||||||
return lines.join("\n");
|
return lines.join("\n");
|
||||||
|
} else if (Array.isArray(text)) {
|
||||||
|
for (let i=0; i<text.length; i++ ) {
|
||||||
|
text[i] = ident(text[i]);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractSizes (o) {
|
function extractSizes (o) {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ async function doTest(circuit, testVectors) {
|
|||||||
|
|
||||||
describe("basic cases", function () {
|
describe("basic cases", function () {
|
||||||
this.timeout(100000);
|
this.timeout(100000);
|
||||||
|
|
||||||
it("inout", async () => {
|
it("inout", async () => {
|
||||||
await doTest(
|
await doTest(
|
||||||
"inout.circom",
|
"inout.circom",
|
||||||
@@ -111,7 +112,6 @@ describe("basic cases", function () {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("function1", async () => {
|
it("function1", async () => {
|
||||||
await doTest(
|
await doTest(
|
||||||
"function1.circom",
|
"function1.circom",
|
||||||
@@ -266,6 +266,7 @@ describe("basic cases", function () {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Conditional Ternary operator", async () => {
|
it("Conditional Ternary operator", async () => {
|
||||||
await doTest(
|
await doTest(
|
||||||
"condternary.circom",
|
"condternary.circom",
|
||||||
@@ -277,6 +278,7 @@ describe("basic cases", function () {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Compute block", async () => {
|
it("Compute block", async () => {
|
||||||
await doTest(
|
await doTest(
|
||||||
"compute.circom",
|
"compute.circom",
|
||||||
@@ -337,4 +339,5 @@ describe("basic cases", function () {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user