/* Copyright 2018 0KIMS association. This file is part of circom (Zero Knowledge Circuit Compiler). circom is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. circom is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with circom. If not, see . */ const assert = require("assert"); const bigInt = require("big-integer"); const utils = require("./utils"); const gen = require("./gencode").gen; const createRefs = require("./gencode").createRefs; module.exports = build; function build(ctx) { ctx.definedFunctions = {}; ctx.functionCodes = []; ctx.buildFunction = buildFunction; ctx.conditionalCodeHeader = ""; ctx.codes_sizes = []; ctx.definedSizes = {}; ctx.addSizes = addSizes; ctx.addConstant = addConstant; ctx.addConstant(bigInt.zero); ctx.addConstant(bigInt.one); buildHeader(ctx); buildEntryTables(ctx); ctx.globalNames = ctx.uniqueNames; buildCode(ctx); buildComponentsArray(ctx); buildMapIsInput(ctx); buildWit2Sig(ctx); } function buildEntryTables(ctx) { const codes_hashMaps = []; const codes_componentEntries = []; const definedHashMaps = {}; for (let i=0; i0 ? " ," : " "; const sizeName = ctx.addSizes(entry.sizes); const ty = entry.type == "S" ? "_typeSignal" : "_typeComponent"; code += `{${entry.offset},${sizeName}, ${ty}}\n`; } code += "};\n"; codes_componentEntries.push(code); ctx.components[i].htName = htName; ctx.components[i].etName = componentEntriesTableName; } return [ "// HashMaps\n" , codes_hashMaps , "\n" , "\n" , "// Component Entries\n" , codes_componentEntries , "\n" , "\n" ]; function addHashTable(cIdx) { const keys = Object.keys(ctx.components[cIdx].names.o); assert(keys.length<128); keys.sort((a,b) => ((a>b) ? 1 : -1)); const h = utils.fnvHash(keys.join(",")); if (definedHashMaps[h]) return definedHashMaps[h]; definedHashMaps[h] = {}; definedHashMaps[h].htName = ctx.getUniqueName("_ht"+ctx.components[cIdx].template); definedHashMaps[h].htMap = []; const t = []; for (let i=0; i=0) continue; // If has an alias, continue.. assert(typeof outIdx != "undefined", `Signal ${i} does not have index`); if (outIdx>=NVars) continue; // Is a constant or a discarded variable if (typeof arr[ctx.signals[i].id] == "undefined") { arr[outIdx] = i; } } ctx.builder.setWit2Sig(arr); } function addSizes(_sizes) { const sizes = _sizes || []; let name = "sizes"; for (let i=0; i0) code += ","; code += accSizes[i]; } code += "};\n"; this.codes_sizes.push(code); return labelName; } function addConstant(c) { return this.builder.addConstant(c); } function buildFunction(name, paramValues) { const ctx = this; const {h, instanceDef} = hashFunctionCall(ctx, name, paramValues); if (ctx.definedFunctions[h]) return ctx.definedFunctions[h]; const res = { fnName: `${name}_${h}` }; const oldRefs = ctx.refs; const oldConditionalCode = ctx.conditionalCode; const oldCodeBuilder = ctx.codeBuilder; const oldFnBuilder = ctx.fnBuilder; const oldUniqueNames = ctx.uniqueNames; const oldFileName = ctx.fileName; const oldFilePath = ctx.oldFilePath; const oldReturnSizes = ctx.returnSizes; const oldReturnValue = ctx.returnValue; ctx.scopes = [{}]; ctx.refs = []; ctx.conditionalCode = false; ctx.fnBuilder = ctx.builder.newFunctionBuilder(`${name}_${h}`, instanceDef, ctx.functions[name].params); ctx.codeBuilder = ctx.fnBuilder.newCodeBuilder(); ctx.uniqueNames = Object.assign({},ctx.globalNames); ctx.returnValue = null; ctx.returnSizes = null; ctx.fileName = ctx.functions[name].fileName; ctx.filePath = ctx.functions[name].filePath; let paramLabels = []; for (let i=0; i { if (utils.isDefined(ctx.signals[offset].v)) { constParams.push(prefix + "=" + bigInt(ctx.signals[offset].value)); } }); } } let instanceDef = ctx.components[cIdx].template; if (constParams.length>0) { instanceDef += "\n"; constParams.sort(); instanceDef += constParams.join("\n"); } const h = utils.fnvHash(instanceDef); return {h, instanceDef}; function travelSizes(prefix, offset, sizes, fn) { if (sizes.length == 0) { fn(prefix, offset); return 1; } else { let o = offset; for (let i=0; i0) S+=","; S+=value2str(v[i]); } S+="]"; return S; } else { return bigInt(v).toString(); } }