Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
eccvm.test.cpp
Go to the documentation of this file.
1#include <cstddef>
2#include <cstdint>
3#include <gtest/gtest.h>
4#include <vector>
5
20
21using namespace bb;
26class ECCVMTests : public ::testing::Test {
27 protected:
29};
30namespace {
32
39void add_hiding_op_for_test(const std::shared_ptr<ECCOpQueue>& op_queue)
40{
42 // Prepend a hiding op with random coordinates - provides statistical hiding
43 op_queue->append_hiding_op(Fq::random_element(), Fq::random_element());
44}
45} // namespace
46
54{
55 using Curve = curve::BN254;
56 using G1 = Curve::Element;
57 using Fr = Curve::ScalarField;
58
60 G1 a = G1::random_element(engine);
61 G1 b = G1::random_element(engine);
62 G1 c = G1::random_element(engine);
65
66 op_queue->add_accumulate(a);
67 op_queue->mul_accumulate(a, x);
68 op_queue->mul_accumulate(b, x);
69 op_queue->mul_accumulate(b, y);
70 op_queue->add_accumulate(a);
71 op_queue->mul_accumulate(b, x);
72 op_queue->eq_and_reset();
73 op_queue->add_accumulate(c);
74 op_queue->mul_accumulate(a, x);
75 op_queue->mul_accumulate(b, x);
76 op_queue->eq_and_reset();
77 op_queue->mul_accumulate(a, x);
78 op_queue->mul_accumulate(b, x);
79 op_queue->mul_accumulate(c, x);
80 op_queue->merge();
81 add_hiding_op_for_test(op_queue);
82 ECCVMCircuitBuilder builder{ op_queue };
83 return builder;
84}
85
86// returns a CircuitBuilder consisting of mul_add ops of the following form: either 0*g, for a group element, or
87// x * e, where x is a scalar and e is the identity element of the group.
88ECCVMCircuitBuilder generate_zero_circuit([[maybe_unused]] numeric::RNG* engine = nullptr, bool zero_scalars = 1)
89{
90 using Curve = curve::BN254;
91 using G1 = Curve::Element;
92 using Fr = Curve::ScalarField;
93
95
96 if (!zero_scalars) {
97 for (auto i = 0; i < 8; i++) {
99 op_queue->mul_accumulate(Curve::Group::affine_point_at_infinity, x);
100 }
101 } else {
102 for (auto i = 0; i < 8; i++) {
103 G1 g = G1::random_element(engine);
104 op_queue->mul_accumulate(g, 0);
105 }
106 }
107 op_queue->merge();
108 add_hiding_op_for_test(op_queue);
109
110 ECCVMCircuitBuilder builder{ op_queue };
111 return builder;
112}
113
116 std::vector<FF>& gate_challenges)
117{
118 // Prepare the inputs for the sumcheck prover:
119 // Compute and add beta to relation parameters
120 const FF beta = FF::random_element();
121 const FF gamma = FF::random_element();
122 const FF beta_sqr = beta * beta;
123 relation_parameters.gamma = gamma;
124 relation_parameters.beta = beta;
125 relation_parameters.beta_sqr = beta_sqr;
126 relation_parameters.beta_cube = beta_sqr * beta;
127 relation_parameters.eccvm_set_permutation_delta =
128 gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr);
129 relation_parameters.eccvm_set_permutation_delta = relation_parameters.eccvm_set_permutation_delta.invert();
130
131 const size_t unmasked_witness_size = pk->circuit_size - NUM_DISABLED_ROWS_IN_SUMCHECK;
132 // Compute z_perm and inverse polynomial for our logarithmic-derivative lookup method
133 compute_logderivative_inverse<FF, ECCVMFlavor::LookupRelation>(
134 pk->polynomials, relation_parameters, unmasked_witness_size);
135 compute_grand_products<ECCVMFlavor>(pk->polynomials, relation_parameters, unmasked_witness_size);
136
137 // Generate gate challenges
138 for (size_t idx = 0; idx < CONST_ECCVM_LOG_N; idx++) {
139 gate_challenges[idx] = FF::random_element();
140 }
141}
142TEST_F(ECCVMTests, ZeroesCoefficients)
143{
145
146 std::shared_ptr<Transcript> prover_transcript = std::make_shared<Transcript>();
147 ECCVMProver prover(builder, prover_transcript);
148 auto [proof, opening_claim] = prover.construct_proof();
149
150 // Compute IPA proof
151 auto ipa_transcript = std::make_shared<Transcript>();
152 ECCVMFlavor::PCS::compute_opening_proof(prover.key->commitment_key, opening_claim, ipa_transcript);
153
154 std::shared_ptr<Transcript> verifier_transcript = std::make_shared<Transcript>();
155 ECCVMVerifier verifier(verifier_transcript, proof);
156 auto verifier_opening_claim = verifier.verify_proof();
157
158 // Verify IPA
159 auto ipa_verifier_transcript = std::make_shared<Transcript>(ipa_transcript->export_proof());
160 bool ipa_verified = ECCVMFlavor::PCS::reduce_verify(
161 verifier.key->pcs_verification_key, verifier_opening_claim, ipa_verifier_transcript);
162
163 bool verified = ipa_verified && verifier.sumcheck_verified && verifier.consistency_checked &&
165
166 ASSERT_TRUE(verified);
167}
168TEST_F(ECCVMTests, PointAtInfinity)
169{
171
172 std::shared_ptr<Transcript> prover_transcript = std::make_shared<Transcript>();
173 ECCVMProver prover(builder, prover_transcript);
174 auto [proof, opening_claim] = prover.construct_proof();
175
176 auto ipa_transcript = std::make_shared<Transcript>();
177 ECCVMFlavor::PCS::compute_opening_proof(prover.key->commitment_key, opening_claim, ipa_transcript);
178
179 std::shared_ptr<Transcript> verifier_transcript = std::make_shared<Transcript>();
180 ECCVMVerifier verifier(verifier_transcript, proof);
181 auto verifier_opening_claim = verifier.verify_proof();
182
183 auto ipa_verifier_transcript = std::make_shared<Transcript>(ipa_transcript->export_proof());
184 bool ipa_verified = ECCVMFlavor::PCS::reduce_verify(
185 verifier.key->pcs_verification_key, verifier_opening_claim, ipa_verifier_transcript);
186
187 bool verified = ipa_verified && verifier.sumcheck_verified && verifier.consistency_checked &&
189
190 ASSERT_TRUE(verified);
191}
192TEST_F(ECCVMTests, ScalarEdgeCase)
193{
194 using Curve = curve::BN254;
195 using G1 = Curve::Element;
196 using Fr = Curve::ScalarField;
197
199 G1 a = G1::one();
200
201 op_queue->mul_accumulate(a, Fr(uint256_t(1) << 128));
202 op_queue->eq_and_reset();
203 op_queue->merge();
204 add_hiding_op_for_test(op_queue);
205 ECCVMCircuitBuilder builder{ op_queue };
206
207 std::shared_ptr<Transcript> prover_transcript = std::make_shared<Transcript>();
208 ECCVMProver prover(builder, prover_transcript);
209 auto [proof, opening_claim] = prover.construct_proof();
210
211 auto ipa_transcript = std::make_shared<Transcript>();
212 ECCVMFlavor::PCS::compute_opening_proof(prover.key->commitment_key, opening_claim, ipa_transcript);
213
214 std::shared_ptr<Transcript> verifier_transcript = std::make_shared<Transcript>();
215 ECCVMVerifier verifier(verifier_transcript, proof);
216 auto verifier_opening_claim = verifier.verify_proof();
217
218 auto ipa_verifier_transcript = std::make_shared<Transcript>(ipa_transcript->export_proof());
219 bool ipa_verified = ECCVMFlavor::PCS::reduce_verify(
220 verifier.key->pcs_verification_key, verifier_opening_claim, ipa_verifier_transcript);
221
222 bool verified = ipa_verified && verifier.sumcheck_verified && verifier.consistency_checked &&
224
225 ASSERT_TRUE(verified);
226}
234TEST_F(ECCVMTests, ProofLengthCheck)
235{
237
238 std::shared_ptr<Transcript> prover_transcript = std::make_shared<Transcript>();
239 ECCVMProver prover(builder, prover_transcript);
240 auto [proof, opening_claim] = prover.construct_proof();
241 EXPECT_EQ(proof.size(), ECCVMFlavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS);
242}
243
244TEST_F(ECCVMTests, BaseCaseFixedSize)
245{
247
248 std::shared_ptr<Transcript> prover_transcript = std::make_shared<Transcript>();
249 ECCVMProver prover(builder, prover_transcript);
250 auto [proof, opening_claim] = prover.construct_proof();
251
252 auto ipa_transcript = std::make_shared<Transcript>();
253 ECCVMFlavor::PCS::compute_opening_proof(prover.key->commitment_key, opening_claim, ipa_transcript);
254
255 std::shared_ptr<Transcript> verifier_transcript = std::make_shared<Transcript>();
256 ECCVMVerifier verifier(verifier_transcript, proof);
257 auto verifier_opening_claim = verifier.verify_proof();
258
259 auto ipa_verifier_transcript = std::make_shared<Transcript>(ipa_transcript->export_proof());
260 bool ipa_verified = ECCVMFlavor::PCS::reduce_verify(
261 verifier.key->pcs_verification_key, verifier_opening_claim, ipa_verifier_transcript);
262
263 bool verified = ipa_verified && verifier.sumcheck_verified && verifier.consistency_checked &&
265
266 ASSERT_TRUE(verified);
267}
268
269TEST_F(ECCVMTests, EqFailsFixedSize)
270{
272 // Tamper with the eq op such that the expected value is incorect
273 builder.op_queue->add_erroneous_equality_op_for_testing();
274 builder.op_queue->merge();
275
276 std::shared_ptr<Transcript> prover_transcript = std::make_shared<Transcript>();
277 ECCVMProver prover(builder, prover_transcript);
278
279 auto [proof, opening_claim] = prover.construct_proof();
280
281 auto ipa_transcript = std::make_shared<Transcript>();
282 ECCVMFlavor::PCS::compute_opening_proof(prover.key->commitment_key, opening_claim, ipa_transcript);
283
284 std::shared_ptr<Transcript> verifier_transcript = std::make_shared<Transcript>();
285 ECCVMVerifier verifier(verifier_transcript, proof);
286 auto verifier_opening_claim = verifier.verify_proof();
287
288 auto ipa_verifier_transcript = std::make_shared<Transcript>(ipa_transcript->export_proof());
289 bool ipa_verified = ECCVMFlavor::PCS::reduce_verify(
290 verifier.key->pcs_verification_key, verifier_opening_claim, ipa_verifier_transcript);
291
292 bool verified = ipa_verified && verifier.sumcheck_verified && verifier.consistency_checked &&
294 ASSERT_FALSE(verified);
295}
296
297TEST_F(ECCVMTests, CommittedSumcheck)
298{
299 using Flavor = ECCVMFlavor;
300 using ProvingKey = ECCVMFlavor::ProvingKey;
301 using FF = ECCVMFlavor::FF;
303 using ZKData = ZKSumcheckData<Flavor>;
304
305 bb::RelationParameters<FF> relation_parameters;
306 std::vector<FF> gate_challenges(CONST_ECCVM_LOG_N);
307
309 std::shared_ptr<Transcript> prover_transcript = std::make_shared<Transcript>();
310 ECCVMProver prover(builder, prover_transcript);
312
313 // Prepare the inputs for the sumcheck prover:
314 // Compute and add beta to relation parameters
315 const FF alpha = FF::random_element();
316 complete_proving_key_for_test(relation_parameters, pk, gate_challenges);
317
318 // Clear the transcript
319 prover_transcript = std::make_shared<Transcript>();
320
321 // Run Sumcheck on the ECCVM Prover polynomials
323 SumcheckProver sumcheck_prover(pk->circuit_size,
324 pk->polynomials,
325 prover_transcript,
326 alpha,
327 gate_challenges,
328 relation_parameters,
329 CONST_ECCVM_LOG_N);
330
331 ZKData zk_sumcheck_data = ZKData(CONST_ECCVM_LOG_N, prover_transcript);
332
333 auto prover_output = sumcheck_prover.prove(zk_sumcheck_data);
334
335 std::shared_ptr<Transcript> verifier_transcript = std::make_shared<Transcript>(prover_transcript->export_proof());
336
337 // Execute Sumcheck Verifier
338 SumcheckVerifier<Flavor> sumcheck_verifier(verifier_transcript, alpha, CONST_ECCVM_LOG_N);
339 std::vector<FF> padding_indicator_array(CONST_ECCVM_LOG_N, FF(1));
340 SumcheckOutput<ECCVMFlavor> verifier_output =
341 sumcheck_verifier.verify(relation_parameters, gate_challenges, padding_indicator_array);
342
343 // Evaluate prover's round univariates at corresponding challenges and compare them with the claimed evaluations
344 // computed by the verifier
345 for (size_t idx = 0; idx < CONST_ECCVM_LOG_N; idx++) {
346 FF true_eval_at_the_challenge = prover_output.round_univariates[idx].evaluate(prover_output.challenge[idx]);
347 FF verifier_eval_at_the_challenge = verifier_output.round_univariate_evaluations[idx][2];
348 EXPECT_TRUE(true_eval_at_the_challenge == verifier_eval_at_the_challenge);
349 }
350
351 // Check that the first sumcheck univariate is consistent with the claimed ZK Sumchek Sum
352 FF prover_target_sum = zk_sumcheck_data.libra_challenge * zk_sumcheck_data.libra_total_sum;
353
354 EXPECT_TRUE(prover_target_sum == verifier_output.round_univariate_evaluations[0][0] +
355 verifier_output.round_univariate_evaluations[0][1]);
356
357 EXPECT_TRUE(verifier_output.verified);
358}
359
367{
368 // Generate a circuit and its verification key (computed at runtime from the proving key)
370 std::shared_ptr<Transcript> prover_transcript = std::make_shared<Transcript>();
371 ECCVMProver prover(builder, prover_transcript);
372 auto [proof, opening_claim] = prover.construct_proof();
373
374 std::shared_ptr<Transcript> verifier_transcript = std::make_shared<Transcript>();
375 ECCVMVerifier verifier(verifier_transcript, proof);
376
377 // Generate the default fixed VK
379 // Generate a VK from PK
380 ECCVMFlavor::VerificationKey vk_computed_by_prover(prover.key);
381
382 // Set verifier PCS key to null in both the fixed VK and the generated VK
383 fixed_vk.pcs_verification_key = VerifierCommitmentKey<curve::Grumpkin>();
385
386 auto labels = verifier.key->get_labels();
387 size_t index = 0;
388 for (auto [vk_commitment, fixed_commitment] : zip_view(vk_computed_by_prover.get_all(), fixed_vk.get_all())) {
389 EXPECT_EQ(vk_commitment, fixed_commitment)
390 << "Mismatch between vk_commitment and fixed_commitment at label: " << labels[index];
391 ++index;
392 }
393
394 // Check that the fixed VK is equal to the generated VK
395 EXPECT_EQ(fixed_vk, vk_computed_by_prover);
396}
void SetUp() override
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
The proving key is responsible for storing the polynomials used by the prover.
The verification key is responsible for storing the commitments to the precomputed (non-witnessk) pol...
VerifierCommitmentKey pcs_verification_key
typename Curve::ScalarField FF
static constexpr size_t PROOF_LENGTH_WITHOUT_PUB_INPUTS
NativeTranscript Transcript
std::pair< Proof, OpeningClaim > construct_proof()
std::shared_ptr< ProvingKey > key
Unified ECCVM verifier class for both native and recursive verification.
bool translation_masking_consistency_checked
std::shared_ptr< VerificationKey > key
OpeningClaim< Curve > verify_proof()
Verifies an ECCVM Honk proof for given program settings.
The implementation of the sumcheck Prover for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:289
SumcheckOutput< Flavor > prove()
Non-ZK version: Compute round univariate, place it in transcript, compute challenge,...
Definition sumcheck.hpp:398
Implementation of the sumcheck Verifier for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:786
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, const std::vector< FF > &gate_challenges, const std::vector< FF > &padding_indicator_array)
The Sumcheck verification method. First it extracts round univariate, checks sum (the sumcheck univar...
Definition sumcheck.hpp:844
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
bb::fq BaseField
Definition bn254.hpp:19
typename Group::element Element
Definition grumpkin.hpp:62
AluTraceBuilder builder
Definition alu.test.cpp:124
FF a
FF b
void complete_proving_key_for_test(bb::RelationParameters< FF > &relation_parameters, std::shared_ptr< PK > &pk, std::vector< FF > &gate_challenges)
ECCVMFlavor::FF FF
ECCVMCircuitBuilder generate_zero_circuit(numeric::RNG *engine=nullptr, bool zero_scalars=1)
ECCVMCircuitBuilder generate_circuit(numeric::RNG *engine=nullptr)
Adds operations in BN254 to the op_queue and then constructs and ECCVM circuit from the op_queue.
numeric::RNG & engine
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:190
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Curve::ScalarField Fr
Curve::AffineElement G1
Container for parameters used by the grand product (permutation, lookup) Honk relations.
Contains the evaluations of multilinear polynomials at the challenge point . These are computed by S...
std::vector< std::array< FF, 3 > > round_univariate_evaluations
This structure is created to contain various polynomials and constants required by ZK Sumcheck.
static field random_element(numeric::RNG *engine=nullptr) noexcept