Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ultra_honk.test.cpp
Go to the documentation of this file.
19
20#include <gtest/gtest.h>
21
22using namespace bb;
23
25
26template <typename Flavor> class UltraHonkTests : public ::testing::Test {
27 public:
32
33 std::vector<uint32_t> add_variables(auto& circuit_builder, std::vector<bb::fr> variables)
34 {
35 std::vector<uint32_t> res;
36 for (auto& variable : variables) {
37 res.emplace_back(circuit_builder.add_variable(variable));
38 }
39 return res;
40 }
41
43 {
45 if constexpr (HasIPAAccumulator<Flavor>) {
46 auto [stdlib_opening_claim, ipa_proof] =
47 IPA<stdlib::grumpkin<UltraCircuitBuilder>>::create_random_valid_ipa_claim_and_proof(builder);
48 stdlib_opening_claim.set_public();
49 builder.ipa_proof = ipa_proof;
50 }
51 }
52
53 void prove_and_verify(typename Flavor::CircuitBuilder& circuit_builder, bool expected_result)
54 {
55 auto prover_instance = std::make_shared<ProverInstance>(circuit_builder);
56 prove_and_verify(prover_instance, expected_result);
57 };
58
59 void prove_and_verify(const std::shared_ptr<ProverInstance>& prover_instance, bool expected_result)
60 {
61 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
62 Prover prover(prover_instance, verification_key);
63 auto proof = prover.construct_proof();
64 if constexpr (HasIPAAccumulator<Flavor>) {
65 VerifierCommitmentKey<curve::Grumpkin> ipa_verification_key(1 << CONST_ECCVM_LOG_N);
66 Verifier verifier(verification_key, ipa_verification_key);
67 bool result = verifier.template verify_proof<RollupIO>(proof, prover_instance->ipa_proof).result;
68 EXPECT_EQ(result, expected_result);
69 } else {
70 Verifier verifier(verification_key);
71 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
72 EXPECT_EQ(result, expected_result);
73 }
74 };
75
76 protected:
78};
79
80#ifdef STARKNET_GARAGA_FLAVORS
81using FlavorTypes = testing::Types<UltraFlavor,
86 UltraStarknetFlavor,
87 UltraStarknetZKFlavor>;
88#else
90 testing::Types<UltraFlavor, UltraZKFlavor, UltraKeccakFlavor, UltraKeccakZKFlavor, UltraRollupFlavor>;
91#endif
92
94
104TYPED_TEST(UltraHonkTests, ProofLengthCheck)
105{
106 using Flavor = TypeParam;
111 using Proof = typename Flavor::Transcript::Proof;
112
113 auto builder = Builder{};
114 IO::add_default(builder);
115 // Construct a UH proof and ensure its size matches expectation; if not, the constant may need to be updated
116 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder);
117 auto verification_key = std::make_shared<typename Flavor::VerificationKey>(prover_instance->get_precomputed());
118 UltraProver_<Flavor> prover(prover_instance, verification_key);
119 Proof ultra_proof = prover.construct_proof();
120 const size_t virtual_log_n = Flavor::USE_PADDING ? CONST_PROOF_SIZE_LOG_N : prover_instance->log_dyadic_size();
121 size_t expected_proof_length = Flavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS(virtual_log_n) + IO::PUBLIC_INPUTS_SIZE;
122 EXPECT_EQ(ultra_proof.size(), expected_proof_length);
123}
124
132TYPED_TEST(UltraHonkTests, ANonZeroPolynomialIsAGoodPolynomial)
133{
134 auto circuit_builder = UltraCircuitBuilder();
135 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
136
137 auto prover_instance = std::make_shared<typename TestFixture::ProverInstance>(circuit_builder);
138 auto verification_key = std::make_shared<typename TypeParam::VerificationKey>(prover_instance->get_precomputed());
139 typename TestFixture::Prover prover(prover_instance, verification_key);
140 auto proof = prover.construct_proof();
141 auto& polynomials = prover_instance->polynomials;
142
143 auto ensure_non_zero = [](auto& polynomial) {
144 bool has_non_zero_coefficient = false;
145 for (auto& coeff : polynomial.coeffs()) {
146 has_non_zero_coefficient |= !coeff.is_zero();
147 }
148 ASSERT_TRUE(has_non_zero_coefficient);
149 };
150
151 for (auto& poly : polynomials.get_selectors()) {
152 ensure_non_zero(poly);
153 }
154
155 for (auto& poly : polynomials.get_tables()) {
156 ensure_non_zero(poly);
157 }
158
159 for (auto& poly : polynomials.get_wires()) {
160 ensure_non_zero(poly);
161 }
162}
163
169{
171 size_t num_gates = 10;
172
173 // Add some arbitrary arithmetic gates that utilize public inputs
175 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
176
177 TestFixture::prove_and_verify(builder, /*expected_result=*/true);
178}
179
181{
182 auto circuit_builder = UltraCircuitBuilder();
183
184 uint32_t left_value = engine.get_random_uint32();
185 uint32_t right_value = engine.get_random_uint32();
186
187 fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form();
188 fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form();
189
190 uint32_t left_witness_index = circuit_builder.add_variable(left_witness_value);
191 uint32_t right_witness_index = circuit_builder.add_variable(right_witness_value);
192
193 uint32_t xor_result_expected = left_value ^ right_value;
194
195 const auto lookup_accumulators = plookup::get_lookup_accumulators(
196 plookup::MultiTableId::UINT32_XOR, left_witness_value, right_witness_value, true);
197 auto xor_result = lookup_accumulators[plookup::ColumnIdx::C3]
198 [0]; // The zeroth index in the 3rd column is the fully accumulated xor
199
200 EXPECT_EQ(xor_result, xor_result_expected);
201 circuit_builder.create_gates_from_plookup_accumulators(
202 plookup::MultiTableId::UINT32_XOR, lookup_accumulators, left_witness_index, right_witness_index);
203 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
204
205 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
206}
207
208TYPED_TEST(UltraHonkTests, CreateGatesFromPlookupAccumulators)
209{
210 auto circuit_builder = UltraCircuitBuilder();
211
212 fr input_value = fr::random_element();
213 const fr input_lo = static_cast<uint256_t>(input_value).slice(0, plookup::fixed_base::table::BITS_PER_LO_SCALAR);
214 const auto input_lo_index = circuit_builder.add_variable(input_lo);
215
216 const auto sequence_data_lo = plookup::get_lookup_accumulators(plookup::MultiTableId::FIXED_BASE_LEFT_LO, input_lo);
217
218 const auto lookup_witnesses = circuit_builder.create_gates_from_plookup_accumulators(
219 plookup::MultiTableId::FIXED_BASE_LEFT_LO, sequence_data_lo, input_lo_index);
220
221 const size_t num_lookups = plookup::fixed_base::table::NUM_TABLES_PER_LO_MULTITABLE;
222
223 EXPECT_EQ(num_lookups, lookup_witnesses[plookup::ColumnIdx::C1].size());
224
225 {
226 const auto mask = plookup::fixed_base::table::MAX_TABLE_SIZE - 1;
227
229 std::vector<uint8_t> input_buf;
230 write(input_buf, base_point);
231 const auto offset_generators =
232 grumpkin::g1::derive_generators(input_buf, plookup::fixed_base::table::NUM_TABLES_PER_LO_MULTITABLE);
233
234 grumpkin::g1::element accumulator = base_point;
235 uint256_t expected_scalar(input_lo);
236 const auto table_bits = plookup::fixed_base::table::BITS_PER_TABLE;
237 const auto num_tables = plookup::fixed_base::table::NUM_TABLES_PER_LO_MULTITABLE;
238 for (size_t i = 0; i < num_tables; ++i) {
239
240 auto round_scalar = circuit_builder.get_variable(lookup_witnesses[plookup::ColumnIdx::C1][i]);
241 auto round_x = circuit_builder.get_variable(lookup_witnesses[plookup::ColumnIdx::C2][i]);
242 auto round_y = circuit_builder.get_variable(lookup_witnesses[plookup::ColumnIdx::C3][i]);
243
244 EXPECT_EQ(uint256_t(round_scalar), expected_scalar);
245
246 auto next_scalar = static_cast<uint256_t>(
247 (i == num_tables - 1) ? fr(0)
248 : circuit_builder.get_variable(lookup_witnesses[plookup::ColumnIdx::C1][i + 1]));
249
250 uint256_t slice = static_cast<uint256_t>(round_scalar) - (next_scalar << table_bits);
251 EXPECT_EQ(slice, (uint256_t(input_lo) >> (i * table_bits)) & mask);
252
253 grumpkin::g1::affine_element expected_point(accumulator * static_cast<uint256_t>(slice) +
254 offset_generators[i]);
255
256 EXPECT_EQ(round_x, expected_point.x);
257 EXPECT_EQ(round_y, expected_point.y);
258 for (size_t j = 0; j < table_bits; ++j) {
259 accumulator = accumulator.dbl();
260 }
261 expected_scalar >>= table_bits;
262 }
263 }
264 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
265
266 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
267}
268
274{
275 using ProverInstance = typename TestFixture::ProverInstance;
276 // Construct a circuit with lookup and arithmetic gates
277 auto construct_circuit_with_lookups = [this]() {
279
282 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
283
284 return builder;
285 };
286
287 // Ensure the unaltered test circuit is valid
288 {
289 auto builder = construct_circuit_with_lookups();
290
291 TestFixture::prove_and_verify(builder, true);
292 }
293
294 // Failure mode 1: bad read counts/tags
295 {
296 auto builder = construct_circuit_with_lookups();
297
298 auto prover_instance = std::make_shared<ProverInstance>(builder);
299 auto& polynomials = prover_instance->polynomials;
300
301 // Erroneously update the read counts/tags at an arbitrary index
302 // Note: updating only one or the other may not cause failure due to the design of the relation algebra. For
303 // example, the inverse is only computed if read tags is non-zero, otherwise the inverse at the row in
304 // question will be zero. So if read counts is incremented at some arbitrary index but read tags is not, the
305 // inverse will be 0 and the erroneous read_counts value will get multiplied by 0 in the relation. This is
306 // expected behavior.
307 polynomials.lookup_inverses = polynomials.lookup_inverses.full();
308 polynomials.lookup_read_counts = polynomials.lookup_read_counts.full();
309 polynomials.lookup_read_counts.at(25) = 1;
310 polynomials.lookup_read_tags = polynomials.lookup_read_tags.full();
311 polynomials.lookup_read_tags.at(25) = 1;
312
313 TestFixture::prove_and_verify(prover_instance, false);
314 }
315
316 // Failure mode 2: bad lookup gate wire value
317 {
318 auto builder = construct_circuit_with_lookups();
319
320 auto prover_instance = std::make_shared<ProverInstance>(builder);
321 auto& polynomials = prover_instance->polynomials;
322
323 bool altered = false;
324 // Find a lookup gate and alter one of the wire values
325 for (auto [i, q_lookup] : polynomials.q_lookup.indexed_values()) {
326 if (!q_lookup.is_zero() && polynomials.q_lookup.is_valid_set_index(i)) {
327 polynomials.w_o.at(i) += 1;
328 altered = true;
329 break;
330 }
331 }
332 EXPECT_TRUE(altered);
333 TestFixture::prove_and_verify(prover_instance, false);
334 }
335
336 // Failure mode 3: erroneous lookup gate
337 {
338 auto builder = construct_circuit_with_lookups();
339
340 auto prover_instance = std::make_shared<ProverInstance>(builder);
341 auto& polynomials = prover_instance->polynomials;
342
343 // Turn the lookup selector on for an arbitrary row where it is not already active
344 polynomials.lookup_inverses = polynomials.lookup_inverses.full();
345 polynomials.q_lookup = polynomials.q_lookup.full();
346 EXPECT_TRUE(polynomials.q_lookup[25] != 1);
347 polynomials.q_lookup.at(25) = 1;
348
349 TestFixture::prove_and_verify(prover_instance, false);
350 }
351}
352
353TYPED_TEST(UltraHonkTests, TestNoLookupProof)
354{
355 auto circuit_builder = UltraCircuitBuilder();
356
357 for (size_t i = 0; i < 16; ++i) {
358 for (size_t j = 0; j < 16; ++j) {
359 uint64_t left = static_cast<uint64_t>(j);
360 uint64_t right = static_cast<uint64_t>(i);
361 uint32_t left_idx = circuit_builder.add_variable(fr(left));
362 uint32_t right_idx = circuit_builder.add_variable(fr(right));
363 uint32_t result_idx = circuit_builder.add_variable(fr(left ^ right));
364
365 uint32_t add_idx =
366 circuit_builder.add_variable(fr(left) + fr(right) + circuit_builder.get_variable(result_idx));
367 circuit_builder.create_big_add_gate(
368 { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) });
369 }
370 }
371 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
372
373 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
374}
375
376TYPED_TEST(UltraHonkTests, TestEllipticGate)
377{
379 typedef grumpkin::g1::element element;
380 auto circuit_builder = UltraCircuitBuilder();
381
384
385 affine_element p3(element(p1) + element(p2));
386
387 uint32_t x1 = circuit_builder.add_variable(p1.x);
388 uint32_t y1 = circuit_builder.add_variable(p1.y);
389 uint32_t x2 = circuit_builder.add_variable(p2.x);
390 uint32_t y2 = circuit_builder.add_variable(p2.y);
391 uint32_t x3 = circuit_builder.add_variable(p3.x);
392 uint32_t y3 = circuit_builder.add_variable(p3.y);
393
394 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 });
395
396 p3 = affine_element(element(p1) + element(p2));
397 x3 = circuit_builder.add_variable(p3.x);
398 y3 = circuit_builder.add_variable(p3.y);
399 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 });
400
401 p3 = affine_element(element(p1) - element(p2));
402 x3 = circuit_builder.add_variable(p3.x);
403 y3 = circuit_builder.add_variable(p3.y);
404 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, -1 });
405
406 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
407
408 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
409}
410
411TYPED_TEST(UltraHonkTests, NonTrivialTagPermutation)
412{
413 auto circuit_builder = UltraCircuitBuilder();
415 fr b = -a;
416
417 auto a_idx = circuit_builder.add_variable(a);
418 auto b_idx = circuit_builder.add_variable(b);
419 auto c_idx = circuit_builder.add_variable(b);
420 auto d_idx = circuit_builder.add_variable(a);
421
422 circuit_builder.create_add_gate(
423 { a_idx, b_idx, circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), fr::zero() });
424 circuit_builder.create_add_gate(
425 { c_idx, d_idx, circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), fr::zero() });
426
427 circuit_builder.create_tag(1, 2);
428 circuit_builder.create_tag(2, 1);
429
430 circuit_builder.assign_tag(a_idx, 1);
431 circuit_builder.assign_tag(b_idx, 1);
432 circuit_builder.assign_tag(c_idx, 2);
433 circuit_builder.assign_tag(d_idx, 2);
434 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
435
436 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
437}
438
439TYPED_TEST(UltraHonkTests, NonTrivialTagPermutationAndCycles)
440{
441 auto circuit_builder = UltraCircuitBuilder();
443 fr c = -a;
444
445 auto a_idx = circuit_builder.add_variable(a);
446 auto b_idx = circuit_builder.add_variable(a);
447 circuit_builder.assert_equal(a_idx, b_idx);
448 auto c_idx = circuit_builder.add_variable(c);
449 auto d_idx = circuit_builder.add_variable(c);
450 circuit_builder.assert_equal(c_idx, d_idx);
451 auto e_idx = circuit_builder.add_variable(a);
452 auto f_idx = circuit_builder.add_variable(a);
453 circuit_builder.assert_equal(e_idx, f_idx);
454 auto g_idx = circuit_builder.add_variable(c);
455 auto h_idx = circuit_builder.add_variable(c);
456 circuit_builder.assert_equal(g_idx, h_idx);
457
458 circuit_builder.create_tag(1, 2);
459 circuit_builder.create_tag(2, 1);
460
461 circuit_builder.assign_tag(a_idx, 1);
462 circuit_builder.assign_tag(c_idx, 1);
463 circuit_builder.assign_tag(e_idx, 2);
464 circuit_builder.assign_tag(g_idx, 2);
465
466 circuit_builder.create_add_gate(
467 { b_idx, a_idx, circuit_builder.zero_idx(), fr::one(), fr::neg_one(), fr::zero(), fr::zero() });
468 circuit_builder.create_add_gate(
469 { c_idx, g_idx, circuit_builder.zero_idx(), fr::one(), -fr::one(), fr::zero(), fr::zero() });
470 circuit_builder.create_add_gate(
471 { e_idx, f_idx, circuit_builder.zero_idx(), fr::one(), -fr::one(), fr::zero(), fr::zero() });
472 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
473
474 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
475}
476
477TYPED_TEST(UltraHonkTests, BadTagPermutation)
478{
479 {
480 auto circuit_builder = UltraCircuitBuilder();
482 fr b = -a;
483
484 auto a_idx = circuit_builder.add_variable(a);
485 auto b_idx = circuit_builder.add_variable(b);
486 auto c_idx = circuit_builder.add_variable(b);
487 auto d_idx = circuit_builder.add_variable(a + 1);
488
489 circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx(), 1, 1, 0, 0 });
490 circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx(), 1, 1, 0, -1 });
491
492 circuit_builder.create_tag(1, 2);
493 circuit_builder.create_tag(2, 1);
494
495 circuit_builder.assign_tag(a_idx, 1);
496 circuit_builder.assign_tag(b_idx, 1);
497 circuit_builder.assign_tag(c_idx, 2);
498 circuit_builder.assign_tag(d_idx, 2);
499 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
500
501 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
502 }
503 // Same as above but without tag creation to check reason of failure is really tag mismatch
504 {
505 auto circuit_builder = UltraCircuitBuilder();
507 fr b = -a;
508
509 auto a_idx = circuit_builder.add_variable(a);
510 auto b_idx = circuit_builder.add_variable(b);
511 auto c_idx = circuit_builder.add_variable(b);
512 auto d_idx = circuit_builder.add_variable(a + 1);
513
514 circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx(), 1, 1, 0, 0 });
515 circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx(), 1, 1, 0, -1 });
516 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
517
518 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
519 }
520}
521
523{
524 auto circuit_builder = UltraCircuitBuilder();
525 fr a = fr::one();
526 fr b = fr(2);
527 fr c = fr(3);
528 fr d = fr(4);
529
530 auto a_idx = circuit_builder.add_variable(a);
531 auto b_idx = circuit_builder.add_variable(b);
532 auto c_idx = circuit_builder.add_variable(c);
533 auto d_idx = circuit_builder.add_variable(d);
534 circuit_builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx });
535
536 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
537
538 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
539}
540
541TYPED_TEST(UltraHonkTests, SortWithEdgesGate)
542{
543 fr a = fr::one();
544 fr b = fr(2);
545 fr c = fr(3);
546 fr d = fr(4);
547 fr e = fr(5);
548 fr f = fr(6);
549 fr g = fr(7);
550 fr h = fr(8);
551
552 {
553 auto circuit_builder = UltraCircuitBuilder();
554 auto a_idx = circuit_builder.add_variable(a);
555 auto b_idx = circuit_builder.add_variable(b);
556 auto c_idx = circuit_builder.add_variable(c);
557 auto d_idx = circuit_builder.add_variable(d);
558 auto e_idx = circuit_builder.add_variable(e);
559 auto f_idx = circuit_builder.add_variable(f);
560 auto g_idx = circuit_builder.add_variable(g);
561 auto h_idx = circuit_builder.add_variable(h);
562 circuit_builder.create_sort_constraint_with_edges(
563 { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, h);
564
565 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
566
567 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
568 }
569
570 {
571 auto circuit_builder = UltraCircuitBuilder();
572 auto a_idx = circuit_builder.add_variable(a);
573 auto b_idx = circuit_builder.add_variable(b);
574 auto c_idx = circuit_builder.add_variable(c);
575 auto d_idx = circuit_builder.add_variable(d);
576 auto e_idx = circuit_builder.add_variable(e);
577 auto f_idx = circuit_builder.add_variable(f);
578 auto g_idx = circuit_builder.add_variable(g);
579 auto h_idx = circuit_builder.add_variable(h);
580 circuit_builder.create_sort_constraint_with_edges(
581 { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, g);
582
583 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
584
585 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
586 }
587 {
588 auto circuit_builder = UltraCircuitBuilder();
589 auto a_idx = circuit_builder.add_variable(a);
590 auto b_idx = circuit_builder.add_variable(b);
591 auto c_idx = circuit_builder.add_variable(c);
592 auto d_idx = circuit_builder.add_variable(d);
593 auto e_idx = circuit_builder.add_variable(e);
594 auto f_idx = circuit_builder.add_variable(f);
595 auto g_idx = circuit_builder.add_variable(g);
596 auto h_idx = circuit_builder.add_variable(h);
597 circuit_builder.create_sort_constraint_with_edges(
598 { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, b, h);
599
600 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
601
602 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
603 }
604 {
605 auto circuit_builder = UltraCircuitBuilder();
606 auto a_idx = circuit_builder.add_variable(a);
607 auto c_idx = circuit_builder.add_variable(c);
608 auto d_idx = circuit_builder.add_variable(d);
609 auto e_idx = circuit_builder.add_variable(e);
610 auto f_idx = circuit_builder.add_variable(f);
611 auto g_idx = circuit_builder.add_variable(g);
612 auto h_idx = circuit_builder.add_variable(h);
613 auto b2_idx = circuit_builder.add_variable(fr(15));
614 circuit_builder.create_sort_constraint_with_edges(
615 { a_idx, b2_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, b, h);
616
617 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
618
619 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
620 }
621 {
622 auto circuit_builder = UltraCircuitBuilder();
623 auto idx =
624 TestFixture::add_variables(circuit_builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25,
625 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 });
626 circuit_builder.create_sort_constraint_with_edges(idx, 1, 45);
627
628 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
629
630 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
631 }
632 {
633 auto circuit_builder = UltraCircuitBuilder();
634 auto idx =
635 TestFixture::add_variables(circuit_builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25,
636 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 });
637 circuit_builder.create_sort_constraint_with_edges(idx, 1, 29);
638
639 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
640
641 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
642 }
643}
644
645TYPED_TEST(UltraHonkTests, RangeConstraint)
646{
647 {
648 auto circuit_builder = UltraCircuitBuilder();
649 auto indices = TestFixture::add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 });
650 for (size_t i = 0; i < indices.size(); i++) {
651 circuit_builder.create_new_range_constraint(indices[i], 8);
652 }
653 // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx};
654 circuit_builder.create_sort_constraint(indices);
655
656 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
657
658 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
659 }
660 {
661 auto circuit_builder = UltraCircuitBuilder();
662 auto indices = TestFixture::add_variables(circuit_builder, { 3 });
663 for (size_t i = 0; i < indices.size(); i++) {
664 circuit_builder.create_new_range_constraint(indices[i], 3);
665 }
666 // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx};
667 circuit_builder.create_unconstrained_gates(indices);
668
669 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
670
671 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
672 }
673 {
674 auto circuit_builder = UltraCircuitBuilder();
675 auto indices = TestFixture::add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 8, 25 });
676 for (size_t i = 0; i < indices.size(); i++) {
677 circuit_builder.create_new_range_constraint(indices[i], 8);
678 }
679 circuit_builder.create_sort_constraint(indices);
680
681 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
682
683 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
684 }
685 {
686 auto circuit_builder = UltraCircuitBuilder();
687 auto indices = TestFixture::add_variables(
688 circuit_builder, { 1, 2, 3, 4, 5, 6, 10, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 19, 51 });
689 for (size_t i = 0; i < indices.size(); i++) {
690 circuit_builder.create_new_range_constraint(indices[i], 128);
691 }
692 circuit_builder.create_unconstrained_gates(indices);
693
694 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
695
696 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
697 }
698 {
699 auto circuit_builder = UltraCircuitBuilder();
700 auto indices = TestFixture::add_variables(
701 circuit_builder, { 1, 2, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 });
702 for (size_t i = 0; i < indices.size(); i++) {
703 circuit_builder.create_new_range_constraint(indices[i], 79);
704 }
705 circuit_builder.create_unconstrained_gates(indices);
706
707 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
708
709 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
710 }
711 {
712 auto circuit_builder = UltraCircuitBuilder();
713 auto indices = TestFixture::add_variables(
714 circuit_builder, { 1, 0, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 });
715 for (size_t i = 0; i < indices.size(); i++) {
716 circuit_builder.create_new_range_constraint(indices[i], 79);
717 }
718 circuit_builder.create_unconstrained_gates(indices);
719
720 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
721
722 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
723 }
724}
725
727{
728 auto circuit_builder = UltraCircuitBuilder();
729 auto idx = TestFixture::add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 });
730 for (size_t i = 0; i < idx.size(); i++) {
731 circuit_builder.create_new_range_constraint(idx[i], 8);
732 }
733
734 circuit_builder.create_add_gate(
735 { idx[0], idx[1], circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), -3 });
736 circuit_builder.create_add_gate(
737 { idx[2], idx[3], circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), -7 });
738 circuit_builder.create_add_gate(
739 { idx[4], idx[5], circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), -11 });
740 circuit_builder.create_add_gate(
741 { idx[6], idx[7], circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), -15 });
742
743 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
744
745 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
746}
747
748TYPED_TEST(UltraHonkTests, RangeWithGatesWhereRangeIsNotAPowerOfTwo)
749{
750 auto circuit_builder = UltraCircuitBuilder();
751 auto idx = TestFixture::add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 });
752 for (size_t i = 0; i < idx.size(); i++) {
753 circuit_builder.create_new_range_constraint(idx[i], 12);
754 }
755
756 circuit_builder.create_add_gate(
757 { idx[0], idx[1], circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), -3 });
758 circuit_builder.create_add_gate(
759 { idx[2], idx[3], circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), -7 });
760 circuit_builder.create_add_gate(
761 { idx[4], idx[5], circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), -11 });
762 circuit_builder.create_add_gate(
763 { idx[6], idx[7], circuit_builder.zero_idx(), fr::one(), fr::one(), fr::zero(), -15 });
764
765 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
766
767 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
768}
769
770TYPED_TEST(UltraHonkTests, SortWidgetComplex)
771{
772 {
773
774 auto circuit_builder = UltraCircuitBuilder();
775 std::vector<fr> a = { 1, 3, 4, 7, 7, 8, 11, 14, 15, 15, 18, 19, 21, 21, 24, 25, 26, 27, 30, 32 };
776 std::vector<uint32_t> ind;
777 for (const fr& val : a)
778 ind.emplace_back(circuit_builder.add_variable(val));
779 circuit_builder.create_sort_constraint(ind);
780
781 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
782
783 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
784 }
785 {
786
787 auto circuit_builder = UltraCircuitBuilder();
788 std::vector<fr> a = { 1, 3, 4, 7, 7, 8, 16, 14, 15, 15, 18, 19, 21, 21, 24, 25, 26, 27, 30, 32 };
789 std::vector<uint32_t> ind;
790 for (const fr& val : a)
791 ind.emplace_back(circuit_builder.add_variable(val));
792 circuit_builder.create_sort_constraint(ind);
793
794 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
795
796 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
797 }
798}
799
801{
802 auto circuit_builder = UltraCircuitBuilder();
803 fr a = fr::one();
804 fr b = fr(2);
805 fr c = fr(3);
806 fr d = fr(8);
807
808 auto a_idx = circuit_builder.add_variable(a);
809 auto b_idx = circuit_builder.add_variable(b);
810 auto c_idx = circuit_builder.add_variable(c);
811 auto d_idx = circuit_builder.add_variable(d);
812 circuit_builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx });
813
814 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
815
816 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false);
817}
818
819TYPED_TEST(UltraHonkTests, ComposedRangeConstraint)
820{
821 auto circuit_builder = UltraCircuitBuilder();
822 auto c = fr::random_element();
823 auto d = uint256_t(c).slice(0, 133);
824 auto e = fr(d);
825 auto a_idx = circuit_builder.add_variable(fr(e));
826 circuit_builder.create_add_gate({ a_idx, circuit_builder.zero_idx(), circuit_builder.zero_idx(), 1, 0, 0, -fr(e) });
827 circuit_builder.decompose_into_default_range(a_idx, 134);
828
829 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
830
831 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
832}
833
834TYPED_TEST(UltraHonkTests, NonNativeFieldMultiplication)
835{
836 using fq = fq;
837 auto circuit_builder = UltraCircuitBuilder();
838
841 uint256_t modulus = fq::modulus;
842
845 uint1024_t p_big = uint512_t(uint256_t(modulus));
846
847 uint1024_t q_big = (a_big * b_big) / p_big;
848 uint1024_t r_big = (a_big * b_big) % p_big;
849
850 uint256_t q(q_big.lo.lo);
851 uint256_t r(r_big.lo.lo);
852
853 const auto split_into_limbs = [&](const uint512_t& input) {
854 constexpr size_t NUM_BITS = 68;
855 std::array<fr, 4> limbs;
856 limbs[0] = input.slice(0, NUM_BITS).lo;
857 limbs[1] = input.slice(NUM_BITS * 1, NUM_BITS * 2).lo;
858 limbs[2] = input.slice(NUM_BITS * 2, NUM_BITS * 3).lo;
859 limbs[3] = input.slice(NUM_BITS * 3, NUM_BITS * 4).lo;
860 return limbs;
861 };
862
863 const auto get_limb_witness_indices = [&](const std::array<fr, 4>& limbs) {
864 std::array<uint32_t, 4> limb_indices;
865 limb_indices[0] = circuit_builder.add_variable(limbs[0]);
866 limb_indices[1] = circuit_builder.add_variable(limbs[1]);
867 limb_indices[2] = circuit_builder.add_variable(limbs[2]);
868 limb_indices[3] = circuit_builder.add_variable(limbs[3]);
869 return limb_indices;
870 };
871 const uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (68 * 4);
872 auto modulus_limbs = split_into_limbs(BINARY_BASIS_MODULUS - uint512_t(modulus));
873
874 const auto a_indices = get_limb_witness_indices(split_into_limbs(uint256_t(a)));
875 const auto b_indices = get_limb_witness_indices(split_into_limbs(uint256_t(b)));
876 const auto q_indices = get_limb_witness_indices(split_into_limbs(uint256_t(q)));
877 const auto r_indices = get_limb_witness_indices(split_into_limbs(uint256_t(r)));
878
880 a_indices, b_indices, q_indices, r_indices, modulus_limbs,
881 };
882 const auto [lo_1_idx, hi_1_idx] = circuit_builder.evaluate_non_native_field_multiplication(inputs);
883
884 // Range constrain the lo and hi carry outputs
885 const bool is_low_70_bits = uint256_t(circuit_builder.get_variable(lo_1_idx)).get_msb() < 70;
886 const bool is_high_70_bits = uint256_t(circuit_builder.get_variable(hi_1_idx)).get_msb() < 70;
887 if (is_low_70_bits && is_high_70_bits) {
888 // Uses more efficient NNF range check if both limbs are < 2^70
889 circuit_builder.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70);
890 } else {
891 // Fallback to default range checks
892 circuit_builder.decompose_into_default_range(lo_1_idx, 72);
893 circuit_builder.decompose_into_default_range(hi_1_idx, 72);
894 }
895
896 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
897
898 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
899}
900
902{
903 auto circuit_builder = UltraCircuitBuilder();
904
905 uint32_t rom_values[8]{
906 circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()),
907 circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()),
908 circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()),
909 circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()),
910 };
911
912 size_t rom_id = circuit_builder.create_ROM_array(8);
913
914 for (size_t i = 0; i < 8; ++i) {
915 circuit_builder.set_ROM_element(rom_id, i, rom_values[i]);
916 }
917
918 uint32_t a_idx = circuit_builder.read_ROM_array(rom_id, circuit_builder.add_variable(5));
919 EXPECT_EQ(a_idx != rom_values[5], true);
920 uint32_t b_idx = circuit_builder.read_ROM_array(rom_id, circuit_builder.add_variable(4));
921 uint32_t c_idx = circuit_builder.read_ROM_array(rom_id, circuit_builder.add_variable(1));
922
923 const auto d_value =
924 circuit_builder.get_variable(a_idx) + circuit_builder.get_variable(b_idx) + circuit_builder.get_variable(c_idx);
925 uint32_t d_idx = circuit_builder.add_variable(d_value);
926
927 circuit_builder.create_big_add_gate({
928 a_idx,
929 b_idx,
930 c_idx,
931 d_idx,
932 1,
933 1,
934 1,
935 -1,
936 0,
937 });
938 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
939
940 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
941}
942
944{
945 auto circuit_builder = UltraCircuitBuilder();
946
947 uint32_t ram_values[8]{
948 circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()),
949 circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()),
950 circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()),
951 circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()),
952 };
953
954 size_t ram_id = circuit_builder.create_RAM_array(8);
955
956 for (size_t i = 0; i < 8; ++i) {
957 circuit_builder.init_RAM_element(ram_id, i, ram_values[i]);
958 }
959
960 uint32_t a_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(5));
961 EXPECT_EQ(a_idx != ram_values[5], true);
962
963 uint32_t b_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(4));
964 uint32_t c_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(1));
965
966 circuit_builder.write_RAM_array(ram_id, circuit_builder.add_variable(4), circuit_builder.add_variable(500));
967 uint32_t d_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(4));
968
969 EXPECT_EQ(circuit_builder.get_variable(d_idx), 500);
970
971 // ensure these vars get used in another arithmetic gate
972 const auto e_value = circuit_builder.get_variable(a_idx) + circuit_builder.get_variable(b_idx) +
973 circuit_builder.get_variable(c_idx) + circuit_builder.get_variable(d_idx);
974 uint32_t e_idx = circuit_builder.add_variable(e_value);
975
976 circuit_builder.create_big_add_gate(
977 {
978 a_idx,
979 b_idx,
980 c_idx,
981 d_idx,
982 -1,
983 -1,
984 -1,
985 -1,
986 0,
987 },
988 true);
989 circuit_builder.create_big_add_gate(
990 {
991 circuit_builder.zero_idx(),
992 circuit_builder.zero_idx(),
993 circuit_builder.zero_idx(),
994 e_idx,
995 0,
996 0,
997 0,
998 0,
999 0,
1000 },
1001 false);
1002
1003 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
1004
1005 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
1006}
1007
1008TYPED_TEST(UltraHonkTests, RangeChecksOnDuplicates)
1009{
1010 auto circuit_builder = UltraCircuitBuilder();
1011
1012 uint32_t a = circuit_builder.add_variable(100);
1013 uint32_t b = circuit_builder.add_variable(100);
1014 uint32_t c = circuit_builder.add_variable(100);
1015 uint32_t d = circuit_builder.add_variable(100);
1016
1017 circuit_builder.assert_equal(a, b);
1018 circuit_builder.assert_equal(a, c);
1019 circuit_builder.assert_equal(a, d);
1020
1021 circuit_builder.create_new_range_constraint(a, 1000);
1022 circuit_builder.create_new_range_constraint(b, 1001);
1023 circuit_builder.create_new_range_constraint(c, 999);
1024 circuit_builder.create_new_range_constraint(d, 1000);
1025
1026 circuit_builder.create_big_add_gate(
1027 {
1028 a,
1029 b,
1030 c,
1031 d,
1032 0,
1033 0,
1034 0,
1035 0,
1036 0,
1037 },
1038 false);
1039
1040 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
1041
1042 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
1043}
1044
1045// Ensure copy constraints added on variables smaller than 2^14, which have been previously
1046// range constrained, do not break the set equivalence checks because of indices mismatch.
1047// 2^14 is DEFAULT_PLOOKUP_RANGE_BITNUM i.e. the maximum size before a variable gets sliced
1048// before range constraints are applied to it.
1049TYPED_TEST(UltraHonkTests, RangeConstraintSmallVariable)
1050{
1051 auto circuit_builder = UltraCircuitBuilder();
1052
1053 uint16_t mask = (1 << 8) - 1;
1054 int a = engine.get_random_uint16() & mask;
1055 uint32_t a_idx = circuit_builder.add_variable(fr(a));
1056 uint32_t b_idx = circuit_builder.add_variable(fr(a));
1057 ASSERT_NE(a_idx, b_idx);
1058 uint32_t c_idx = circuit_builder.add_variable(fr(a));
1059 ASSERT_NE(c_idx, b_idx);
1060 circuit_builder.create_range_constraint(b_idx, 8, "bad range");
1061 circuit_builder.assert_equal(a_idx, b_idx);
1062 circuit_builder.create_range_constraint(c_idx, 8, "bad range");
1063 circuit_builder.assert_equal(a_idx, c_idx);
1064
1065 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
1066
1067 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
1068}
static void SetUpTestSuite()
std::vector< uint32_t > add_variables(auto &circuit_builder, std::vector< bb::fr > variables)
typename Flavor::VerificationKey VerificationKey
void prove_and_verify(const std::shared_ptr< ProverInstance > &prover_instance, bool expected_result)
void set_default_pairing_points_and_ipa_claim_and_proof(UltraCircuitBuilder &builder)
void prove_and_verify(typename Flavor::CircuitBuilder &circuit_builder, bool expected_result)
static constexpr size_t PROOF_LENGTH_WITHOUT_PUB_INPUTS
IPA (inner product argument) commitment scheme class.
Definition ipa.hpp:93
The verification key is responsible for storing the commitments to the precomputed (non-witness) poly...
MegaCircuitBuilder CircuitBuilder
static constexpr bool USE_PADDING
static void add_arithmetic_gates_with_public_inputs(Builder &builder, const size_t num_gates=4)
Add a specified number of arithmetic gates (with public inputs) to the provided circuit.
static void add_lookup_gates(Builder &builder, size_t num_iterations=1)
Add lookup gates using the uint32 XOR lookup table (table size 4096)
static void add_arithmetic_gates(Builder &builder, const size_t num_gates=4)
Add a specified number of arithmetic gates to the provided circuit.
A ProverInstance is normally constructed from a finalized circuit and it contains all the information...
Child class of UltraFlavor that runs with ZK Sumcheck.
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
static affine_element random_element(numeric::RNG *engine=nullptr) noexcept
Samples a random point on the curve.
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:33
constexpr element dbl() const noexcept
static std::vector< affine_element > derive_generators(const std::vector< uint8_t > &domain_separator_bytes, const size_t num_generators, const size_t starting_index=0)
Derives generator points via hash-to-curve.
Definition group.hpp:87
constexpr uint256_t slice(uint64_t start, uint64_t end) const
constexpr uint64_t get_msb() const
static constexpr affine_element lhs_generator_point()
Manages the data that is propagated on the public inputs of an application/function circuit.
The data that is propagated on the public inputs of a rollup circuit.
AluTraceBuilder builder
Definition alu.test.cpp:123
FF a
FF b
bool expected_result
grumpkin::g1::affine_element affine_element
Definition c_bind.hpp:15
Base class templates for structures that contain data parameterized by the fundamental polynomials of...
testing::Types< MegaFlavor, UltraFlavor, UltraZKFlavor, UltraRollupFlavor > FlavorTypes
uintx< uint256_t > uint512_t
Definition uintx.hpp:307
ReadData< bb::fr > get_lookup_accumulators(const MultiTableId id, const fr &key_a, const fr &key_b, const bool is_2_to_1_lookup)
Given a table ID and the key(s) for a key-value lookup, return the lookup accumulators.
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
field< Bn254FqParams > fq
Definition fq.hpp:169
void write(std::vector< uint8_t > &buf, ClientIVC::VerificationKey const &vk)
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
field< Bn254FrParams > fr
Definition fr.hpp:174
C slice(C const &container, size_t start)
Definition container.hpp:9
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field neg_one()
static constexpr field one()
static constexpr uint256_t modulus
BB_INLINE constexpr field to_montgomery_form() const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept
static constexpr field zero()
An object storing two EC points that represent the inputs to a pairing check.
static void add_default_to_public_inputs(Builder &builder)
Adds default public inputs to the builder.
void ensure_non_zero(auto &polynomial)