circom/src/circuit_generator.js
src/circuit_generator.jsRaw
1
2const fs = require("fs");
3const path = require("path");
4const bigInt = require("big-integer");
5const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
6const __MASK__ = new bigInt(2).pow(253).minus(1);
7const assert = require("assert");
8const gen = require("./gencode");
9const exec = require("./exec");
10const lc = require("./lcalgebra");
11
12
13const argv = require("optimist")
14 .alias("c", "circuit")
15 .alias("o", "output")
16 .alias("w", "witnes")
17 .argv;
18
19const parser = require("../jaz.js").parser;
20
21const fullFileName = path.resolve(process.cwd(), argv.circuit);
22const fullFilePath = path.dirname(fullFileName);
23
24const src = fs.readFileSync(fullFileName, "utf8");
25const ast = parser.parse(src);
26
27assert(ast.type == "BLOCK");
28
29const ctx = {
30 scopes: [{}],
31 signals: {
32 one: {
33 fullName: "one",
34 value: bigInt(1),
35 equivalence: "",
36 direction: ""
37 }
38 },
39 currentComponent: "",
40 constrains: [],
41 components: {},
42 templates: {},
43 functions: {},
44 functionParams: {},
45 filePath: fullFilePath,
46 fileName: fullFileName
47};
48
49exec(ctx, ast);
50
51reduceConstrains(ctx);
52generateWitnessNames(ctx);
53generateWitnessConstrains(ctx);
54
55if (ctx.error) {
56 console.log(`ERROR at ${ctx.error.errFile}:${ctx.error.pos.first_line},${ctx.error.pos.first_column}-${ctx.error.pos.last_line},${ctx.error.pos.last_column} ${ctx.error.errStr}`);
57 console.log(JSON.stringify(ctx.error.ast, null, 1));
58 process.exit(1);
59}
60
61/*
62console.log("SIGNALS");
63console.log("==========");
64for (let key in ctx.signals) {
65 const signal = ctx.signals[key];
66 console.log(signal.fullName);
67}
68
69console.log("CONSTRAINS");
70console.log("==========");
71for (let i=0; i<ctx.constrains.length; i++) {
72 console.log(lc.toString(ctx.constrains[i], ctx) + " === 0");
73}
74*/
75ctx.scopes = [{}];
76
77const mainCode = gen(ctx,ast);
78if (ctx.error) {
79 console.log(`ERROR at ${ctx.error.pos.first_line},${ctx.error.pos.first_column}-${ctx.error.pos.last_line},${ctx.error.pos.last_column} ${ctx.error.errStr}`);
80 console.log(JSON.stringify(ctx.error.ast, null, 1));
81 process.exit(1);
82}
83
84
85let outCode = "";
86outCode += "const bigInt = require(\"big-integer\");\n";
87outCode += "const __P__ = new bigInt(\"21888242871839275222246405745257275088696311157297823662689037894645226208583\");\n";
88outCode += "const __MASK__ = new bigInt(2).pow(253).minus(1);\n";
89outCode += "const circuit = {};\n";
90outCode += "module.exports = circuit;\n\n";
91outCode += `circuit.signals=${JSON.stringify(ctx.signals, null, 1)};\n\n`;
92outCode += `circuit.components=${JSON.stringify(ctx.components, null, 1)};\n\n`;
93outCode += `circuit.signalConstrains=${JSON.stringify(ctx.constrains, null, 1)};\n\n`;
94outCode += `circuit.witnessNames=${JSON.stringify(ctx.witnessNames, null, 1)};\n\n`;
95outCode += mainCode;
96outCode += "\ncircuit.templates = {};\n";
97for (let t in ctx.templates) {
98 outCode += `\ncircuit.templates["${t}"] = ${ctx.templates[t]};\n`;
99}
100outCode += `circuit.functionParams=${JSON.stringify(ctx.functionParams, null, 1)};\n\n`;
101outCode += "\ncircuit.functions = {};\n";
102for (let f in ctx.functions) {
103 outCode += `\ncircuit.functions["${f}"] = ${ctx.functions[f]};\n`;
104}
105
106/*
107console.log("CODE");
108console.log("====");
109console.log(outCode);
110*/
111
112
113console.log("#Constrains:" +ctx.constrains.length);
114
115fs.writeFileSync(argv.output, outCode, "utf8");
116
117function generateWitnessNames(ctx) {
118 ctx.witnessNames = [];
119 for (let c in ctx.components) {
120 ctx.components[c].inputSignals = 0;
121 }
122 for (let s in ctx.signals) {
123 const signal = ctx.signals[s];
124 let lSignal = signal;
125 while (lSignal.equivalence) {
126 lSignal = ctx.signals[lSignal.equivalence];
127 }
128 if ( typeof(lSignal.id) === "undefined" ) {
129 lSignal.id = ctx.witnessNames.length;
130 ctx.witnessNames.push([]);
131 }
132 if (signal.direction == "IN") {
133 ctx.components[signal.component].inputSignals++;
134 }
135
136 signal.id = lSignal.id;
137 ctx.witnessNames[signal.id].push(signal.fullName);
138 }
139}
140
141function reduceConstrains(ctx) {
142 const newConstrains = [];
143 for (let i=0; i<ctx.constrains.length; i++) {
144 const c = lc.canonize(ctx, ctx.constrains[i]);
145 if (!lc.isZero(c)) {
146 newConstrains.push(c);
147 }
148 }
149 ctx.constrains = newConstrains;
150}
151
152function generateWitnessConstrains(ctx) {
153
154}
155
156