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.

227 lines
6.0 KiB

  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. // Not needed
  68. // this.instance.exports.getRawPrime();
  69. // const arr = new Array(this.n32);
  70. // for (let i=0; i<this.n32; i++) {
  71. // arr[this.n32-1-i] = this.instance.exports.readSharedRWMemory(i);
  72. // }
  73. // this.prime = utils.fromArray32(arr);
  74. this.witnessSize = this.instance.exports.getWitnessSize();
  75. this.sanityCheck = sanityCheck;
  76. }
  77. async _doCalculateWitness(input, sanityCheck) {
  78. //input is assumed to be a map from signals to arrays of bigints
  79. this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0);
  80. const keys = Object.keys(input);
  81. keys.forEach( (k) => {
  82. const h = utils.fnvHash(k);
  83. const hMSB = parseInt(h.slice(0,8), 16);
  84. const hLSB = parseInt(h.slice(8,16), 16);
  85. const fArr = utils.flatArray(input[k]);
  86. for (let i=0; i<fArr.length; i++) {
  87. const arrFr = utils.toArray32(fArr[i],this.n32)
  88. for (let j=0; j<this.n32; j++) {
  89. this.instance.exports.writeSharedRWMemory(j,arrFr[this.n32-1-j]);
  90. }
  91. try {
  92. this.instance.exports.setInputSignal(hMSB, hLSB,i);
  93. } catch (err) {
  94. // console.log(`After adding signal ${i} of ${k}`)
  95. throw new Error(err);
  96. }
  97. }
  98. });
  99. }
  100. async calculateWitness(input, sanityCheck) {
  101. const w = [];
  102. await this._doCalculateWitness(input, sanityCheck);
  103. for (let i=0; i<this.witnessSize; i++) {
  104. this.instance.exports.getWitness(i);
  105. const arr = new Uint32Array(this.n32);
  106. for (let j=0; j<this.n32; j++) {
  107. arr[this.n32-1-j] = this.instance.exports.readSharedRWMemory(j);
  108. }
  109. w.push(utils.fromArray32(arr));
  110. }
  111. return w;
  112. }
  113. async calculateBinWitness(input, sanityCheck) {
  114. const buff32 = new Uint32Array(this.witnessSize*this.n32);
  115. const buff = new Uint8Array( buff32.buffer);
  116. await this._doCalculateWitness(input, sanityCheck);
  117. for (let i=0; i<this.witnessSize; i++) {
  118. this.instance.exports.getWitness(i);
  119. const pos = i*this.n32;
  120. for (let j=0; j<this.n32; j++) {
  121. buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
  122. }
  123. }
  124. return buff;
  125. }
  126. async calculateWTNSBin(input, sanityCheck) {
  127. const buff32 = new Uint32Array(this.witnessSize*this.n32+this.n32+11);
  128. const buff = new Uint8Array( buff32.buffer);
  129. await this._doCalculateWitness(input, sanityCheck);
  130. //"wtns"
  131. buff[0] = "w".charCodeAt(0)
  132. buff[1] = "t".charCodeAt(0)
  133. buff[2] = "n".charCodeAt(0)
  134. buff[3] = "s".charCodeAt(0)
  135. //version 2
  136. buff32[1] = 2;
  137. //number of sections: 2
  138. buff32[2] = 2;
  139. //id section 1
  140. buff32[3] = 1;
  141. const n8 = this.n32*4;
  142. //id section 1 length in 64bytes
  143. const idSection1length = 8 + n8;
  144. const idSection1lengthHex = idSection1length.toString(16);
  145. buff32[4] = parseInt(idSection1lengthHex.slice(0,8), 16);
  146. buff32[5] = parseInt(idSection1lengthHex.slice(8,16), 16);
  147. //this.n32
  148. buff32[6] = n8;
  149. //prime number
  150. this.instance.exports.getRawPrime();
  151. var pos = 7;
  152. for (let j=0; j<this.n32; j++) {
  153. buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
  154. }
  155. pos += this.n32;
  156. // witness size
  157. buff32[pos] = this.witnessSize;
  158. pos++;
  159. //id section 2
  160. buff32[pos] = 2;
  161. pos++;
  162. // section 2 length
  163. const idSection2length = n8*this.witnessSize;
  164. const idSection2lengthHex = idSection2length.toString(16);
  165. buff32[pos] = parseInt(idSection2lengthHex.slice(0,8), 16);
  166. buff32[pos+1] = parseInt(idSection2lengthHex.slice(8,16), 16);
  167. pos += 2;
  168. for (let i=0; i<this.witnessSize; i++) {
  169. this.instance.exports.getWitness(i);
  170. for (let j=0; j<this.n32; j++) {
  171. buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
  172. }
  173. pos += this.n32;
  174. }
  175. return buff;
  176. }
  177. }