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.

258 lines
6.9 KiB

  1. include "mux3.circom";
  2. include "montgomery.circom";
  3. include "babyjub.circom";
  4. /*
  5. Window of 3 elements, it calculates
  6. out = base + base*in[0] + 2*base*in[1] + 4*base*in[2]
  7. out4 = 4*base
  8. The result should be compensated.
  9. */
  10. template WindowMulFix() {
  11. signal input in[3];
  12. signal input base[2];
  13. signal output out[2];
  14. signal output out8[2]; // Returns 8*Base (To be linked)
  15. component mux = MultiMux3(2);
  16. mux.s[0] <== in[0];
  17. mux.s[1] <== in[1];
  18. mux.s[2] <== in[2];
  19. component dbl2 = MontgomeryDouble();
  20. component adr3 = MontgomeryAdd();
  21. component adr4 = MontgomeryAdd();
  22. component adr5 = MontgomeryAdd();
  23. component adr6 = MontgomeryAdd();
  24. component adr7 = MontgomeryAdd();
  25. component adr8 = MontgomeryAdd();
  26. // in[0] -> 1*BASE
  27. mux.c[0][0] <== base[0];
  28. mux.c[1][0] <== base[1];
  29. // in[1] -> 2*BASE
  30. dbl2.in[0] <== base[0];
  31. dbl2.in[1] <== base[1];
  32. mux.c[0][1] <== dbl2.out[0];
  33. mux.c[1][1] <== dbl2.out[1];
  34. // in[2] -> 3*BASE
  35. adr3.in1[0] <== base[0];
  36. adr3.in1[1] <== base[1];
  37. adr3.in2[0] <== dbl2.out[0];
  38. adr3.in2[1] <== dbl2.out[1];
  39. mux.c[0][2] <== adr3.out[0];
  40. mux.c[1][2] <== adr3.out[1];
  41. // in[3] -> 4*BASE
  42. adr4.in1[0] <== base[0];
  43. adr4.in1[1] <== base[1];
  44. adr4.in2[0] <== adr3.out[0];
  45. adr4.in2[1] <== adr3.out[1];
  46. mux.c[0][3] <== adr4.out[0];
  47. mux.c[1][3] <== adr4.out[1];
  48. // in[4] -> 5*BASE
  49. adr5.in1[0] <== base[0];
  50. adr5.in1[1] <== base[1];
  51. adr5.in2[0] <== adr4.out[0];
  52. adr5.in2[1] <== adr4.out[1];
  53. mux.c[0][4] <== adr5.out[0];
  54. mux.c[1][4] <== adr5.out[1];
  55. // in[5] -> 6*BASE
  56. adr6.in1[0] <== base[0];
  57. adr6.in1[1] <== base[1];
  58. adr6.in2[0] <== adr5.out[0];
  59. adr6.in2[1] <== adr5.out[1];
  60. mux.c[0][5] <== adr6.out[0];
  61. mux.c[1][5] <== adr6.out[1];
  62. // in[6] -> 7*BASE
  63. adr7.in1[0] <== base[0];
  64. adr7.in1[1] <== base[1];
  65. adr7.in2[0] <== adr6.out[0];
  66. adr7.in2[1] <== adr6.out[1];
  67. mux.c[0][6] <== adr7.out[0];
  68. mux.c[1][6] <== adr7.out[1];
  69. // in[7] -> 8*BASE
  70. adr8.in1[0] <== base[0];
  71. adr8.in1[1] <== base[1];
  72. adr8.in2[0] <== adr7.out[0];
  73. adr8.in2[1] <== adr7.out[1];
  74. mux.c[0][7] <== adr8.out[0];
  75. mux.c[1][7] <== adr8.out[1];
  76. out8[0] <== adr8.out[0];
  77. out8[1] <== adr8.out[1];
  78. out[0] <== mux.out[0];
  79. out[1] <== mux.out[1];
  80. }
  81. /*
  82. This component does a multiplication of a escalar times a fix base
  83. Signals:
  84. e: The scalar in bits
  85. base: the base point in edwards format
  86. out: The result
  87. dbl: Point in Edwards to be linked to the next segment.
  88. */
  89. template SegmentMulFix(nWindows) {
  90. signal input e[nWindows*3];
  91. signal input base[2];
  92. signal output out[2];
  93. signal output dbl[2];
  94. var i;
  95. var j;
  96. // Convert the base to montgomery
  97. component e2m = Edwards2Montgomery();
  98. e2m.in[0] <== base[0];
  99. e2m.in[1] <== base[1];
  100. component windows[nWindows];
  101. component adders[nWindows-1];
  102. component cadders[nWindows-1];
  103. for (i=0; i<nWindows; i++) {
  104. windows[i] = WindowMulFix();
  105. if (i==0) {
  106. windows[i].base[0] <== e2m.out[0];
  107. windows[i].base[1] <== e2m.out[1];
  108. } else {
  109. windows[i].base[0] <== windows[i-1].out8[0];
  110. windows[i].base[1] <== windows[i-1].out8[1];
  111. adders[i-1] = MontgomeryAdd();
  112. cadders[i-1] = MontgomeryAdd();
  113. if (i==1) {
  114. adders[i-1].in1[0] <== windows[0].out[0];
  115. adders[i-1].in1[1] <== windows[0].out[1];
  116. cadders[i-1].in1[0] <== e2m.out[0];
  117. cadders[i-1].in1[1] <== e2m.out[1];
  118. } else {
  119. adders[i-1].in1[0] <== adders[i-2].out[0];
  120. adders[i-1].in1[1] <== adders[i-2].out[1];
  121. cadders[i-1].in1[0] <== cadders[i-2].out[0];
  122. cadders[i-1].in1[1] <== cadders[i-2].out[1];
  123. }
  124. adders[i-1].in2[0] <== windows[i].out[0];
  125. adders[i-1].in2[1] <== windows[i].out[1];
  126. cadders[i-1].in2[0] <== windows[i-1].out8[0];
  127. cadders[i-1].in2[1] <== windows[i-1].out8[1];
  128. }
  129. for (j=0; j<3; j++) {
  130. windows[i].in[j] <== e[3*i+j];
  131. }
  132. }
  133. component m2e = Montgomery2Edwards();
  134. component cm2e = Montgomery2Edwards();
  135. if (nWindows > 1) {
  136. m2e.in[0] <== adders[nWindows-2].out[0];
  137. m2e.in[1] <== adders[nWindows-2].out[1];
  138. cm2e.in[0] <== cadders[nWindows-2].out[0];
  139. cm2e.in[1] <== cadders[nWindows-2].out[1];
  140. } else {
  141. m2e.in[0] <== windows[0].out[0];
  142. m2e.in[1] <== windows[0].out[1];
  143. cm2e.in[0] <== e2m.out[0];
  144. cm2e.in[1] <== e2m.out[1];
  145. }
  146. component cAdd = BabyAdd();
  147. cAdd.x1 <== m2e.out[0];
  148. cAdd.y1 <== m2e.out[1];
  149. cAdd.x2 <== -cm2e.out[0];
  150. cAdd.y2 <== cm2e.out[1];
  151. cAdd.xout ==> out[0];
  152. cAdd.yout ==> out[1];
  153. windows[nWindows-1].out8[0] ==> dbl[0];
  154. windows[nWindows-1].out8[1] ==> dbl[1];
  155. }
  156. /*
  157. This component multiplies a escalar times a fixed point BASE (twisted edwards format)
  158. Signals
  159. e: The escalar in binary format
  160. out: The output point in twisted edwards
  161. */
  162. template EscalarMulFix(n, BASE) {
  163. signal input e[n]; // Input in binary format
  164. signal output out[2]; // Point (Twisted format)
  165. var nsegments = (n-1)\249 +1;
  166. var nlastsegment = n - (nsegments-1)*249;
  167. component segments[nsegments];
  168. component m2e[nsegments-1];
  169. component adders[nsegments-1];
  170. var s;
  171. var i;
  172. var nseg;
  173. var nWindows
  174. for (s=0; s<nsegments; s++) {
  175. nseg = (s < nsegments-1) ? 249 : nlastsegment;
  176. nWindows = ((nseg - 1)\3)+1;
  177. segments[s] = SegmentMulFix(nWindows);
  178. for (i=0; i<nseg; i++) {
  179. segments[s].e[i] <== e[s*249+i];
  180. }
  181. for (i = nseg; i<nWindows*3; i++) {
  182. segments[s].e[i] <== 0;
  183. }
  184. if (s==0) {
  185. segments[s].base[0] <== BASE[0];
  186. segments[s].base[1] <== BASE[1];
  187. } else {
  188. m2e[s-1] = Montgomery2Edwards();
  189. adders[s-1] = BabyAdd();
  190. segments[s-1].dbl[0] ==> m2e[s-1].in[0];
  191. segments[s-1].dbl[1] ==> m2e[s-1].in[1];
  192. m2e[s-1].out[0] ==> segments[s].base[0];
  193. m2e[s-1].out[1] ==> segments[s].base[1];
  194. if (s==1) {
  195. segments[s-1].out[0] ==> adders[s-1].x1;
  196. segments[s-1].out[1] ==> adders[s-1].y1;
  197. } else {
  198. adders[s-2].xout ==> adders[s-1].x1;
  199. adders[s-2].yout ==> adders[s-1].y1;
  200. }
  201. segments[s].out[0] ==> adders[s-1].x2;
  202. segments[s].out[1] ==> adders[s-1].y2;
  203. }
  204. }
  205. if (nsegments == 1) {
  206. segments[0].out[0] ==> out[0];
  207. segments[0].out[1] ==> out[1];
  208. } else {
  209. adders[nsegments-2].xout ==> out[0];
  210. adders[nsegments-2].yout ==> out[1];
  211. }
  212. }