circom/ports/c/builder.js
ports/c/builder.jsRaw
1const utils = require("../../src/utils");
2const assert = require("assert");
3const Scalar = require("ffjavascript").Scalar;
4const F1Field = require("ffjavascript").F1Field;
5const BigArray = require("../../src/bigarray");
6
7function ref2src(c) {
8 if ((c[0] == "R")||(c[0] == "RI")) {
9 return c[1];
10 } else if (c[0] == "V") {
11 return c[1].toString();
12 } else if (c[0] == "C") {
13 return `(ctx->circuit->constants + ${c[1]})`;
14 } else if (c[0] == "CC") {
15 return "__cIdx";
16 } else {
17 assert(false);
18 }
19}
20
21class CodeBuilderC {
22 constructor() {
23 this.ops = [];
24 }
25
26 addComment(comment) {
27 this.ops.push({op: "COMMENT", comment});
28 }
29
30 addBlock(block) {
31 this.ops.push({op: "BLOCK", block});
32 }
33
34 calcOffset(dLabel, offsets) {
35 this.ops.push({op: "CALCOFFSETS", dLabel, offsets});
36 }
37
38 assign(dLabel, src, sOffset) {
39 this.ops.push({op: "ASSIGN", dLabel, src, sOffset});
40 }
41
42 getSubComponentOffset(dLabel, component, hash, hashLabel) {
43 this.ops.push({op: "GETSUBCOMPONENTOFFSET", dLabel, component, hash, hashLabel});
44 }
45
46 getSubComponentSizes(dLabel, component, hash, hashLabel) {
47 this.ops.push({op: "GETSUBCOMPONENTSIZES", dLabel, component, hash, hashLabel});
48 }
49
50 getSignalOffset(dLabel, component, hash, hashLabel) {
51 this.ops.push({op: "GETSIGNALOFFSET", dLabel, component, hash, hashLabel});
52 }
53
54 getSignalSizes(dLabel, component, hash, hashLabel) {
55 this.ops.push({op: "GETSIGNALSIZES", dLabel, component, hash, hashLabel});
56 }
57
58 setSignal(component, signal, value) {
59 this.ops.push({op: "SETSIGNAL", component, signal, value});
60 }
61
62 getSignal(dLabel, component, signal) {
63 this.ops.push({op: "GETSIGNAL", dLabel, component, signal});
64 }
65
66 copyN(dLabel, offset, src, n) {
67 this.ops.push({op: "COPYN", dLabel, offset, src, n});
68 }
69
70 copyNRet(src, n) {
71 this.ops.push({op: "COPYNRET", src, n});
72 }
73
74 fieldOp(dLabel, fOp, params) {
75 this.ops.push({op: "FOP", dLabel, fOp, params});
76 }
77
78 ret() {
79 this.ops.push({op: "RET"});
80 }
81
82 addLoop(condLabel, body) {
83 this.ops.push({op: "LOOP", condLabel, body});
84 }
85
86 addIf(condLabel, thenCode, elseCode) {
87 this.ops.push({op: "IF", condLabel, thenCode, elseCode});
88 }
89
90 fnCall(fnName, retLabel, params) {
91 this.ops.push({op: "FNCALL", fnName, retLabel, params});
92 }
93
94 checkConstraint(a, b, strErr) {
95 this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr});
96 }
97
98 checkAssert(a, strErr) {
99 this.ops.push({op: "CHECKASSERT", a, strErr});
100 }
101
102 log(val) {
103 this.ops.push({op: "LOG", val});
104 }
105
106 concat(cb) {
107 this.ops.push(...cb.ops);
108 }
109
110 hasCode() {
111 for (let i=0; i<this.ops.length; i++) {
112 if (this.ops[i].op != "COMMENT") return true;
113 }
114 return false;
115 }
116
117 _buildOffset(offsets) {
118 let rN=0;
119 let S = "";
120 offsets.forEach((o) => {
121 if ((o[0][0] == "V") && (o[1][0]== "V")) {
122 rN += o[0][1]*o[1][1];
123 return;
124 }
125 let f="";
126 if (o[0][0] == "V") {
127 if (o[0][1]==0) return;
128 f += o[0][1];
129 } else if (o[0][0] == "RI") {
130 if (o[0][1]==0) return;
131 f += o[0][1];
132 } else if (o[0][0] == "R") {
133 f += `Fr_toInt(${o[0][1]})`;
134 } else {
135 assert(false);
136 }
137 if (o[1][0] == "V") {
138 if (o[1][1]==0) return;
139 if (o[1][1]>1) {
140 f += "*" + o[1][1];
141 }
142 } else if (o[1][0] == "RS") {
143 f += `*${o[1][1]}[${o[1][2]}]`;
144 } else {
145 assert(false);
146 }
147 if (S!="") S+= " + ";
148 S += f;
149 });
150 if (rN>0) {
151 S = `${rN} + ${S}`;
152 }
153 return S;
154 }
155
156 build(code) {
157 this.ops.forEach( (o) => {
158 if (o.op == "COMMENT") {
159 code.push(`/* ${o.comment} */`);
160 } else if (o.op == "BLOCK") {
161 const codeBlock=[];
162 o.block.build(codeBlock);
163 code.push(utils.ident(codeBlock));
164 } else if (o.op == "CALCOFFSETS") {
165 code.push(`${o.dLabel} = ${this._buildOffset(o.offsets)};`);
166 } else if (o.op == "ASSIGN") {
167 const oS = ref2src(o.sOffset);
168 if (oS != "0") {
169 code.push(`${o.dLabel} = ${ref2src(o.src)} + ${oS};`);
170 } else {
171 code.push(`${o.dLabel} = ${ref2src(o.src)};`);
172 }
173 } else if (o.op == "GETSUBCOMPONENTOFFSET") {
174 code.push(`${o.dLabel} = ctx->getSubComponentOffset(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
175 } else if (o.op == "GETSUBCOMPONENTSIZES") {
176 code.push(`${o.dLabel} = ctx->getSubComponentSizes(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
177 } else if (o.op == "GETSIGNALOFFSET") {
178 code.push(`${o.dLabel} = ctx->getSignalOffset(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
179 } else if (o.op == "GETSIGNALSIZES") {
180 code.push(`${o.dLabel} = ctx->getSignalSizes(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
181 } else if (o.op == "SETSIGNAL") {
182 code.push(`ctx->setSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${ref2src(o.value)});`);
183 } else if (o.op == "GETSIGNAL") {
184 code.push(`ctx->getSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${o.dLabel});`);
185 } else if (o.op == "COPYN") {
186 const oS = ref2src(o.offset);
187 const dLabel = (oS != "0") ? (o.dLabel + "+" + oS) : o.dLabel;
188 code.push(`Fr_copyn(${dLabel}, ${ref2src(o.src)}, ${o.n});`);
189 } else if (o.op == "COPYNRET") {
190 code.push(`Fr_copyn(__retValue, ${ref2src(o.src)}, ${o.n});`);
191 } else if (o.op == "RET") {
192 code.push("goto returnFunc;");
193 } else if (o.op == "FOP") {
194 let paramsS = "";
195 for (let i=0; i<o.params.length; i++) {
196 if (i>0) paramsS += ", ";
197 paramsS += ref2src(o.params[i]);
198 }
199 code.push(`Fr_${o.fOp}(${o.dLabel}, ${paramsS});`);
200 } else if (o.op == "LOOP") {
201 code.push(`while (Fr_isTrue(${o.condLabel})) {`);
202 const body = [];
203 o.body.build(body);
204 code.push(utils.ident(body));
205 code.push("}");
206 } else if (o.op == "IF") {
207 code.push(`if (Fr_isTrue(${o.condLabel})) {`);
208 const thenCode = [];
209 o.thenCode.build(thenCode);
210 code.push(utils.ident(thenCode));
211 if (o.elseCode) {
212 code.push("} else {");
213 const elseCode = [];
214 o.elseCode.build(elseCode);
215 code.push(utils.ident(elseCode));
216 }
217 code.push("}");
218 } else if (o.op == "FNCALL") {
219 code.push(`${o.fnName}(ctx, ${o.retLabel}, ${o.params.join(",")});`);
220 } else if (o.op == "CHECKCONSTRAINT") {
221 code.push(`ctx->checkConstraint(__cIdx, ${ref2src(o.a)}, ${ref2src(o.b)}, "${o.strErr}");`);
222 } else if (o.op == "CHECKASSERT") {
223 code.push(`ctx->checkAssert(__cIdx, ${ref2src(o.a)}, "${o.strErr}");`);
224 } else if (o.op == "LOG") {
225 code.push(`ctx->log(${ref2src(o.val)});`);
226 }
227 });
228 }
229}
230
231class FunctionBuilderC {
232
233 constructor(name, instanceDef, type) {
234 this.name = name;
235 this.instanceDef = instanceDef;
236 this.type = type; // "COMPONENT" or "FUNCTIOM"
237 this.definedFrElements = [];
238 this.definedIntElements = [];
239 this.definedSizeElements = [];
240 this.definedPFrElements = [];
241 this.initializedElements = [];
242 this.initializedSignalOffset = [];
243 this.initializedSignalSizes = [];
244
245 }
246
247 defineFrElements(dLabel, size) {
248 this.definedFrElements.push({dLabel, size});
249 }
250
251 defineIntElement(dLabel) {
252 this.definedIntElements.push({dLabel});
253 }
254
255 defineSizesElement(dLabel) {
256 this.definedSizeElements.push({dLabel});
257 }
258
259 definePFrElement(dLabel) {
260 this.definedPFrElements.push({dLabel});
261 }
262
263 initializeFrElement(dLabel, offset, idConstant) {
264 this.initializedElements.push({dLabel, offset, idConstant});
265 }
266
267 initializeSignalOffset(dLabel, component, hash, hashLabel) {
268 this.initializedSignalOffset.push({dLabel, component, hash, hashLabel});
269 }
270
271 initializeSignalSizes(dLabel, component, hash, hashLabel) {
272 this.initializedSignalSizes.push({dLabel, component, hash, hashLabel});
273 }
274
275 setParams(params) {
276 this.params = params;
277 }
278
279 _buildHeader(code) {
280 this.definedFrElements.forEach( (o) => {
281 code.push(`FrElement ${o.dLabel}[${o.size}];`);
282 });
283 this.definedIntElements.forEach( (o) => {
284 code.push(`int ${o.dLabel};`);
285 });
286 this.definedSizeElements.forEach( (o) => {
287 code.push(`Circom_Sizes ${o.dLabel};`);
288 });
289 this.definedPFrElements.forEach( (o) => {
290 code.push(`PFrElement ${o.dLabel};`);
291 });
292 this.initializedElements.forEach( (o) => {
293 code.push(`Fr_copy(&(${o.dLabel}[${o.offset}]), ctx->circuit->constants +${o.idConstant});`);
294 });
295 this.initializedSignalOffset.forEach( (o) => {
296 code.push(`${o.dLabel} = ctx->getSignalOffset(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
297 });
298 this.initializedSignalSizes.forEach( (o) => {
299 code.push(`${o.dLabel} = ctx->getSignalSizes(${ref2src(o.component)}, 0x${o.hash}LL /* ${o.hashLabel} */);`);
300 });
301 }
302
303 _buildFooter(code) {
304 }
305
306 newCodeBuilder() {
307 return new CodeBuilderC();
308 }
309
310 setBody(body) {
311 this.body = body;
312 }
313
314 build(code) {
315 code.push(
316 "/*",
317 this.instanceDef,
318 "*/"
319 );
320
321 if (this.type=="COMPONENT") {
322 code.push(`void ${this.name}(Circom_CalcWit *ctx, int __cIdx) {`);
323 } else if (this.type=="FUNCTION") {
324 let sParams = "";
325 for (let i=0;i<this.params.length;i++ ) sParams += `, PFrElement ${this.params[i]}`;
326 code.push(`void ${this.name}(Circom_CalcWit *ctx, PFrElement __retValue ${sParams}) {`);
327 } else {
328 assert(false);
329 }
330
331 const fnCode = [];
332 this._buildHeader(fnCode);
333 this.body.build(fnCode);
334 if (this.type=="COMPONENT") {
335 fnCode.push("ctx->finished(__cIdx);");
336 } else if (this.type=="FUNCTION") {
337 fnCode.push("returnFunc: ;");
338 } else {
339 assert(false);
340 }
341 this._buildFooter(fnCode);
342
343 code.push(utils.ident(fnCode));
344 code.push("}");
345 }
346
347}
348
349class BuilderC {
350 constructor(p, verbose) {
351 this.F = new F1Field(p);
352
353 this.hashMaps={};
354 this.componentEntriesTables=new BigArray();
355 this.sizes ={};
356 this.constants = [];
357 this.functions = [];
358 this.components = new BigArray();
359 this.usedConstants = {};
360 this.verbose = verbose;
361
362
363 this.sizePointers = {};
364 this.hashMapPointers = {};
365 this.functionIdx = {};
366 this.nCets = 0;
367 }
368
369 setHeader(header) {
370 this.header=header;
371 }
372
373 // ht is an array of 256 element that can be undefined or [Hash, Idx, KeyName] elements.
374 addHashMap(name, hm) {
375 this.hashMaps[name] = hm;
376 }
377
378 addComponentEntriesTable(name, cet, idComponent) {
379 this.componentEntriesTables[idComponent] = {
380 name: name,
381 cet: cet
382 };
383 }
384
385 addSizes(name, accSizes) {
386 this.sizes[name] = accSizes;
387 }
388
389 addConstant(c) {
390 c = this.F.e(c);
391 const cS = c.toString();
392 if (typeof this.usedConstants[cS] != "undefined") return this.usedConstants[cS];
393 this.constants.push(c);
394 this.usedConstants[cS] = this.constants.length - 1;
395 return this.constants.length - 1;
396 }
397
398 addFunction(fnBuilder) {
399 this.functions.push(fnBuilder);
400 }
401
402 addComponent(component) {
403 this.components.push(component);
404 }
405
406 setMapIsInput(map) {
407 this.mapIsInput = map;
408 }
409
410 setWit2Sig(wit2sig) {
411 this.wit2sig = wit2sig;
412 }
413
414
415 newComponentFunctionBuilder(name, instanceDef) {
416 return new FunctionBuilderC(name, instanceDef, "COMPONENT");
417 }
418
419 newFunctionBuilder(name, instanceDef) {
420 return new FunctionBuilderC(name, instanceDef, "FUNCTION");
421 }
422
423
424 // Body functions
425
426 _buildHeader(code) {
427 code.push(
428 "#include \"circom.hpp\"",
429 "#include \"calcwit.hpp\"",
430 `#define NSignals ${this.header.NSignals}`,
431 `#define NComponents ${this.header.NComponents}`,
432 `#define NOutputs ${this.header.NOutputs}`,
433 `#define NInputs ${this.header.NInputs}`,
434 `#define NVars ${this.header.NVars}`,
435 `#define __P__ "${this.header.P.toString()}"`,
436 ""
437 );
438 }
439
440 async _buildHashMaps(fdData) {
441
442 while (fdData.pos % 8) fdData.pos++;
443 this.pHashMaps = fdData.pos;
444
445 const buff = new Uint8Array(256*12);
446 const buffV = new DataView(buff.buffer);
447 for (let hmName in this.hashMaps ) {
448
449 while (fdData.pos % 8) fdData.pos++;
450 this.hashMapPointers[hmName] = fdData.pos;
451 const hm = this.hashMaps[hmName];
452
453 for (let i=0; i<256; i++) {
454 buffV.setUint32(i*12, hm[i] ? parseInt( hm[i][0].slice(8), 16 ) : 0, true);
455 buffV.setUint32(i*12+4, hm[i] ? parseInt( hm[i][0].slice(0,8), 16 ) : 0, true);
456 buffV.setUint32(i*12+8, hm[i] ? hm[i][1] : 0, true);
457 }
458
459 await fdData.write(buff);
460 }
461
462 }
463
464 async _buildComponentEntriesTables(fdData) {
465
466 while (fdData.pos % 8) fdData.pos++;
467 this.pCets = fdData.pos;
468 for (let i=0; i< this.componentEntriesTables.length; i++) {
469 if ((this.verbose)&&(i%100000 ==0)) console.log(`_buildComponentEntriesTables ${i}/${this.componentEntriesTables.length}`);
470 const cet = this.componentEntriesTables[i].cet;
471
472 this.components[i].entryTablePointer = fdData.pos;
473 const buff = new Uint8Array(16*cet.length);
474 const buffV = new DataView(buff.buffer);
475
476 for (let j=0; j<cet.length; j++) {
477 utils.setUint64(buffV, 16*j+0, this.sizePointers[ cet[j].sizeName]);
478 buffV.setUint32(16*j+8, cet[j].offset, true);
479 buffV.setUint32(16*j+12, cet[j].type == "S" ? 0 : 1, true); // Size type 0-> Signal, 1->Component
480 this.nCets ++;
481 }
482
483 await fdData.write(buff);
484
485 }
486 }
487
488 async _buildSizes(fdData) {
489 for (let sName in this.sizes) {
490 const accSizes = this.sizes[sName];
491
492 while (fdData.pos % 8) fdData.pos++;
493 this.sizePointers[sName] = fdData.pos;
494
495 const buff = new Uint8Array(4*accSizes.length);
496 const buffV = new DataView(buff.buffer);
497 for (let i=0; i<accSizes.length; i++) {
498 buffV.setUint32(i*4, accSizes[i], true);
499 }
500 await fdData.write(buff);
501 }
502 }
503
504
505 async _buildConstants(fdData) {
506 const self = this;
507
508 const frSize = (8 + self.F.n64*8);
509 const buff = new Uint8Array(self.constants.length* frSize);
510 const buffV = new DataView(buff.buffer);
511
512
513 while (fdData.pos % 8) fdData.pos++;
514 this.pConstants = fdData.pos;
515
516 let o = 0;
517 for (let i=0; i<self.constants.length; i++) {
518 Fr2Bytes(buffV, o, self.constants[i]);
519 o += frSize;
520 }
521 await fdData.write(buff);
522
523
524 function Fr2Bytes(buffV, offset, n) {
525 const minShort = self.F.neg(self.F.e("80000000"));
526 const maxShort = self.F.e("7FFFFFFF", 16);
527
528 if ( (self.F.geq(n, minShort))
529 &&(self.F.leq(n, maxShort)))
530 {
531 if (self.F.geq(n, self.F.zero)) {
532 return shortMontgomeryPositive(n);
533 } else {
534 return shortMontgomeryNegative(n);
535 }
536 }
537
538 return longMontgomery(n);
539
540
541 function shortMontgomeryPositive(a) {
542 buffV.setUint32(offset, Scalar.toNumber(a) , true );
543 buffV.setUint32(offset + 4, 0x40000000 , true );
544 long(buffV, offset + 8, toMontgomery(a));
545 }
546
547
548 function shortMontgomeryNegative(a) {
549 const b = -Scalar.toNumber(self.F.neg(a));
550 buffV.setUint32(offset, b , true );
551 buffV.setUint32(offset + 4, 0x40000000 , true );
552 long(buffV, offset + 8, toMontgomery(a));
553 }
554
555 function longMontgomery(a) {
556 buffV.setUint32(offset, 0 , true );
557 buffV.setUint32(offset + 4, 0xC0000000 , true );
558 long(buffV, offset + 8, toMontgomery(a));
559 }
560
561 function long(buffV, offset, a) {
562
563 let p = offset;
564 const arr = Scalar.toArray(a, 0x100000000);
565 for (let i=0; i<self.F.n64*2; i++) {
566 const idx = arr.length-1-i;
567
568 if ( idx >=0) {
569 buffV.setUint32(p, arr[idx], true);
570 } else {
571 buffV.setUint32(p, 0, true);
572 }
573 p+= 4;
574 }
575 }
576
577 function toMontgomery(a) {
578 return self.F.mul(a, self.F.R);
579 }
580
581 }
582
583 }
584
585 _buildFunctions(code) {
586 const listedFunctions = [];
587 for (let i=0; i<this.functions.length; i++) {
588 const cfb = this.functions[i];
589 cfb.build(code);
590 if (this.functions[i].type == "COMPONENT") {
591 this.functionIdx[this.functions[i].name] = listedFunctions.length;
592 listedFunctions.push(i);
593 }
594 }
595
596 code.push("// Function Table");
597 code.push(`Circom_ComponentFunction _functionTable[${listedFunctions.length}] = {`);
598 for (let i=0; i<listedFunctions.length; i++) {
599 const sep = i>0 ? " ," : " ";
600 code.push(`${sep}${this.functions[listedFunctions[i]].name}`);
601 }
602 code.push("};");
603 }
604
605
606 async _buildComponents(fdData) {
607
608 const buff = new Uint8Array(32);
609 const buffV = new DataView(buff.buffer);
610
611 while (fdData.pos % 8) fdData.pos++;
612 this.pComponents = fdData.pos;
613
614 for (let i=0; i<this.components.length; i++) {
615 if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildComponents ${i}/${this.components.length}`);
616 const c = this.components[i];
617
618 utils.setUint64(buffV, 0, this.hashMapPointers[c.hashMapName], true);
619 utils.setUint64(buffV, 8, c.entryTablePointer, true);
620 utils.setUint64(buffV, 16, this.functionIdx[c.functionName], true);
621 buffV.setUint32(24, c.nInSignals, true);
622 buffV.setUint32(28, c.newThread ? 1 : 0, true);
623
624 await fdData.write(buff);
625 }
626 }
627
628 async _buildMapIsInput(fdData) {
629
630 const buff = new Uint8Array(this.mapIsInput.length * 4);
631 const buffV = new DataView(buff.buffer);
632
633 while (fdData.pos % 8) fdData.pos++;
634 this.pMapIsInput = fdData.pos;
635
636 for (let i=0; i<this.mapIsInput.length; i++) {
637 if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildMapIsInput ${i}/${this.mapIsInput.length}`);
638
639 buffV.setUint32(4*i, this.mapIsInput[i], true);
640 }
641
642 await fdData.write(buff);
643 }
644
645 async _buildWit2Sig(fdData) {
646
647 const buff = new Uint8Array(this.wit2sig.length * 4);
648 const buffV = new DataView(buff.buffer);
649
650 while (fdData.pos % 8) fdData.pos++;
651 this.pWit2Sig = fdData.pos;
652
653 for (let i=0; i<this.wit2sig.length; i++) {
654 if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildWit2Sig ${i}/${this.wit2sig.length}`);
655
656 buffV.setUint32(4*i, this.wit2sig[i], true);
657 }
658
659 await fdData.write(buff);
660 }
661
662 async _buildCircuitVar(fdData) {
663
664 const buff = new Uint8Array(72);
665 const buffV = new DataView(buff.buffer);
666
667 utils.setUint64(buffV, 0, this.pWit2Sig, true);
668 utils.setUint64(buffV, 8, this.pComponents, true);
669 utils.setUint64(buffV, 16, this.pMapIsInput, true);
670 utils.setUint64(buffV, 24, this.pConstants, true);
671 utils.setUint64(buffV, 32, this.pPriemStr, true);
672 utils.setUint64(buffV, 40, this.pCets, true);
673
674 buffV.setUint32(48, this.header.NSignals, true);
675 buffV.setUint32(52, this.header.NComponents, true);
676 buffV.setUint32(56, this.header.NOutputs, true);
677 buffV.setUint32(60, this.header.NInputs, true);
678 buffV.setUint32(64, this.header.NVars, true);
679 buffV.setUint32(68, this.nCets, true);
680
681 fdData.pos = 0;
682
683 await fdData.write(buff);
684 }
685
686 async _buildPrimeStr(fdData) {
687 this.pPriemStr = fdData.pos;
688 const strBuff = new TextEncoder("utf-8").encode(this.header.P.toString());
689 await fdData.write(strBuff);
690
691 const zB = new Uint8Array(1);
692 zB[0] =0;
693 await fdData.write(zB);
694 }
695
696
697 async build(fdCode, fdData) {
698 const encoder = new TextEncoder("utf-8");
699 fdData.pos = 72;
700 while (fdData.pos % 8) fdData.pos++;
701
702 const code=new BigArray();
703 this._buildHeader(code);
704 await this._buildPrimeStr(fdData);
705 await this._buildSizes(fdData);
706 await this._buildConstants(fdData);
707 await this._buildHashMaps(fdData);
708 await this._buildComponentEntriesTables(fdData);
709 this._buildFunctions(code);
710 await this._buildComponents(fdData);
711 await this._buildMapIsInput(fdData);
712 await this._buildWit2Sig(fdData);
713 await this._buildCircuitVar(fdData);
714 await writeCode(code);
715
716 async function writeCode(c) {
717 if (c.push) {
718 for (let i=0; i<c.length; i++) {
719 await writeCode(c[i]);
720 }
721 } else if (typeof c === "string") {
722 await fdCode.write(encoder.encode(c + "\n"));
723 }
724 }
725 }
726}
727
728
729module.exports = BuilderC;