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.

192 lines
5.2 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. /*
  2. Copyright 2018 0KIMS association.
  3. This file is part of circom (Zero Knowledge Circuit Compiler).
  4. circom 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. circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. include "montgomery.circom";
  16. include "babyjub.circom";
  17. template Multiplexor2() {
  18. signal input sel;
  19. signal input in[2][2];
  20. signal output out[2];
  21. out[0] <== (in[1][0] - in[0][0])*sel + in[0][0];
  22. out[1] <== (in[1][1] - in[0][1])*sel + in[0][1];
  23. }
  24. template BitElementMulAny() {
  25. signal input sel;
  26. signal input dblIn[2];
  27. signal input addIn[2];
  28. signal output dblOut[2];
  29. signal output addOut[2];
  30. component doubler = MontgomeryDouble();
  31. component adder = MontgomeryAdd();
  32. component selector = Multiplexor2();
  33. sel ==> selector.sel;
  34. dblIn[0] ==> doubler.in[0];
  35. dblIn[1] ==> doubler.in[1];
  36. doubler.out[0] ==> adder.in1[0];
  37. doubler.out[1] ==> adder.in1[1];
  38. addIn[0] ==> adder.in2[0];
  39. addIn[1] ==> adder.in2[1];
  40. addIn[0] ==> selector.in[0][0];
  41. addIn[1] ==> selector.in[0][1];
  42. adder.out[0] ==> selector.in[1][0];
  43. adder.out[1] ==> selector.in[1][1];
  44. doubler.out[0] ==> dblOut[0];
  45. doubler.out[1] ==> dblOut[1];
  46. selector.out[0] ==> addOut[0];
  47. selector.out[1] ==> addOut[1];
  48. }
  49. // p is montgomery point
  50. // n must be <= 248
  51. // returns out in twisted edwards
  52. // Double is in montgomery to be linked;
  53. template SegmentMulAny(n) {
  54. signal input e[n];
  55. signal input p[2];
  56. signal output out[2];
  57. signal output dbl[2];
  58. component bits[n-1];
  59. component e2m = Edwards2Montgomery();
  60. p[0] ==> e2m.in[0];
  61. p[1] ==> e2m.in[1];
  62. var i;
  63. bits[0] = BitElementMulAny();
  64. e2m.out[0] ==> bits[0].dblIn[0]
  65. e2m.out[1] ==> bits[0].dblIn[1]
  66. e2m.out[0] ==> bits[0].addIn[0]
  67. e2m.out[1] ==> bits[0].addIn[1]
  68. e[1] ==> bits[0].sel;
  69. for (i=1; i<n-1; i++) {
  70. bits[i] = BitElementMulAny();
  71. bits[i-1].dblOut[0] ==> bits[i].dblIn[0]
  72. bits[i-1].dblOut[1] ==> bits[i].dblIn[1]
  73. bits[i-1].addOut[0] ==> bits[i].addIn[0]
  74. bits[i-1].addOut[1] ==> bits[i].addIn[1]
  75. e[i+1] ==> bits[i].sel;
  76. }
  77. bits[n-2].dblOut[0] ==> dbl[0];
  78. bits[n-2].dblOut[1] ==> dbl[1];
  79. component m2e = Montgomery2Edwards();
  80. bits[n-2].addOut[0] ==> m2e.in[0];
  81. bits[n-2].addOut[1] ==> m2e.in[1];
  82. component eadder = BabyAdd();
  83. m2e.out[0] ==> eadder.x1;
  84. m2e.out[1] ==> eadder.y1;
  85. -p[0] ==> eadder.x2;
  86. p[1] ==> eadder.y2;
  87. component lastSel = Multiplexor2();
  88. e[0] ==> lastSel.sel;
  89. eadder.xout ==> lastSel.in[0][0];
  90. eadder.yout ==> lastSel.in[0][1];
  91. m2e.out[0] ==> lastSel.in[1][0];
  92. m2e.out[1] ==> lastSel.in[1][1];
  93. lastSel.out[0] ==> out[0];
  94. lastSel.out[1] ==> out[1];
  95. }
  96. // This function assumes that p is in the subgroup and it is different to 0
  97. template EscalarMulAny(n) {
  98. signal input e[n]; // Input in binary format
  99. signal input p[2]; // Point (Twisted format)
  100. signal output out[2]; // Point (Twisted format)
  101. var nsegments = (n-1)\148 +1;
  102. var nlastsegment = n - (nsegments-1)*148;
  103. component segments[nsegments];
  104. component doublers[nsegments-1];
  105. component m2e[nsegments-1];
  106. component adders[nsegments-1];
  107. var s;
  108. var i;
  109. var nseg;
  110. for (s=0; s<nsegments; s++) {
  111. nseg = (s < nsegments-1) ? 148 : nlastsegment;
  112. segments[s] = SegmentMulAny(nseg);
  113. for (i=0; i<nseg; i++) {
  114. e[s*148+i] ==> segments[s].e[i];
  115. }
  116. if (s==0) {
  117. p[0] ==> segments[s].p[0];
  118. p[1] ==> segments[s].p[1];
  119. } else {
  120. doublers[s-1] = MontgomeryDouble();
  121. m2e[s-1] = Montgomery2Edwards();
  122. adders[s-1] = BabyAdd();
  123. segments[s-1].dbl[0] ==> doublers[s-1].in[0];
  124. segments[s-1].dbl[1] ==> doublers[s-1].in[1];
  125. doublers[s-1].out[0] ==> m2e[s-1].in[0];
  126. doublers[s-1].out[1] ==> m2e[s-1].in[1];
  127. m2e[s-1].out[0] ==> segments[s].p[0];
  128. m2e[s-1].out[1] ==> segments[s].p[1];
  129. if (s==1) {
  130. segments[s-1].out[0] ==> adders[s-1].x1;
  131. segments[s-1].out[1] ==> adders[s-1].y1;
  132. } else {
  133. adders[s-2].xout ==> adders[s-1].x1;
  134. adders[s-2].yout ==> adders[s-1].y1;
  135. }
  136. segments[s].out[0] ==> adders[s-1].x2;
  137. segments[s].out[1] ==> adders[s-1].y2;
  138. }
  139. }
  140. if (nsegments == 1) {
  141. segments[0].out[0] ==> out[0];
  142. segments[0].out[1] ==> out[1];
  143. } else {
  144. adders[nsegments-2].xout ==> out[0];
  145. adders[nsegments-2].yout ==> out[1];
  146. }
  147. }