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
17{
19 using FF = typename Flavor::FF;
22
25 ProverPolynomials& prover_polynomials = key.proving_key->polynomials;
26
27 // Construct lagrange polynomials that are needed for Translator's DeltaRangeConstraint Relation
28 prover_polynomials.lagrange_first.at(0) = 0;
29 prover_polynomials.lagrange_real_last.at(key.dyadic_circuit_size - 1) = 1;
30
31 // Create a vector and fill with necessary steps for the DeltaRangeConstraint relation
32 auto sorted_steps = TranslatorProvingKey::get_sorted_steps();
33 std::vector<uint64_t> vector_for_sorting(sorted_steps.begin(), sorted_steps.end());
34
35 // Add random values to fill the leftover space
36 for (size_t i = sorted_steps.size(); i < prover_polynomials.ordered_range_constraints_0.size(); i++) {
37 vector_for_sorting.emplace_back(engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1));
38 }
39
40 // Get ordered polynomials
41 auto polynomial_pointers = std::vector{ &prover_polynomials.ordered_range_constraints_0,
42 &prover_polynomials.ordered_range_constraints_1,
43 &prover_polynomials.ordered_range_constraints_2,
44 &prover_polynomials.ordered_range_constraints_3,
45 &prover_polynomials.ordered_range_constraints_4 };
46
47 // Sort the vector
48 std::sort(vector_for_sorting.begin(), vector_for_sorting.end());
49
50 // Copy values, transforming them into Finite Field elements
51 std::transform(vector_for_sorting.cbegin(),
52 vector_for_sorting.cend(),
53 prover_polynomials.ordered_range_constraints_0.coeffs().begin(),
54 [](uint64_t in) { return FF(in); });
55
56 // Copy the same polynomial into the 4 other ordered polynomials (they are not the same in an actual proof, but
57 // we only need to check the correctness of the relation and it acts independently on each polynomial)
58 parallel_for(4, [&](size_t i) {
59 std::copy(prover_polynomials.ordered_range_constraints_0.coeffs().begin(),
60 prover_polynomials.ordered_range_constraints_0.coeffs().end(),
61 polynomial_pointers[i + 1]->coeffs().begin());
62 });
63
64 // Check that DeltaRangeConstraint relation is satisfied across each row of the prover polynomials
66 prover_polynomials, RelationParameters<FF>(), "TranslatorDeltaRangeConstraintRelation");
67}
68
74TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness)
75{
77 using FF = typename Flavor::FF;
79
81
82 // We only use accumulated_result from relation parameters in this relation
84 params.accumulated_result = {
85 FF::random_element(), FF::random_element(), FF::random_element(), FF::random_element()
86 };
87
88 // Create storage for polynomials
89 ProverPolynomials prover_polynomials;
90 constexpr size_t mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE;
91 // Fill in lagrange even polynomial
92 for (size_t i = 2; i < mini_circuit_size - 1; i += 2) {
93 prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1;
94 prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1;
95 }
96 constexpr size_t NUMBER_OF_POSSIBLE_OPCODES = 4;
97 constexpr std::array<uint64_t, NUMBER_OF_POSSIBLE_OPCODES> possible_opcode_values = { 0, 3, 4, 8 };
98
99 // Assign random opcode values
100 for (size_t i = 1; i < mini_circuit_size - 1; i += 2) {
101 prover_polynomials.op.at(i) =
102 possible_opcode_values[static_cast<size_t>(engine.get_random_uint8() % NUMBER_OF_POSSIBLE_OPCODES)];
103 }
104
105 // Initialize used lagrange polynomials
106 prover_polynomials.lagrange_result_row.at(2) = 1;
107 prover_polynomials.lagrange_last_in_minicircuit.at(mini_circuit_size - 1) = 1;
108
109 // Put random values in accumulator binary limbs (values should be preserved across even->next odd shift)
110 for (size_t i = 3; i < mini_circuit_size - 1; i += 2) {
111 prover_polynomials.accumulators_binary_limbs_0.at(i) = FF ::random_element();
112 prover_polynomials.accumulators_binary_limbs_1.at(i) = FF ::random_element();
113 prover_polynomials.accumulators_binary_limbs_2.at(i) = FF ::random_element();
114 prover_polynomials.accumulators_binary_limbs_3.at(i) = FF ::random_element();
115 prover_polynomials.accumulators_binary_limbs_0.at(i + 1) = prover_polynomials.accumulators_binary_limbs_0[i];
116 prover_polynomials.accumulators_binary_limbs_2.at(i + 1) = prover_polynomials.accumulators_binary_limbs_2[i];
117 prover_polynomials.accumulators_binary_limbs_1.at(i + 1) = prover_polynomials.accumulators_binary_limbs_1[i];
118 prover_polynomials.accumulators_binary_limbs_3.at(i + 1) = prover_polynomials.accumulators_binary_limbs_3[i];
119 }
120
121 // The values of accumulator binary limbs at index 1 should equal the accumulated result from relation parameters
122 prover_polynomials.accumulators_binary_limbs_0.at(2) = params.accumulated_result[0];
123 prover_polynomials.accumulators_binary_limbs_1.at(2) = params.accumulated_result[1];
124 prover_polynomials.accumulators_binary_limbs_2.at(2) = params.accumulated_result[2];
125 prover_polynomials.accumulators_binary_limbs_3.at(2) = params.accumulated_result[3];
126
127 // Check that Opcode Constraint relation is satisfied across each row of the prover polynomials
129 prover_polynomials, params, "TranslatorOpcodeConstraintRelation");
130
131 // Check that Accumulator Transfer relation is satisfied across each row of the prover polynomials
133 prover_polynomials, params, "TranslatorAccumulatorTransferRelation");
134
135 // Check that Zero Constraint relation is satisfied across each row of the prover polynomials
137 prover_polynomials, params, "TranslatorZeroConstraintsRelation");
138}
144{
145 using Flavor = TranslatorFlavor;
146 using FF = typename Flavor::FF;
147 using BF = typename Flavor::BF;
150
151 constexpr size_t mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE;
152
153 // Decomposition relation doesn't use any relation parameters
155
156 // Create storage for polynomials
157 ProverPolynomials prover_polynomials;
158
159 // Fill in lagrange odd polynomial (the only non-witness one we are using)
160 for (size_t i = 1; i < mini_circuit_size - 1; i += 2) {
161 prover_polynomials.lagrange_odd_in_minicircuit.at(i) = 1;
162 }
163
164 constexpr size_t NUM_LIMB_BITS = Flavor::CircuitBuilder::NUM_LIMB_BITS;
165 constexpr size_t HIGH_WIDE_LIMB_WIDTH =
166 Flavor::CircuitBuilder::NUM_LIMB_BITS + Flavor::CircuitBuilder::NUM_LAST_LIMB_BITS;
167 constexpr size_t LOW_WIDE_LIMB_WIDTH = Flavor::CircuitBuilder::NUM_LIMB_BITS * 2;
168 constexpr size_t Z_LIMB_WIDTH = 128;
169 constexpr size_t MICRO_LIMB_WIDTH = Flavor::MICRO_LIMB_BITS;
170 constexpr size_t SHIFT_12_TO_14 = 4;
171 constexpr size_t SHIFT_10_TO_14 = 16;
172 constexpr size_t SHIFT_8_TO_14 = 64;
173 constexpr size_t SHIFT_4_TO_14 = 1024;
174
180 auto decompose_standard_limb =
181 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& limb_4, auto& shifted_limb) {
182 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
183 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
184 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
185 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
186 limb_4 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 4, MICRO_LIMB_WIDTH * 5);
187 shifted_limb = limb_4 * SHIFT_12_TO_14;
188 };
189
195 auto decompose_standard_top_limb =
196 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& shifted_limb) {
197 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
198 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
199 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
200 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
201 shifted_limb = limb_3 * SHIFT_8_TO_14;
202 };
203
209 auto decompose_standard_top_z_limb =
210 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& limb_4, auto& shifted_limb) {
211 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
212 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
213 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
214 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
215 limb_4 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 4, MICRO_LIMB_WIDTH * 5);
216 shifted_limb = limb_4 * SHIFT_4_TO_14;
217 };
218
224 auto decompose_top_quotient_limb =
225 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& shifted_limb) {
226 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
227 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
228 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
229 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
230 shifted_limb = limb_3 * SHIFT_10_TO_14;
231 };
232
237 auto decompose_relation_limb =
238 [](auto& input, auto& limb_0, auto& limb_1, auto& limb_2, auto& limb_3, auto& limb_4, auto& limb_5) {
239 limb_0 = uint256_t(input).slice(0, MICRO_LIMB_WIDTH);
240 limb_1 = uint256_t(input).slice(MICRO_LIMB_WIDTH, MICRO_LIMB_WIDTH * 2);
241 limb_2 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 2, MICRO_LIMB_WIDTH * 3);
242 limb_3 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 3, MICRO_LIMB_WIDTH * 4);
243 limb_4 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 4, MICRO_LIMB_WIDTH * 5);
244 limb_5 = uint256_t(input).slice(MICRO_LIMB_WIDTH * 5, MICRO_LIMB_WIDTH * 6);
245 };
246
247 // Put random values in all the non-interleaved constraint polynomials used to range constrain the values
248 for (size_t i = 1; i < mini_circuit_size - 1; i += 2) {
249 // P.x
250 prover_polynomials.x_lo_y_hi.at(i) =
251 FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1));
252 prover_polynomials.x_hi_z_1.at(i) =
253 FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1));
254
255 // P.y
256 prover_polynomials.y_lo_z_2.at(i) =
257 FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1));
258 prover_polynomials.x_lo_y_hi.at(i + 1) =
259 FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1));
260
261 // z1 and z2
262 prover_polynomials.x_hi_z_1.at(i + 1) = FF(engine.get_random_uint256() & ((uint256_t(1) << Z_LIMB_WIDTH) - 1));
263 prover_polynomials.y_lo_z_2.at(i + 1) = FF(engine.get_random_uint256() & ((uint256_t(1) << Z_LIMB_WIDTH) - 1));
264
265 // Slice P.x into chunks
266 prover_polynomials.p_x_low_limbs.at(i) = uint256_t(prover_polynomials.x_lo_y_hi.at(i)).slice(0, NUM_LIMB_BITS);
267 prover_polynomials.p_x_low_limbs.at(i + 1) =
268 uint256_t(prover_polynomials.x_lo_y_hi.at(i)).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
269 prover_polynomials.p_x_high_limbs.at(i) = uint256_t(prover_polynomials.x_hi_z_1[i]).slice(0, NUM_LIMB_BITS);
270 prover_polynomials.p_x_high_limbs.at(i + 1) =
271 uint256_t(prover_polynomials.x_hi_z_1.at(i)).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
272
273 // Slice P.y into chunks
274 prover_polynomials.p_y_low_limbs.at(i) = uint256_t(prover_polynomials.y_lo_z_2[i]).slice(0, NUM_LIMB_BITS);
275 prover_polynomials.p_y_low_limbs.at(i + 1) =
276 uint256_t(prover_polynomials.y_lo_z_2[i]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
277 prover_polynomials.p_y_high_limbs.at(i) =
278 uint256_t(prover_polynomials.x_lo_y_hi[i + 1]).slice(0, NUM_LIMB_BITS);
279 prover_polynomials.p_y_high_limbs.at(i + 1) =
280 uint256_t(prover_polynomials.x_lo_y_hi[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
281
282 // Slice z1 and z2 into chunks
283 prover_polynomials.z_low_limbs.at(i) = uint256_t(prover_polynomials.x_hi_z_1[i + 1]).slice(0, NUM_LIMB_BITS);
284 prover_polynomials.z_low_limbs.at(i + 1) =
285 uint256_t(prover_polynomials.y_lo_z_2[i + 1]).slice(0, NUM_LIMB_BITS);
286 prover_polynomials.z_high_limbs.at(i) =
287 uint256_t(prover_polynomials.x_hi_z_1[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
288 prover_polynomials.z_high_limbs.at(i + 1) =
289 uint256_t(prover_polynomials.y_lo_z_2[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS);
290
291 // Slice accumulator
292 auto tmp = uint256_t(BF::random_element(&engine));
293 prover_polynomials.accumulators_binary_limbs_0.at(i) = tmp.slice(0, NUM_LIMB_BITS);
294 prover_polynomials.accumulators_binary_limbs_1.at(i) = tmp.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2);
295 prover_polynomials.accumulators_binary_limbs_2.at(i) = tmp.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3);
296 prover_polynomials.accumulators_binary_limbs_3.at(i) = tmp.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4);
297
298 // Slice low limbs of P.x into range constraint microlimbs
299 decompose_standard_limb(prover_polynomials.p_x_low_limbs.at(i),
300 prover_polynomials.p_x_low_limbs_range_constraint_0.at(i),
301 prover_polynomials.p_x_low_limbs_range_constraint_1.at(i),
302 prover_polynomials.p_x_low_limbs_range_constraint_2.at(i),
303 prover_polynomials.p_x_low_limbs_range_constraint_3.at(i),
304 prover_polynomials.p_x_low_limbs_range_constraint_4.at(i),
305 prover_polynomials.p_x_low_limbs_range_constraint_tail.at(i));
306
307 decompose_standard_limb(prover_polynomials.p_x_low_limbs.at(i + 1),
308 prover_polynomials.p_x_low_limbs_range_constraint_0.at(i + 1),
309 prover_polynomials.p_x_low_limbs_range_constraint_1.at(i + 1),
310 prover_polynomials.p_x_low_limbs_range_constraint_2.at(i + 1),
311 prover_polynomials.p_x_low_limbs_range_constraint_3.at(i + 1),
312 prover_polynomials.p_x_low_limbs_range_constraint_4.at(i + 1),
313 prover_polynomials.p_x_low_limbs_range_constraint_tail.at(i + 1));
314
315 // Slice high limbs of P.x into range constraint microlimbs
316 decompose_standard_limb(prover_polynomials.p_x_high_limbs.at(i),
317 prover_polynomials.p_x_high_limbs_range_constraint_0.at(i),
318 prover_polynomials.p_x_high_limbs_range_constraint_1.at(i),
319 prover_polynomials.p_x_high_limbs_range_constraint_2.at(i),
320 prover_polynomials.p_x_high_limbs_range_constraint_3.at(i),
321 prover_polynomials.p_x_high_limbs_range_constraint_4.at(i),
322 prover_polynomials.p_x_high_limbs_range_constraint_tail.at(i));
323
324 decompose_standard_top_limb(prover_polynomials.p_x_high_limbs.at(i + 1),
325 prover_polynomials.p_x_high_limbs_range_constraint_0.at(i + 1),
326 prover_polynomials.p_x_high_limbs_range_constraint_1.at(i + 1),
327 prover_polynomials.p_x_high_limbs_range_constraint_2.at(i + 1),
328 prover_polynomials.p_x_high_limbs_range_constraint_3.at(i + 1),
329 prover_polynomials.p_x_high_limbs_range_constraint_4.at(i + 1));
330
331 // Slice low limbs of P.y into range constraint microlimbs
332 decompose_standard_limb(prover_polynomials.p_y_low_limbs.at(i),
333 prover_polynomials.p_y_low_limbs_range_constraint_0.at(i),
334 prover_polynomials.p_y_low_limbs_range_constraint_1.at(i),
335 prover_polynomials.p_y_low_limbs_range_constraint_2.at(i),
336 prover_polynomials.p_y_low_limbs_range_constraint_3.at(i),
337 prover_polynomials.p_y_low_limbs_range_constraint_4.at(i),
338 prover_polynomials.p_y_low_limbs_range_constraint_tail.at(i));
339
340 decompose_standard_limb(prover_polynomials.p_y_low_limbs.at(i + 1),
341 prover_polynomials.p_y_low_limbs_range_constraint_0.at(i + 1),
342 prover_polynomials.p_y_low_limbs_range_constraint_1.at(i + 1),
343 prover_polynomials.p_y_low_limbs_range_constraint_2.at(i + 1),
344 prover_polynomials.p_y_low_limbs_range_constraint_3.at(i + 1),
345 prover_polynomials.p_y_low_limbs_range_constraint_4.at(i + 1),
346 prover_polynomials.p_y_low_limbs_range_constraint_tail.at(i + 1));
347
348 // Slice high limbs of P.y into range constraint microlimbs
349 decompose_standard_limb(prover_polynomials.p_y_high_limbs.at(i),
350 prover_polynomials.p_y_high_limbs_range_constraint_0.at(i),
351 prover_polynomials.p_y_high_limbs_range_constraint_1.at(i),
352 prover_polynomials.p_y_high_limbs_range_constraint_2.at(i),
353 prover_polynomials.p_y_high_limbs_range_constraint_3.at(i),
354 prover_polynomials.p_y_high_limbs_range_constraint_4.at(i),
355 prover_polynomials.p_y_high_limbs_range_constraint_tail.at(i));
356
357 decompose_standard_top_limb(prover_polynomials.p_y_high_limbs.at(i + 1),
358 prover_polynomials.p_y_high_limbs_range_constraint_0.at(i + 1),
359 prover_polynomials.p_y_high_limbs_range_constraint_1.at(i + 1),
360 prover_polynomials.p_y_high_limbs_range_constraint_2.at(i + 1),
361 prover_polynomials.p_y_high_limbs_range_constraint_3.at(i + 1),
362 prover_polynomials.p_y_high_limbs_range_constraint_4.at(i + 1));
363
364 // Slice low limb of of z1 and z2 into range constraints
365 decompose_standard_limb(prover_polynomials.z_low_limbs.at(i),
366 prover_polynomials.z_low_limbs_range_constraint_0.at(i),
367 prover_polynomials.z_low_limbs_range_constraint_1.at(i),
368 prover_polynomials.z_low_limbs_range_constraint_2.at(i),
369 prover_polynomials.z_low_limbs_range_constraint_3.at(i),
370 prover_polynomials.z_low_limbs_range_constraint_4.at(i),
371 prover_polynomials.z_low_limbs_range_constraint_tail.at(i));
372
373 decompose_standard_limb(prover_polynomials.z_low_limbs.at(i + 1),
374 prover_polynomials.z_low_limbs_range_constraint_0.at(i + 1),
375 prover_polynomials.z_low_limbs_range_constraint_1.at(i + 1),
376 prover_polynomials.z_low_limbs_range_constraint_2.at(i + 1),
377 prover_polynomials.z_low_limbs_range_constraint_3.at(i + 1),
378 prover_polynomials.z_low_limbs_range_constraint_4.at(i + 1),
379 prover_polynomials.z_low_limbs_range_constraint_tail.at(i + 1));
380
381 // Slice high limb of of z1 and z2 into range constraints
382 decompose_standard_top_z_limb(prover_polynomials.z_high_limbs.at(i),
383 prover_polynomials.z_high_limbs_range_constraint_0.at(i),
384 prover_polynomials.z_high_limbs_range_constraint_1.at(i),
385 prover_polynomials.z_high_limbs_range_constraint_2.at(i),
386 prover_polynomials.z_high_limbs_range_constraint_3.at(i),
387 prover_polynomials.z_high_limbs_range_constraint_4.at(i),
388 prover_polynomials.z_high_limbs_range_constraint_tail.at(i));
389
390 decompose_standard_top_z_limb(prover_polynomials.z_high_limbs.at(i + 1),
391 prover_polynomials.z_high_limbs_range_constraint_0.at(i + 1),
392 prover_polynomials.z_high_limbs_range_constraint_1.at(i + 1),
393 prover_polynomials.z_high_limbs_range_constraint_2.at(i + 1),
394 prover_polynomials.z_high_limbs_range_constraint_3.at(i + 1),
395 prover_polynomials.z_high_limbs_range_constraint_4.at(i + 1),
396 prover_polynomials.z_high_limbs_range_constraint_tail.at(i + 1));
397
398 // Slice accumulator limbs into range constraints
399 decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_0.at(i),
400 prover_polynomials.accumulator_low_limbs_range_constraint_0.at(i),
401 prover_polynomials.accumulator_low_limbs_range_constraint_1.at(i),
402 prover_polynomials.accumulator_low_limbs_range_constraint_2.at(i),
403 prover_polynomials.accumulator_low_limbs_range_constraint_3.at(i),
404 prover_polynomials.accumulator_low_limbs_range_constraint_4.at(i),
405 prover_polynomials.accumulator_low_limbs_range_constraint_tail.at(i));
406 decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_1.at(i),
407 prover_polynomials.accumulator_low_limbs_range_constraint_0.at(i + 1),
408 prover_polynomials.accumulator_low_limbs_range_constraint_1.at(i + 1),
409 prover_polynomials.accumulator_low_limbs_range_constraint_2.at(i + 1),
410 prover_polynomials.accumulator_low_limbs_range_constraint_3.at(i + 1),
411 prover_polynomials.accumulator_low_limbs_range_constraint_4.at(i + 1),
412 prover_polynomials.accumulator_low_limbs_range_constraint_tail.at(i + 1));
413
414 decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_2.at(i),
415 prover_polynomials.accumulator_high_limbs_range_constraint_0.at(i),
416 prover_polynomials.accumulator_high_limbs_range_constraint_1.at(i),
417 prover_polynomials.accumulator_high_limbs_range_constraint_2.at(i),
418 prover_polynomials.accumulator_high_limbs_range_constraint_3.at(i),
419 prover_polynomials.accumulator_high_limbs_range_constraint_4.at(i),
420 prover_polynomials.accumulator_high_limbs_range_constraint_tail.at(i));
421 decompose_standard_top_limb(prover_polynomials.accumulators_binary_limbs_3.at(i),
422 prover_polynomials.accumulator_high_limbs_range_constraint_0.at(i + 1),
423 prover_polynomials.accumulator_high_limbs_range_constraint_1.at(i + 1),
424 prover_polynomials.accumulator_high_limbs_range_constraint_2.at(i + 1),
425 prover_polynomials.accumulator_high_limbs_range_constraint_3.at(i + 1),
426 prover_polynomials.accumulator_high_limbs_range_constraint_4.at(i + 1));
427
428 // Slice quotient limbs into range constraints
429 decompose_standard_limb(prover_polynomials.quotient_low_binary_limbs.at(i),
430 prover_polynomials.quotient_low_limbs_range_constraint_0.at(i),
431 prover_polynomials.quotient_low_limbs_range_constraint_1.at(i),
432 prover_polynomials.quotient_low_limbs_range_constraint_2.at(i),
433 prover_polynomials.quotient_low_limbs_range_constraint_3.at(i),
434 prover_polynomials.quotient_low_limbs_range_constraint_4.at(i),
435 prover_polynomials.quotient_low_limbs_range_constraint_tail.at(i));
436 decompose_standard_limb(prover_polynomials.quotient_low_binary_limbs_shift.at(i),
437 prover_polynomials.quotient_low_limbs_range_constraint_0.at(i + 1),
438 prover_polynomials.quotient_low_limbs_range_constraint_1.at(i + 1),
439 prover_polynomials.quotient_low_limbs_range_constraint_2.at(i + 1),
440 prover_polynomials.quotient_low_limbs_range_constraint_3.at(i + 1),
441 prover_polynomials.quotient_low_limbs_range_constraint_4.at(i + 1),
442 prover_polynomials.quotient_low_limbs_range_constraint_tail.at(i + 1));
443
444 decompose_standard_limb(prover_polynomials.quotient_high_binary_limbs.at(i),
445 prover_polynomials.quotient_high_limbs_range_constraint_0.at(i),
446 prover_polynomials.quotient_high_limbs_range_constraint_1.at(i),
447 prover_polynomials.quotient_high_limbs_range_constraint_2.at(i),
448 prover_polynomials.quotient_high_limbs_range_constraint_3.at(i),
449 prover_polynomials.quotient_high_limbs_range_constraint_4.at(i),
450 prover_polynomials.quotient_high_limbs_range_constraint_tail.at(i));
451
452 decompose_top_quotient_limb(prover_polynomials.quotient_high_binary_limbs_shift.at(i),
453 prover_polynomials.quotient_high_limbs_range_constraint_0.at(i + 1),
454 prover_polynomials.quotient_high_limbs_range_constraint_1.at(i + 1),
455 prover_polynomials.quotient_high_limbs_range_constraint_2.at(i + 1),
456 prover_polynomials.quotient_high_limbs_range_constraint_3.at(i + 1),
457 prover_polynomials.quotient_high_limbs_range_constraint_4.at(i + 1));
458
459 // Decompose wide relation limbs into range constraints
460 decompose_relation_limb(prover_polynomials.relation_wide_limbs.at(i),
461 prover_polynomials.relation_wide_limbs_range_constraint_0.at(i),
462 prover_polynomials.relation_wide_limbs_range_constraint_1.at(i),
463 prover_polynomials.relation_wide_limbs_range_constraint_2.at(i),
464 prover_polynomials.relation_wide_limbs_range_constraint_3.at(i),
465 prover_polynomials.p_x_high_limbs_range_constraint_tail.at(i + 1),
466 prover_polynomials.accumulator_high_limbs_range_constraint_tail.at(i + 1));
467
468 decompose_relation_limb(prover_polynomials.relation_wide_limbs.at(i + 1),
469 prover_polynomials.relation_wide_limbs_range_constraint_0.at(i + 1),
470 prover_polynomials.relation_wide_limbs_range_constraint_1.at(i + 1),
471 prover_polynomials.relation_wide_limbs_range_constraint_2.at(i + 1),
472 prover_polynomials.relation_wide_limbs_range_constraint_3.at(i + 1),
473 prover_polynomials.p_y_high_limbs_range_constraint_tail.at(i + 1),
474 prover_polynomials.quotient_high_limbs_range_constraint_tail.at(i + 1));
475 }
476
477 // Check that Decomposition relation is satisfied across each row of the prover polynomials
479 prover_polynomials, params, "TranslatorDecompositionRelation");
480}
481
487{
488 using Flavor = TranslatorFlavor;
489 using FF = typename Flavor::FF;
490 using BF = typename Flavor::BF;
492 using GroupElement = typename Flavor::GroupElement;
493
494 constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS;
495 constexpr auto mini_circuit_size = TranslatorFlavor::MINI_CIRCUIT_SIZE;
496
498
499 auto op_queue = std::make_shared<bb::ECCOpQueue>();
500
501 // Generate random EccOpQueue actions
502
503 for (size_t i = 0; i < ((mini_circuit_size >> 1) - 2); i++) {
504 switch (engine.get_random_uint8() & 3) {
505 case 0:
506 op_queue->empty_row_for_testing();
507 break;
508 case 1:
509 op_queue->eq_and_reset();
510 break;
511 case 2:
512 op_queue->add_accumulate(GroupElement::random_element(&engine));
513 break;
514 case 3:
515 op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine));
516 break;
517 }
518 }
519 op_queue->merge();
520 const auto batching_challenge_v = BF::random_element(&engine);
521 const auto evaluation_input_x = BF::random_element(&engine);
522
523 // Generating all the values is pretty tedious, so just use CircuitBuilder
524 auto circuit_builder = TranslatorCircuitBuilder(batching_challenge_v, evaluation_input_x, op_queue);
525
526 // The non-native field relation uses limbs of evaluation_input_x and powers of batching_challenge_v as inputs
528 auto v_power = BF::one();
529 for (size_t i = 0; i < 4 /*Number of powers of v that we need {1,2,3,4}*/; i++) {
530 v_power *= batching_challenge_v;
531 auto uint_v_power = uint256_t(v_power);
532 params.batching_challenge_v.at(i) = { uint_v_power.slice(0, NUM_LIMB_BITS),
533 uint_v_power.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2),
534 uint_v_power.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3),
535 uint_v_power.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4),
536 uint_v_power };
537 }
538 auto uint_input_x = uint256_t(evaluation_input_x);
539 params.evaluation_input_x = { uint_input_x.slice(0, NUM_LIMB_BITS),
540 uint_input_x.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2),
541 uint_input_x.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3),
542 uint_input_x.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4),
543 uint_input_x };
544
545 // Create storage for polynomials
547
548 // Copy values of wires used in the non-native field relation from the circuit builder
549 for (size_t i = 1; i < circuit_builder.get_estimated_num_finalized_gates(); i++) {
550 prover_polynomials.op.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.OP][i]);
551 prover_polynomials.p_x_low_limbs.at(i) =
552 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_LOW_LIMBS][i]);
553 prover_polynomials.p_x_high_limbs.at(i) =
554 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_HIGH_LIMBS][i]);
555 prover_polynomials.p_y_low_limbs.at(i) =
556 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_LOW_LIMBS][i]);
557 prover_polynomials.p_y_high_limbs.at(i) =
558 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_HIGH_LIMBS][i]);
559 prover_polynomials.z_low_limbs.at(i) =
560 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_LOW_LIMBS][i]);
561 prover_polynomials.z_high_limbs.at(i) =
562 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_HIGH_LIMBS][i]);
563 prover_polynomials.accumulators_binary_limbs_0.at(i) =
564 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_0][i]);
565 prover_polynomials.accumulators_binary_limbs_1.at(i) =
566 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_1][i]);
567 prover_polynomials.accumulators_binary_limbs_2.at(i) =
568 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_2][i]);
569 prover_polynomials.accumulators_binary_limbs_3.at(i) =
570 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_3][i]);
571 prover_polynomials.quotient_low_binary_limbs.at(i) =
572 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_LOW_BINARY_LIMBS][i]);
573 prover_polynomials.quotient_high_binary_limbs.at(i) =
574 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_HIGH_BINARY_LIMBS][i]);
575 prover_polynomials.relation_wide_limbs.at(i) =
576 circuit_builder.get_variable(circuit_builder.wires[circuit_builder.RELATION_WIDE_LIMBS][i]);
577 }
578
579 // Fill in lagrange odd polynomial
580 for (size_t i = 2; i < mini_circuit_size; i += 2) {
581 prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1;
582 prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1;
583 }
584
585 // Check that Non-Native Field relation is satisfied across each row of the prover polynomials
587 prover_polynomials, params, "TranslatorNonNativeFieldRelation");
588}
589
591{
592 using Flavor = TranslatorFlavor;
593 using FF = typename Flavor::FF;
595
596 const size_t full_circuit_size = Flavor::MINI_CIRCUIT_SIZE * Flavor::INTERLEAVING_GROUP_SIZE;
598 const size_t full_masking_offset = NUM_DISABLED_ROWS_IN_SUMCHECK * Flavor::INTERLEAVING_GROUP_SIZE;
599
602 ProverPolynomials& prover_polynomials = key.proving_key->polynomials;
603 const size_t dyadic_circuit_size_without_masking = full_circuit_size - full_masking_offset;
604
605 // Fill required relation parameters
606 RelationParameters<FF> params{ .beta = FF::random_element(), .gamma = FF::random_element() };
607
608 // Populate the group polynomials with appropriate values and also enough random values to mask their commitment
609 // and evaluation
610 auto fill_polynomial_with_random_14_bit_values = [&](auto& polynomial) {
611 for (size_t i = polynomial.start_index(); i < polynomial.end_index() - NUM_DISABLED_ROWS_IN_SUMCHECK; i++) {
612 polynomial.at(i) = engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1);
613 }
614 for (size_t i = polynomial.end_index() - NUM_DISABLED_ROWS_IN_SUMCHECK; i < polynomial.end_index(); i++) {
615 polynomial.at(i) = FF::random_element();
616 }
617 };
618
619 for (const auto& group : prover_polynomials.get_groups_to_be_interleaved()) {
620 for (auto& poly : group) {
621 fill_polynomial_with_random_14_bit_values(poly);
622 }
623 }
624
625 // Fill in lagrange polynomials used in the permutation relation
626 prover_polynomials.lagrange_first.at(0) = 1;
627 prover_polynomials.lagrange_real_last.at(dyadic_circuit_size_without_masking - 1) = 1;
628 prover_polynomials.lagrange_last.at(full_circuit_size - 1) = 1;
629 for (size_t i = dyadic_circuit_size_without_masking; i < full_circuit_size; i++) {
630 prover_polynomials.lagrange_masking.at(i) = 1;
631 }
632
633 key.compute_interleaved_polynomials();
634 key.compute_extra_range_constraint_numerator();
635 key.compute_translator_range_constraint_ordered_polynomials();
636
637 // Compute the grand product polynomial
638 compute_grand_product<Flavor, bb::TranslatorPermutationRelation<FF>>(prover_polynomials, params);
639
640 // Check that permutation relation is satisfied across each row of the prover polynomials
642 prover_polynomials, params, "TranslatorPermutationRelation");
644 prover_polynomials, params, "TranslatorPermutationRelation");
645}
646
648{
649 using Flavor = TranslatorFlavor;
650 using FF = typename Flavor::FF;
653
656 ProverPolynomials& prover_polynomials = key.proving_key->polynomials;
657
658 const size_t full_masking_offset = NUM_DISABLED_ROWS_IN_SUMCHECK * Flavor::INTERLEAVING_GROUP_SIZE;
659 const size_t dyadic_circuit_size_without_masking = key.dyadic_circuit_size - full_masking_offset;
660
661 // Construct lagrange polynomials that are needed for Translator's DeltaRangeConstraint Relation
662 prover_polynomials.lagrange_first.at(0) = 0;
663 prover_polynomials.lagrange_real_last.at(dyadic_circuit_size_without_masking - 1) = 1;
664
665 for (size_t i = dyadic_circuit_size_without_masking; i < key.dyadic_circuit_size; i++) {
666 prover_polynomials.lagrange_masking.at(i) = 1;
667 }
668
669 // Create a vector and fill with necessary steps for the DeltaRangeConstraint relation
670 auto sorted_steps = TranslatorProvingKey::get_sorted_steps();
671 std::vector<uint64_t> vector_for_sorting(sorted_steps.begin(), sorted_steps.end());
672
673 // Add random values in the appropriate range to fill the leftover space
674 for (size_t i = sorted_steps.size();
675 i < prover_polynomials.ordered_range_constraints_0.size() - full_masking_offset;
676 i++) {
677 vector_for_sorting.emplace_back(engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1));
678 }
679
680 // Get ordered polynomials
681 auto polynomial_pointers = std::vector{ &prover_polynomials.ordered_range_constraints_0,
682 &prover_polynomials.ordered_range_constraints_1,
683 &prover_polynomials.ordered_range_constraints_2,
684 &prover_polynomials.ordered_range_constraints_3,
685 &prover_polynomials.ordered_range_constraints_4 };
686
687 std::sort(vector_for_sorting.begin(), vector_for_sorting.end());
688
689 // Add masking values
690 for (size_t i = dyadic_circuit_size_without_masking; i < key.dyadic_circuit_size; i++) {
691 vector_for_sorting.emplace_back(FF::random_element());
692 }
693
694 // Copy values, transforming them into Finite Field elements
695 std::transform(vector_for_sorting.cbegin(),
696 vector_for_sorting.cend(),
697 prover_polynomials.ordered_range_constraints_0.coeffs().begin(),
698 [](uint64_t in) { return FF(in); });
699
700 // Copy the same polynomial into the 4 other ordered polynomials (they are not the same in an actual proof, but
701 // we only need to check the correctness of the relation and it acts independently on each polynomial)
702 for (size_t i = 0; i < 4; ++i) {
703 std::copy(prover_polynomials.ordered_range_constraints_0.coeffs().begin(),
704 prover_polynomials.ordered_range_constraints_0.coeffs().end(),
705 polynomial_pointers[i + 1]->coeffs().begin());
706 }
707
708 // Check that DeltaRangeConstraint relation is satisfied across each row of the prover polynomials
710 prover_polynomials, RelationParameters<FF>(), "TranslatorDeltaRangeConstraintRelation");
711}
A container for the prover polynomials.
typename Curve::BaseField BF
Curve::ScalarField FF
Curve::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 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...
std::shared_ptr< ProvingKey > proving_key
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.
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:123
typename Flavor::FF FF
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:72
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