1+ pragma circom 2.1 .5 ;
2+
3+ include " @zk-email/zk-regex-circom/circuits/regex_helpers.circom" ;
4+
5+ // regex: [^A-ZX]$
6+ template TestRegex (msg_bytes ) {
7+ signal input msg[msg_bytes];
8+ signal output out;
9+
10+ var num_bytes = msg_bytes+ 1 ;
11+ signal in [num_bytes];
12+ in [0 ]<== 255 ;
13+ for (var i = 0 ; i < msg_bytes; i++ ) {
14+ in [i+ 1 ] <== msg[i];
15+ }
16+
17+ component eq[37 ][num_bytes];
18+ component lt[14 ][num_bytes];
19+ component and[22 ][num_bytes];
20+ component multi_or[6 ][num_bytes];
21+ signal states[num_bytes+ 1 ][9 ];
22+ signal states_tmp[num_bytes+ 1 ][9 ];
23+ signal from_zero_enabled[num_bytes+ 1 ];
24+ from_zero_enabled[num_bytes] <== 0 ;
25+ component state_changed[num_bytes];
26+
27+ signal padding_start[num_bytes+ 1 ];
28+ padding_start[0 ] <== 0 ;
29+ for (var i = 1 ; i < 9 ; i++ ) {
30+ states[0 ][i] <== 0 ;
31+ }
32+
33+ for (var i = 0 ; i < num_bytes; i++ ) {
34+ state_changed[i] = MultiOR(8 );
35+ states[i][0 ] <== 1 ;
36+ padding_start[i+ 1 ] <== IsNotZeroAcc()(padding_start[i], in [i]);
37+ lt[0 ][i] = LessEqThan(8 );
38+ lt[0 ][i].in [0 ] <== 1 ;
39+ lt[0 ][i].in [1 ] <== in [i];
40+ lt[1 ][i] = LessEqThan(8 );
41+ lt[1 ][i].in [0 ] <== in [i];
42+ lt[1 ][i].in [1 ] <== 64 ;
43+ and[0 ][i] = AND();
44+ and[0 ][i].a <== lt[0 ][i].out;
45+ and[0 ][i].b <== lt[1 ][i].out;
46+ lt[2 ][i] = LessEqThan(8 );
47+ lt[2 ][i].in [0 ] <== 91 ;
48+ lt[2 ][i].in [1 ] <== in [i];
49+ lt[3 ][i] = LessEqThan(8 );
50+ lt[3 ][i].in [0 ] <== in [i];
51+ lt[3 ][i].in [1 ] <== 127 ;
52+ and[1 ][i] = AND();
53+ and[1 ][i].a <== lt[2 ][i].out;
54+ and[1 ][i].b <== lt[3 ][i].out;
55+ and[2 ][i] = AND();
56+ and[2 ][i].a <== states[i][0 ];
57+ multi_or[0 ][i] = MultiOR(2 );
58+ multi_or[0 ][i].in [0 ] <== and[0 ][i].out;
59+ multi_or[0 ][i].in [1 ] <== and[1 ][i].out;
60+ and[2 ][i].b <== multi_or[0 ][i].out;
61+ lt[4 ][i] = LessEqThan(8 );
62+ lt[4 ][i].in [0 ] <== 128 ;
63+ lt[4 ][i].in [1 ] <== in [i];
64+ lt[5 ][i] = LessEqThan(8 );
65+ lt[5 ][i].in [0 ] <== in [i];
66+ lt[5 ][i].in [1 ] <== 191 ;
67+ and[3 ][i] = AND();
68+ and[3 ][i].a <== lt[4 ][i].out;
69+ and[3 ][i].b <== lt[5 ][i].out;
70+ and[4 ][i] = AND();
71+ and[4 ][i].a <== states[i][2 ];
72+ and[4 ][i].b <== and[3 ][i].out;
73+ states_tmp[i+ 1 ][1 ] <== and[4 ][i].out;
74+ lt[6 ][i] = LessEqThan(8 );
75+ lt[6 ][i].in [0 ] <== 194 ;
76+ lt[6 ][i].in [1 ] <== in [i];
77+ lt[7 ][i] = LessEqThan(8 );
78+ lt[7 ][i].in [0 ] <== in [i];
79+ lt[7 ][i].in [1 ] <== 223 ;
80+ and[5 ][i] = AND();
81+ and[5 ][i].a <== lt[6 ][i].out;
82+ and[5 ][i].b <== lt[7 ][i].out;
83+ and[6 ][i] = AND();
84+ and[6 ][i].a <== states[i][0 ];
85+ and[6 ][i].b <== and[5 ][i].out;
86+ lt[8 ][i] = LessEqThan(8 );
87+ lt[8 ][i].in [0 ] <== 160 ;
88+ lt[8 ][i].in [1 ] <== in [i];
89+ lt[9 ][i] = LessEqThan(8 );
90+ lt[9 ][i].in [0 ] <== in [i];
91+ lt[9 ][i].in [1 ] <== 191 ;
92+ and[7 ][i] = AND();
93+ and[7 ][i].a <== lt[8 ][i].out;
94+ and[7 ][i].b <== lt[9 ][i].out;
95+ and[8 ][i] = AND();
96+ and[8 ][i].a <== states[i][3 ];
97+ and[8 ][i].b <== and[7 ][i].out;
98+ and[9 ][i] = AND();
99+ and[9 ][i].a <== states[i][4 ];
100+ and[9 ][i].b <== and[3 ][i].out;
101+ lt[10 ][i] = LessEqThan(8 );
102+ lt[10 ][i].in [0 ] <== 128 ;
103+ lt[10 ][i].in [1 ] <== in [i];
104+ lt[11 ][i] = LessEqThan(8 );
105+ lt[11 ][i].in [0 ] <== in [i];
106+ lt[11 ][i].in [1 ] <== 159 ;
107+ and[10 ][i] = AND();
108+ and[10 ][i].a <== lt[10 ][i].out;
109+ and[10 ][i].b <== lt[11 ][i].out;
110+ and[11 ][i] = AND();
111+ and[11 ][i].a <== states[i][5 ];
112+ and[11 ][i].b <== and[10 ][i].out;
113+ multi_or[1 ][i] = MultiOR(3 );
114+ multi_or[1 ][i].in [0 ] <== and[8 ][i].out;
115+ multi_or[1 ][i].in [1 ] <== and[9 ][i].out;
116+ multi_or[1 ][i].in [2 ] <== and[11 ][i].out;
117+ states_tmp[i+ 1 ][2 ] <== multi_or[1 ][i].out;
118+ eq[0 ][i] = IsEqual();
119+ eq[0 ][i].in [0 ] <== in [i];
120+ eq[0 ][i].in [1 ] <== 224 ;
121+ and[12 ][i] = AND();
122+ and[12 ][i].a <== states[i][0 ];
123+ and[12 ][i].b <== eq[0 ][i].out;
124+ states_tmp[i+ 1 ][3 ] <== 0 ;
125+ eq[1 ][i] = IsEqual();
126+ eq[1 ][i].in [0 ] <== in [i];
127+ eq[1 ][i].in [1 ] <== 225 ;
128+ eq[2 ][i] = IsEqual();
129+ eq[2 ][i].in [0 ] <== in [i];
130+ eq[2 ][i].in [1 ] <== 226 ;
131+ eq[3 ][i] = IsEqual();
132+ eq[3 ][i].in [0 ] <== in [i];
133+ eq[3 ][i].in [1 ] <== 227 ;
134+ eq[4 ][i] = IsEqual();
135+ eq[4 ][i].in [0 ] <== in [i];
136+ eq[4 ][i].in [1 ] <== 228 ;
137+ eq[5 ][i] = IsEqual();
138+ eq[5 ][i].in [0 ] <== in [i];
139+ eq[5 ][i].in [1 ] <== 229 ;
140+ eq[6 ][i] = IsEqual();
141+ eq[6 ][i].in [0 ] <== in [i];
142+ eq[6 ][i].in [1 ] <== 230 ;
143+ eq[7 ][i] = IsEqual();
144+ eq[7 ][i].in [0 ] <== in [i];
145+ eq[7 ][i].in [1 ] <== 231 ;
146+ eq[8 ][i] = IsEqual();
147+ eq[8 ][i].in [0 ] <== in [i];
148+ eq[8 ][i].in [1 ] <== 232 ;
149+ eq[9 ][i] = IsEqual();
150+ eq[9 ][i].in [0 ] <== in [i];
151+ eq[9 ][i].in [1 ] <== 233 ;
152+ eq[10 ][i] = IsEqual();
153+ eq[10 ][i].in [0 ] <== in [i];
154+ eq[10 ][i].in [1 ] <== 234 ;
155+ eq[11 ][i] = IsEqual();
156+ eq[11 ][i].in [0 ] <== in [i];
157+ eq[11 ][i].in [1 ] <== 235 ;
158+ eq[12 ][i] = IsEqual();
159+ eq[12 ][i].in [0 ] <== in [i];
160+ eq[12 ][i].in [1 ] <== 236 ;
161+ eq[13 ][i] = IsEqual();
162+ eq[13 ][i].in [0 ] <== in [i];
163+ eq[13 ][i].in [1 ] <== 238 ;
164+ eq[14 ][i] = IsEqual();
165+ eq[14 ][i].in [0 ] <== in [i];
166+ eq[14 ][i].in [1 ] <== 239 ;
167+ and[13 ][i] = AND();
168+ and[13 ][i].a <== states[i][0 ];
169+ multi_or[2 ][i] = MultiOR(14 );
170+ multi_or[2 ][i].in [0 ] <== eq[1 ][i].out;
171+ multi_or[2 ][i].in [1 ] <== eq[2 ][i].out;
172+ multi_or[2 ][i].in [2 ] <== eq[3 ][i].out;
173+ multi_or[2 ][i].in [3 ] <== eq[4 ][i].out;
174+ multi_or[2 ][i].in [4 ] <== eq[5 ][i].out;
175+ multi_or[2 ][i].in [5 ] <== eq[6 ][i].out;
176+ multi_or[2 ][i].in [6 ] <== eq[7 ][i].out;
177+ multi_or[2 ][i].in [7 ] <== eq[8 ][i].out;
178+ multi_or[2 ][i].in [8 ] <== eq[9 ][i].out;
179+ multi_or[2 ][i].in [9 ] <== eq[10 ][i].out;
180+ multi_or[2 ][i].in [10 ] <== eq[11 ][i].out;
181+ multi_or[2 ][i].in [11 ] <== eq[12 ][i].out;
182+ multi_or[2 ][i].in [12 ] <== eq[13 ][i].out;
183+ multi_or[2 ][i].in [13 ] <== eq[14 ][i].out;
184+ and[13 ][i].b <== multi_or[2 ][i].out;
185+ lt[12 ][i] = LessEqThan(8 );
186+ lt[12 ][i].in [0 ] <== 144 ;
187+ lt[12 ][i].in [1 ] <== in [i];
188+ lt[13 ][i] = LessEqThan(8 );
189+ lt[13 ][i].in [0 ] <== in [i];
190+ lt[13 ][i].in [1 ] <== 191 ;
191+ and[14 ][i] = AND();
192+ and[14 ][i].a <== lt[12 ][i].out;
193+ and[14 ][i].b <== lt[13 ][i].out;
194+ and[15 ][i] = AND();
195+ and[15 ][i].a <== states[i][6 ];
196+ and[15 ][i].b <== and[14 ][i].out;
197+ and[16 ][i] = AND();
198+ and[16 ][i].a <== states[i][7 ];
199+ and[16 ][i].b <== and[3 ][i].out;
200+ eq[15 ][i] = IsEqual();
201+ eq[15 ][i].in [0 ] <== in [i];
202+ eq[15 ][i].in [1 ] <== 128 ;
203+ eq[16 ][i] = IsEqual();
204+ eq[16 ][i].in [0 ] <== in [i];
205+ eq[16 ][i].in [1 ] <== 129 ;
206+ eq[17 ][i] = IsEqual();
207+ eq[17 ][i].in [0 ] <== in [i];
208+ eq[17 ][i].in [1 ] <== 130 ;
209+ eq[18 ][i] = IsEqual();
210+ eq[18 ][i].in [0 ] <== in [i];
211+ eq[18 ][i].in [1 ] <== 131 ;
212+ eq[19 ][i] = IsEqual();
213+ eq[19 ][i].in [0 ] <== in [i];
214+ eq[19 ][i].in [1 ] <== 132 ;
215+ eq[20 ][i] = IsEqual();
216+ eq[20 ][i].in [0 ] <== in [i];
217+ eq[20 ][i].in [1 ] <== 133 ;
218+ eq[21 ][i] = IsEqual();
219+ eq[21 ][i].in [0 ] <== in [i];
220+ eq[21 ][i].in [1 ] <== 134 ;
221+ eq[22 ][i] = IsEqual();
222+ eq[22 ][i].in [0 ] <== in [i];
223+ eq[22 ][i].in [1 ] <== 135 ;
224+ eq[23 ][i] = IsEqual();
225+ eq[23 ][i].in [0 ] <== in [i];
226+ eq[23 ][i].in [1 ] <== 136 ;
227+ eq[24 ][i] = IsEqual();
228+ eq[24 ][i].in [0 ] <== in [i];
229+ eq[24 ][i].in [1 ] <== 137 ;
230+ eq[25 ][i] = IsEqual();
231+ eq[25 ][i].in [0 ] <== in [i];
232+ eq[25 ][i].in [1 ] <== 138 ;
233+ eq[26 ][i] = IsEqual();
234+ eq[26 ][i].in [0 ] <== in [i];
235+ eq[26 ][i].in [1 ] <== 139 ;
236+ eq[27 ][i] = IsEqual();
237+ eq[27 ][i].in [0 ] <== in [i];
238+ eq[27 ][i].in [1 ] <== 140 ;
239+ eq[28 ][i] = IsEqual();
240+ eq[28 ][i].in [0 ] <== in [i];
241+ eq[28 ][i].in [1 ] <== 141 ;
242+ eq[29 ][i] = IsEqual();
243+ eq[29 ][i].in [0 ] <== in [i];
244+ eq[29 ][i].in [1 ] <== 142 ;
245+ eq[30 ][i] = IsEqual();
246+ eq[30 ][i].in [0 ] <== in [i];
247+ eq[30 ][i].in [1 ] <== 143 ;
248+ and[17 ][i] = AND();
249+ and[17 ][i].a <== states[i][8 ];
250+ multi_or[3 ][i] = MultiOR(16 );
251+ multi_or[3 ][i].in [0 ] <== eq[15 ][i].out;
252+ multi_or[3 ][i].in [1 ] <== eq[16 ][i].out;
253+ multi_or[3 ][i].in [2 ] <== eq[17 ][i].out;
254+ multi_or[3 ][i].in [3 ] <== eq[18 ][i].out;
255+ multi_or[3 ][i].in [4 ] <== eq[19 ][i].out;
256+ multi_or[3 ][i].in [5 ] <== eq[20 ][i].out;
257+ multi_or[3 ][i].in [6 ] <== eq[21 ][i].out;
258+ multi_or[3 ][i].in [7 ] <== eq[22 ][i].out;
259+ multi_or[3 ][i].in [8 ] <== eq[23 ][i].out;
260+ multi_or[3 ][i].in [9 ] <== eq[24 ][i].out;
261+ multi_or[3 ][i].in [10 ] <== eq[25 ][i].out;
262+ multi_or[3 ][i].in [11 ] <== eq[26 ][i].out;
263+ multi_or[3 ][i].in [12 ] <== eq[27 ][i].out;
264+ multi_or[3 ][i].in [13 ] <== eq[28 ][i].out;
265+ multi_or[3 ][i].in [14 ] <== eq[29 ][i].out;
266+ multi_or[3 ][i].in [15 ] <== eq[30 ][i].out;
267+ and[17 ][i].b <== multi_or[3 ][i].out;
268+ multi_or[4 ][i] = MultiOR(3 );
269+ multi_or[4 ][i].in [0 ] <== and[15 ][i].out;
270+ multi_or[4 ][i].in [1 ] <== and[16 ][i].out;
271+ multi_or[4 ][i].in [2 ] <== and[17 ][i].out;
272+ states_tmp[i+ 1 ][4 ] <== multi_or[4 ][i].out;
273+ eq[31 ][i] = IsEqual();
274+ eq[31 ][i].in [0 ] <== in [i];
275+ eq[31 ][i].in [1 ] <== 237 ;
276+ and[18 ][i] = AND();
277+ and[18 ][i].a <== states[i][0 ];
278+ and[18 ][i].b <== eq[31 ][i].out;
279+ states_tmp[i+ 1 ][5 ] <== 0 ;
280+ eq[32 ][i] = IsEqual();
281+ eq[32 ][i].in [0 ] <== in [i];
282+ eq[32 ][i].in [1 ] <== 240 ;
283+ and[19 ][i] = AND();
284+ and[19 ][i].a <== states[i][0 ];
285+ and[19 ][i].b <== eq[32 ][i].out;
286+ states_tmp[i+ 1 ][6 ] <== 0 ;
287+ eq[33 ][i] = IsEqual();
288+ eq[33 ][i].in [0 ] <== in [i];
289+ eq[33 ][i].in [1 ] <== 241 ;
290+ eq[34 ][i] = IsEqual();
291+ eq[34 ][i].in [0 ] <== in [i];
292+ eq[34 ][i].in [1 ] <== 242 ;
293+ eq[35 ][i] = IsEqual();
294+ eq[35 ][i].in [0 ] <== in [i];
295+ eq[35 ][i].in [1 ] <== 243 ;
296+ and[20 ][i] = AND();
297+ and[20 ][i].a <== states[i][0 ];
298+ multi_or[5 ][i] = MultiOR(3 );
299+ multi_or[5 ][i].in [0 ] <== eq[33 ][i].out;
300+ multi_or[5 ][i].in [1 ] <== eq[34 ][i].out;
301+ multi_or[5 ][i].in [2 ] <== eq[35 ][i].out;
302+ and[20 ][i].b <== multi_or[5 ][i].out;
303+ states_tmp[i+ 1 ][7 ] <== 0 ;
304+ eq[36 ][i] = IsEqual();
305+ eq[36 ][i].in [0 ] <== in [i];
306+ eq[36 ][i].in [1 ] <== 244 ;
307+ and[21 ][i] = AND();
308+ and[21 ][i].a <== states[i][0 ];
309+ and[21 ][i].b <== eq[36 ][i].out;
310+ states_tmp[i+ 1 ][8 ] <== 0 ;
311+ from_zero_enabled[i] <== MultiNOR(8 )([states_tmp[i+ 1 ][1 ], states_tmp[i+ 1 ][2 ], states_tmp[i+ 1 ][3 ], states_tmp[i+ 1 ][4 ], states_tmp[i+ 1 ][5 ], states_tmp[i+ 1 ][6 ], states_tmp[i+ 1 ][7 ], states_tmp[i+ 1 ][8 ]]);
312+ states[i+ 1 ][1 ] <== MultiOR(2 )([states_tmp[i+ 1 ][1 ], from_zero_enabled[i] * and[2 ][i].out]);
313+ states[i+ 1 ][2 ] <== MultiOR(2 )([states_tmp[i+ 1 ][2 ], from_zero_enabled[i] * and[6 ][i].out]);
314+ states[i+ 1 ][3 ] <== MultiOR(2 )([states_tmp[i+ 1 ][3 ], from_zero_enabled[i] * and[12 ][i].out]);
315+ states[i+ 1 ][4 ] <== MultiOR(2 )([states_tmp[i+ 1 ][4 ], from_zero_enabled[i] * and[13 ][i].out]);
316+ states[i+ 1 ][5 ] <== MultiOR(2 )([states_tmp[i+ 1 ][5 ], from_zero_enabled[i] * and[18 ][i].out]);
317+ states[i+ 1 ][6 ] <== MultiOR(2 )([states_tmp[i+ 1 ][6 ], from_zero_enabled[i] * and[19 ][i].out]);
318+ states[i+ 1 ][7 ] <== MultiOR(2 )([states_tmp[i+ 1 ][7 ], from_zero_enabled[i] * and[20 ][i].out]);
319+ states[i+ 1 ][8 ] <== MultiOR(2 )([states_tmp[i+ 1 ][8 ], from_zero_enabled[i] * and[21 ][i].out]);
320+ state_changed[i].in [0 ] <== states[i+ 1 ][1 ];
321+ state_changed[i].in [1 ] <== states[i+ 1 ][2 ];
322+ state_changed[i].in [2 ] <== states[i+ 1 ][3 ];
323+ state_changed[i].in [3 ] <== states[i+ 1 ][4 ];
324+ state_changed[i].in [4 ] <== states[i+ 1 ][5 ];
325+ state_changed[i].in [5 ] <== states[i+ 1 ][6 ];
326+ state_changed[i].in [6 ] <== states[i+ 1 ][7 ];
327+ state_changed[i].in [7 ] <== states[i+ 1 ][8 ];
328+ }
329+
330+ component is_accepted = MultiOR(num_bytes+ 1 );
331+ for (var i = 0 ; i <= num_bytes; i++ ) {
332+ is_accepted.in [i] <== states[i][1 ];
333+ }
334+ signal end_anchor_check[num_bytes+ 1 ][2 ];
335+ end_anchor_check[0 ][1 ] <== 0 ;
336+ for (var i = 0 ; i < num_bytes; i++ ) {
337+ end_anchor_check[i+ 1 ][0 ] <== IsEqual()([i, padding_start[num_bytes]]);
338+ end_anchor_check[i+ 1 ][1 ] <== end_anchor_check[i][1 ] + states[i][1 ] * end_anchor_check[i+ 1 ][0 ];
339+ }
340+ out <== is_accepted.out * end_anchor_check[num_bytes][1 ];
341+ signal is_consecutive[msg_bytes+ 1 ][3 ];
342+ is_consecutive[msg_bytes][2 ] <== 0 ;
343+ for (var i = 0 ; i < msg_bytes; i++ ) {
344+ is_consecutive[msg_bytes- 1 - i][0 ] <== states[num_bytes- i][1 ] * (1 - is_consecutive[msg_bytes- i][2 ]) + is_consecutive[msg_bytes- i][2 ];
345+ is_consecutive[msg_bytes- 1 - i][1 ] <== state_changed[msg_bytes- i].out * is_consecutive[msg_bytes- 1 - i][0 ];
346+ is_consecutive[msg_bytes- 1 - i][2 ] <== ORAnd()([(1 - from_zero_enabled[msg_bytes- i+ 1 ]), states[num_bytes- i][1 ], is_consecutive[msg_bytes- 1 - i][1 ]]);
347+ }
348+ // substrings calculated: []
349+ }
350+
351+ component main {public [msg]} = TestRegex(600 );
0 commit comments