Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
mega_honk.test.cpp
Go to the documentation of this file.
1#include <cstddef>
2#include <cstdint>
3#include <gtest/gtest.h>
4
15
16using namespace bb;
17
19
20using FlavorTypes = ::testing::Types<MegaFlavor, MegaZKFlavor>;
21
22template <typename Flavor> class MegaHonkTests : public ::testing::Test {
23 public:
25
35
41 {
42 auto prover_instance = std::make_shared<ProverInstance>(builder);
43 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
44 Prover prover(prover_instance, verification_key);
45 Verifier verifier(verification_key);
46 auto proof = prover.construct_proof();
47 bool verified = verifier.template verify_proof<DefaultIO>(proof).result;
48
49 return verified;
50 }
51
57 {
58 // no ZK flavor for now
63 auto prover_instance = std::make_shared<ProverInstance>(builder, trace_settings);
64
65 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
66 Prover prover(prover_instance, verification_key);
67 Verifier verifier(verification_key);
68 auto proof = prover.construct_proof();
69 bool verified = verifier.template verify_proof<DefaultIO>(proof).result;
70
71 return verified;
72 }
73
78 bool construct_and_verify_merge_proof(auto& op_queue, MergeSettings settings = MergeSettings::PREPEND)
79 {
80 MergeProver merge_prover{ op_queue, settings };
81 MergeVerifier merge_verifier{ settings };
82 auto merge_proof = merge_prover.construct_proof();
83
84 // Construct Merge commitments
85 MergeVerifier::InputCommitments merge_commitments;
86 auto t_current = op_queue->construct_current_ultra_ops_subtable_columns();
87 auto T_prev = op_queue->construct_previous_ultra_ops_table_columns();
88 for (size_t idx = 0; idx < Flavor::NUM_WIRES; idx++) {
89 merge_commitments.t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]);
90 merge_commitments.T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]);
91 }
92
93 auto [verified, _] = merge_verifier.verify_proof(merge_proof, merge_commitments);
94
95 return verified;
96 }
97};
98
100
110TYPED_TEST(MegaHonkTests, ProofLengthCheck)
111{
112 using Flavor = TypeParam;
115
116 auto builder = Builder{};
117 DefaultIO::add_default(builder);
118
119 // Construct a mega proof and ensure its size matches expectation; if not, the constant may need to be updated
120 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder);
121 auto verification_key = std::make_shared<typename Flavor::VerificationKey>(prover_instance->get_precomputed());
122 UltraProver_<Flavor> prover(prover_instance, verification_key);
123 HonkProof mega_proof = prover.construct_proof();
125}
126
132TYPED_TEST(MegaHonkTests, MergeProofSizeCheck)
133{
134 using Flavor = TypeParam;
135
136 auto builder = typename Flavor::CircuitBuilder{};
138
139 // Construct a merge proof and ensure its size matches expectation; if not, the constant may need to be updated
140 MergeProver merge_prover{ builder.op_queue };
141 auto merge_proof = merge_prover.construct_proof();
142
143 EXPECT_EQ(merge_proof.size(), MERGE_PROOF_SIZE);
144}
145
152{
153 using Flavor = TypeParam;
155
157
158 // Construct and verify Honk proof
159 bool honk_verified = this->construct_and_verify_honk_proof(builder);
160 EXPECT_TRUE(honk_verified);
161}
162
167TYPED_TEST(MegaHonkTests, BasicStructured)
168{
169 using Flavor = TypeParam;
170
171 // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i for
172 // i=1,2,3. This mechanism does not work with structured polynomials yet.
174 GTEST_SKIP() << "Skipping 'BasicStructured' test for MegaZKFlavor.";
175 }
177 using Prover = UltraProver_<Flavor>;
178 using Verifier = UltraVerifier_<Flavor>;
179
181
182 // Construct and verify Honk proof using a structured trace
183 TraceSettings trace_settings{ SMALL_TEST_STRUCTURE };
184 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder, trace_settings);
185 auto verification_key = std::make_shared<typename Flavor::VerificationKey>(prover_instance->get_precomputed());
186 Prover prover(prover_instance, verification_key);
187 Verifier verifier(verification_key);
188 auto proof = prover.construct_proof();
189
190 // Sanity check: ensure z_perm is not zero everywhere
191 EXPECT_TRUE(!prover_instance->polynomials.z_perm.is_zero());
192
193 RelationChecker<Flavor>::check_all(prover_instance->polynomials, prover_instance->relation_parameters);
194
195 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
196 EXPECT_TRUE(result);
197}
198
204TYPED_TEST(MegaHonkTests, DynamicVirtualSizeIncrease)
205{
206 using Flavor = TypeParam;
207
208 // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i for
209 // i=1,2,3. This mechanism does not work with structured polynomials yet.
211 GTEST_SKIP() << "Skipping 'DynamicVirtualSizeIncrease' test for MegaZKFlavor.";
212 }
214 using Prover = UltraProver_<Flavor>;
215 using Verifier = UltraVerifier_<Flavor>;
216
218
219 auto builder_copy = builder;
220
221 // Construct and verify Honk proof using a structured trace
222 TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS };
223 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder, trace_settings);
224 auto prover_instance_copy = std::make_shared<ProverInstance_<Flavor>>(builder_copy, trace_settings);
225 auto circuit_size = prover_instance->dyadic_size();
226
227 auto doubled_circuit_size = 2 * circuit_size;
228 prover_instance_copy->polynomials.increase_polynomials_virtual_size(doubled_circuit_size);
229 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1158)
230 // prover_instance_copy->dyadic_circuit_size = doubled_circuit_size;
231
232 auto verification_key = std::make_shared<typename Flavor::VerificationKey>(prover_instance->get_precomputed());
233 Prover prover(prover_instance, verification_key);
234
235 auto verification_key_copy = std::make_shared<typename Flavor::VerificationKey>(prover_instance->get_precomputed());
236 Prover prover_copy(prover_instance_copy, verification_key_copy);
237
238 for (auto [entry, entry_copy] : zip_view(verification_key->get_all(), verification_key_copy->get_all())) {
239 EXPECT_EQ(entry, entry_copy);
240 }
241
242 Verifier verifier(verification_key);
243 auto proof = prover.construct_proof();
244
245 RelationChecker<Flavor>::check_all(prover_instance->polynomials, prover_instance->relation_parameters);
246 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
247 EXPECT_TRUE(result);
248
249 Verifier verifier_copy(verification_key_copy);
250 auto proof_copy = prover_copy.construct_proof();
251
252 RelationChecker<Flavor>::check_all(prover_instance->polynomials, prover_instance->relation_parameters);
253 bool result_copy = verifier_copy.template verify_proof<DefaultIO>(proof_copy).result;
254 EXPECT_TRUE(result_copy);
255}
256
265{
266 using Flavor = TypeParam;
267 auto builder = typename Flavor::CircuitBuilder{};
268
270
271 // Construct and verify Honk proof
272 bool honk_verified = this->construct_and_verify_honk_proof(builder);
273 EXPECT_TRUE(honk_verified);
274
275 // Construct and verify Goblin ECC op queue Merge proof
276 auto merge_verified = this->construct_and_verify_merge_proof(builder.op_queue);
277 EXPECT_TRUE(merge_verified);
278}
279
285TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly)
286{
287 using Flavor = TypeParam;
288 // Instantiate EccOpQueue. This will be shared across all circuits in the series
289 auto op_queue = std::make_shared<bb::ECCOpQueue>();
290 // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each.
291 size_t NUM_CIRCUITS = 3;
292 for (size_t i = 0; i < NUM_CIRCUITS; ++i) {
293 auto builder = typename Flavor::CircuitBuilder{ op_queue };
294
296
297 // Construct and verify Goblin ECC op queue Merge proof
298 auto merge_verified = this->construct_and_verify_merge_proof(op_queue);
299 EXPECT_TRUE(merge_verified);
300 }
301}
302
303TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnlyPrependThenAppend)
304{
305 using Flavor = TypeParam;
306 // Instantiate EccOpQueue. This will be shared across all circuits in the series
307 auto op_queue = std::make_shared<bb::ECCOpQueue>();
308 // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each.
309 size_t NUM_CIRCUITS = 3;
310 for (size_t i = 0; i < NUM_CIRCUITS; ++i) {
311 auto builder = typename Flavor::CircuitBuilder{ op_queue };
312
314
315 // Construct and verify Goblin ECC op queue Merge proof
316 auto merge_verified = this->construct_and_verify_merge_proof(op_queue);
317 EXPECT_TRUE(merge_verified);
318 }
319
320 // Construct a final circuit and append its ecc ops to the op queue
321 auto builder = typename Flavor::CircuitBuilder{ op_queue };
322
324
325 // Construct and verify Goblin ECC op queue Merge proof
326 auto merge_verified = this->construct_and_verify_merge_proof(op_queue, MergeSettings::APPEND);
327 EXPECT_TRUE(merge_verified);
328}
329
335TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkOnly)
336{
337 using Flavor = TypeParam;
338
339 // Instantiate EccOpQueue. This will be shared across all circuits in the series
340 auto op_queue = std::make_shared<bb::ECCOpQueue>();
341 // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each.
342 size_t NUM_CIRCUITS = 3;
343 for (size_t i = 0; i < NUM_CIRCUITS; ++i) {
344 auto builder = typename Flavor::CircuitBuilder{ op_queue };
346 // Construct and verify Honk proof
347 bool honk_verified = this->construct_and_verify_honk_proof(builder);
348 EXPECT_TRUE(honk_verified);
349 // Artificially merge the op queue sincer we're not running the merge protocol in this test
350 builder.op_queue->merge();
351 }
352}
353
359TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge)
360{
361 using Flavor = TypeParam;
362
363 // Instantiate EccOpQueue. This will be shared across all circuits in the series
364 auto op_queue = std::make_shared<bb::ECCOpQueue>();
365 // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each.
366 size_t NUM_CIRCUITS = 3;
367 for (size_t i = 0; i < NUM_CIRCUITS; ++i) {
368 auto builder = typename Flavor::CircuitBuilder{ op_queue };
369
371
372 // Construct and verify Honk proof
373 bool honk_verified = this->construct_and_verify_honk_proof(builder);
374 EXPECT_TRUE(honk_verified);
375
376 // Construct and verify Goblin ECC op queue Merge proof
377 auto merge_verified = this->construct_and_verify_merge_proof(op_queue);
378 EXPECT_TRUE(merge_verified);
379 }
380
381 // Construct a final circuit whose ecc ops will be appended rather than prepended to the op queue
382 auto builder = typename Flavor::CircuitBuilder{ op_queue };
383
385
386 // Construct and verify Honk proof
387 bool honk_verified = this->construct_and_verify_honk_proof(builder);
388 EXPECT_TRUE(honk_verified);
389
390 // Construct and verify Goblin ECC op queue Merge proof
391 auto merge_verified = this->construct_and_verify_merge_proof(op_queue, MergeSettings::APPEND);
392 EXPECT_TRUE(merge_verified);
393}
394
399TYPED_TEST(MegaHonkTests, StructuredTraceOverflow)
400{
401 using Flavor = TypeParam;
403
404 TraceSettings trace_settings{ TINY_TEST_STRUCTURE };
405
406 { // Overflow in Arithmetic block only
408
411
412 bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings);
413 EXPECT_TRUE(verified);
414
415 // We expect that the circuit has overflowed the provided structured trace
416 EXPECT_TRUE(builder.blocks.has_overflow);
417 }
418
419 { // Overflow in Aux block (RAM gates; uses memory records which requires specific logic in overflow mechanism)
421
424
425 bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings);
426 EXPECT_TRUE(verified);
427
428 // We expect that the circuit has overflowed the provided structured trace
429 EXPECT_TRUE(builder.blocks.has_overflow);
430 }
431
432 { // Overflow in Lookup block only
434
436 MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8);
437
438 bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings);
439 EXPECT_TRUE(verified);
440
441 // We expect that the circuit has overflowed the provided structured trace
442 EXPECT_TRUE(builder.blocks.has_overflow);
443 }
444
445 { // Overflow in Multiple blocks simultaneously
447
451 MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8);
452
453 bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings);
454 EXPECT_TRUE(verified);
455
456 // We expect that the circuit has overflowed the provided structured trace
457 EXPECT_TRUE(builder.blocks.has_overflow);
458 }
459}
460
469{
470 using Flavor = TypeParam;
471 // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i, for
472 // i=1,2,3. This mechanism does not work with structured polynomials yet.
474 GTEST_SKIP() << "Skipping 'PolySwap' test for MegaZKFlavor.";
475 }
477
478 TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS };
479
480 // Construct a simple circuit and make a copy of it
483 auto builder_copy = builder;
484
485 // Construct two identical proving keys
486 auto prover_instance_1 = std::make_shared<typename TestFixture::ProverInstance>(builder, trace_settings);
487 auto prover_instance_2 = std::make_shared<typename TestFixture::ProverInstance>(builder_copy, trace_settings);
488
489 // Tamper with the polys of pkey 1 in such a way that verification should fail
490 for (size_t i = 0; i < prover_instance_1->dyadic_size(); ++i) {
491 if (prover_instance_1->polynomials.q_arith[i] != 0) {
492 prover_instance_1->polynomials.w_l.at(i) += 1;
493 break;
494 }
495 }
496
497 // Swap the polys of the two proving keys; result should be pkey 1 is valid and pkey 2 should fail
498 std::swap(prover_instance_1->polynomials, prover_instance_2->polynomials);
499
500 { // Verification based on pkey 1 should succeed
501 auto verification_key =
502 std::make_shared<typename TestFixture::VerificationKey>(prover_instance_1->get_precomputed());
503 typename TestFixture::Prover prover(prover_instance_1, verification_key);
504 typename TestFixture::Verifier verifier(verification_key);
505 auto proof = prover.construct_proof();
506 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
507 EXPECT_TRUE(result);
508 }
509
510 { // Verification based on pkey 2 should fail
511 auto verification_key =
512 std::make_shared<typename TestFixture::VerificationKey>(prover_instance_2->get_precomputed());
513 typename TestFixture::Prover prover(prover_instance_2, verification_key);
514 typename TestFixture::Verifier verifier(verification_key);
515 auto proof = prover.construct_proof();
516 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
517 EXPECT_FALSE(result);
518 }
519}
520
528TYPED_TEST(MegaHonkTests, OpQueueWithRandomValues)
529{
530 using Flavor = TypeParam;
532
533 // Test for randomness added at the beginning
534 {
538
539 // Construct and verify Honk proof
540 bool honk_verified = this->construct_and_verify_honk_proof(builder);
541 EXPECT_TRUE(honk_verified);
542 }
543
544 // Test for randomness added at the end
545 {
549
550 // Construct and verify Honk proof
551 bool honk_verified = this->construct_and_verify_honk_proof(builder);
552 EXPECT_TRUE(honk_verified);
553 }
554}
Curve::AffineElement Point
bool construct_and_verify_merge_proof(auto &op_queue, MergeSettings settings=MergeSettings::PREPEND)
Construct and verify a Goblin ECC op queue merge proof.
bool construct_and_verify_honk_proof_with_structured_trace(auto &builder, TraceSettings &trace_settings)
Construct and a verify a Honk proof using a specified structured trace.
typename Flavor::VerificationKey VerificationKey
static void SetUpTestSuite()
bool construct_and_verify_honk_proof(auto &builder)
Construct and a verify a Honk proof.
CommitmentKey object over a pairing group 𝔾₁.
Manages the data that is propagated on the public inputs of an application/function circuit.
static constexpr size_t PUBLIC_INPUTS_SIZE
static constexpr size_t PROOF_LENGTH_WITHOUT_PUB_INPUTS
static void construct_simple_circuit(MegaBuilder &builder)
Generate a simple test circuit with some ECC op gates and conventional arithmetic gates.
static void randomise_op_queue(MegaBuilder &builder, size_t num_ops)
Add some randomness into the op queue.
The verification key is responsible for storing the commitments to the precomputed (non-witness) poly...
static constexpr size_t NUM_WIRES
MegaCircuitBuilder CircuitBuilder
Prover class for the Goblin ECC op queue transcript merge protocol.
std::shared_ptr< ECCOpQueue > op_queue
Verifier class for the Goblin ECC op queue transcript merge protocol.
static void add_RAM_gates(Builder &builder)
Add some simple RAM (memory) gates for testing memory read/write functionality.
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...
static void check_all(const auto &polynomials, const auto &params)
Check that the provided polynomials satisfy all relations for a given Flavor.
The VerifierInstance encapsulates all the necessary information for a Mega Honk Verifier to verify a ...
typename Group::affine_element AffineElement
Definition bn254.hpp:22
bb::fr ScalarField
Definition bn254.hpp:18
Manages the data that is propagated on the public inputs of an application/function circuit.
AluTraceBuilder builder
Definition alu.test.cpp:123
auto & engine
testing::Types< MegaFlavor, UltraFlavor, UltraZKFlavor, UltraRollupFlavor > FlavorTypes
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.
std::vector< fr > HonkProof
Definition proof.hpp:15
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
MergeSettings
The MergeSettings define whether an current subtable will be added at the beginning (PREPEND) or at t...
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13