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.

230 lines
6.1 KiB

3 years ago
3 years ago
  1. const utils = require("./utils");
  2. module.exports = async function builder(code, options) {
  3. options = options || {};
  4. const wasmModule = await WebAssembly.compile(code);
  5. let wc;
  6. const instance = await WebAssembly.instantiate(wasmModule, {
  7. runtime: {
  8. exceptionHandler : function(code) {
  9. let errStr;
  10. if (code == 1) {
  11. errStr= "Signal not found. ";
  12. } else if (code == 2) {
  13. errStr= "Too many signals set. ";
  14. } else if (code == 3) {
  15. errStr= "Signal already set. ";
  16. } else if (code == 4) {
  17. errStr= "Assert Failed. ";
  18. } else if (code == 5) {
  19. errStr= "Not enough memory. ";
  20. } else {
  21. errStr= "Unknown error\n";
  22. }
  23. // get error message from wasm
  24. errStr += getMessage();
  25. throw new Error(errStr);
  26. },
  27. showSharedRWMemory: function() {
  28. printSharedRWMemory ();
  29. }
  30. }
  31. });
  32. const sanityCheck =
  33. options
  34. // options &&
  35. // (
  36. // options.sanityCheck ||
  37. // options.logGetSignal ||
  38. // options.logSetSignal ||
  39. // options.logStartComponent ||
  40. // options.logFinishComponent
  41. // );
  42. wc = new WitnessCalculator(instance, sanityCheck);
  43. return wc;
  44. function getMessage() {
  45. var message = "";
  46. var c = instance.exports.getMessageChar();
  47. while ( c != 0 ) {
  48. message += String.fromCharCode(c);
  49. c = instance.exports.getMessageChar();
  50. }
  51. return message;
  52. }
  53. function printSharedRWMemory () {
  54. const shared_rw_memory_size = instance.exports.getFieldNumLen32();
  55. const arr = new Uint32Array(shared_rw_memory_size);
  56. for (let j=0; j<shared_rw_memory_size; j++) {
  57. arr[shared_rw_memory_size-1-j] = instance.exports.readSharedRWMemory(j);
  58. }
  59. console.log(utils.fromArray32(arr));
  60. }
  61. };
  62. class WitnessCalculator {
  63. constructor(instance, sanityCheck) {
  64. this.instance = instance;
  65. this.version = this.instance.exports.getVersion();
  66. this.n32 = this.instance.exports.getFieldNumLen32();
  67. this.instance.exports.getRawPrime();
  68. const arr = new Array(this.n32);
  69. for (let i=0; i<this.n32; i++) {
  70. arr[this.n32-1-i] = this.instance.exports.readSharedRWMemory(i);
  71. }
  72. this.prime = utils.fromArray32(arr);
  73. this.witnessSize = this.instance.exports.getWitnessSize();
  74. this.sanityCheck = sanityCheck;
  75. }
  76. circom_version() {
  77. return this.instance.exports.getVersion();
  78. }
  79. async _doCalculateWitness(input, sanityCheck) {
  80. //input is assumed to be a map from signals to arrays of bigints
  81. this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0);
  82. const keys = Object.keys(input);
  83. keys.forEach( (k) => {
  84. const h = utils.fnvHash(k);
  85. const hMSB = parseInt(h.slice(0,8), 16);
  86. const hLSB = parseInt(h.slice(8,16), 16);
  87. const fArr = utils.flatArray(input[k]);
  88. for (let i=0; i<fArr.length; i++) {
  89. const arrFr = utils.toArray32(fArr[i],this.n32)
  90. for (let j=0; j<this.n32; j++) {
  91. this.instance.exports.writeSharedRWMemory(j,arrFr[this.n32-1-j]);
  92. }
  93. try {
  94. this.instance.exports.setInputSignal(hMSB, hLSB,i);
  95. } catch (err) {
  96. // console.log(`After adding signal ${i} of ${k}`)
  97. throw new Error(err);
  98. }
  99. }
  100. });
  101. }
  102. async calculateWitness(input, sanityCheck) {
  103. const w = [];
  104. await this._doCalculateWitness(input, sanityCheck);
  105. for (let i=0; i<this.witnessSize; i++) {
  106. this.instance.exports.getWitness(i);
  107. const arr = new Uint32Array(this.n32);
  108. for (let j=0; j<this.n32; j++) {
  109. arr[this.n32-1-j] = this.instance.exports.readSharedRWMemory(j);
  110. }
  111. w.push(utils.fromArray32(arr));
  112. }
  113. return w;
  114. }
  115. async calculateBinWitness(input, sanityCheck) {
  116. const buff32 = new Uint32Array(this.witnessSize*this.n32);
  117. const buff = new Uint8Array( buff32.buffer);
  118. await this._doCalculateWitness(input, sanityCheck);
  119. for (let i=0; i<this.witnessSize; i++) {
  120. this.instance.exports.getWitness(i);
  121. const pos = i*this.n32;
  122. for (let j=0; j<this.n32; j++) {
  123. buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
  124. }
  125. }
  126. return buff;
  127. }
  128. async calculateWTNSBin(input, sanityCheck) {
  129. const buff32 = new Uint32Array(this.witnessSize*this.n32+this.n32+11);
  130. const buff = new Uint8Array( buff32.buffer);
  131. await this._doCalculateWitness(input, sanityCheck);
  132. //"wtns"
  133. buff[0] = "w".charCodeAt(0)
  134. buff[1] = "t".charCodeAt(0)
  135. buff[2] = "n".charCodeAt(0)
  136. buff[3] = "s".charCodeAt(0)
  137. //version 2
  138. buff32[1] = 2;
  139. //number of sections: 2
  140. buff32[2] = 2;
  141. //id section 1
  142. buff32[3] = 1;
  143. const n8 = this.n32*4;
  144. //id section 1 length in 64bytes
  145. const idSection1length = 8 + n8;
  146. const idSection1lengthHex = idSection1length.toString(16);
  147. buff32[4] = parseInt(idSection1lengthHex.slice(0,8), 16);
  148. buff32[5] = parseInt(idSection1lengthHex.slice(8,16), 16);
  149. //this.n32
  150. buff32[6] = n8;
  151. //prime number
  152. this.instance.exports.getRawPrime();
  153. var pos = 7;
  154. for (let j=0; j<this.n32; j++) {
  155. buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
  156. }
  157. pos += this.n32;
  158. // witness size
  159. buff32[pos] = this.witnessSize;
  160. pos++;
  161. //id section 2
  162. buff32[pos] = 2;
  163. pos++;
  164. // section 2 length
  165. const idSection2length = n8*this.witnessSize;
  166. const idSection2lengthHex = idSection2length.toString(16);
  167. buff32[pos] = parseInt(idSection2lengthHex.slice(0,8), 16);
  168. buff32[pos+1] = parseInt(idSection2lengthHex.slice(8,16), 16);
  169. pos += 2;
  170. for (let i=0; i<this.witnessSize; i++) {
  171. this.instance.exports.getWitness(i);
  172. for (let j=0; j<this.n32; j++) {
  173. buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
  174. }
  175. pos += this.n32;
  176. }
  177. return buff;
  178. }
  179. }