barretenberg
Loading...
Searching...
No Matches
contract.hpp
1#pragma once
2#include <iostream>
3
4// Source code for the Ultraplonk Solidity verifier.
5// It's expected that the AcirComposer will inject a library which will load the verification key into memory.
6
7const std::string CONTRACT_SOURCE = R"(
12abstract contract BaseUltraVerifier {
13 // VERIFICATION KEY MEMORY LOCATIONS
14 uint256 internal constant N_LOC = 0x380;
15 uint256 internal constant NUM_INPUTS_LOC = 0x3a0;
16 uint256 internal constant OMEGA_LOC = 0x3c0;
17 uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0;
18 uint256 internal constant Q1_X_LOC = 0x400;
19 uint256 internal constant Q1_Y_LOC = 0x420;
20 uint256 internal constant Q2_X_LOC = 0x440;
21 uint256 internal constant Q2_Y_LOC = 0x460;
22 uint256 internal constant Q3_X_LOC = 0x480;
23 uint256 internal constant Q3_Y_LOC = 0x4a0;
24 uint256 internal constant Q4_X_LOC = 0x4c0;
25 uint256 internal constant Q4_Y_LOC = 0x4e0;
26 uint256 internal constant QM_X_LOC = 0x500;
27 uint256 internal constant QM_Y_LOC = 0x520;
28 uint256 internal constant QC_X_LOC = 0x540;
29 uint256 internal constant QC_Y_LOC = 0x560;
30 uint256 internal constant QARITH_X_LOC = 0x580;
31 uint256 internal constant QARITH_Y_LOC = 0x5a0;
32 uint256 internal constant QSORT_X_LOC = 0x5c0;
33 uint256 internal constant QSORT_Y_LOC = 0x5e0;
34 uint256 internal constant QELLIPTIC_X_LOC = 0x600;
35 uint256 internal constant QELLIPTIC_Y_LOC = 0x620;
36 uint256 internal constant QAUX_X_LOC = 0x640;
37 uint256 internal constant QAUX_Y_LOC = 0x660;
38 uint256 internal constant SIGMA1_X_LOC = 0x680;
39 uint256 internal constant SIGMA1_Y_LOC = 0x6a0;
40 uint256 internal constant SIGMA2_X_LOC = 0x6c0;
41 uint256 internal constant SIGMA2_Y_LOC = 0x6e0;
42 uint256 internal constant SIGMA3_X_LOC = 0x700;
43 uint256 internal constant SIGMA3_Y_LOC = 0x720;
44 uint256 internal constant SIGMA4_X_LOC = 0x740;
45 uint256 internal constant SIGMA4_Y_LOC = 0x760;
46 uint256 internal constant TABLE1_X_LOC = 0x780;
47 uint256 internal constant TABLE1_Y_LOC = 0x7a0;
48 uint256 internal constant TABLE2_X_LOC = 0x7c0;
49 uint256 internal constant TABLE2_Y_LOC = 0x7e0;
50 uint256 internal constant TABLE3_X_LOC = 0x800;
51 uint256 internal constant TABLE3_Y_LOC = 0x820;
52 uint256 internal constant TABLE4_X_LOC = 0x840;
53 uint256 internal constant TABLE4_Y_LOC = 0x860;
54 uint256 internal constant TABLE_TYPE_X_LOC = 0x880;
55 uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0;
56 uint256 internal constant ID1_X_LOC = 0x8c0;
57 uint256 internal constant ID1_Y_LOC = 0x8e0;
58 uint256 internal constant ID2_X_LOC = 0x900;
59 uint256 internal constant ID2_Y_LOC = 0x920;
60 uint256 internal constant ID3_X_LOC = 0x940;
61 uint256 internal constant ID3_Y_LOC = 0x960;
62 uint256 internal constant ID4_X_LOC = 0x980;
63 uint256 internal constant ID4_Y_LOC = 0x9a0;
64 uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0;
65 uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0;
66 uint256 internal constant G2X_X0_LOC = 0xa00;
67 uint256 internal constant G2X_X1_LOC = 0xa20;
68 uint256 internal constant G2X_Y0_LOC = 0xa40;
69 uint256 internal constant G2X_Y1_LOC = 0xa60;
70
71 // ### PROOF DATA MEMORY LOCATIONS
72 uint256 internal constant W1_X_LOC = 0x1200;
73 uint256 internal constant W1_Y_LOC = 0x1220;
74 uint256 internal constant W2_X_LOC = 0x1240;
75 uint256 internal constant W2_Y_LOC = 0x1260;
76 uint256 internal constant W3_X_LOC = 0x1280;
77 uint256 internal constant W3_Y_LOC = 0x12a0;
78 uint256 internal constant W4_X_LOC = 0x12c0;
79 uint256 internal constant W4_Y_LOC = 0x12e0;
80 uint256 internal constant S_X_LOC = 0x1300;
81 uint256 internal constant S_Y_LOC = 0x1320;
82 uint256 internal constant Z_X_LOC = 0x1340;
83 uint256 internal constant Z_Y_LOC = 0x1360;
84 uint256 internal constant Z_LOOKUP_X_LOC = 0x1380;
85 uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0;
86 uint256 internal constant T1_X_LOC = 0x13c0;
87 uint256 internal constant T1_Y_LOC = 0x13e0;
88 uint256 internal constant T2_X_LOC = 0x1400;
89 uint256 internal constant T2_Y_LOC = 0x1420;
90 uint256 internal constant T3_X_LOC = 0x1440;
91 uint256 internal constant T3_Y_LOC = 0x1460;
92 uint256 internal constant T4_X_LOC = 0x1480;
93 uint256 internal constant T4_Y_LOC = 0x14a0;
94
95 uint256 internal constant W1_EVAL_LOC = 0x1600;
96 uint256 internal constant W2_EVAL_LOC = 0x1620;
97 uint256 internal constant W3_EVAL_LOC = 0x1640;
98 uint256 internal constant W4_EVAL_LOC = 0x1660;
99 uint256 internal constant S_EVAL_LOC = 0x1680;
100 uint256 internal constant Z_EVAL_LOC = 0x16a0;
101 uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0;
102 uint256 internal constant Q1_EVAL_LOC = 0x16e0;
103 uint256 internal constant Q2_EVAL_LOC = 0x1700;
104 uint256 internal constant Q3_EVAL_LOC = 0x1720;
105 uint256 internal constant Q4_EVAL_LOC = 0x1740;
106 uint256 internal constant QM_EVAL_LOC = 0x1760;
107 uint256 internal constant QC_EVAL_LOC = 0x1780;
108 uint256 internal constant QARITH_EVAL_LOC = 0x17a0;
109 uint256 internal constant QSORT_EVAL_LOC = 0x17c0;
110 uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0;
111 uint256 internal constant QAUX_EVAL_LOC = 0x1800;
112 uint256 internal constant TABLE1_EVAL_LOC = 0x1840;
113 uint256 internal constant TABLE2_EVAL_LOC = 0x1860;
114 uint256 internal constant TABLE3_EVAL_LOC = 0x1880;
115 uint256 internal constant TABLE4_EVAL_LOC = 0x18a0;
116 uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0;
117 uint256 internal constant ID1_EVAL_LOC = 0x18e0;
118 uint256 internal constant ID2_EVAL_LOC = 0x1900;
119 uint256 internal constant ID3_EVAL_LOC = 0x1920;
120 uint256 internal constant ID4_EVAL_LOC = 0x1940;
121 uint256 internal constant SIGMA1_EVAL_LOC = 0x1960;
122 uint256 internal constant SIGMA2_EVAL_LOC = 0x1980;
123 uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0;
124 uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0;
125 uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0;
126 uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000;
127 uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020;
128 uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040;
129 uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060;
130 uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080;
131 uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0;
132 uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0;
133 uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0;
134 uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100;
135 uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120;
136
137 uint256 internal constant PI_Z_X_LOC = 0x2300;
138 uint256 internal constant PI_Z_Y_LOC = 0x2320;
139 uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340;
140 uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360;
141
142 // Used for elliptic widget. These are alias names for wire + shifted wire evaluations
143 uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC;
144 uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC;
145 uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC;
146 uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC;
147 uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC;
148 uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC;
149 uint256 internal constant QBETA_LOC = Q3_EVAL_LOC;
150 uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC;
151 uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC;
152
153 // ### CHALLENGES MEMORY OFFSETS
154
155 uint256 internal constant C_BETA_LOC = 0x2600;
156 uint256 internal constant C_GAMMA_LOC = 0x2620;
157 uint256 internal constant C_ALPHA_LOC = 0x2640;
158 uint256 internal constant C_ETA_LOC = 0x2660;
159 uint256 internal constant C_ETA_SQR_LOC = 0x2680;
160 uint256 internal constant C_ETA_CUBE_LOC = 0x26a0;
161
162 uint256 internal constant C_ZETA_LOC = 0x26c0;
163 uint256 internal constant C_CURRENT_LOC = 0x26e0;
164 uint256 internal constant C_V0_LOC = 0x2700;
165 uint256 internal constant C_V1_LOC = 0x2720;
166 uint256 internal constant C_V2_LOC = 0x2740;
167 uint256 internal constant C_V3_LOC = 0x2760;
168 uint256 internal constant C_V4_LOC = 0x2780;
169 uint256 internal constant C_V5_LOC = 0x27a0;
170 uint256 internal constant C_V6_LOC = 0x27c0;
171 uint256 internal constant C_V7_LOC = 0x27e0;
172 uint256 internal constant C_V8_LOC = 0x2800;
173 uint256 internal constant C_V9_LOC = 0x2820;
174 uint256 internal constant C_V10_LOC = 0x2840;
175 uint256 internal constant C_V11_LOC = 0x2860;
176 uint256 internal constant C_V12_LOC = 0x2880;
177 uint256 internal constant C_V13_LOC = 0x28a0;
178 uint256 internal constant C_V14_LOC = 0x28c0;
179 uint256 internal constant C_V15_LOC = 0x28e0;
180 uint256 internal constant C_V16_LOC = 0x2900;
181 uint256 internal constant C_V17_LOC = 0x2920;
182 uint256 internal constant C_V18_LOC = 0x2940;
183 uint256 internal constant C_V19_LOC = 0x2960;
184 uint256 internal constant C_V20_LOC = 0x2980;
185 uint256 internal constant C_V21_LOC = 0x29a0;
186 uint256 internal constant C_V22_LOC = 0x29c0;
187 uint256 internal constant C_V23_LOC = 0x29e0;
188 uint256 internal constant C_V24_LOC = 0x2a00;
189 uint256 internal constant C_V25_LOC = 0x2a20;
190 uint256 internal constant C_V26_LOC = 0x2a40;
191 uint256 internal constant C_V27_LOC = 0x2a60;
192 uint256 internal constant C_V28_LOC = 0x2a80;
193 uint256 internal constant C_V29_LOC = 0x2aa0;
194 uint256 internal constant C_V30_LOC = 0x2ac0;
195
196 uint256 internal constant C_U_LOC = 0x2b00;
197
198 // ### LOCAL VARIABLES MEMORY OFFSETS
199 uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000;
200 uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020;
201 uint256 internal constant ZETA_POW_N_LOC = 0x3040;
202 uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060;
203 uint256 internal constant ZERO_POLY_LOC = 0x3080;
204 uint256 internal constant L_START_LOC = 0x30a0;
205 uint256 internal constant L_END_LOC = 0x30c0;
206 uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0;
207
208 uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100;
209 uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120;
210 uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140;
211
212 uint256 internal constant ACCUMULATOR_X_LOC = 0x3160;
213 uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180;
214 uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0;
215 uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0;
216 uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0;
217 uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200;
218 uint256 internal constant PAIRING_RHS_X_LOC = 0x3220;
219 uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240;
220
221 // ### SUCCESS FLAG MEMORY LOCATIONS
222 uint256 internal constant GRAND_PRODUCT_SUCCESS_FLAG = 0x3300;
223 uint256 internal constant ARITHMETIC_TERM_SUCCESS_FLAG = 0x3020;
224 uint256 internal constant BATCH_OPENING_SUCCESS_FLAG = 0x3340;
225 uint256 internal constant OPENING_COMMITMENT_SUCCESS_FLAG = 0x3360;
226 uint256 internal constant PAIRING_PREAMBLE_SUCCESS_FLAG = 0x3380;
227 uint256 internal constant PAIRING_SUCCESS_FLAG = 0x33a0;
228 uint256 internal constant RESULT_FLAG = 0x33c0;
229
230 // misc stuff
231 uint256 internal constant OMEGA_INVERSE_LOC = 0x3400;
232 uint256 internal constant C_ALPHA_SQR_LOC = 0x3420;
233 uint256 internal constant C_ALPHA_CUBE_LOC = 0x3440;
234 uint256 internal constant C_ALPHA_QUAD_LOC = 0x3460;
235 uint256 internal constant C_ALPHA_BASE_LOC = 0x3480;
236
237 // ### RECURSION VARIABLE MEMORY LOCATIONS
238 uint256 internal constant RECURSIVE_P1_X_LOC = 0x3500;
239 uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3520;
240 uint256 internal constant RECURSIVE_P2_X_LOC = 0x3540;
241 uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3560;
242
243 uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3580;
244
245 // sub-identity storage
246 uint256 internal constant PERMUTATION_IDENTITY = 0x3600;
247 uint256 internal constant PLOOKUP_IDENTITY = 0x3620;
248 uint256 internal constant ARITHMETIC_IDENTITY = 0x3640;
249 uint256 internal constant SORT_IDENTITY = 0x3660;
250 uint256 internal constant ELLIPTIC_IDENTITY = 0x3680;
251 uint256 internal constant AUX_IDENTITY = 0x36a0;
252 uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x36c0;
253 uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x36e0;
254 uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3700;
255 uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3720;
256 uint256 internal constant AUX_MEMORY_EVALUATION = 0x3740;
257
258 uint256 internal constant QUOTIENT_EVAL_LOC = 0x3760;
259 uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3780;
260
261 // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time
262 uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x37a0;
263 uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x37c0;
264 uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0;
265
266 bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6;
267 bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f;
268 bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc;
269 bytes4 internal constant EC_SCALAR_MUL_FAILURE_SELECTOR = 0xf755f369;
270 bytes4 internal constant PROOF_FAILURE_SELECTOR = 0x0711fcec;
271
272 uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes
273
274 // We need to hash 41 field elements when generating the NU challenge
275 // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14)
276 // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7)
277 // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9)
278 // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7)
279 // table1_omega, table2_omega, table3_omega, table4_omega (4)
280 uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20
281
282 // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over
283 // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4
284 uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0
285
286 uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P =
287 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
288 uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68
289 uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14
290
291 // y^2 = x^3 + ax + b
292 // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic
293 uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17;
294 error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual);
295 error PUBLIC_INPUT_INVALID_BN128_G1_POINT();
296 error PUBLIC_INPUT_GE_P();
297 error MOD_EXP_FAILURE();
298 error EC_SCALAR_MUL_FAILURE();
299 error PROOF_FAILURE();
300
301 function getVerificationKeyHash() public pure virtual returns (bytes32);
302
303 function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual;
304
311 function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) {
312 loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC);
313
314 uint256 requiredPublicInputCount;
315 assembly {
316 requiredPublicInputCount := mload(NUM_INPUTS_LOC)
317 }
318 if (requiredPublicInputCount != _publicInputs.length) {
319 revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length);
320 }
321
322 assembly {
323 let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order
324 let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order
325
329 {
330 let data_ptr := add(calldataload(0x04), 0x24)
331
332 mstore(W1_Y_LOC, mod(calldataload(data_ptr), q))
333 mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q))
334
335 mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q))
336 mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q))
337
338 mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q))
339 mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q))
340
341 mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q))
342 mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q))
343
344 mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q))
345 mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q))
346 mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q))
347 mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q))
348 mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q))
349 mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q))
350 mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q))
351 mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q))
352
353 mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q))
354 mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q))
355
356 mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q))
357 mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q))
358
359 mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q))
360 mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q))
361
362 mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p))
363 mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p))
364 mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p))
365 mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p))
366 mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p))
367 mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p))
368 mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p))
369 mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p))
370 mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p))
371 mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p))
372 mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p))
373 mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p))
374 mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p))
375 mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p))
376 mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p))
377 mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p))
378 mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p))
379
380 mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p))
381 mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p))
382
383 mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p))
384 mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p))
385
386 mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p))
387 mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p))
388 mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p))
389 mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p))
390 mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p))
391
392 mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p))
393 mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p))
394 mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p))
395 mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p))
396
397 mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p))
398 mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p))
399 mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p))
400 mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p))
401 mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p))
402
403 mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p))
404
405 mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p))
406 mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p))
407 mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p))
408 mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p))
409 mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p))
410
411 mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q))
412 mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q))
413
414 mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q))
415 mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q))
416 }
417
421 {
422 if mload(CONTAINS_RECURSIVE_PROOF_LOC) {
423 let public_inputs_ptr := add(calldataload(0x24), 0x24)
424 let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr)
425
426 let x0 := calldataload(index_counter)
427 x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20))))
428 x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40))))
429 x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60))))
430 let y0 := calldataload(add(index_counter, 0x80))
431 y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0))))
432 y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0))))
433 y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0))))
434 let x1 := calldataload(add(index_counter, 0x100))
435 x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120))))
436 x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140))))
437 x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160))))
438 let y1 := calldataload(add(index_counter, 0x180))
439 y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0))))
440 y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0))))
441 y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0))))
442 mstore(RECURSIVE_P1_X_LOC, x0)
443 mstore(RECURSIVE_P1_Y_LOC, y0)
444 mstore(RECURSIVE_P2_X_LOC, x1)
445 mstore(RECURSIVE_P2_Y_LOC, y1)
446
447 // validate these are valid bn128 G1 points
448 if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) {
449 mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR)
450 revert(0x00, 0x04)
451 }
452 }
453 }
454
455 {
459 mstore(0x00, shl(224, mload(N_LOC)))
460 mstore(0x04, shl(224, mload(NUM_INPUTS_LOC)))
461 let challenge := keccak256(0x00, 0x08)
462
466 mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge)
467 // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs
468 let public_inputs_start := add(calldataload(0x24), 0x24)
469 // copy the public inputs over
470 let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20)
471 calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size)
472
473 // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length)
474 let w_start := add(calldataload(0x04), 0x24)
475 calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH)
476
477 // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0)
478 let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH))
479
480 challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size)
481 {
482 let eta := mod(challenge, p)
483 mstore(C_ETA_LOC, eta)
484 mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p))
485 mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p))
486 }
487
491 mstore(0x00, challenge)
492 mstore(0x20, mload(W4_Y_LOC))
493 mstore(0x40, mload(W4_X_LOC))
494 mstore(0x60, mload(S_Y_LOC))
495 mstore(0x80, mload(S_X_LOC))
496 challenge := keccak256(0x00, 0xa0)
497 mstore(C_BETA_LOC, mod(challenge, p))
498
502 mstore(0x00, challenge)
503 mstore8(0x20, 0x01)
504 challenge := keccak256(0x00, 0x21)
505 mstore(C_GAMMA_LOC, mod(challenge, p))
506
510 mstore(0x00, challenge)
511 mstore(0x20, mload(Z_Y_LOC))
512 mstore(0x40, mload(Z_X_LOC))
513 mstore(0x60, mload(Z_LOOKUP_Y_LOC))
514 mstore(0x80, mload(Z_LOOKUP_X_LOC))
515 challenge := keccak256(0x00, 0xa0)
516 mstore(C_ALPHA_LOC, mod(challenge, p))
517
521 let alpha := mload(C_ALPHA_LOC)
522 mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p))
523 mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p))
524 mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p))
525 mstore(C_ALPHA_BASE_LOC, alpha)
526
530 mstore(0x00, challenge)
531 mstore(0x20, mload(T1_Y_LOC))
532 mstore(0x40, mload(T1_X_LOC))
533 mstore(0x60, mload(T2_Y_LOC))
534 mstore(0x80, mload(T2_X_LOC))
535 mstore(0xa0, mload(T3_Y_LOC))
536 mstore(0xc0, mload(T3_X_LOC))
537 mstore(0xe0, mload(T4_Y_LOC))
538 mstore(0x100, mload(T4_X_LOC))
539
540 challenge := keccak256(0x00, 0x120)
541
542 mstore(C_ZETA_LOC, mod(challenge, p))
543 mstore(C_CURRENT_LOC, challenge)
544 }
545
554 {
555 let beta := mload(C_BETA_LOC) // β
556 let gamma := mload(C_GAMMA_LOC) // γ
557 let work_root := mload(OMEGA_LOC) // ω
558 let numerator_value := 1
559 let denominator_value := 1
560
561 let p_clone := p // move p to the front of the stack
562 let valid_inputs := true
563
564 // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24])
565 let public_inputs_ptr := add(calldataload(0x24), 0x24)
566
567 // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes
568 let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20))
569
570 // root_1 = β * 0x05
571 let root_1 := mulmod(beta, 0x05, p_clone) // k1.β
572 // root_2 = β * 0x0c
573 let root_2 := mulmod(beta, 0x0c, p_clone)
574 // @note 0x05 + 0x07 == 0x0c == external coset generator
575
576 for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } {
587 let input := calldataload(public_inputs_ptr)
588 valid_inputs := and(valid_inputs, lt(input, p_clone))
589 let temp := addmod(input, gamma, p_clone)
590
591 numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone)
592 denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone)
593
594 root_1 := mulmod(root_1, work_root, p_clone)
595 root_2 := mulmod(root_2, work_root, p_clone)
596 }
597
598 // Revert if not all public inputs are field elements (i.e. < p)
599 if iszero(valid_inputs) {
600 mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR)
601 revert(0x00, 0x04)
602 }
603
604 mstore(DELTA_NUMERATOR_LOC, numerator_value)
605 mstore(DELTA_DENOMINATOR_LOC, denominator_value)
606 }
607
612 {
613 let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p)
614 let delta_numerator := delta_base
615 {
616 let exponent := mload(N_LOC)
617 let count := 1
618 for {} lt(count, exponent) { count := add(count, count) } {
619 delta_numerator := mulmod(delta_numerator, delta_numerator, p)
620 }
621 }
622 mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator)
623
624 let delta_denominator := mulmod(delta_base, delta_base, p)
625 delta_denominator := mulmod(delta_denominator, delta_denominator, p)
626 mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator)
627 }
631 {
653 let zeta := mload(C_ZETA_LOC)
654
655 // compute zeta^n, where n is a power of 2
656 let vanishing_numerator := zeta
657 {
658 // pow_small
659 let exponent := mload(N_LOC)
660 let count := 1
661 for {} lt(count, exponent) { count := add(count, count) } {
662 vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p)
663 }
664 }
665 mstore(ZETA_POW_N_LOC, vanishing_numerator)
666 vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p)
667
668 let accumulating_root := mload(OMEGA_INVERSE_LOC)
669 let work_root := sub(p, accumulating_root)
670 let domain_inverse := mload(DOMAIN_INVERSE_LOC)
671
672 let vanishing_denominator := addmod(zeta, work_root, p)
673 work_root := mulmod(work_root, accumulating_root, p)
674 vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p)
675 work_root := mulmod(work_root, accumulating_root, p)
676 vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p)
677 vanishing_denominator :=
678 mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p)
679
680 work_root := mload(OMEGA_LOC)
681
682 let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p)
683 let l_start_denominator := addmod(zeta, sub(p, 1), p)
684
685 accumulating_root := mulmod(work_root, work_root, p)
686
687 let l_end_denominator :=
688 addmod(
689 mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p
690 )
691
695 let accumulator := mload(DELTA_DENOMINATOR_LOC)
696 let t0 := accumulator
697 accumulator := mulmod(accumulator, vanishing_denominator, p)
698 let t1 := accumulator
699 accumulator := mulmod(accumulator, vanishing_numerator, p)
700 let t2 := accumulator
701 accumulator := mulmod(accumulator, l_start_denominator, p)
702 let t3 := accumulator
703 accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p)
704 let t4 := accumulator
705 {
706 mstore(0, 0x20)
707 mstore(0x20, 0x20)
708 mstore(0x40, 0x20)
709 mstore(0x60, mulmod(accumulator, l_end_denominator, p))
710 mstore(0x80, sub(p, 2))
711 mstore(0xa0, p)
712 if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) {
713 mstore(0x0, MOD_EXP_FAILURE_SELECTOR)
714 revert(0x00, 0x04)
715 }
716 accumulator := mload(0x00)
717 }
718
719 t4 := mulmod(accumulator, t4, p)
720 accumulator := mulmod(accumulator, l_end_denominator, p)
721
722 t3 := mulmod(accumulator, t3, p)
723 accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p)
724
725 t2 := mulmod(accumulator, t2, p)
726 accumulator := mulmod(accumulator, l_start_denominator, p)
727
728 t1 := mulmod(accumulator, t1, p)
729 accumulator := mulmod(accumulator, vanishing_numerator, p)
730
731 t0 := mulmod(accumulator, t0, p)
732 accumulator := mulmod(accumulator, vanishing_denominator, p)
733
734 accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p)
735
736 mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p))
737 mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p))
738 mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p))
739 mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p))
740 mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p))
741 mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p))
742 }
743
759 {
760 let alpha := mload(C_ALPHA_LOC)
761 let beta := mload(C_BETA_LOC)
762 let gamma := mload(C_GAMMA_LOC)
763
772 let t1 :=
773 mulmod(
774 add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)),
775 add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)),
776 p
777 )
778 let t2 :=
779 mulmod(
780 add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)),
781 add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)),
782 p
783 )
784 let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p)
785 t1 :=
786 mulmod(
787 add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)),
788 add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)),
789 p
790 )
791 t2 :=
792 mulmod(
793 add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)),
794 add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)),
795 p
796 )
797 result :=
798 addmod(
799 result,
800 sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)),
801 p
802 )
803
811 mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
812 result :=
813 addmod(
814 result,
815 mulmod(
816 mload(C_ALPHA_BASE_LOC),
817 mulmod(
818 mload(L_END_LOC),
819 addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p),
820 p
821 ),
822 p
823 ),
824 p
825 )
826 mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
827 mstore(
828 PERMUTATION_IDENTITY,
829 addmod(
830 result,
831 mulmod(
832 mload(C_ALPHA_BASE_LOC),
833 mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p),
834 p
835 ),
836 p
837 )
838 )
839 mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
840 }
841
845 {
855 let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p)
856 f :=
857 addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p)
858 f := mulmod(f, mload(C_ETA_LOC), p)
859 f :=
860 addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p)
861 f := mulmod(f, mload(C_ETA_LOC), p)
862 f :=
863 addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p)
864
865 // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z)
866 let t :=
867 addmod(
868 addmod(
869 addmod(
870 mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p),
871 mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p),
872 p
873 ),
874 mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p),
875 p
876 ),
877 mload(TABLE1_EVAL_LOC),
878 p
879 )
880
881 // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw)
882 let t_omega :=
883 addmod(
884 addmod(
885 addmod(
886 mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p),
887 mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p),
888 p
889 ),
890 mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p),
891 p
892 ),
893 mload(TABLE1_OMEGA_EVAL_LOC),
894 p
895 )
896
909 let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p)
910 let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p)
911 let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p)
912 numerator := mulmod(numerator, temp0, p)
913 numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p)
914 temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p)
915 numerator := addmod(numerator, temp0, p)
916 numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p)
917 numerator := addmod(numerator, sub(p, temp0), p)
918
930 let denominator :=
931 addmod(
932 addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p),
933 gamma_beta_constant,
934 p
935 )
936 let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p)
937 denominator := addmod(denominator, sub(p, temp1), p)
938 denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p)
939 denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p)
940
941 mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p))
942
943 // update alpha
944 mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p))
945 }
946
950 {
987 let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p)
988 let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p)
989 let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p)
990 let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p)
991
992 // @todo - Add a explicit test that hits QARITH == 3
993 // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2
994 let w1w2qm :=
995 mulmod(
996 mulmod(
997 mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p),
998 addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p),
999 p
1000 ),
1001 NEGATIVE_INVERSE_OF_2_MODULO_P,
1002 p
1003 )
1004
1005 // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c
1006 let identity :=
1007 addmod(
1008 mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p
1009 )
1010
1011 // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where:
1012 // w_1 + w_4 - w_1_omega + q_m = 0
1013 // we use this gate to save an addition gate when adding or subtracting non-native field elements
1014 // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m)
1015 let extra_small_addition_gate_identity :=
1016 mulmod(
1017 mload(C_ALPHA_LOC),
1018 mulmod(
1019 addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p),
1020 addmod(
1021 mload(QM_EVAL_LOC),
1022 addmod(
1023 sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p
1024 ),
1025 p
1026 ),
1027 p
1028 ),
1029 p
1030 )
1031
1032 // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity
1033 // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires!
1034 // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity))
1035 mstore(
1036 ARITHMETIC_IDENTITY,
1037 mulmod(
1038 mload(C_ALPHA_BASE_LOC),
1039 mulmod(
1040 mload(QARITH_EVAL_LOC),
1041 addmod(
1042 identity,
1043 mulmod(
1044 addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p),
1045 addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p),
1046 p
1047 ),
1048 p
1049 ),
1050 p
1051 ),
1052 p
1053 )
1054 )
1055
1056 // update alpha
1057 mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p))
1058 }
1059
1063 {
1082 let minus_two := sub(p, 2)
1083 let minus_three := sub(p, 3)
1084 let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p)
1085 let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p)
1086 let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p)
1087 let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)
1088
1089 let range_accumulator :=
1090 mulmod(
1091 mulmod(
1092 mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p),
1093 addmod(d1, minus_three, p),
1094 p
1095 ),
1096 mload(C_ALPHA_BASE_LOC),
1097 p
1098 )
1099 range_accumulator :=
1100 addmod(
1101 range_accumulator,
1102 mulmod(
1103 mulmod(
1104 mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p),
1105 addmod(d2, minus_three, p),
1106 p
1107 ),
1108 mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p),
1109 p
1110 ),
1111 p
1112 )
1113 range_accumulator :=
1114 addmod(
1115 range_accumulator,
1116 mulmod(
1117 mulmod(
1118 mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p),
1119 addmod(d3, minus_three, p),
1120 p
1121 ),
1122 mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p),
1123 p
1124 ),
1125 p
1126 )
1127 range_accumulator :=
1128 addmod(
1129 range_accumulator,
1130 mulmod(
1131 mulmod(
1132 mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p),
1133 addmod(d4, minus_three, p),
1134 p
1135 ),
1136 mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p),
1137 p
1138 ),
1139 p
1140 )
1141 range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p)
1142
1143 mstore(SORT_IDENTITY, range_accumulator)
1144
1145 // update alpha
1146 mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p))
1147 }
1148
1152 {
1166 // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0
1167 let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p)
1168 let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p)
1169 let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p)
1170 let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p)
1171
1172 let x_add_identity :=
1173 addmod(
1174 mulmod(
1175 addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p),
1176 mulmod(x_diff, x_diff, p),
1177 p
1178 ),
1179 addmod(
1180 sub(
1181 p,
1182 addmod(y2_sqr, y1_sqr, p)
1183 ),
1184 addmod(y1y2, y1y2, p),
1185 p
1186 ),
1187 p
1188 )
1189 x_add_identity :=
1190 mulmod(
1191 mulmod(
1192 x_add_identity,
1193 addmod(
1194 1,
1195 sub(p, mload(QM_EVAL_LOC)),
1196 p
1197 ),
1198 p
1199 ),
1200 mload(C_ALPHA_BASE_LOC),
1201 p
1202 )
1203
1204 // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0
1205 let y1_plus_y3 := addmod(
1206 mload(Y1_EVAL_LOC),
1207 mload(Y3_EVAL_LOC),
1208 p
1209 )
1210 let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p)
1211 let y_add_identity :=
1212 addmod(
1213 mulmod(y1_plus_y3, x_diff, p),
1214 mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p),
1215 p
1216 )
1217 y_add_identity :=
1218 mulmod(
1219 mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p),
1220 mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p),
1221 p
1222 )
1223
1224 // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL
1225 mstore(
1226 ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p)
1227 )
1228 }
1229 {
1243 // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0
1244 let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p)
1245 let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p)
1246 let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p)
1247 let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p)
1248 let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p)
1249 let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p)
1250 let x_double_identity :=
1251 addmod(
1252 mulmod(
1253 addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p),
1254 y1_sqr_mul_4,
1255 p
1256 ),
1257 sub(p, x1_pow_4_mul_9),
1258 p
1259 )
1260 // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0
1261 let y_double_identity :=
1262 addmod(
1263 mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p),
1264 sub(
1265 p,
1266 mulmod(
1267 addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p),
1268 addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p),
1269 p
1270 )
1271 ),
1272 p
1273 )
1274 x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p)
1275 y_double_identity :=
1276 mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p)
1277 x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p)
1278 y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p)
1279 // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL
1280 mstore(
1281 ELLIPTIC_IDENTITY,
1282 addmod(
1283 mload(ELLIPTIC_IDENTITY),
1284 mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p),
1285 p
1286 )
1287 )
1288
1289 // update alpha
1290 mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p))
1291 }
1292
1296 {
1297 {
1318 let limb_subproduct :=
1319 addmod(
1320 mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p),
1321 mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p),
1322 p
1323 )
1324
1325 let non_native_field_gate_2 :=
1326 addmod(
1327 addmod(
1328 mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p),
1329 mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p),
1330 p
1331 ),
1332 sub(p, mload(W3_OMEGA_EVAL_LOC)),
1333 p
1334 )
1335 non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p)
1336 non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p)
1337 non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p)
1338 non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p)
1339 limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p)
1340 limb_subproduct :=
1341 addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p)
1342 let non_native_field_gate_1 :=
1343 mulmod(
1344 addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p),
1345 mload(Q3_EVAL_LOC),
1346 p
1347 )
1348 let non_native_field_gate_3 :=
1349 mulmod(
1350 addmod(
1351 addmod(limb_subproduct, mload(W4_EVAL_LOC), p),
1352 sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)),
1353 p
1354 ),
1355 mload(QM_EVAL_LOC),
1356 p
1357 )
1358 let non_native_field_identity :=
1359 mulmod(
1360 addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p),
1361 mload(Q2_EVAL_LOC),
1362 p
1363 )
1364
1365 mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity)
1366 }
1367
1368 {
1382 let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p)
1383 limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p)
1384 limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
1385 limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p)
1386 limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
1387 limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p)
1388 limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
1389 limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p)
1390 limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p)
1391 limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p)
1392
1406 let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p)
1407 limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p)
1408 limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
1409 limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p)
1410 limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
1411 limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p)
1412 limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
1413 limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p)
1414 limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p)
1415 limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p)
1416
1417 mstore(
1418 AUX_LIMB_ACCUMULATOR_EVALUATION,
1419 mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p)
1420 )
1421 }
1422
1423 {
1438 let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p)
1439 memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p)
1440 memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p)
1441 memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p)
1442 memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p)
1443 memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p)
1444
1445 let partial_record_check := memory_record_check
1446 memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p)
1447
1448 mstore(AUX_MEMORY_EVALUATION, memory_record_check)
1449
1450 // index_delta = w_1_omega - w_1
1451 let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p)
1452 // record_delta = w_4_omega - w_4
1453 let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)
1454 // index_is_monotonically_increasing = index_delta * (index_delta - 1)
1455 let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p)
1456
1457 // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta)
1458 let adjacent_values_match_if_adjacent_indices_match :=
1459 mulmod(record_delta, addmod(1, sub(p, index_delta), p), p)
1460
1461 // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check
1462 mstore(
1463 AUX_ROM_CONSISTENCY_EVALUATION,
1464 addmod(
1465 mulmod(
1466 addmod(
1467 mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p),
1468 index_is_monotonically_increasing,
1469 p
1470 ),
1471 mload(C_ALPHA_LOC),
1472 p
1473 ),
1474 memory_record_check,
1475 p
1476 )
1477 )
1478
1479 {
1489 let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p)
1490 next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p)
1491 next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p)
1492 next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p)
1493 next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p)
1494 next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p)
1495
1496 // value_delta = w_3_omega - w_3
1497 let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p)
1498 // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type);
1499
1500 let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation :=
1501 mulmod(
1502 addmod(1, sub(p, index_delta), p),
1503 mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p),
1504 p
1505 )
1506
1507 // AUX_RAM_CONSISTENCY_EVALUATION
1508
1522 let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p)
1523 let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p)
1524 let next_gate_access_type_is_boolean :=
1525 mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p)
1526 let RAM_cci :=
1527 mulmod(
1528 adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation,
1529 mload(C_ALPHA_LOC),
1530 p
1531 )
1532 RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p)
1533 RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p)
1534 RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p)
1535 RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p)
1536 RAM_cci := addmod(RAM_cci, access_check, p)
1537
1538 mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci)
1539 }
1540
1541 {
1542 // timestamp_delta = w_2_omega - w_2
1543 let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p)
1544
1545 // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3
1546 let RAM_timestamp_check_identity :=
1547 addmod(
1548 mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p
1549 )
1550
1562 let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p)
1563 memory_identity :=
1564 addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p)
1565 memory_identity :=
1566 addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p)
1567 memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p)
1568 memory_identity :=
1569 addmod(
1570 memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p
1571 )
1572
1573 let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p)
1574 auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p)
1575 auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p)
1576 auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p)
1577
1578 mstore(AUX_IDENTITY, auxiliary_identity)
1579
1580 // update alpha
1581 mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p))
1582 }
1583 }
1584 }
1585
1586 {
1596 mstore(
1597 QUOTIENT_EVAL_LOC,
1598 mulmod(
1599 addmod(
1600 addmod(
1601 addmod(
1602 addmod(
1603 addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p),
1604 mload(ARITHMETIC_IDENTITY),
1605 p
1606 ),
1607 mload(SORT_IDENTITY),
1608 p
1609 ),
1610 mload(ELLIPTIC_IDENTITY),
1611 p
1612 ),
1613 mload(AUX_IDENTITY),
1614 p
1615 ),
1616 mload(ZERO_POLY_INVERSE_LOC),
1617 p
1618 )
1619 )
1620 }
1621
1625 {
1626 let current_challenge := mload(C_CURRENT_LOC)
1627 // get a calldata pointer that points to the start of the data we want to copy
1628 let calldata_ptr := add(calldataload(0x04), 0x24)
1629
1630 calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH)
1631
1632 mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge)
1633 mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC))
1634 calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH)
1635
1636 // hash length = (0x20 + num field elements), we include the previous challenge in the hash
1637 let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40))
1638
1639 mstore(C_V0_LOC, mod(challenge, p))
1640 // We need THIRTY-ONE independent nu challenges!
1641 mstore(0x00, challenge)
1642 mstore8(0x20, 0x01)
1643 mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p))
1644 mstore8(0x20, 0x02)
1645 mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p))
1646 mstore8(0x20, 0x03)
1647 mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p))
1648 mstore8(0x20, 0x04)
1649 mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p))
1650 mstore8(0x20, 0x05)
1651 mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p))
1652 mstore8(0x20, 0x06)
1653 mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p))
1654 mstore8(0x20, 0x07)
1655 mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p))
1656 mstore8(0x20, 0x08)
1657 mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p))
1658 mstore8(0x20, 0x09)
1659 mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p))
1660 mstore8(0x20, 0x0a)
1661 mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p))
1662 mstore8(0x20, 0x0b)
1663 mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p))
1664 mstore8(0x20, 0x0c)
1665 mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p))
1666 mstore8(0x20, 0x0d)
1667 mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p))
1668 mstore8(0x20, 0x0e)
1669 mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p))
1670 mstore8(0x20, 0x0f)
1671 mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p))
1672 mstore8(0x20, 0x10)
1673 mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p))
1674 mstore8(0x20, 0x11)
1675 mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p))
1676 mstore8(0x20, 0x12)
1677 mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p))
1678 mstore8(0x20, 0x13)
1679 mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p))
1680 mstore8(0x20, 0x14)
1681 mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p))
1682 mstore8(0x20, 0x15)
1683 mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p))
1684 mstore8(0x20, 0x16)
1685 mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p))
1686 mstore8(0x20, 0x17)
1687 mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p))
1688 mstore8(0x20, 0x18)
1689 mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p))
1690 mstore8(0x20, 0x19)
1691 mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p))
1692 mstore8(0x20, 0x1a)
1693 mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p))
1694 mstore8(0x20, 0x1b)
1695 mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p))
1696 mstore8(0x20, 0x1c)
1697 mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p))
1698 mstore8(0x20, 0x1d)
1699 mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p))
1700
1701 // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change?
1702 mstore8(0x20, 0x1d)
1703 challenge := keccak256(0x00, 0x21)
1704 mstore(C_V30_LOC, mod(challenge, p))
1705
1706 // separator
1707 mstore(0x00, challenge)
1708 mstore(0x20, mload(PI_Z_Y_LOC))
1709 mstore(0x40, mload(PI_Z_X_LOC))
1710 mstore(0x60, mload(PI_Z_OMEGA_Y_LOC))
1711 mstore(0x80, mload(PI_Z_OMEGA_X_LOC))
1712
1713 mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p))
1714 }
1715
1716 let success := 0
1717 // VALIDATE T1
1718 {
1719 let x := mload(T1_X_LOC)
1720 let y := mload(T1_Y_LOC)
1721 let xx := mulmod(x, x, q)
1722 // validate on curve
1723 success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))
1724 mstore(ACCUMULATOR_X_LOC, x)
1725 mstore(add(ACCUMULATOR_X_LOC, 0x20), y)
1726 }
1727 // VALIDATE T2
1728 {
1729 let x := mload(T2_X_LOC) // 0x1400
1730 let y := mload(T2_Y_LOC) // 0x1420
1731 let xx := mulmod(x, x, q)
1732 // validate on curve
1733 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1734 mstore(0x00, x)
1735 mstore(0x20, y)
1736 }
1737 mstore(0x40, mload(ZETA_POW_N_LOC))
1738 // accumulator_2 = [T2].zeta^n
1739 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1740 // accumulator = [T1] + accumulator_2
1741 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1742
1743 // VALIDATE T3
1744 {
1745 let x := mload(T3_X_LOC)
1746 let y := mload(T3_Y_LOC)
1747 let xx := mulmod(x, x, q)
1748 // validate on curve
1749 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1750 mstore(0x00, x)
1751 mstore(0x20, y)
1752 }
1753 mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p))
1754 // accumulator_2 = [T3].zeta^{2n}
1755 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1756 // accumulator = accumulator + accumulator_2
1757 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1758
1759 // VALIDATE T4
1760 {
1761 let x := mload(T4_X_LOC)
1762 let y := mload(T4_Y_LOC)
1763 let xx := mulmod(x, x, q)
1764 // validate on curve
1765 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1766 mstore(0x00, x)
1767 mstore(0x20, y)
1768 }
1769 mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p))
1770 // accumulator_2 = [T4].zeta^{3n}
1771 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1772 // accumulator = accumulator + accumulator_2
1773 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1774
1775 // VALIDATE W1
1776 {
1777 let x := mload(W1_X_LOC)
1778 let y := mload(W1_Y_LOC)
1779 let xx := mulmod(x, x, q)
1780 // validate on curve
1781 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1782 mstore(0x00, x)
1783 mstore(0x20, y)
1784 }
1785 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p))
1786 // accumulator_2 = v0.(u + 1).[W1]
1787 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1788 // accumulator = accumulator + accumulator_2
1789 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1790
1791 // VALIDATE W2
1792 {
1793 let x := mload(W2_X_LOC)
1794 let y := mload(W2_Y_LOC)
1795 let xx := mulmod(x, x, q)
1796 // validate on curve
1797 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1798 mstore(0x00, x)
1799 mstore(0x20, y)
1800 }
1801 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p))
1802 // accumulator_2 = v1.(u + 1).[W2]
1803 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1804 // accumulator = accumulator + accumulator_2
1805 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1806
1807 // VALIDATE W3
1808 {
1809 let x := mload(W3_X_LOC)
1810 let y := mload(W3_Y_LOC)
1811 let xx := mulmod(x, x, q)
1812 // validate on curve
1813 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1814 mstore(0x00, x)
1815 mstore(0x20, y)
1816 }
1817 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p))
1818 // accumulator_2 = v2.(u + 1).[W3]
1819 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1820 // accumulator = accumulator + accumulator_2
1821 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1822
1823 // VALIDATE W4
1824 {
1825 let x := mload(W4_X_LOC)
1826 let y := mload(W4_Y_LOC)
1827 let xx := mulmod(x, x, q)
1828 // validate on curve
1829 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1830 mstore(0x00, x)
1831 mstore(0x20, y)
1832 }
1833 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p))
1834 // accumulator_2 = v3.(u + 1).[W4]
1835 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1836 // accumulator = accumulator + accumulator_2
1837 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1838
1839 // VALIDATE S
1840 {
1841 let x := mload(S_X_LOC)
1842 let y := mload(S_Y_LOC)
1843 let xx := mulmod(x, x, q)
1844 // validate on curve
1845 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1846 mstore(0x00, x)
1847 mstore(0x20, y)
1848 }
1849 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p))
1850 // accumulator_2 = v4.(u + 1).[S]
1851 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1852 // accumulator = accumulator + accumulator_2
1853 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1854
1855 // VALIDATE Z
1856 {
1857 let x := mload(Z_X_LOC)
1858 let y := mload(Z_Y_LOC)
1859 let xx := mulmod(x, x, q)
1860 // validate on curve
1861 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1862 mstore(0x00, x)
1863 mstore(0x20, y)
1864 }
1865 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p))
1866 // accumulator_2 = v5.(u + 1).[Z]
1867 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1868 // accumulator = accumulator + accumulator_2
1869 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1870
1871 // VALIDATE Z_LOOKUP
1872 {
1873 let x := mload(Z_LOOKUP_X_LOC)
1874 let y := mload(Z_LOOKUP_Y_LOC)
1875 let xx := mulmod(x, x, q)
1876 // validate on curve
1877 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1878 mstore(0x00, x)
1879 mstore(0x20, y)
1880 }
1881 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p))
1882 // accumulator_2 = v6.(u + 1).[Z_LOOKUP]
1883 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1884 // accumulator = accumulator + accumulator_2
1885 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1886
1887 // VALIDATE Q1
1888 {
1889 let x := mload(Q1_X_LOC)
1890 let y := mload(Q1_Y_LOC)
1891 let xx := mulmod(x, x, q)
1892 // validate on curve
1893 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1894 mstore(0x00, x)
1895 mstore(0x20, y)
1896 }
1897 mstore(0x40, mload(C_V7_LOC))
1898 // accumulator_2 = v7.[Q1]
1899 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1900 // accumulator = accumulator + accumulator_2
1901 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1902
1903 // VALIDATE Q2
1904 {
1905 let x := mload(Q2_X_LOC)
1906 let y := mload(Q2_Y_LOC)
1907 let xx := mulmod(x, x, q)
1908 // validate on curve
1909 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1910 mstore(0x00, x)
1911 mstore(0x20, y)
1912 }
1913 mstore(0x40, mload(C_V8_LOC))
1914 // accumulator_2 = v8.[Q2]
1915 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1916 // accumulator = accumulator + accumulator_2
1917 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1918
1919 // VALIDATE Q3
1920 {
1921 let x := mload(Q3_X_LOC)
1922 let y := mload(Q3_Y_LOC)
1923 let xx := mulmod(x, x, q)
1924 // validate on curve
1925 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1926 mstore(0x00, x)
1927 mstore(0x20, y)
1928 }
1929 mstore(0x40, mload(C_V9_LOC))
1930 // accumulator_2 = v9.[Q3]
1931 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1932 // accumulator = accumulator + accumulator_2
1933 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1934
1935 // VALIDATE Q4
1936 {
1937 let x := mload(Q4_X_LOC)
1938 let y := mload(Q4_Y_LOC)
1939 let xx := mulmod(x, x, q)
1940 // validate on curve
1941 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1942 mstore(0x00, x)
1943 mstore(0x20, y)
1944 }
1945 mstore(0x40, mload(C_V10_LOC))
1946 // accumulator_2 = v10.[Q4]
1947 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1948 // accumulator = accumulator + accumulator_2
1949 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1950
1951 // VALIDATE QM
1952 {
1953 let x := mload(QM_X_LOC)
1954 let y := mload(QM_Y_LOC)
1955 let xx := mulmod(x, x, q)
1956 // validate on curve
1957 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1958 mstore(0x00, x)
1959 mstore(0x20, y)
1960 }
1961 mstore(0x40, mload(C_V11_LOC))
1962 // accumulator_2 = v11.[Q;]
1963 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1964 // accumulator = accumulator + accumulator_2
1965 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1966
1967 // VALIDATE QC
1968 {
1969 let x := mload(QC_X_LOC)
1970 let y := mload(QC_Y_LOC)
1971 let xx := mulmod(x, x, q)
1972 // validate on curve
1973 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1974 mstore(0x00, x)
1975 mstore(0x20, y)
1976 }
1977 mstore(0x40, mload(C_V12_LOC))
1978 // accumulator_2 = v12.[QC]
1979 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1980 // accumulator = accumulator + accumulator_2
1981 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1982
1983 // VALIDATE QARITH
1984 {
1985 let x := mload(QARITH_X_LOC)
1986 let y := mload(QARITH_Y_LOC)
1987 let xx := mulmod(x, x, q)
1988 // validate on curve
1989 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
1990 mstore(0x00, x)
1991 mstore(0x20, y)
1992 }
1993 mstore(0x40, mload(C_V13_LOC))
1994 // accumulator_2 = v13.[QARITH]
1995 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
1996 // accumulator = accumulator + accumulator_2
1997 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
1998
1999 // VALIDATE QSORT
2000 {
2001 let x := mload(QSORT_X_LOC)
2002 let y := mload(QSORT_Y_LOC)
2003 let xx := mulmod(x, x, q)
2004 // validate on curve
2005 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2006 mstore(0x00, x)
2007 mstore(0x20, y)
2008 }
2009 mstore(0x40, mload(C_V14_LOC))
2010 // accumulator_2 = v14.[QSORT]
2011 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2012 // accumulator = accumulator + accumulator_2
2013 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2014
2015 // VALIDATE QELLIPTIC
2016 {
2017 let x := mload(QELLIPTIC_X_LOC)
2018 let y := mload(QELLIPTIC_Y_LOC)
2019 let xx := mulmod(x, x, q)
2020 // validate on curve
2021 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2022 mstore(0x00, x)
2023 mstore(0x20, y)
2024 }
2025 mstore(0x40, mload(C_V15_LOC))
2026 // accumulator_2 = v15.[QELLIPTIC]
2027 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2028 // accumulator = accumulator + accumulator_2
2029 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2030
2031 // VALIDATE QAUX
2032 {
2033 let x := mload(QAUX_X_LOC)
2034 let y := mload(QAUX_Y_LOC)
2035 let xx := mulmod(x, x, q)
2036 // validate on curve
2037 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2038 mstore(0x00, x)
2039 mstore(0x20, y)
2040 }
2041 mstore(0x40, mload(C_V16_LOC))
2042 // accumulator_2 = v15.[Q_AUX]
2043 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2044 // accumulator = accumulator + accumulator_2
2045 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2046
2047 // VALIDATE SIGMA1
2048 {
2049 let x := mload(SIGMA1_X_LOC)
2050 let y := mload(SIGMA1_Y_LOC)
2051 let xx := mulmod(x, x, q)
2052 // validate on curve
2053 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2054 mstore(0x00, x)
2055 mstore(0x20, y)
2056 }
2057 mstore(0x40, mload(C_V17_LOC))
2058 // accumulator_2 = v17.[sigma1]
2059 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2060 // accumulator = accumulator + accumulator_2
2061 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2062
2063 // VALIDATE SIGMA2
2064 {
2065 let x := mload(SIGMA2_X_LOC)
2066 let y := mload(SIGMA2_Y_LOC)
2067 let xx := mulmod(x, x, q)
2068 // validate on curve
2069 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2070 mstore(0x00, x)
2071 mstore(0x20, y)
2072 }
2073 mstore(0x40, mload(C_V18_LOC))
2074 // accumulator_2 = v18.[sigma2]
2075 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2076 // accumulator = accumulator + accumulator_2
2077 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2078
2079 // VALIDATE SIGMA3
2080 {
2081 let x := mload(SIGMA3_X_LOC)
2082 let y := mload(SIGMA3_Y_LOC)
2083 let xx := mulmod(x, x, q)
2084 // validate on curve
2085 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2086 mstore(0x00, x)
2087 mstore(0x20, y)
2088 }
2089 mstore(0x40, mload(C_V19_LOC))
2090 // accumulator_2 = v19.[sigma3]
2091 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2092 // accumulator = accumulator + accumulator_2
2093 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2094
2095 // VALIDATE SIGMA4
2096 {
2097 let x := mload(SIGMA4_X_LOC)
2098 let y := mload(SIGMA4_Y_LOC)
2099 let xx := mulmod(x, x, q)
2100 // validate on curve
2101 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2102 mstore(0x00, x)
2103 mstore(0x20, y)
2104 }
2105 mstore(0x40, mload(C_V20_LOC))
2106 // accumulator_2 = v20.[sigma4]
2107 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2108 // accumulator = accumulator + accumulator_2
2109 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2110
2111 // VALIDATE TABLE1
2112 {
2113 let x := mload(TABLE1_X_LOC)
2114 let y := mload(TABLE1_Y_LOC)
2115 let xx := mulmod(x, x, q)
2116 // validate on curve
2117 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2118 mstore(0x00, x)
2119 mstore(0x20, y)
2120 }
2121 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p))
2122 // accumulator_2 = u.[table1]
2123 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2124 // accumulator = accumulator + accumulator_2
2125 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2126
2127 // VALIDATE TABLE2
2128 {
2129 let x := mload(TABLE2_X_LOC)
2130 let y := mload(TABLE2_Y_LOC)
2131 let xx := mulmod(x, x, q)
2132 // validate on curve
2133 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2134 mstore(0x00, x)
2135 mstore(0x20, y)
2136 }
2137 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p))
2138 // accumulator_2 = u.[table2]
2139 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2140 // accumulator = accumulator + accumulator_2
2141 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2142
2143 // VALIDATE TABLE3
2144 {
2145 let x := mload(TABLE3_X_LOC)
2146 let y := mload(TABLE3_Y_LOC)
2147 let xx := mulmod(x, x, q)
2148 // validate on curve
2149 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2150 mstore(0x00, x)
2151 mstore(0x20, y)
2152 }
2153 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p))
2154 // accumulator_2 = u.[table3]
2155 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2156 // accumulator = accumulator + accumulator_2
2157 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2158
2159 // VALIDATE TABLE4
2160 {
2161 let x := mload(TABLE4_X_LOC)
2162 let y := mload(TABLE4_Y_LOC)
2163 let xx := mulmod(x, x, q)
2164 // validate on curve
2165 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2166 mstore(0x00, x)
2167 mstore(0x20, y)
2168 }
2169 mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p))
2170 // accumulator_2 = u.[table4]
2171 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2172 // accumulator = accumulator + accumulator_2
2173 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2174
2175 // VALIDATE TABLE_TYPE
2176 {
2177 let x := mload(TABLE_TYPE_X_LOC)
2178 let y := mload(TABLE_TYPE_Y_LOC)
2179 let xx := mulmod(x, x, q)
2180 // validate on curve
2181 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2182 mstore(0x00, x)
2183 mstore(0x20, y)
2184 }
2185 mstore(0x40, mload(C_V25_LOC))
2186 // accumulator_2 = v25.[TableType]
2187 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2188 // accumulator = accumulator + accumulator_2
2189 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2190
2191 // VALIDATE ID1
2192 {
2193 let x := mload(ID1_X_LOC)
2194 let y := mload(ID1_Y_LOC)
2195 let xx := mulmod(x, x, q)
2196 // validate on curve
2197 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2198 mstore(0x00, x)
2199 mstore(0x20, y)
2200 }
2201 mstore(0x40, mload(C_V26_LOC))
2202 // accumulator_2 = v26.[ID1]
2203 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2204 // accumulator = accumulator + accumulator_2
2205 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2206
2207 // VALIDATE ID2
2208 {
2209 let x := mload(ID2_X_LOC)
2210 let y := mload(ID2_Y_LOC)
2211 let xx := mulmod(x, x, q)
2212 // validate on curve
2213 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2214 mstore(0x00, x)
2215 mstore(0x20, y)
2216 }
2217 mstore(0x40, mload(C_V27_LOC))
2218 // accumulator_2 = v27.[ID2]
2219 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2220 // accumulator = accumulator + accumulator_2
2221 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2222
2223 // VALIDATE ID3
2224 {
2225 let x := mload(ID3_X_LOC)
2226 let y := mload(ID3_Y_LOC)
2227 let xx := mulmod(x, x, q)
2228 // validate on curve
2229 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2230 mstore(0x00, x)
2231 mstore(0x20, y)
2232 }
2233 mstore(0x40, mload(C_V28_LOC))
2234 // accumulator_2 = v28.[ID3]
2235 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2236 // accumulator = accumulator + accumulator_2
2237 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2238
2239 // VALIDATE ID4
2240 {
2241 let x := mload(ID4_X_LOC)
2242 let y := mload(ID4_Y_LOC)
2243 let xx := mulmod(x, x, q)
2244 // validate on curve
2245 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2246 mstore(0x00, x)
2247 mstore(0x20, y)
2248 }
2249 mstore(0x40, mload(C_V29_LOC))
2250 // accumulator_2 = v29.[ID4]
2251 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2252 // accumulator = accumulator + accumulator_2
2253 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2254
2258 {
2268 let batch_evaluation :=
2269 mulmod(
2270 mload(C_V0_LOC),
2271 addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p),
2272 p
2273 )
2274 batch_evaluation :=
2275 addmod(
2276 batch_evaluation,
2277 mulmod(
2278 mload(C_V1_LOC),
2279 addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p),
2280 p
2281 ),
2282 p
2283 )
2284 batch_evaluation :=
2285 addmod(
2286 batch_evaluation,
2287 mulmod(
2288 mload(C_V2_LOC),
2289 addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p),
2290 p
2291 ),
2292 p
2293 )
2294 batch_evaluation :=
2295 addmod(
2296 batch_evaluation,
2297 mulmod(
2298 mload(C_V3_LOC),
2299 addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p),
2300 p
2301 ),
2302 p
2303 )
2304 batch_evaluation :=
2305 addmod(
2306 batch_evaluation,
2307 mulmod(
2308 mload(C_V4_LOC),
2309 addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p),
2310 p
2311 ),
2312 p
2313 )
2314 batch_evaluation :=
2315 addmod(
2316 batch_evaluation,
2317 mulmod(
2318 mload(C_V5_LOC),
2319 addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p),
2320 p
2321 ),
2322 p
2323 )
2324 batch_evaluation :=
2325 addmod(
2326 batch_evaluation,
2327 mulmod(
2328 mload(C_V6_LOC),
2329 addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p),
2330 p
2331 ),
2332 p
2333 )
2334
2351 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p)
2352 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p)
2353 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p)
2354 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p)
2355 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p)
2356 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p)
2357 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p)
2358 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p)
2359 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p)
2360 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p)
2361 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p)
2362 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p)
2363 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p)
2364 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p)
2365
2378 batch_evaluation :=
2379 addmod(
2380 batch_evaluation,
2381 mulmod(
2382 mload(C_V21_LOC),
2383 addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p),
2384 p
2385 ),
2386 p
2387 )
2388 batch_evaluation :=
2389 addmod(
2390 batch_evaluation,
2391 mulmod(
2392 mload(C_V22_LOC),
2393 addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p),
2394 p
2395 ),
2396 p
2397 )
2398 batch_evaluation :=
2399 addmod(
2400 batch_evaluation,
2401 mulmod(
2402 mload(C_V23_LOC),
2403 addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p),
2404 p
2405 ),
2406 p
2407 )
2408 batch_evaluation :=
2409 addmod(
2410 batch_evaluation,
2411 mulmod(
2412 mload(C_V24_LOC),
2413 addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p),
2414 p
2415 ),
2416 p
2417 )
2418 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p)
2419 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p)
2420 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p)
2421 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p)
2422 batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p)
2423 batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p)
2424
2425 mstore(0x00, 0x01) // [1].x
2426 mstore(0x20, 0x02) // [1].y
2427 mstore(0x40, sub(p, batch_evaluation))
2428 // accumulator_2 = -[1].(batch_evaluation)
2429 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2430 // accumulator = accumulator + accumulator_2
2431 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2432
2433 mstore(OPENING_COMMITMENT_SUCCESS_FLAG, success)
2434 }
2435
2439 {
2440 let u := mload(C_U_LOC)
2441 let zeta := mload(C_ZETA_LOC)
2442 // VALIDATE PI_Z
2443 {
2444 let x := mload(PI_Z_X_LOC)
2445 let y := mload(PI_Z_Y_LOC)
2446 let xx := mulmod(x, x, q)
2447 // validate on curve
2448 success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))
2449 mstore(0x00, x)
2450 mstore(0x20, y)
2451 }
2452 // compute zeta.[PI_Z] and add into accumulator
2453 mstore(0x40, zeta)
2454 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2455 // accumulator = accumulator + accumulator_2
2456 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
2457
2458 // VALIDATE PI_Z_OMEGA
2459 {
2460 let x := mload(PI_Z_OMEGA_X_LOC)
2461 let y := mload(PI_Z_OMEGA_Y_LOC)
2462 let xx := mulmod(x, x, q)
2463 // validate on curve
2464 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2465 mstore(0x00, x)
2466 mstore(0x20, y)
2467 }
2468 mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p))
2469 // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA]
2470 success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
2471 // PAIRING_RHS = accumulator + accumulator_2
2472 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40))
2473
2474 mstore(0x00, mload(PI_Z_X_LOC))
2475 mstore(0x20, mload(PI_Z_Y_LOC))
2476 mstore(0x40, mload(PI_Z_OMEGA_X_LOC))
2477 mstore(0x60, mload(PI_Z_OMEGA_Y_LOC))
2478 mstore(0x80, u)
2479 success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40))
2480 // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u
2481 success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40))
2482 // negate lhs y-coordinate
2483 mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC)))
2484
2485 if mload(CONTAINS_RECURSIVE_PROOF_LOC) {
2486 // VALIDATE RECURSIVE P1
2487 {
2488 let x := mload(RECURSIVE_P1_X_LOC)
2489 let y := mload(RECURSIVE_P1_Y_LOC)
2490 let xx := mulmod(x, x, q)
2491 // validate on curve
2492 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2493 mstore(0x00, x)
2494 mstore(0x20, y)
2495 }
2496
2497 // compute u.u.[recursive_p1] and write into 0x60
2498 mstore(0x40, mulmod(u, u, p))
2499 success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40))
2500 // VALIDATE RECURSIVE P2
2501 {
2502 let x := mload(RECURSIVE_P2_X_LOC)
2503 let y := mload(RECURSIVE_P2_Y_LOC)
2504 let xx := mulmod(x, x, q)
2505 // validate on curve
2506 success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
2507 mstore(0x00, x)
2508 mstore(0x20, y)
2509 }
2510 // compute u.u.[recursive_p2] and write into 0x00
2511 // 0x40 still contains u*u
2512 success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40))
2513
2514 // compute u.u.[recursiveP1] + rhs and write into rhs
2515 mstore(0xa0, mload(PAIRING_RHS_X_LOC))
2516 mstore(0xc0, mload(PAIRING_RHS_Y_LOC))
2517 success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40))
2518
2519 // compute u.u.[recursiveP2] + lhs and write into lhs
2520 mstore(0x40, mload(PAIRING_LHS_X_LOC))
2521 mstore(0x60, mload(PAIRING_LHS_Y_LOC))
2522 success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40))
2523 }
2524
2525 if iszero(success) {
2526 mstore(0x0, EC_SCALAR_MUL_FAILURE_SELECTOR)
2527 revert(0x00, 0x04)
2528 }
2529 mstore(PAIRING_PREAMBLE_SUCCESS_FLAG, success)
2530 }
2531
2535 {
2536 // rhs paired with [1]_2
2537 // lhs paired with [x]_2
2538
2539 mstore(0x00, mload(PAIRING_RHS_X_LOC))
2540 mstore(0x20, mload(PAIRING_RHS_Y_LOC))
2541 mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2
2542 mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed)
2543 mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b)
2544 mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa)
2545
2546 mstore(0xc0, mload(PAIRING_LHS_X_LOC))
2547 mstore(0xe0, mload(PAIRING_LHS_Y_LOC))
2548 mstore(0x100, mload(G2X_X0_LOC))
2549 mstore(0x120, mload(G2X_X1_LOC))
2550 mstore(0x140, mload(G2X_Y0_LOC))
2551 mstore(0x160, mload(G2X_Y1_LOC))
2552
2553 success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20)
2554 mstore(PAIRING_SUCCESS_FLAG, success)
2555 mstore(RESULT_FLAG, mload(0x00))
2556 }
2557 if iszero(
2558 and(
2559 and(and(mload(PAIRING_SUCCESS_FLAG), mload(RESULT_FLAG)), mload(PAIRING_PREAMBLE_SUCCESS_FLAG)),
2560 mload(OPENING_COMMITMENT_SUCCESS_FLAG)
2561 )
2562 ) {
2563 mstore(0x0, PROOF_FAILURE_SELECTOR)
2564 revert(0x00, 0x04)
2565 }
2566 {
2567 mstore(0x00, 0x01)
2568 return(0x00, 0x20) // Proof succeeded!
2569 }
2570 }
2571 }
2572}
2573
2574contract UltraVerifier is BaseUltraVerifier {
2575 function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) {
2576 return UltraVerificationKey.verificationKeyHash();
2577 }
2578
2579 function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) {
2580 UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc);
2581 }
2582}
2583)";