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 {
43 auto verification_key = std::make_shared<VerificationKey>(proving_key->get_precomputed());
44 Prover prover(proving_key, 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 proving_key = std::make_shared<DeciderProvingKey>(builder, trace_settings);
64
65 auto verification_key = std::make_shared<VerificationKey>(proving_key->get_precomputed());
66 Prover prover(proving_key, 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
121 auto verification_key = std::make_shared<typename Flavor::VerificationKey>(proving_key->get_precomputed());
122 UltraProver_<Flavor> prover(proving_key, 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.
173 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1240) Structured Polynomials in
174 // ECCVM/Translator/MegaZK
176 GTEST_SKIP() << "Skipping 'BasicStructured' test for MegaZKFlavor.";
177 }
179 using Prover = UltraProver_<Flavor>;
180 using Verifier = UltraVerifier_<Flavor>;
181
183
184 // Construct and verify Honk proof using a structured trace
185 TraceSettings trace_settings{ SMALL_TEST_STRUCTURE };
186 auto proving_key = std::make_shared<DeciderProvingKey_<Flavor>>(builder, trace_settings);
187 auto verification_key = std::make_shared<typename Flavor::VerificationKey>(proving_key->get_precomputed());
188 Prover prover(proving_key, verification_key);
189 Verifier verifier(verification_key);
190 auto proof = prover.construct_proof();
191
192 // Sanity check: ensure z_perm is not zero everywhere
193 EXPECT_TRUE(!proving_key->polynomials.z_perm.is_zero());
194
195 RelationChecker<Flavor>::check_all(proving_key->polynomials, proving_key->relation_parameters);
196
197 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
198 EXPECT_TRUE(result);
199}
200
206TYPED_TEST(MegaHonkTests, DynamicVirtualSizeIncrease)
207{
208 using Flavor = TypeParam;
209
210 // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i for
211 // i=1,2,3. This mechanism does not work with structured polynomials yet.
212 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1240) Structured Polynomials in
213 // ECCVM/Translator/MegaZK
215 GTEST_SKIP() << "Skipping 'DynamicVirtualSizeIncrease' test for MegaZKFlavor.";
216 }
218 using Prover = UltraProver_<Flavor>;
219 using Verifier = UltraVerifier_<Flavor>;
220
222
223 auto builder_copy = builder;
224
225 // Construct and verify Honk proof using a structured trace
226 TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS };
227 auto proving_key = std::make_shared<DeciderProvingKey_<Flavor>>(builder, trace_settings);
228 auto proving_key_copy = std::make_shared<DeciderProvingKey_<Flavor>>(builder_copy, trace_settings);
229 auto circuit_size = proving_key->dyadic_size();
230
231 auto doubled_circuit_size = 2 * circuit_size;
232 proving_key_copy->polynomials.increase_polynomials_virtual_size(doubled_circuit_size);
233 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1158)
234 // proving_key_copy->dyadic_circuit_size = doubled_circuit_size;
235
236 auto verification_key = std::make_shared<typename Flavor::VerificationKey>(proving_key->get_precomputed());
237 Prover prover(proving_key, verification_key);
238
239 auto verification_key_copy = std::make_shared<typename Flavor::VerificationKey>(proving_key->get_precomputed());
240 Prover prover_copy(proving_key_copy, verification_key_copy);
241
242 for (auto [entry, entry_copy] : zip_view(verification_key->get_all(), verification_key_copy->get_all())) {
243 EXPECT_EQ(entry, entry_copy);
244 }
245
246 Verifier verifier(verification_key);
247 auto proof = prover.construct_proof();
248
249 RelationChecker<Flavor>::check_all(proving_key->polynomials, proving_key->relation_parameters);
250 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
251 EXPECT_TRUE(result);
252
253 Verifier verifier_copy(verification_key_copy);
254 auto proof_copy = prover_copy.construct_proof();
255
256 RelationChecker<Flavor>::check_all(proving_key->polynomials, proving_key->relation_parameters);
257 bool result_copy = verifier_copy.template verify_proof<DefaultIO>(proof_copy).result;
258 EXPECT_TRUE(result_copy);
259}
260
269{
270 using Flavor = TypeParam;
271 auto builder = typename Flavor::CircuitBuilder{};
272
274
275 // Construct and verify Honk proof
276 bool honk_verified = this->construct_and_verify_honk_proof(builder);
277 EXPECT_TRUE(honk_verified);
278
279 // Construct and verify Goblin ECC op queue Merge proof
280 auto merge_verified = this->construct_and_verify_merge_proof(builder.op_queue);
281 EXPECT_TRUE(merge_verified);
282}
283
289TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly)
290{
291 using Flavor = TypeParam;
292 // Instantiate EccOpQueue. This will be shared across all circuits in the series
293 auto op_queue = std::make_shared<bb::ECCOpQueue>();
294 // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each.
295 size_t NUM_CIRCUITS = 3;
296 for (size_t i = 0; i < NUM_CIRCUITS; ++i) {
297 auto builder = typename Flavor::CircuitBuilder{ op_queue };
298
300
301 // Construct and verify Goblin ECC op queue Merge proof
302 auto merge_verified = this->construct_and_verify_merge_proof(op_queue);
303 EXPECT_TRUE(merge_verified);
304 }
305}
306
307TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnlyPrependThenAppend)
308{
309 using Flavor = TypeParam;
310 // Instantiate EccOpQueue. This will be shared across all circuits in the series
311 auto op_queue = std::make_shared<bb::ECCOpQueue>();
312 // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each.
313 size_t NUM_CIRCUITS = 3;
314 for (size_t i = 0; i < NUM_CIRCUITS; ++i) {
315 auto builder = typename Flavor::CircuitBuilder{ op_queue };
316
318
319 // Construct and verify Goblin ECC op queue Merge proof
320 auto merge_verified = this->construct_and_verify_merge_proof(op_queue);
321 EXPECT_TRUE(merge_verified);
322 }
323
324 // Construct a final circuit and append its ecc ops to the op queue
325 auto builder = typename Flavor::CircuitBuilder{ op_queue };
326
328
329 // Construct and verify Goblin ECC op queue Merge proof
330 auto merge_verified = this->construct_and_verify_merge_proof(op_queue, MergeSettings::APPEND);
331 EXPECT_TRUE(merge_verified);
332}
333
339TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkOnly)
340{
341 using Flavor = TypeParam;
342
343 // Instantiate EccOpQueue. This will be shared across all circuits in the series
344 auto op_queue = std::make_shared<bb::ECCOpQueue>();
345 // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each.
346 size_t NUM_CIRCUITS = 3;
347 for (size_t i = 0; i < NUM_CIRCUITS; ++i) {
348 auto builder = typename Flavor::CircuitBuilder{ op_queue };
350 // Construct and verify Honk proof
351 bool honk_verified = this->construct_and_verify_honk_proof(builder);
352 EXPECT_TRUE(honk_verified);
353 // Artificially merge the op queue sincer we're not running the merge protocol in this test
354 builder.op_queue->merge();
355 }
356}
357
363TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge)
364{
365 using Flavor = TypeParam;
366
367 // Instantiate EccOpQueue. This will be shared across all circuits in the series
368 auto op_queue = std::make_shared<bb::ECCOpQueue>();
369 // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each.
370 size_t NUM_CIRCUITS = 3;
371 for (size_t i = 0; i < NUM_CIRCUITS; ++i) {
372 auto builder = typename Flavor::CircuitBuilder{ op_queue };
373
375
376 // Construct and verify Honk proof
377 bool honk_verified = this->construct_and_verify_honk_proof(builder);
378 EXPECT_TRUE(honk_verified);
379
380 // Construct and verify Goblin ECC op queue Merge proof
381 auto merge_verified = this->construct_and_verify_merge_proof(op_queue);
382 EXPECT_TRUE(merge_verified);
383 }
384
385 // Construct a final circuit whose ecc ops will be appended rather than prepended to the op queue
386 auto builder = typename Flavor::CircuitBuilder{ op_queue };
387
389
390 // Construct and verify Honk proof
391 bool honk_verified = this->construct_and_verify_honk_proof(builder);
392 EXPECT_TRUE(honk_verified);
393
394 // Construct and verify Goblin ECC op queue Merge proof
395 auto merge_verified = this->construct_and_verify_merge_proof(op_queue, MergeSettings::APPEND);
396 EXPECT_TRUE(merge_verified);
397}
398
403TYPED_TEST(MegaHonkTests, StructuredTraceOverflow)
404{
405 using Flavor = TypeParam;
407
408 TraceSettings trace_settings{ TINY_TEST_STRUCTURE };
409
410 { // Overflow in Arithmetic block only
412
415
416 bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings);
417 EXPECT_TRUE(verified);
418
419 // We expect that the circuit has overflowed the provided structured trace
420 EXPECT_TRUE(builder.blocks.has_overflow);
421 }
422
423 { // Overflow in Aux block (RAM gates; uses memory records which requires specific logic in overflow mechanism)
425
428
429 bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings);
430 EXPECT_TRUE(verified);
431
432 // We expect that the circuit has overflowed the provided structured trace
433 EXPECT_TRUE(builder.blocks.has_overflow);
434 }
435
436 { // Overflow in Lookup block only
438
440 MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8);
441
442 bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings);
443 EXPECT_TRUE(verified);
444
445 // We expect that the circuit has overflowed the provided structured trace
446 EXPECT_TRUE(builder.blocks.has_overflow);
447 }
448
449 { // Overflow in Multiple blocks simultaneously
451
455 MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8);
456
457 bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings);
458 EXPECT_TRUE(verified);
459
460 // We expect that the circuit has overflowed the provided structured trace
461 EXPECT_TRUE(builder.blocks.has_overflow);
462 }
463}
464
473{
474 using Flavor = TypeParam;
475 // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i, for
476 // i=1,2,3. This mechanism does not work with structured polynomials yet.
477 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1240) Structured Polynomials in
478 // ECCVM/Translator/MegaZK
480 GTEST_SKIP() << "Skipping 'PolySwap' test for MegaZKFlavor.";
481 }
483
484 TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS };
485
486 // Construct a simple circuit and make a copy of it
489 auto builder_copy = builder;
490
491 // Construct two identical proving keys
492 auto proving_key_1 = std::make_shared<typename TestFixture::DeciderProvingKey>(builder, trace_settings);
493 auto proving_key_2 = std::make_shared<typename TestFixture::DeciderProvingKey>(builder_copy, trace_settings);
494
495 // Tamper with the polys of pkey 1 in such a way that verification should fail
496 for (size_t i = 0; i < proving_key_1->dyadic_size(); ++i) {
497 if (proving_key_1->polynomials.q_arith[i] != 0) {
498 proving_key_1->polynomials.w_l.at(i) += 1;
499 break;
500 }
501 }
502
503 // Swap the polys of the two proving keys; result should be pkey 1 is valid and pkey 2 should fail
504 std::swap(proving_key_1->polynomials, proving_key_2->polynomials);
505
506 { // Verification based on pkey 1 should succeed
507 auto verification_key =
508 std::make_shared<typename TestFixture::VerificationKey>(proving_key_1->get_precomputed());
509 typename TestFixture::Prover prover(proving_key_1, verification_key);
510 typename TestFixture::Verifier verifier(verification_key);
511 auto proof = prover.construct_proof();
512 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
513 EXPECT_TRUE(result);
514 }
515
516 { // Verification based on pkey 2 should fail
517 auto verification_key =
518 std::make_shared<typename TestFixture::VerificationKey>(proving_key_2->get_precomputed());
519 typename TestFixture::Prover prover(proving_key_2, verification_key);
520 typename TestFixture::Verifier verifier(verification_key);
521 auto proof = prover.construct_proof();
522 bool result = verifier.template verify_proof<DefaultIO>(proof).result;
523 EXPECT_FALSE(result);
524 }
525}
526
534TYPED_TEST(MegaHonkTests, OpQueueWithRandomValues)
535{
536 using Flavor = TypeParam;
538
539 // Test for randomness added at the beginning
540 {
544
545 // Construct and verify Honk proof
546 bool honk_verified = this->construct_and_verify_honk_proof(builder);
547 EXPECT_TRUE(honk_verified);
548 }
549
550 // Test for randomness added at the end
551 {
555
556 // Construct and verify Honk proof
557 bool honk_verified = this->construct_and_verify_honk_proof(builder);
558 EXPECT_TRUE(honk_verified);
559 }
560}
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 𝔾₁.
A DeciderProvingKey is normally constructed from a finalized circuit and it contains all the informat...
The DeciderVerificationKey encapsulates all the necessary information for a Mega Honk Verifier to ver...
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, bool last_circuit=false)
Generate a simple test circuit with some ECC op gates and conventional arithmetic gates.
static void randomise_op_queue(MegaBuilder &builder)
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.
static void check_all(const auto &polynomials, const auto &params)
Check that the provided polynomials satisfy all relations for a given Flavor.
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