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.

174 lines
4.4 KiB

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