Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
permutation.test.cpp
Go to the documentation of this file.
5#include "ultra_honk.test.hpp"
6
7using namespace bb;
8
9#ifdef STARKNET_GARAGA_FLAVORS
10using FlavorTypes = testing::Types<UltraFlavor,
14 UltraStarknetFlavor,
15 UltraStarknetZKFlavor>;
16#else
17using FlavorTypes = testing::Types<UltraFlavor, UltraZKFlavor, UltraKeccakFlavor, UltraKeccakZKFlavor>;
18#endif
19template <typename T> using PermutationTests = UltraHonkTests<T>;
21#ifdef STARKNET_GARAGA_FLAVORS
22using NonZKFlavorTypes = testing::Types<UltraFlavor, UltraKeccakFlavor, UltraStarknetFlavor, MegaFlavor>;
23#else
24using NonZKFlavorTypes = testing::Types<UltraFlavor, UltraKeccakFlavor, MegaFlavor>;
25#endif
26template <typename T> using PermutationNonZKTests = UltraHonkTests<T>;
28
42TYPED_TEST(PermutationTests, NonTrivialTagPermutation)
43{
45
46 // Create two distinct values
48 fr y = -x;
49
50 // first multiset {x, y}
51 auto x1_idx = builder.add_variable(x);
52 auto y1_idx = builder.add_variable(y);
53
54 // second multiset {y, x}
55 auto y2_idx = builder.add_variable(y);
56 auto x2_idx = builder.add_variable(x);
57
58 // Dummy gates to include variables in the trace
59 builder.create_add_gate({ x1_idx, y1_idx, builder.zero_idx(), 1, 1, 0, 0 });
60 builder.create_add_gate({ y2_idx, x2_idx, builder.zero_idx(), 1, 1, 0, 0 });
61
62 // Set up tag transposition: first_tag <-> second_tag
63 auto first_tag = builder.get_new_tag();
64 auto second_tag = builder.get_new_tag();
65 builder.set_tau_transposition(first_tag, second_tag);
66
67 // Assign tags: first_tag -> {x, y}, second_tag -> {y, x}
68 builder.assign_tag(x1_idx, first_tag);
69 builder.assign_tag(y1_idx, first_tag);
70 builder.assign_tag(y2_idx, second_tag);
71 builder.assign_tag(x2_idx, second_tag);
72
73 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
74 TestFixture::prove_and_verify(builder, /*expected_result=*/true);
75}
76
88TYPED_TEST(PermutationTests, NonTrivialGeneralizedPerm)
89{
91
93 fr y = -x;
94
95 // Helper to create a pair of equal variables (linked by copy constraint)
96 auto add_equal_pair = [&](fr value) {
97 auto idx1 = builder.add_variable(value);
98 auto idx2 = builder.add_variable(value);
99 builder.assert_equal(idx1, idx2);
100 return std::make_pair(idx1, idx2);
101 };
102
103 // Create pairs of equal variables
104 auto [x1_idx, x1_copy_idx] = add_equal_pair(x);
105 auto [y1_idx, y1_copy_idx] = add_equal_pair(y);
106 auto [x2_idx, x2_copy_idx] = add_equal_pair(x);
107 auto [y2_idx, y2_copy_idx] = add_equal_pair(y);
108
109 // Set up tag transposition for multiset-equality check
110 auto first_tag = builder.get_new_tag();
111 auto second_tag = builder.get_new_tag();
112 builder.set_tau_transposition(first_tag, second_tag);
113
114 // first_tag -> {x, y}, second_tag -> {x, y} (same multisets)
115 builder.assign_tag(x1_idx, first_tag);
116 builder.assign_tag(y1_idx, first_tag);
117 builder.assign_tag(x2_idx, second_tag);
118 builder.assign_tag(y2_idx, second_tag);
119
120 // Dummy gates using copy variables (z1 - z2 = 0)
121 builder.create_add_gate({ x1_copy_idx, x1_idx, builder.zero_idx(), 1, -1, 0, 0 });
122 builder.create_add_gate({ y1_idx, y2_idx, builder.zero_idx(), 1, -1, 0, 0 });
123 builder.create_add_gate({ x2_idx, x2_copy_idx, builder.zero_idx(), 1, -1, 0, 0 });
124
125 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
126 TestFixture::prove_and_verify(builder, /*expected_result=*/true);
127}
128
140TYPED_TEST(PermutationTests, BadTagPermutation)
141{
142 // With tags: multisets {x, y} vs {y, x+1} are NOT equal, so verification should FAIL
143 {
145
147 fr y = -x;
148
149 // multiset: {x, y}
150 auto x1_idx = builder.add_variable(x);
151 auto y1_idx = builder.add_variable(y);
152
153 // multiset: {y, x+1}
154 auto y2_idx = builder.add_variable(y);
155 auto x_plus_1_idx = builder.add_variable(x + 1);
156
157 // Dummy gates: x + y = 0, y + (x+1) = 1
158 builder.create_add_gate({ x1_idx, y1_idx, builder.zero_idx(), 1, 1, 0, 0 });
159 builder.create_add_gate({ y2_idx, x_plus_1_idx, builder.zero_idx(), 1, 1, 0, -1 });
160
161 auto first_tag = builder.get_new_tag();
162 auto second_tag = builder.get_new_tag();
163 builder.set_tau_transposition(first_tag, second_tag);
164
165 builder.assign_tag(x1_idx, first_tag);
166 builder.assign_tag(y1_idx, first_tag);
167 builder.assign_tag(y2_idx, second_tag);
168 builder.assign_tag(x_plus_1_idx, second_tag);
169
170 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
171 TestFixture::prove_and_verify(builder, /*expected_result=*/false);
172 }
173 // Without tags: same circuit passes, confirming failure above is due to tag mismatch
174 {
176
178 fr y = -x;
179
180 auto x1_idx = builder.add_variable(x);
181 auto y1_idx = builder.add_variable(y);
182 auto y2_idx = builder.add_variable(y);
183 auto x_plus_1_idx = builder.add_variable(x + 1);
184
185 builder.create_add_gate({ x1_idx, y1_idx, builder.zero_idx(), 1, 1, 0, 0 });
186 builder.create_add_gate({ y2_idx, x_plus_1_idx, builder.zero_idx(), 1, 1, 0, -1 });
187
188 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
189 TestFixture::prove_and_verify(builder, /*expected_result=*/true);
190 }
191}
192
210TYPED_TEST(PermutationNonZKTests, ZPermZeroedOutFailure)
211{
212 using Flavor = TypeParam;
213 using Builder = typename Flavor::CircuitBuilder;
214
217
218 using Prover = TestFixture::Prover;
219
221
222 auto a = fr::random_element();
223 auto b = fr::random_element();
224 auto c = a + b;
225
226 uint32_t a_idx = builder.add_variable(a);
227 uint32_t a_copy_idx = builder.add_variable(a);
228 uint32_t b_idx = builder.add_variable(b);
229 uint32_t c_idx = builder.add_variable(c);
230
231 builder.create_add_gate({ a_idx, b_idx, c_idx, 1, 1, -1, 0 });
232 builder.create_add_gate({ a_copy_idx, b_idx, c_idx, 1, 1, -1, 0 });
233 builder.assert_equal(a_copy_idx, a_idx);
234
235 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
236
237 auto prover_instance = std::make_shared<ProverInstance>(builder);
238 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
239
240 Prover prover(prover_instance, verification_key);
241 auto proof = prover.construct_proof();
242 // First verify that the Permutation relation holds.
243 auto permutation_relation_failures = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
244 prover_instance->polynomials, prover_instance->relation_parameters, "UltraPermutation - Before Tampering");
245 EXPECT_TRUE(permutation_relation_failures.empty());
246
247 // Tamper: zero-out z_perm
248 {
249 auto& z_perm_mut = prover_instance->polynomials.z_perm();
250 for (size_t i = z_perm_mut.start_index(); i < z_perm_mut.end_index(); ++i) {
251 z_perm_mut.at(i) = fr(0);
252 }
253 }
254 prover_instance->polynomials.set_shifted();
255 auto tampered_permutation_relation_failures = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
256 prover_instance->polynomials,
257 prover_instance->relation_parameters,
258 "UltraPermutation - After zeroing out z_perm");
259 // Verify that the Permutation relation now fails
260 EXPECT_FALSE(tampered_permutation_relation_failures.empty());
261}
262
279TYPED_TEST(PermutationNonZKTests, ZPermNonZeroAtFirstRowFailure)
280{
281 using Flavor = TypeParam;
282 using Builder = typename Flavor::CircuitBuilder;
283
286
287 using Prover = TestFixture::Prover;
288
290
291 auto a = fr::random_element();
292 auto b = fr::random_element();
293 auto c = a + b;
294
295 uint32_t a_idx = builder.add_variable(a);
296 uint32_t a_copy_idx = builder.add_variable(a);
297 uint32_t b_idx = builder.add_variable(b);
298 uint32_t c_idx = builder.add_variable(c);
299
300 builder.create_add_gate({ a_idx, b_idx, c_idx, 1, 1, -1, 0 });
301 builder.create_add_gate({ a_copy_idx, b_idx, c_idx, 1, 1, -1, 0 });
302 builder.assert_equal(a_copy_idx, a_idx);
303
304 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
305
306 auto prover_instance = std::make_shared<ProverInstance>(builder);
307 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
308
309 Prover prover(prover_instance, verification_key);
310 auto proof = prover.construct_proof();
311
312 // Verify the permutation relation holds before tampering.
313 auto permutation_relation_failures = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
314 prover_instance->polynomials, prover_instance->relation_parameters, "UltraPermutation - Before Tampering");
315 EXPECT_TRUE(permutation_relation_failures.empty());
316
317 // lagrange_first is at row TRACE_OFFSET.
318 const size_t first_row = ProverInstance::TRACE_OFFSET;
319
320 // Verify lagrange_first is indeed 1 at the expected position.
321 ASSERT_EQ(prover_instance->polynomials.lagrange_first()[first_row], fr(1))
322 << "lagrange_first should be 1 at row TRACE_OFFSET";
323
324 auto& z_perm = prover_instance->polynomials.z_perm();
325 auto& z_perm_shift = prover_instance->polynomials.z_perm_shift();
326
327 // z_perm is shiftable (start_index = 1), so z_perm at first_row may be a virtual zero.
328 // Expand to a full polynomial to write at that index. Also expand z_perm_shift independently
329 // (it cannot be derived via shifted() from a full polynomial with start_index = 0).
330 prover_instance->polynomials.z_perm() = z_perm.full();
331 prover_instance->polynomials.z_perm_shift() = z_perm_shift.full();
332
333 // Sanity check: z_perm is currently 0 at the lagrange_first row
334 ASSERT_EQ(prover_instance->polynomials.z_perm()[first_row], fr(0));
335
336 // Tamper: set z_perm to non-zero where lagrange_first is active
337 prover_instance->polynomials.z_perm().at(first_row) = fr(1);
338
339 // Verify the permutation relation now fails.
340 auto tampered_failures = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
341 prover_instance->polynomials,
342 prover_instance->relation_parameters,
343 "UltraPermutation - After setting z_perm != 0 at lagrange_first");
344 EXPECT_FALSE(tampered_failures.empty());
345 // Sub-relation 2 (lagrange_first * z_perm = 0) should fail at the lagrange_first row
346 ASSERT_TRUE(tampered_failures.contains(2)) << "Expected sub-relation 2 (z_perm init) to fail";
347 ASSERT_EQ(tampered_failures.at(2), first_row) << "Expected failure at lagrange_first row";
348}
349
364TYPED_TEST(PermutationNonZKTests, ZPermShiftNotZeroAtLagrangeLastFailure)
365{
366 using Flavor = TypeParam;
367 using Builder = typename Flavor::CircuitBuilder;
368
371
372 using Prover = TestFixture::Prover;
373
375
376 auto a = fr::random_element();
377 auto b = fr::random_element();
378 auto c = a + b;
379
380 uint32_t a_idx = builder.add_variable(a);
381 uint32_t a_copy_idx = builder.add_variable(a);
382 uint32_t b_idx = builder.add_variable(b);
383 uint32_t c_idx = builder.add_variable(c);
384
385 builder.create_add_gate({ a_idx, b_idx, c_idx, 1, 1, -1, 0 });
386 builder.create_add_gate({ a_copy_idx, b_idx, c_idx, 1, 1, -1, 0 });
387 builder.assert_equal(a_copy_idx, a_idx);
388
389 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
390
391 auto prover_instance = std::make_shared<ProverInstance>(builder);
392 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
393
394 Prover prover(prover_instance, verification_key);
395 auto proof = prover.construct_proof();
396
397 // first verify that the Permutation relation holds.
398 auto permutation_relation_failures = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
399 prover_instance->polynomials, prover_instance->relation_parameters, "UltraPermutation - Before Tampering");
400 EXPECT_TRUE(permutation_relation_failures.empty());
401 // we make z_perm and z_perm_shift full polynomials to tamper with values that are outside the usual allocated
402 // range. This allows us to failure test for the subrelation `z_perm_shift * lagrange_last == 0`.
403 auto& z_perm = prover_instance->polynomials.z_perm();
404 auto last_valid_index = z_perm.end_index();
405 auto& z_perm_shift = prover_instance->polynomials.z_perm_shift();
406 // make the polynomial full to tamper with a last value.
407 prover_instance->polynomials.z_perm() = z_perm.full();
408 prover_instance->polynomials.z_perm_shift() = z_perm_shift.full();
409
410 ASSERT_EQ(prover_instance->polynomials.lagrange_last().at(last_valid_index - 1), fr(1));
411 ASSERT_EQ(prover_instance->polynomials.z_perm().at(last_valid_index), fr(0));
412 ASSERT_EQ(prover_instance->polynomials.z_perm_shift().at(last_valid_index - 1), fr(0));
413 // Tamper: change `z_perm_shift` to something non-zero when `lagrange_last == 1`.
414 prover_instance->polynomials.z_perm_shift().at(last_valid_index - 1) += fr(1);
415 // Note that `z_perm_shift` and `z_perm` are no longer inextricably linked because we have replaced them by their
416 // full incarnations. Therefore, we still `z_perm.at(last_valid_index) == 0`. This does not effect the test we
417 // wish to check.
418
419 // Verify that the Permutation relation now fails.
420 auto tampered_permutation_relation_failures = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
421 prover_instance->polynomials,
422 prover_instance->relation_parameters,
423 "UltraPermutation - After incrementing z_perm_shift where lagrange_last is 1");
424 EXPECT_FALSE(tampered_permutation_relation_failures.empty());
425 // the first subrelation first fails at `row_idx == last_valid_index - 1`.
426 ASSERT_EQ(tampered_permutation_relation_failures[1], last_valid_index - 1);
427}
428
440TYPED_TEST(PermutationNonZKTests, SigmaCorruptionFailure)
441{
442 using Flavor = TypeParam;
445 using Prover = typename TestFixture::Prover;
446
447 auto builder = typename Flavor::CircuitBuilder();
448
449 // Create variables with a copy constraint
450 auto a = fr::random_element();
451 auto b = fr::random_element();
452 auto c = a + b;
453
454 uint32_t a_idx = builder.add_variable(a);
455 uint32_t a_copy_idx = builder.add_variable(a);
456 uint32_t b_idx = builder.add_variable(b);
457 uint32_t c_idx = builder.add_variable(c);
458
459 // Gates using a_idx and a_copy_idx (which should be equal)
460 builder.create_add_gate({ a_idx, b_idx, c_idx, 1, 1, -1, 0 });
461 builder.create_add_gate({ a_copy_idx, b_idx, c_idx, 1, 1, -1, 0 });
462 // copy cycle we'll break
463 builder.assert_equal(a_copy_idx, a_idx);
464
465 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
466
467 auto prover_instance = std::make_shared<ProverInstance>(builder);
468 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
469
470 // Construct proof to compute z_perm
471 Prover prover(prover_instance, verification_key);
472 auto proof = prover.construct_proof();
473
474 // The Permutation relation holds before tampering
475 auto permutation_relation_failures = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
476 prover_instance->polynomials, prover_instance->relation_parameters, "Permutation Relation - Before Tampering");
477 ASSERT_TRUE(permutation_relation_failures.empty());
478
479 // TAMPER
480
481 // Corrupt sigma_1 at a row that's part of the copy cycle.
482 auto& sigma_1 = prover_instance->polynomials.sigma_1();
483 auto& id_1 = prover_instance->polynomials.id_1();
484
485 // Find the first row that's part of a non-trivial cycle (sigma != id)
486 size_t row_to_corrupt = 0;
487 for (size_t row = 1; row < sigma_1.size(); ++row) {
488 if (sigma_1.at(row) != id_1.at(row)) {
489 row_to_corrupt = row;
490 vinfo("Found copy cycle at row ", row, "; will corrupt this one");
491 break;
492 }
493 }
494 ASSERT_NE(row_to_corrupt, 0) << "No copy cycle found in sigma_1!";
495
496 fr original_value = sigma_1.at(row_to_corrupt);
497 sigma_1.at(row_to_corrupt) = original_value + fr(1); // Break the cycle by pointing elsewhere
498 // We perform two distinct tests.
499 //
500 // Failure test 1: make sure that the subrelation fails when when we change sigma_1 without updating z_perm.
501 {
502 auto failures_of_tampered_instance = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
503 prover_instance->polynomials,
504 prover_instance->relation_parameters,
505 "Permutation Relation - After corrupting sigma_1");
506
507 ASSERT_TRUE(failures_of_tampered_instance.at(0));
508 }
509 // Failure test 2: make sure the subrelation fails when we DO update z_perm
510 {
511 // Sanity check: if we are recompute z_perm, the first different value will be at `row_to_corrupt + 1`. Store
512 // this to ensure that this value indeed changes.
513 auto& z_perm = prover_instance->polynomials.z_perm();
514 auto z_perm_before = z_perm.at(row_to_corrupt + 1);
515
516 // Recompute z_perm with the corrupted sigma.
517 size_t real_circuit_size = prover_instance->get_final_active_wire_idx() + 1;
518 compute_grand_product<Flavor, UltraPermutationRelation<fr>>(
519 prover_instance->polynomials, prover_instance->relation_parameters, real_circuit_size);
520 prover_instance->polynomials.set_shifted(); // Refresh z_perm_shift
521
522 // Verify z_perm actually changed after recomputation with corrupted sigma
523 auto z_perm_after = z_perm.at(row_to_corrupt + 1);
524 ASSERT_NE(z_perm_before, z_perm_after) << "z_perm should change after recomputing with corrupted sigma";
525
526 // After recomputing z_perm, we expect a failure at the very last active wire.
527 auto failures_of_tampered_instance = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
528 prover_instance->polynomials,
529 prover_instance->relation_parameters,
530 "Permutation Relation - After corrupting sigma_1 and recomputing z_perm");
531
532 ASSERT_EQ(failures_of_tampered_instance.at(0), real_circuit_size - 1)
533 << "Expected failure at row " << (real_circuit_size - 1) << " (the recomputation boundary)";
534 }
535}
536
547TYPED_TEST(PermutationNonZKTests, PublicInputDeltaMismatch)
548{
549 using Flavor = TypeParam;
552 using Prover = typename TestFixture::Prover;
553
554 auto builder = typename Flavor::CircuitBuilder();
555
556 // Add a public input
557 fr public_value = fr(314159);
558 auto pub_var = builder.add_public_variable(public_value);
559
560 // Use the public input in a simple constraint so it appears in the trace
561 auto private_val = fr::random_element();
562 auto private_var = builder.add_variable(private_val);
563 auto result_var = builder.add_variable(public_value + private_val);
564 builder.create_add_gate({ pub_var, private_var, result_var, 1, 1, -1, 0 });
565
566 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
567
568 auto prover_instance = std::make_shared<ProverInstance>(builder);
569 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
570
571 // Construct proof to compute z_perm (with correct public_input_delta)
572 Prover prover(prover_instance, verification_key);
573 auto proof = prover.construct_proof();
574
575 // Verify the permutation relation holds before tampering
576 auto permutation_relation_failures = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
577 prover_instance->polynomials, prover_instance->relation_parameters, "Permutation Relation - Before Tampering");
578 ASSERT_TRUE(permutation_relation_failures.empty());
579
580 // Store the original public_input_delta
581 fr original_delta = prover_instance->relation_parameters.public_input_delta;
582
583 // TAMPER
584
585 // Recompute public_input_delta with a different public input value
586 // The wire polynomials still contain the original value (314159), but we compute delta as if it were 99999
587 fr tampered_public_val = fr(99999);
588 std::vector<fr> tampered_public_inputs = { tampered_public_val };
589 fr tampered_delta = compute_public_input_delta<Flavor>(tampered_public_inputs,
590 prover_instance->relation_parameters.beta,
591 prover_instance->relation_parameters.gamma,
592 prover_instance->pub_inputs_offset());
593
594 // Sanity check: the tampered delta should differ from the original
595 ASSERT_NE(original_delta, tampered_delta) << "Tampered delta should differ from original";
596
597 // Apply the tampered delta
598 prover_instance->relation_parameters.public_input_delta = tampered_delta;
599
600 // Verify the permutation relation now fails
601 auto failures_of_tampered_instance = RelationChecker<Flavor>::template check<UltraPermutationRelation<fr>>(
602 prover_instance->polynomials,
603 prover_instance->relation_parameters,
604 "Permutation Relation - After tampering with public_input_delta");
605 // The failure should be in subrelation 0 (the recurrence relation) since z_perm was computed with
606 // a different public_input_delta than what we're now using in the relation check
607 ASSERT_TRUE(failures_of_tampered_instance.contains(0)) << "Expected subrelation 0 to fail";
608 size_t final_active_wire_idx = prover_instance->get_final_active_wire_idx();
609 ASSERT_TRUE(failures_of_tampered_instance.at(0) == final_active_wire_idx);
610}
ECCVMCircuitBuilder CircuitBuilder
FixedVKAndHash_< PrecomputedEntities< Commitment >, BF, ECCVMHardcodedVKAndHash > VerificationKey
The verification key stores commitments to the precomputed polynomials used by the verifier.
Base Native verification key class.
Definition flavor.hpp:138
Contains all the information required by a Honk prover to create a proof, constructed from a finalize...
static constexpr size_t TRACE_OFFSET
A debugging utility for checking whether a set of polynomials satisfies the relations for a given Fla...
Child class of UltraFlavor that runs with ZK Sumcheck.
#define vinfo(...)
Definition log.hpp:94
AluTraceBuilder builder
Definition alu.test.cpp:124
FF a
FF b
testing::Types< UltraFlavor, UltraKeccakFlavor, MegaFlavor > FlavorTypes
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
field< Bn254FrParams > fr
Definition fr.hpp:155
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
testing::Types< UltraFlavor, UltraKeccakFlavor, MegaFlavor > NonZKFlavorTypes
static field random_element(numeric::RNG *engine=nullptr) noexcept