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