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.

166 lines
8.0 KiB

  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. /*
  16. ┏━━━━━━━━━━━┓
  17. ┃ ┃
  18. ┃ ┃
  19. (inx, iny) ══════════════════════════════════════════▶┃ EC Point ┃
  20. ┃ ╠═▶ (outx, outy)
  21. ╔══▶┃ Adder ┃
  22. ║ ┃ ┃
  23. ║ ┃ ┃
  24. ║ ┃ ┃
  25. ┏━━━━━━━━━━━┓ ┏━━━━━━━━━━━━┓ ║ ┗━━━━━━━━━━━┛
  26. ┃ ┃ ┃ ┃ ║
  27. ┃ ┃ ┃ ┃ ║
  28. ┃ ╠═══(p0x,p0y)═══▶┃ ┃ ║
  29. ┃ ╠═══(p1x,p1y)═══▶┃ ┃ ║
  30. ┃ ╠═══(p2x,p2y)═══▶┃ ┃ ║
  31. ┃ ╠═══(p3x,p3y)═══▶┃ ┃ ║
  32. ┃ ╠═══(p4x,p4y)═══▶┃ ┃ ║
  33. ┃ ╠═══(p5x,p5y)═══▶┃ ┃ ║
  34. ┃ ╠═══(p6x,p6y)═══▶┃ ┃ ║
  35. ┃ Constant ╠═══(p7x,p7y)═══▶┃ ┃ ║
  36. ┃ Points ┃ ┃ Mux4 ╠══╝
  37. ┃ ╠═══(p8x,p8y)═══▶┃ ┃
  38. ┃ ╠═══(p9x,p9y)═══▶┃ ┃
  39. ┃ ╠══(p10x,p10y)══▶┃ ┃
  40. ┃ ╠══(p11x,p11y)══▶┃ ┃
  41. ┃ ╠══(p12x,p12y)══▶┃ ┃
  42. ┃ ╠══(p13x,p13y)══▶┃ ┃
  43. ┃ ╠══(p14x,p14y)══▶┃ ┃
  44. ┃ ╠══(p15x,p15y)══▶┃ ┃
  45. ┃ ┃ ┃ ┃
  46. ┃ ┃ ┃ ┃
  47. ┗━━━━━━━━━━━┛ ┗━━━━━━━━━━━━┛
  48. ▲ ▲ ▲ ▲
  49. │ │ │ │
  50. s0 ─────────────────────────────────┘ │ │ │
  51. s1 ────────────────────────────────────┘ │ │
  52. s2 ───────────────────────────────────────┘ │
  53. s3 ──────────────────────────────────────────┘
  54. */
  55. pragma circom 2.0.0;
  56. include "mux4.circom";
  57. include "escalarmulw4table.circom";
  58. include "babyjub.circom";
  59. template EscalarMulWindow(base, k) {
  60. signal input in[2];
  61. signal input sel[4];
  62. signal output out[2];
  63. var table[16][2];
  64. component mux;
  65. component adder;
  66. var i;
  67. table = EscalarMulW4Table(base, k);
  68. mux = MultiMux4(2);
  69. adder = BabyAdd();
  70. for (i=0; i<4; i++) {
  71. sel[i] ==> mux.s[i];
  72. }
  73. for (i=0; i<16; i++) {
  74. mux.c[0][i] <== table[i][0];
  75. mux.c[1][i] <== table[i][1];
  76. }
  77. in[0] ==> adder.x1;
  78. in[1] ==> adder.y1;
  79. mux.out[0] ==> adder.x2;
  80. mux.out[1] ==> adder.y2;
  81. adder.xout ==> out[0];
  82. adder.yout ==> out[1];
  83. }
  84. /*
  85. ┏━━━━━━━━━┓ ┏━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━┓
  86. ┃ ┃ ┃ ┃ ┃ ┃
  87. inp ════▶┃Window(0)┃═════▶┃Window(1)┃════════ . . . . ═════════▶┃ Window(nBlocks-1) ┃═════▶ out
  88. ┃ ┃ ┃ ┃ ┃ ┃
  89. ┗━━━━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━┛
  90. ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
  91. in[0]─────────┘ │ │ │ │ │ │ │ │ │ │ │
  92. in[1]───────────┘ │ │ │ │ │ │ │ │ │ │
  93. in[2]─────────────┘ │ │ │ │ │ │ │ 0 0
  94. in[3]───────────────┘ │ │ │ │ │ │
  95. in[4]──────────────────────────┘ │ │ │ │ │
  96. in[5]────────────────────────────┘ │ │ │ │
  97. in[6]──────────────────────────────┘ │ │ │
  98. in[7]────────────────────────────────┘ │ │
  99. . │ │
  100. . │ │
  101. in[n-2]─────────────────────────────────────────────────────────────────────┘ │
  102. in[n-1]───────────────────────────────────────────────────────────────────────┘
  103. */
  104. template EscalarMul(n, base) {
  105. signal input in[n];
  106. signal input inp[2]; // Point input to be added
  107. signal output out[2];
  108. var nBlocks = ((n-1)>>2)+1;
  109. var i;
  110. var j;
  111. component windows[nBlocks];
  112. // Construct the windows
  113. for (i=0; i<nBlocks; i++) {
  114. windows[i] = EscalarMulWindow(base, i);
  115. }
  116. // Connect the selectors
  117. for (i=0; i<nBlocks; i++) {
  118. for (j=0; j<4; j++) {
  119. if (i*4+j >= n) {
  120. windows[i].sel[j] <== 0;
  121. } else {
  122. windows[i].sel[j] <== in[i*4+j];
  123. }
  124. }
  125. }
  126. // Start with generator
  127. windows[0].in[0] <== inp[0];
  128. windows[0].in[1] <== inp[1];
  129. for(i=0; i<nBlocks-1; i++) {
  130. windows[i].out[0] ==> windows[i+1].in[0];
  131. windows[i].out[1] ==> windows[i+1].in[1];
  132. }
  133. windows[nBlocks-1].out[0] ==> out[0];
  134. windows[nBlocks-1].out[1] ==> out[1];
  135. }