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