Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
relation_correctness.test.cpp
Go to the documentation of this file.
6
7#include <gtest/gtest.h>
8#include <unordered_set>
9using namespace bb;
10
11class TranslatorRelationCorrectnessTests : public ::testing::Test {
12 protected:
14};
15
21TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness)
22{
24 using FF = typename Flavor::FF;
26
28
29 // We only use accumulated_result from relation parameters in this relation
31 params.accumulated_result = {
33 };
34
35 // Create storage for polynomials
36 ProverPolynomials prover_polynomials;
37 constexpr size_t mini_circuit_size_without_masking = TranslatorProvingKey::dyadic_mini_circuit_size_without_masking;
38 // Fill in lagrange even polynomial
39 for (size_t i = prover_polynomials.lagrange_even_in_minicircuit.start_index();
40 i < prover_polynomials.lagrange_even_in_minicircuit.end_index();
41 i += 2) {
42 prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1;
43 prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1;
44 }
45 constexpr size_t NUMBER_OF_POSSIBLE_OPCODES = 3;
46 constexpr std::array<uint64_t, NUMBER_OF_POSSIBLE_OPCODES> possible_opcode_values = { 3, 4, 8 };
47
48 // Assign random opcode values
49 for (size_t i = Flavor::RESULT_ROW; i < mini_circuit_size_without_masking; i += 2) {
50 prover_polynomials.op.at(i) =
51 possible_opcode_values[static_cast<size_t>(engine.get_random_uint8() % NUMBER_OF_POSSIBLE_OPCODES)];
52 }
53
54 // Initialize used lagrange polynomials
55 prover_polynomials.lagrange_result_row.at(Flavor::RESULT_ROW) = 1;
56 prover_polynomials.lagrange_last_in_minicircuit.at(mini_circuit_size_without_masking - 1) = 1;
57
58 // Put random values in accumulator binary limbs (values should be preserved across even->next odd shift)
59 for (size_t i = Flavor::RESULT_ROW + 1; i < mini_circuit_size_without_masking - 1; i += 2) {
60 prover_polynomials.accumulators_binary_limbs_0.at(i) = FF ::random_element();
61 prover_polynomials.accumulators_binary_limbs_1.at(i) = FF ::random_element();
62 prover_polynomials.accumulators_binary_limbs_2.at(i) = FF ::random_element();
63 prover_polynomials.accumulators_binary_limbs_3.at(i) = FF ::random_element();
64 prover_polynomials.accumulators_binary_limbs_0.at(i + 1) = prover_polynomials.accumulators_binary_limbs_0[i];
65 prover_polynomials.accumulators_binary_limbs_2.at(i + 1) = prover_polynomials.accumulators_binary_limbs_2[i];
66 prover_polynomials.accumulators_binary_limbs_1.at(i + 1) = prover_polynomials.accumulators_binary_limbs_1[i];
67 prover_polynomials.accumulators_binary_limbs_3.at(i + 1) = prover_polynomials.accumulators_binary_limbs_3[i];
68 }
69
70 // The values of accumulator binary limbs at index 1 should equal the accumulated result from relation parameters
71 prover_polynomials.accumulators_binary_limbs_0.at(Flavor::RESULT_ROW) = params.accumulated_result[0];
72 prover_polynomials.accumulators_binary_limbs_1.at(Flavor::RESULT_ROW) = params.accumulated_result[1];
73 prover_polynomials.accumulators_binary_limbs_2.at(Flavor::RESULT_ROW) = params.accumulated_result[2];
74 prover_polynomials.accumulators_binary_limbs_3.at(Flavor::RESULT_ROW) = params.accumulated_result[3];
75
76 // Check that Opcode Constraint relation is satisfied across each row of the prover polynomials
78 prover_polynomials, params, "TranslatorOpcodeConstraintRelation");
79 EXPECT_TRUE(translator_op_code_failures.empty());
80 // Check that Accumulator Transfer relation is satisfied across each row of the prover polynomials
81 auto translator_accumulator_transfer_failures =
83 prover_polynomials, params, "TranslatorAccumulatorTransferRelation");
84 EXPECT_TRUE(translator_accumulator_transfer_failures.empty());
85 // Check that Zero Constraint relation is satisfied across each row of the prover polynomials
86 auto translator_zero_constraints_failures = RelationChecker<Flavor>::check<TranslatorZeroConstraintsRelation<FF>>(
87 prover_polynomials, params, "TranslatorZeroConstraintsRelation");
88 EXPECT_TRUE(translator_zero_constraints_failures.empty());
89}
95{
97 using FF = typename Flavor::FF;
98 using BF = typename Flavor::BF;
101
102 constexpr size_t mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE;
103
104 // Decomposition relation doesn't use any relation parameters
106
107 // Create storage for polynomials
108 ProverPolynomials prover_polynomials;
109
110 auto lagrange_odd_in_minicircuit = prover_polynomials.lagrange_odd_in_minicircuit;
111 // Fill in lagrange odd polynomial (the only non-witness one we are using)
112 for (size_t i = prover_polynomials.lagrange_odd_in_minicircuit.start_index();
113 i < lagrange_odd_in_minicircuit.end_index();
114 i += 2) {
115 prover_polynomials.lagrange_odd_in_minicircuit.at(i) = 1;
116 }
117
118 constexpr size_t NUM_LIMB_BITS = Flavor::CircuitBuilder::NUM_LIMB_BITS;
119 constexpr size_t HIGH_WIDE_LIMB_WIDTH =
120 Flavor::CircuitBuilder::NUM_LIMB_BITS + Flavor::CircuitBuilder::NUM_LAST_LIMB_BITS;
121 constexpr size_t LOW_WIDE_LIMB_WIDTH = Flavor::CircuitBuilder::NUM_LIMB_BITS * 2;
122 constexpr size_t Z_LIMB_WIDTH = 128;
123 constexpr size_t MICRO_LIMB_WIDTH = Flavor::MICRO_LIMB_BITS;
124 constexpr size_t SHIFT_12_TO_14 = 4;
125 constexpr size_t SHIFT_10_TO_14 = 16;
126 constexpr size_t SHIFT_8_TO_14 = 64;
127 constexpr size_t SHIFT_4_TO_14 = 1024;
128
134 auto decompose_standard_limb =
135 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& limb_4, auto& shifted_limb) {
136 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
137 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
138 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
139 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
140 limb_4 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 4, MICRO_LIMB_WIDTH * 5);
141 shifted_limb = limb_4 * SHIFT_12_TO_14;
142 };
143
149 auto decompose_standard_top_limb =
150 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& shifted_limb) {
151 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
152 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
153 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
154 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
155 shifted_limb = limb_3 * SHIFT_8_TO_14;
156 };
157
163 auto decompose_standard_top_z_limb =
164 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& limb_4, auto& shifted_limb) {
165 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
166 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
167 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
168 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
169 limb_4 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 4, MICRO_LIMB_WIDTH * 5);
170 shifted_limb = limb_4 * SHIFT_4_TO_14;
171 };
172
178 auto decompose_top_quotient_limb =
179 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& shifted_limb) {
180 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
181 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
182 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
183 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
184 shifted_limb = limb_3 * SHIFT_10_TO_14;
185 };
186
191 auto decompose_relation_limb =
192 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& limb_4, auto& limb_5) {
193 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
194 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
195 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
196 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
197 limb_4 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 4, MICRO_LIMB_WIDTH * 5);
198 limb_5 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 5, MICRO_LIMB_WIDTH * 6);
199 };
200
201 // Put random values in all the non-interleaved constraint polynomials used to range constrain the values
202 for (size_t i = 1; i < mini_circuit_size - 1; i += 2) {
203 // P.x
204 prover_polynomials.x_lo_y_hi.at(i) =
205 FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1));
206 prover_polynomials.x_hi_z_1.at(i) =
207 FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1));
208
209 // P.y
210 prover_polynomials.y_lo_z_2.at(i) =
211 FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1));
212 prover_polynomials.x_lo_y_hi.at(i + 1) =
213 FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1));
214
215 // z1 and z2
216 prover_polynomials.x_hi_z_1.at(i + 1) = FF(engine.get_random_uint256() & ((uint256_t(1) << Z_LIMB_WIDTH) - 1));
217 prover_polynomials.y_lo_z_2.at(i + 1) = FF(engine.get_random_uint256() & ((uint256_t(1) << Z_LIMB_WIDTH) - 1));
218
219 // Slice P.x into chunks
220 prover_polynomials.p_x_low_limbs.at(i) = uint256_t(prover_polynomials.x_lo_y_hi.at(i)).slice(0, NUM_LIMB_BITS);
221 prover_polynomials.p_x_low_limbs.at(i + 1) =
222 uint256_t(prover_polynomials.x_lo_y_hi.at(i)).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
223 prover_polynomials.p_x_high_limbs.at(i) = uint256_t(prover_polynomials.x_hi_z_1[i]).slice(0, NUM_LIMB_BITS);
224 prover_polynomials.p_x_high_limbs.at(i + 1) =
225 uint256_t(prover_polynomials.x_hi_z_1.at(i)).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
226
227 // Slice P.y into chunks
228 prover_polynomials.p_y_low_limbs.at(i) = uint256_t(prover_polynomials.y_lo_z_2[i]).slice(0, NUM_LIMB_BITS);
229 prover_polynomials.p_y_low_limbs.at(i + 1) =
230 uint256_t(prover_polynomials.y_lo_z_2[i]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
231 prover_polynomials.p_y_high_limbs.at(i) =
232 uint256_t(prover_polynomials.x_lo_y_hi[i + 1]).slice(0, NUM_LIMB_BITS);
233 prover_polynomials.p_y_high_limbs.at(i + 1) =
234 uint256_t(prover_polynomials.x_lo_y_hi[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
235
236 // Slice z1 and z2 into chunks
237 prover_polynomials.z_low_limbs.at(i) = uint256_t(prover_polynomials.x_hi_z_1[i + 1]).slice(0, NUM_LIMB_BITS);
238 prover_polynomials.z_low_limbs.at(i + 1) =
239 uint256_t(prover_polynomials.y_lo_z_2[i + 1]).slice(0, NUM_LIMB_BITS);
240 prover_polynomials.z_high_limbs.at(i) =
241 uint256_t(prover_polynomials.x_hi_z_1[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
242 prover_polynomials.z_high_limbs.at(i + 1) =
243 uint256_t(prover_polynomials.y_lo_z_2[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
244
245 // Slice accumulator
246 auto tmp = uint256_t(BF::random_element(&engine));
247 prover_polynomials.accumulators_binary_limbs_0.at(i) = tmp.slice(0, NUM_LIMB_BITS);
248 prover_polynomials.accumulators_binary_limbs_1.at(i) = tmp.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2);
249 prover_polynomials.accumulators_binary_limbs_2.at(i) = tmp.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3);
250 prover_polynomials.accumulators_binary_limbs_3.at(i) = tmp.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4);
251
252 // Slice low limbs of P.x into range constraint microlimbs
253 decompose_standard_limb(prover_polynomials.p_x_low_limbs.at(i),
254 prover_polynomials.p_x_low_limbs_range_constraint_0.at(i),
255 prover_polynomials.p_x_low_limbs_range_constraint_1.at(i),
256 prover_polynomials.p_x_low_limbs_range_constraint_2.at(i),
257 prover_polynomials.p_x_low_limbs_range_constraint_3.at(i),
258 prover_polynomials.p_x_low_limbs_range_constraint_4.at(i),
259 prover_polynomials.p_x_low_limbs_range_constraint_tail.at(i));
260
261 decompose_standard_limb(prover_polynomials.p_x_low_limbs.at(i + 1),
262 prover_polynomials.p_x_low_limbs_range_constraint_0.at(i + 1),
263 prover_polynomials.p_x_low_limbs_range_constraint_1.at(i + 1),
264 prover_polynomials.p_x_low_limbs_range_constraint_2.at(i + 1),
265 prover_polynomials.p_x_low_limbs_range_constraint_3.at(i + 1),
266 prover_polynomials.p_x_low_limbs_range_constraint_4.at(i + 1),
267 prover_polynomials.p_x_low_limbs_range_constraint_tail.at(i + 1));
268
269 // Slice high limbs of P.x into range constraint microlimbs
270 decompose_standard_limb(prover_polynomials.p_x_high_limbs.at(i),
271 prover_polynomials.p_x_high_limbs_range_constraint_0.at(i),
272 prover_polynomials.p_x_high_limbs_range_constraint_1.at(i),
273 prover_polynomials.p_x_high_limbs_range_constraint_2.at(i),
274 prover_polynomials.p_x_high_limbs_range_constraint_3.at(i),
275 prover_polynomials.p_x_high_limbs_range_constraint_4.at(i),
276 prover_polynomials.p_x_high_limbs_range_constraint_tail.at(i));
277
278 decompose_standard_top_limb(prover_polynomials.p_x_high_limbs.at(i + 1),
279 prover_polynomials.p_x_high_limbs_range_constraint_0.at(i + 1),
280 prover_polynomials.p_x_high_limbs_range_constraint_1.at(i + 1),
281 prover_polynomials.p_x_high_limbs_range_constraint_2.at(i + 1),
282 prover_polynomials.p_x_high_limbs_range_constraint_3.at(i + 1),
283 prover_polynomials.p_x_high_limbs_range_constraint_4.at(i + 1));
284
285 // Slice low limbs of P.y into range constraint microlimbs
286 decompose_standard_limb(prover_polynomials.p_y_low_limbs.at(i),
287 prover_polynomials.p_y_low_limbs_range_constraint_0.at(i),
288 prover_polynomials.p_y_low_limbs_range_constraint_1.at(i),
289 prover_polynomials.p_y_low_limbs_range_constraint_2.at(i),
290 prover_polynomials.p_y_low_limbs_range_constraint_3.at(i),
291 prover_polynomials.p_y_low_limbs_range_constraint_4.at(i),
292 prover_polynomials.p_y_low_limbs_range_constraint_tail.at(i));
293
294 decompose_standard_limb(prover_polynomials.p_y_low_limbs.at(i + 1),
295 prover_polynomials.p_y_low_limbs_range_constraint_0.at(i + 1),
296 prover_polynomials.p_y_low_limbs_range_constraint_1.at(i + 1),
297 prover_polynomials.p_y_low_limbs_range_constraint_2.at(i + 1),
298 prover_polynomials.p_y_low_limbs_range_constraint_3.at(i + 1),
299 prover_polynomials.p_y_low_limbs_range_constraint_4.at(i + 1),
300 prover_polynomials.p_y_low_limbs_range_constraint_tail.at(i + 1));
301
302 // Slice high limbs of P.y into range constraint microlimbs
303 decompose_standard_limb(prover_polynomials.p_y_high_limbs.at(i),
304 prover_polynomials.p_y_high_limbs_range_constraint_0.at(i),
305 prover_polynomials.p_y_high_limbs_range_constraint_1.at(i),
306 prover_polynomials.p_y_high_limbs_range_constraint_2.at(i),
307 prover_polynomials.p_y_high_limbs_range_constraint_3.at(i),
308 prover_polynomials.p_y_high_limbs_range_constraint_4.at(i),
309 prover_polynomials.p_y_high_limbs_range_constraint_tail.at(i));
310
311 decompose_standard_top_limb(prover_polynomials.p_y_high_limbs.at(i + 1),
312 prover_polynomials.p_y_high_limbs_range_constraint_0.at(i + 1),
313 prover_polynomials.p_y_high_limbs_range_constraint_1.at(i + 1),
314 prover_polynomials.p_y_high_limbs_range_constraint_2.at(i + 1),
315 prover_polynomials.p_y_high_limbs_range_constraint_3.at(i + 1),
316 prover_polynomials.p_y_high_limbs_range_constraint_4.at(i + 1));
317
318 // Slice low limb of of z1 and z2 into range constraints
319 decompose_standard_limb(prover_polynomials.z_low_limbs.at(i),
320 prover_polynomials.z_low_limbs_range_constraint_0.at(i),
321 prover_polynomials.z_low_limbs_range_constraint_1.at(i),
322 prover_polynomials.z_low_limbs_range_constraint_2.at(i),
323 prover_polynomials.z_low_limbs_range_constraint_3.at(i),
324 prover_polynomials.z_low_limbs_range_constraint_4.at(i),
325 prover_polynomials.z_low_limbs_range_constraint_tail.at(i));
326
327 decompose_standard_limb(prover_polynomials.z_low_limbs.at(i + 1),
328 prover_polynomials.z_low_limbs_range_constraint_0.at(i + 1),
329 prover_polynomials.z_low_limbs_range_constraint_1.at(i + 1),
330 prover_polynomials.z_low_limbs_range_constraint_2.at(i + 1),
331 prover_polynomials.z_low_limbs_range_constraint_3.at(i + 1),
332 prover_polynomials.z_low_limbs_range_constraint_4.at(i + 1),
333 prover_polynomials.z_low_limbs_range_constraint_tail.at(i + 1));
334
335 // Slice high limb of of z1 and z2 into range constraints
336 decompose_standard_top_z_limb(prover_polynomials.z_high_limbs.at(i),
337 prover_polynomials.z_high_limbs_range_constraint_0.at(i),
338 prover_polynomials.z_high_limbs_range_constraint_1.at(i),
339 prover_polynomials.z_high_limbs_range_constraint_2.at(i),
340 prover_polynomials.z_high_limbs_range_constraint_3.at(i),
341 prover_polynomials.z_high_limbs_range_constraint_4.at(i),
342 prover_polynomials.z_high_limbs_range_constraint_tail.at(i));
343
344 decompose_standard_top_z_limb(prover_polynomials.z_high_limbs.at(i + 1),
345 prover_polynomials.z_high_limbs_range_constraint_0.at(i + 1),
346 prover_polynomials.z_high_limbs_range_constraint_1.at(i + 1),
347 prover_polynomials.z_high_limbs_range_constraint_2.at(i + 1),
348 prover_polynomials.z_high_limbs_range_constraint_3.at(i + 1),
349 prover_polynomials.z_high_limbs_range_constraint_4.at(i + 1),
350 prover_polynomials.z_high_limbs_range_constraint_tail.at(i + 1));
351
352 // Slice accumulator limbs into range constraints
353 decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_0.at(i),
354 prover_polynomials.accumulator_low_limbs_range_constraint_0.at(i),
355 prover_polynomials.accumulator_low_limbs_range_constraint_1.at(i),
356 prover_polynomials.accumulator_low_limbs_range_constraint_2.at(i),
357 prover_polynomials.accumulator_low_limbs_range_constraint_3.at(i),
358 prover_polynomials.accumulator_low_limbs_range_constraint_4.at(i),
359 prover_polynomials.accumulator_low_limbs_range_constraint_tail.at(i));
360 decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_1.at(i),
361 prover_polynomials.accumulator_low_limbs_range_constraint_0.at(i + 1),
362 prover_polynomials.accumulator_low_limbs_range_constraint_1.at(i + 1),
363 prover_polynomials.accumulator_low_limbs_range_constraint_2.at(i + 1),
364 prover_polynomials.accumulator_low_limbs_range_constraint_3.at(i + 1),
365 prover_polynomials.accumulator_low_limbs_range_constraint_4.at(i + 1),
366 prover_polynomials.accumulator_low_limbs_range_constraint_tail.at(i + 1));
367
368 decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_2.at(i),
369 prover_polynomials.accumulator_high_limbs_range_constraint_0.at(i),
370 prover_polynomials.accumulator_high_limbs_range_constraint_1.at(i),
371 prover_polynomials.accumulator_high_limbs_range_constraint_2.at(i),
372 prover_polynomials.accumulator_high_limbs_range_constraint_3.at(i),
373 prover_polynomials.accumulator_high_limbs_range_constraint_4.at(i),
374 prover_polynomials.accumulator_high_limbs_range_constraint_tail.at(i));
375 decompose_standard_top_limb(prover_polynomials.accumulators_binary_limbs_3.at(i),
376 prover_polynomials.accumulator_high_limbs_range_constraint_0.at(i + 1),
377 prover_polynomials.accumulator_high_limbs_range_constraint_1.at(i + 1),
378 prover_polynomials.accumulator_high_limbs_range_constraint_2.at(i + 1),
379 prover_polynomials.accumulator_high_limbs_range_constraint_3.at(i + 1),
380 prover_polynomials.accumulator_high_limbs_range_constraint_4.at(i + 1));
381
382 // Slice quotient limbs into range constraints
383 decompose_standard_limb(prover_polynomials.quotient_low_binary_limbs.at(i),
384 prover_polynomials.quotient_low_limbs_range_constraint_0.at(i),
385 prover_polynomials.quotient_low_limbs_range_constraint_1.at(i),
386 prover_polynomials.quotient_low_limbs_range_constraint_2.at(i),
387 prover_polynomials.quotient_low_limbs_range_constraint_3.at(i),
388 prover_polynomials.quotient_low_limbs_range_constraint_4.at(i),
389 prover_polynomials.quotient_low_limbs_range_constraint_tail.at(i));
390 decompose_standard_limb(prover_polynomials.quotient_low_binary_limbs_shift.at(i),
391 prover_polynomials.quotient_low_limbs_range_constraint_0.at(i + 1),
392 prover_polynomials.quotient_low_limbs_range_constraint_1.at(i + 1),
393 prover_polynomials.quotient_low_limbs_range_constraint_2.at(i + 1),
394 prover_polynomials.quotient_low_limbs_range_constraint_3.at(i + 1),
395 prover_polynomials.quotient_low_limbs_range_constraint_4.at(i + 1),
396 prover_polynomials.quotient_low_limbs_range_constraint_tail.at(i + 1));
397
398 decompose_standard_limb(prover_polynomials.quotient_high_binary_limbs.at(i),
399 prover_polynomials.quotient_high_limbs_range_constraint_0.at(i),
400 prover_polynomials.quotient_high_limbs_range_constraint_1.at(i),
401 prover_polynomials.quotient_high_limbs_range_constraint_2.at(i),
402 prover_polynomials.quotient_high_limbs_range_constraint_3.at(i),
403 prover_polynomials.quotient_high_limbs_range_constraint_4.at(i),
404 prover_polynomials.quotient_high_limbs_range_constraint_tail.at(i));
405
406 decompose_top_quotient_limb(prover_polynomials.quotient_high_binary_limbs_shift.at(i),
407 prover_polynomials.quotient_high_limbs_range_constraint_0.at(i + 1),
408 prover_polynomials.quotient_high_limbs_range_constraint_1.at(i + 1),
409 prover_polynomials.quotient_high_limbs_range_constraint_2.at(i + 1),
410 prover_polynomials.quotient_high_limbs_range_constraint_3.at(i + 1),
411 prover_polynomials.quotient_high_limbs_range_constraint_4.at(i + 1));
412
413 // Decompose wide relation limbs into range constraints
414 decompose_relation_limb(prover_polynomials.relation_wide_limbs.at(i),
415 prover_polynomials.relation_wide_limbs_range_constraint_0.at(i),
416 prover_polynomials.relation_wide_limbs_range_constraint_1.at(i),
417 prover_polynomials.relation_wide_limbs_range_constraint_2.at(i),
418 prover_polynomials.relation_wide_limbs_range_constraint_3.at(i),
419 prover_polynomials.p_x_high_limbs_range_constraint_tail.at(i + 1),
420 prover_polynomials.accumulator_high_limbs_range_constraint_tail.at(i + 1));
421
422 decompose_relation_limb(prover_polynomials.relation_wide_limbs.at(i + 1),
423 prover_polynomials.relation_wide_limbs_range_constraint_0.at(i + 1),
424 prover_polynomials.relation_wide_limbs_range_constraint_1.at(i + 1),
425 prover_polynomials.relation_wide_limbs_range_constraint_2.at(i + 1),
426 prover_polynomials.relation_wide_limbs_range_constraint_3.at(i + 1),
427 prover_polynomials.p_y_high_limbs_range_constraint_tail.at(i + 1),
428 prover_polynomials.quotient_high_limbs_range_constraint_tail.at(i + 1));
429 }
430
431 // Check that Decomposition relation is satisfied across each row of the prover polynomials
433 prover_polynomials, params, "TranslatorDecompositionRelation");
434}
435
441{
442 using Flavor = TranslatorFlavor;
444 using FF = typename Flavor::FF;
445 using BF = typename Flavor::BF;
447 using GroupElement = typename Flavor::GroupElement;
448
449 constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS;
450 constexpr size_t mini_circuit_size = TranslatorFlavor::MINI_CIRCUIT_SIZE;
451 constexpr size_t mini_circuit_size_without_masking =
453
455
456 auto op_queue = std::make_shared<bb::ECCOpQueue>();
457 op_queue->no_op_ultra_only();
458 op_queue->random_op_ultra_only();
459 op_queue->random_op_ultra_only();
460 op_queue->random_op_ultra_only();
461
462 // Generate random EccOpQueue actions
463
464 for (size_t i = 0; i < (mini_circuit_size >> 1) / 2; i++) {
465 switch (engine.get_random_uint8() & 3) {
466 case 0:
467 op_queue->no_op_ultra_only();
468 break;
469 case 1:
470 op_queue->eq_and_reset();
471 break;
472 case 2:
473 op_queue->add_accumulate(GroupElement::random_element(&engine));
474 break;
475 case 3:
476 op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine));
477 break;
478 }
479 }
480 op_queue->merge();
481 for (size_t i = 0; i < 100; i++) {
482 switch (engine.get_random_uint8() & 3) {
483 case 0:
484 op_queue->no_op_ultra_only();
485 break;
486 case 1:
487 op_queue->eq_and_reset();
488 break;
489 case 2:
490 op_queue->add_accumulate(GroupElement::random_element(&engine));
491 break;
492 case 3:
493 op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine));
494 break;
495 }
496 }
497 op_queue->random_op_ultra_only();
498 op_queue->random_op_ultra_only();
499 op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size());
500
501 const auto batching_challenge_v = BF::random_element(&engine);
502 const auto evaluation_input_x = BF::random_element(&engine);
503
504 // Generating all the values is pretty tedious, so just use CircuitBuilder
505 auto circuit_builder = TranslatorCircuitBuilder(batching_challenge_v, evaluation_input_x, op_queue);
506
507 // The non-native field relation uses limbs of evaluation_input_x and powers of batching_challenge_v as inputs
509 auto v_power = BF::one();
510 for (size_t i = 0; i < 4 /*Number of powers of v that we need {1,2,3,4}*/; i++) {
511 v_power *= batching_challenge_v;
512 auto uint_v_power = uint256_t(v_power);
513 params.batching_challenge_v.at(i) = { uint_v_power.slice(0, NUM_LIMB_BITS),
514 uint_v_power.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2),
515 uint_v_power.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3),
516 uint_v_power.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4),
517 uint_v_power };
518 }
519 auto uint_input_x = uint256_t(evaluation_input_x);
520 params.evaluation_input_x = { uint_input_x.slice(0, NUM_LIMB_BITS),
521 uint_input_x.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2),
522 uint_input_x.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3),
523 uint_input_x.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4),
524 uint_input_x };
525
526 // Create storage for polynomials
528
529 // Copy values of wires used in the non-native field relation from the circuit builder
530 for (size_t i = Builder::NUM_NO_OPS_START + Builder::NUM_RANDOM_OPS_START;
531 i < circuit_builder.num_gates() - Builder::NUM_RANDOM_OPS_END;
532 i++) {
533 prover_polynomials.op.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.OP][i]);
534 prover_polynomials.p_x_low_limbs.at(i) =
535 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_LOW_LIMBS][i]);
536 prover_polynomials.p_x_high_limbs.at(i) =
537 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_HIGH_LIMBS][i]);
538 prover_polynomials.p_y_low_limbs.at(i) =
539 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_LOW_LIMBS][i]);
540 prover_polynomials.p_y_high_limbs.at(i) =
541 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_HIGH_LIMBS][i]);
542 prover_polynomials.z_low_limbs.at(i) =
543 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_LOW_LIMBS][i]);
544 prover_polynomials.z_high_limbs.at(i) =
545 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_HIGH_LIMBS][i]);
546 prover_polynomials.accumulators_binary_limbs_0.at(i) =
547 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_0][i]);
548 prover_polynomials.accumulators_binary_limbs_1.at(i) =
549 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_1][i]);
550 prover_polynomials.accumulators_binary_limbs_2.at(i) =
551 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_2][i]);
552 prover_polynomials.accumulators_binary_limbs_3.at(i) =
553 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_3][i]);
554 prover_polynomials.quotient_low_binary_limbs.at(i) =
555 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_LOW_BINARY_LIMBS][i]);
556 prover_polynomials.quotient_high_binary_limbs.at(i) =
557 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_HIGH_BINARY_LIMBS][i]);
558 prover_polynomials.relation_wide_limbs.at(i) =
559 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.RELATION_WIDE_LIMBS][i]);
560 }
561
562 // Fill in lagrange odd polynomial
563 for (size_t i = Flavor::RESULT_ROW; i < mini_circuit_size_without_masking; i += 2) {
564 prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1;
565 prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1;
566 }
567
568 // Check that Non-Native Field relation is satisfied across each row of the prover polynomials
570 prover_polynomials, params, "TranslatorNonNativeFieldRelation");
571}
572
574{
575 using Flavor = TranslatorFlavor;
576 using FF = typename Flavor::FF;
578
579 const size_t full_circuit_size = Flavor::MINI_CIRCUIT_SIZE * Flavor::INTERLEAVING_GROUP_SIZE;
581 const size_t full_masking_offset = NUM_DISABLED_ROWS_IN_SUMCHECK * Flavor::INTERLEAVING_GROUP_SIZE;
582
585 ProverPolynomials& prover_polynomials = key.proving_key->polynomials;
586 const size_t dyadic_circuit_size_without_masking = full_circuit_size - full_masking_offset;
587
588 // Fill required relation parameters
590
591 // Populate the group polynomials with appropriate values and also enough random values to mask their commitment
592 // and evaluation
593 auto fill_polynomial_with_random_14_bit_values = [&](auto& polynomial) {
594 for (size_t i = polynomial.start_index(); i < polynomial.end_index() - NUM_DISABLED_ROWS_IN_SUMCHECK; i++) {
595 polynomial.at(i) = engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1);
596 }
597 for (size_t i = polynomial.end_index() - NUM_DISABLED_ROWS_IN_SUMCHECK; i < polynomial.end_index(); i++) {
598 polynomial.at(i) = FF::random_element();
599 }
600 };
601
602 for (const auto& group : prover_polynomials.get_groups_to_be_interleaved()) {
603 for (auto& poly : group) {
604 fill_polynomial_with_random_14_bit_values(poly);
605 }
606 }
607
608 // Fill in lagrange polynomials used in the permutation relation
609 prover_polynomials.lagrange_first.at(0) = 1;
610 prover_polynomials.lagrange_real_last.at(dyadic_circuit_size_without_masking - 1) = 1;
611 prover_polynomials.lagrange_last.at(full_circuit_size - 1) = 1;
612 for (size_t i = dyadic_circuit_size_without_masking; i < full_circuit_size; i++) {
613 prover_polynomials.lagrange_masking.at(i) = 1;
614 }
615
616 key.compute_interleaved_polynomials();
617 key.compute_extra_range_constraint_numerator();
618 key.compute_translator_range_constraint_ordered_polynomials();
619
620 // Compute the grand product polynomial
621 compute_grand_product<Flavor, bb::TranslatorPermutationRelation<FF>>(prover_polynomials, params);
622
623 // Check that permutation relation is satisfied across each row of the prover polynomials
625 prover_polynomials, params, "TranslatorPermutationRelation");
627 prover_polynomials, params, "TranslatorPermutationRelation");
628}
629
631{
632 using Flavor = TranslatorFlavor;
633 using FF = typename Flavor::FF;
636
639 ProverPolynomials& prover_polynomials = key.proving_key->polynomials;
640
641 const size_t full_masking_offset = NUM_DISABLED_ROWS_IN_SUMCHECK * Flavor::INTERLEAVING_GROUP_SIZE;
642 const size_t dyadic_circuit_size_without_masking = TranslatorProvingKey::dyadic_circuit_size_without_masking;
643
644 // Construct lagrange polynomials that are needed for Translator's DeltaRangeConstraint Relation
645 prover_polynomials.lagrange_first.at(0) = 0;
646 prover_polynomials.lagrange_real_last.at(dyadic_circuit_size_without_masking - 1) = 1;
647
648 for (size_t i = dyadic_circuit_size_without_masking; i < key.dyadic_circuit_size; i++) {
649 prover_polynomials.lagrange_masking.at(i) = 1;
650 }
651
652 // Create a vector and fill with necessary steps for the DeltaRangeConstraint relation
653 auto sorted_steps = TranslatorProvingKey::get_sorted_steps();
654 std::vector<uint64_t> vector_for_sorting(sorted_steps.begin(), sorted_steps.end());
655
656 // Add random values in the appropriate range to fill the leftover space
657 for (size_t i = sorted_steps.size();
658 i < prover_polynomials.ordered_range_constraints_0.size() - full_masking_offset;
659 i++) {
660 vector_for_sorting.emplace_back(engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1));
661 }
662
663 // Get ordered polynomials
664 auto polynomial_pointers = std::vector{ &prover_polynomials.ordered_range_constraints_0,
665 &prover_polynomials.ordered_range_constraints_1,
666 &prover_polynomials.ordered_range_constraints_2,
667 &prover_polynomials.ordered_range_constraints_3,
668 &prover_polynomials.ordered_range_constraints_4 };
669
670 std::sort(vector_for_sorting.begin(), vector_for_sorting.end());
671
672 // Add masking values
673 for (size_t i = dyadic_circuit_size_without_masking; i < key.dyadic_circuit_size; i++) {
674 vector_for_sorting.emplace_back(FF::random_element());
675 }
676
677 // Copy values, transforming them into Finite Field elements
678 std::transform(vector_for_sorting.cbegin(),
679 vector_for_sorting.cend(),
680 prover_polynomials.ordered_range_constraints_0.coeffs().begin(),
681 [](uint64_t in) { return FF(in); });
682
683 // Copy the same polynomial into the 4 other ordered polynomials (they are not the same in an actual proof, but
684 // we only need to check the correctness of the relation and it acts independently on each polynomial)
685 for (size_t i = 0; i < 4; ++i) {
686 std::copy(prover_polynomials.ordered_range_constraints_0.coeffs().begin(),
687 prover_polynomials.ordered_range_constraints_0.coeffs().end(),
688 polynomial_pointers[i + 1]->coeffs().begin());
689 }
690
691 // Check that DeltaRangeConstraint relation is satisfied across each row of the prover polynomials
693 prover_polynomials, RelationParameters<FF>(), "TranslatorDeltaRangeConstraintRelation");
694}
static const size_t OP_QUEUE_SIZE
A container for the prover polynomials.
typename Curve::ScalarField FF
ECCVMCircuitBuilder CircuitBuilder
typename Curve::BaseField BF
typename G1::element GroupElement
A debugging utility for checking whether a set of polynomials satisfies the relations for a given Fla...
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
TranslatorCircuitBuilder creates a circuit that evaluates the correctness of the evaluation of EccOpQ...
A container for the prover polynomials handles.
static constexpr size_t MINI_CIRCUIT_SIZE
static constexpr size_t NUM_MASKED_ROWS_END
static std::array< size_t, Flavor::SORTED_STEPS_COUNT > get_sorted_steps()
Create the array of steps inserted in each ordered range constraint to ensure they respect the approp...
static constexpr size_t dyadic_circuit_size_without_masking
static constexpr size_t dyadic_mini_circuit_size_without_masking
group class. Represents an elliptic curve group element. Group is parametrised by Fq and Fr
Definition group.hpp:36
virtual uint8_t get_random_uint8()=0
virtual uint16_t get_random_uint16()=0
virtual uint256_t get_random_uint256()=0
constexpr uint256_t slice(uint64_t start, uint64_t end) const
typename ECCVMFlavor::ProverPolynomials ProverPolynomials
numeric::RNG & engine
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:190
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Container for parameters used by the grand product (permutation, lookup) Honk relations.
std::array< std::array< T, NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR+NUM_NATIVE_LIMBS_IN_GOBLIN_TRANSLATOR >, NUM_CHALLENGE_POWERS_IN_GOBLIN_TRANSLATOR > batching_challenge_v
std::array< T, NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR > accumulated_result
std::array< T, NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR+NUM_NATIVE_LIMBS_IN_GOBLIN_TRANSLATOR > evaluation_input_x
static field random_element(numeric::RNG *engine=nullptr) noexcept