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.

153 lines
3.9 KiB

5 years ago
  1. /*
  2. Copyright 2019 0KIMS association.
  3. This file is part of websnark (Web Assembly zkSnark Prover).
  4. websnark is a free software: you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. websnark is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  11. License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with websnark. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. /* globals WebAssembly */
  16. const bigInt = require("big-integer");
  17. const ModuleBuilder = require("wasmbuilder");
  18. const buildF1 = require("./build_f1.js");
  19. const buildTestF1 = require("./build_testf1.js");
  20. async function build(q) {
  21. const f1 = new F1(q);
  22. f1.q = bigInt(q);
  23. f1.n64 = Math.floor((f1.q.minus(1).bitLength() - 1)/64) +1;
  24. f1.n32 = f1.n64*2;
  25. f1.n8 = f1.n64*8;
  26. f1.memory = new WebAssembly.Memory({initial:1});
  27. f1.i32 = new Uint32Array(f1.memory.buffer);
  28. const moduleBuilder = new ModuleBuilder();
  29. buildF1(moduleBuilder, f1.q);
  30. buildTestF1(moduleBuilder);
  31. const code = moduleBuilder.build();
  32. const wasmModule = await WebAssembly.compile(code);
  33. f1.instance = await WebAssembly.instantiate(wasmModule, {
  34. env: {
  35. "memory": f1.memory
  36. }
  37. });
  38. Object.assign(f1, f1.instance.exports);
  39. return f1;
  40. }
  41. class F1 {
  42. constructor() {
  43. }
  44. alloc(length) {
  45. const res = this.i32[0];
  46. this.i32[0] += length;
  47. return res;
  48. }
  49. putInt(pos, _a) {
  50. const a = bigInt(_a);
  51. if (pos & 0x7) throw new Error("Pointer must be aligned");
  52. if (a.bitLength > this.n64*64) {
  53. return this.putInt(a.mod(this.q));
  54. }
  55. for (let i=0; i<this.n32; i++) {
  56. this.i32[(pos>>2)+i] = a.shiftRight(i*32).and(0xFFFFFFFF).toJSNumber();
  57. }
  58. }
  59. allocInt(_a) {
  60. const p = this.alloc(this.n8);
  61. if (_a) this.putInt(p, _a);
  62. return p;
  63. }
  64. putInt2(pos, _a) {
  65. const a = bigInt(_a);
  66. if (pos & 0x7) throw new Error("Pointer must be aligned");
  67. if (a.bitLength > this.n64*64*2) {
  68. return this.putInt(a.mod(this.q));
  69. }
  70. for (let i=0; i<this.n32*2; i++) {
  71. this.i32[(pos>>2)+i] = a.shiftRight(i*32).and(0xFFFFFFFF).toJSNumber();
  72. }
  73. }
  74. getInt(pos) {
  75. if (pos & 0x7) throw new Error("Pointer must be aligned");
  76. let acc = bigInt(this.i32[(pos>>2)+this.n32-1]);
  77. for (let i=this.n32-2; i>=0; i--) {
  78. acc = acc.shiftLeft(32);
  79. acc = acc.add(this.i32[(pos>>2)+i]);
  80. }
  81. return acc;
  82. }
  83. getInt2(pos) {
  84. if (pos & 0x7) throw new Error("Pointer must be aligned");
  85. const last = this.n32*2-1;
  86. let acc = bigInt(this.i32[(pos>>2)+last]);
  87. for (let i=last; i>=0; i--) {
  88. acc = acc.shiftLeft(32);
  89. acc = acc.add(this.i32[(pos>>2)+i]);
  90. }
  91. return acc;
  92. }
  93. allocInt2(_a) {
  94. const p = this.alloc(this.n8*2);
  95. if (_a) this.putInt2(p, _a);
  96. return p;
  97. }
  98. test_F1(n) {
  99. const start = new Date().getTime();
  100. this.instance.exports.testF1(n);
  101. const end = new Date().getTime();
  102. const time = end - start;
  103. return time;
  104. }
  105. /*
  106. function test(n) {
  107. const q = 21888242871839275222246405745257275088696311157297823662689037894645226208583n;
  108. let a = (1n << 512n)%q ;
  109. let b = a >> 128n;
  110. let c;
  111. const start = new Date().getTime();
  112. for (let i=0; i<n; i++) c = a+b;
  113. const end = new Date().getTime();
  114. const time = end - start;
  115. console.log(time);
  116. }
  117. */
  118. }
  119. module.exports = build;