You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

732 lines
23 KiB

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