Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
kzg.test.cpp
Go to the documentation of this file.
1
2#include "kzg.hpp"
3#include "../commitment_key.test.hpp"
7
8namespace bb {
9using Curve = curve::BN254;
10
11class KZGTest : public CommitmentTest<Curve> {
12 public:
13 using Fr = typename Curve::ScalarField;
16
22
23 static constexpr size_t n = 16;
24 static constexpr size_t log_n = 4;
25
28 static CK ck;
29 static VK vk;
30
31 static constexpr Commitment g1_identity = Commitment::one();
32
33 static void SetUpTestSuite()
34 {
35 ck = create_commitment_key<CK>(n);
36 vk = create_verifier_commitment_key<VK>();
37 }
38
39 static void prove_and_verify(const OpeningPair<Curve>& opening_pair, bb::Polynomial<Fr>& witness)
40 {
41 const Commitment commitment = ck.commit(witness);
42
43 auto opening_claim = OpeningClaim<Curve>{ opening_pair, commitment };
44
45 auto prover_transcript = NativeTranscript::prover_init_empty();
46
47 PCS::compute_opening_proof(ck, { witness, opening_pair }, prover_transcript);
48
49 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
50 const auto pairing_points = PCS::reduce_verify(opening_claim, verifier_transcript);
51
52 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
53 }
54};
55
57{
58
59 auto witness = bb::Polynomial<Fr>::random(n);
60 const Fr challenge = Fr::random_element();
61 const Fr evaluation = witness.evaluate(challenge);
62
63 prove_and_verify({ challenge, evaluation }, witness);
64}
65
66TEST_F(KZGTest, ZeroEvaluation)
67{
68
69 auto witness = bb::Polynomial<Fr>::random(n);
70 const Fr challenge = Fr::random_element();
71 const Fr evaluation = witness.evaluate(challenge);
72
73 // Modify witness to achieve zero evaluation
74 witness.at(0) -= evaluation;
75
76 prove_and_verify({ challenge, Fr::zero() }, witness);
77}
78
79TEST_F(KZGTest, ZeroPolynomial)
80{
81 static constexpr size_t POLY_SIZE = 10;
82 bb::Polynomial<Fr> zero(POLY_SIZE);
83 for (size_t idx = 0; idx < POLY_SIZE; ++idx) {
84 zero.at(idx) = 0;
85 }
86
87 // Sanity check
88 ASSERT_TRUE(zero.is_zero());
89
90 const Fr challenge = Fr::random_element();
91 const Fr evaluation = zero.evaluate(challenge);
92
93 prove_and_verify({ challenge, evaluation }, zero);
94}
95
96TEST_F(KZGTest, ConstantPolynomial)
97{
98 auto constant = bb::Polynomial<Fr>::random(1);
99 const Fr challenge = Fr::random_element();
100 const Fr evaluation = constant.evaluate(challenge);
101
102 prove_and_verify({ challenge, evaluation }, constant);
103}
104
105TEST_F(KZGTest, EmptyPolynomial)
106{
107 bb::Polynomial<Fr> empty_poly;
108 const Fr challenge = Fr::random_element();
109 const Fr evaluation = empty_poly.evaluate(challenge);
110
111 prove_and_verify({ challenge, evaluation }, empty_poly);
112}
113
119TEST_F(KZGTest, SingleInLagrangeBasis)
120{
121 const size_t n = 4;
122
123 // create a random univariate (coefficients are in Lagrange basis)
124 auto witness = bb::Univariate<Fr, n>::get_random();
125 // define the interpolation domain
126 std::array<Fr, 4> eval_points = { Fr(0), Fr(1), Fr(2), Fr(3) };
127 // compute the monomial coefficients
128 bb::Polynomial<Fr> witness_polynomial(std::span<Fr>(eval_points), std::span<Fr>(witness), n);
129 // commit to the polynomial in the monomial form
130 g1::element commitment = ck.commit(witness_polynomial);
131
132 const Fr challenge = Fr::random_element();
133 // evaluate the original univariate
134 const Fr evaluation = witness.evaluate(challenge);
135 auto opening_pair = OpeningPair<Curve>{ challenge, evaluation };
136 auto opening_claim = OpeningClaim<Curve>{ opening_pair, commitment };
137
138 auto prover_transcript = NativeTranscript::prover_init_empty();
139
140 PCS::compute_opening_proof(ck, { witness_polynomial, opening_pair }, prover_transcript);
141
142 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
143 auto pairing_points = PCS::reduce_verify(opening_claim, verifier_transcript);
144
145 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
146}
153TEST_F(KZGTest, GeminiShplonkKzgWithShift)
154{
155
156 // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random
157 // point.
158 std::vector<Fr> mle_opening_point = random_evaluation_point(log_n); // sometimes denoted 'u'
159
160 MockClaimGenerator mock_claims(n,
161 /*num_polynomials*/ 2,
162 /*num_to_be_shifted*/ 1,
163 /*num_to_be_right_shifted_by_k*/ 0,
164 mle_opening_point,
165 ck);
166
167 auto prover_transcript = NativeTranscript::prover_init_empty();
168
169 // Run the full prover PCS protocol:
170
171 // Compute:
172 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
173 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
174 auto prover_opening_claims =
175 GeminiProver::prove(n, mock_claims.polynomial_batcher, mle_opening_point, ck, prover_transcript);
176
177 // Shplonk prover output:
178 // - opening pair: (z_challenge, 0)
179 // - witness: polynomial Q - Q_z
180 const auto opening_claim = ShplonkProver::prove(ck, prover_opening_claims, prover_transcript);
181
182 // KZG prover:
183 // - Adds commitment [W] to transcript
184 PCS::compute_opening_proof(ck, opening_claim, prover_transcript);
185
186 // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation)
187
188 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
189
190 // Gemini verifier output:
191 // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1
192 auto gemini_verifier_claim =
193 GeminiVerifier::reduce_verification(mle_opening_point, mock_claims.claim_batcher, verifier_transcript);
194
195 // Shplonk verifier claim: commitment [Q] - [Q_z], opening point (z_challenge, 0)
196 const auto shplonk_verifier_claim =
197 ShplonkVerifier::reduce_verification(vk.get_g1_identity(), gemini_verifier_claim, verifier_transcript);
198
199 // KZG verifier:
200 // aggregates inputs [Q] - [Q_z] and [W] into an 'accumulator' (can perform pairing check on result)
201 auto pairing_points = PCS::reduce_verify(shplonk_verifier_claim, verifier_transcript);
202
203 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
204
205 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
206}
207
208TEST_F(KZGTest, ShpleminiKzgWithShift)
209{
210 // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random
211 // point.
212 std::vector<Fr> mle_opening_point = random_evaluation_point(log_n); // sometimes denoted 'u'
213
214 MockClaimGenerator mock_claims(n,
215 /*num_polynomials*/ 4,
216 /*num_to_be_shifted*/ 2,
217 /*num_to_be_right_shifted_by_k*/ 0,
218 mle_opening_point,
219 ck);
220
221 auto prover_transcript = NativeTranscript::prover_init_empty();
222
223 // Run the full prover PCS protocol:
224
225 // Compute:
226 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
227 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
228 auto prover_opening_claims =
229 GeminiProver::prove(n, mock_claims.polynomial_batcher, mle_opening_point, ck, prover_transcript);
230
231 // Shplonk prover output:
232 // - opening pair: (z_challenge, 0)
233 // - witness: polynomial Q - Q_z
234 const auto opening_claim = ShplonkProver::prove(ck, prover_opening_claims, prover_transcript);
235
236 // KZG prover:
237 // - Adds commitment [W] to transcript
238 PCS::compute_opening_proof(ck, opening_claim, prover_transcript);
239
240 // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation)
241
242 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
243
244 // Gemini verifier output:
245 // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1
246 std::array<Fr, log_n> padding_indicator_array;
247 std::ranges::fill(padding_indicator_array, Fr{ 1 });
248
249 const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array,
250 mock_claims.claim_batcher,
251 mle_opening_point,
253 verifier_transcript);
254
255 const auto pairing_points = PCS::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript);
256 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
257
258 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
259}
260
261TEST_F(KZGTest, ShpleminiKzgWithShiftAndInterleaving)
262{
263 std::vector<Fr> mle_opening_point = random_evaluation_point(log_n); // sometimes denoted 'u'
264 // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random
265 // point.
266 MockClaimGenerator mock_claims(n,
267 /*num_polynomials*/ 4,
268 /*num_to_be_shifted*/ 2,
269 /*num_to_be_right_shifted_by_k*/ 0,
270 mle_opening_point,
271 ck,
272 3,
273 2);
274
275 auto prover_transcript = NativeTranscript::prover_init_empty();
276
277 // Run the full prover PCS protocol:
278
279 // Compute:
280 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
281 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
282 auto prover_opening_claims =
283 GeminiProver::prove(n, mock_claims.polynomial_batcher, mle_opening_point, ck, prover_transcript);
284
285 // Shplonk prover output:
286 // - opening pair: (z_challenge, 0)
287 // - witness: polynomial Q - Q_z
288 const auto opening_claim = ShplonkProver::prove(ck, prover_opening_claims, prover_transcript);
289
290 // KZG prover:
291 // - Adds commitment [W] to transcript
292 PCS::compute_opening_proof(ck, opening_claim, prover_transcript);
293
294 // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation)
295
296 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
297
298 // Gemini verifier output:
299 // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1
300 std::array<Fr, log_n> padding_indicator_array;
301 std::ranges::fill(padding_indicator_array, Fr{ 1 });
302
303 const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array,
304 mock_claims.claim_batcher,
305 mle_opening_point,
307 verifier_transcript,
308 /* repeated commitments= */ {},
309 /* has zk = */ {},
310 nullptr,
311 /* libra commitments = */ {},
312 /* libra evaluations = */ {},
313 {},
314 {});
315 const auto pairing_points = PCS::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript);
316 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
317
318 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
319}
320TEST_F(KZGTest, ShpleminiKzgShiftsRemoval)
321{
322 std::vector<Fr> mle_opening_point = random_evaluation_point(log_n); // sometimes denoted 'u'
323 // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random
324 // point.
325 MockClaimGenerator mock_claims(n,
326 /*num_polynomials*/ 4,
327 /*num_to_be_shifted*/ 2,
328 /*num_to_be_right_shifted_by_k*/ 0,
329 mle_opening_point,
330 ck);
331
332 auto prover_transcript = NativeTranscript::prover_init_empty();
333
334 // Run the full prover PCS protocol:
335
336 // Compute:
337 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
338 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
339 auto prover_opening_claims =
340 GeminiProver::prove(n, mock_claims.polynomial_batcher, mle_opening_point, ck, prover_transcript);
341
342 // Shplonk prover output:
343 // - opening pair: (z_challenge, 0)
344 // - witness: polynomial Q - Q_z
345 const auto opening_claim = ShplonkProver::prove(ck, prover_opening_claims, prover_transcript);
346
347 // KZG prover:
348 // - Adds commitment [W] to transcript
349 PCS::compute_opening_proof(ck, opening_claim, prover_transcript);
350
351 // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation)
352
353 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
354 // the index of the first commitment to a polynomial to be shifted in the union of unshifted_commitments and
355 // shifted_commitments. in our case, it is poly2
356 const size_t to_be_shifted_commitments_start = 2;
357 // the index of the first commitment to a shifted polynomial in the union of unshifted_commitments and
358 // shifted_commitments. in our case, it is the second occurence of poly2
359 const size_t shifted_commitments_start = 4;
360 // number of shifted polynomials
361 const size_t num_shifted_commitments = 2;
362 // since commitments to poly2, poly3 and their shifts are the same group elements, we simply combine the scalar
363 // multipliers of commitment2 and commitment3 in one place and remove the entries of the commitments and scalars
364 // vectors corresponding to the "shifted" commitment
365 const RepeatedCommitmentsData repeated_commitments =
366 RepeatedCommitmentsData(to_be_shifted_commitments_start, shifted_commitments_start, num_shifted_commitments);
367
368 // Gemini verifier output:
369 // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1
370 std::array<Fr, log_n> padding_indicator_array;
371 std::ranges::fill(padding_indicator_array, Fr{ 1 });
372
373 const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array,
374 mock_claims.claim_batcher,
375 mle_opening_point,
377 verifier_transcript,
378 repeated_commitments);
379
380 const auto pairing_points = PCS::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript);
381
382 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
383 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
384}
385
386} // namespace bb
static std::shared_ptr< BaseTranscript > verifier_init_empty(const std::shared_ptr< BaseTranscript > &transcript)
For testing: initializes transcript based on proof data then receives junk data produced by BaseTrans...
static std::shared_ptr< BaseTranscript > prover_init_empty()
For testing: initializes transcript with some arbitrary data so that a challenge can be generated aft...
CommitmentKey object over a pairing group 𝔾₁.
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
static VerifierAccumulator reduce_verify(const OpeningClaim< Curve > &claim, const std::shared_ptr< Transcript > &verifier_transcript)
Computes the input points for the pairing check needed to verify a KZG opening claim of a single poly...
Definition kzg.hpp:75
static void compute_opening_proof(const CK &ck, const ProverOpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &prover_trancript)
Computes the KZG commitment to an opening proof polynomial at a single evaluation point.
Definition kzg.hpp:40
typename Curve::ScalarField Fr
Definition kzg.test.cpp:13
static constexpr size_t log_n
Definition kzg.test.cpp:24
typename Curve::AffineElement Commitment
Definition kzg.test.cpp:14
static CK ck
Definition kzg.test.cpp:28
static VK vk
Definition kzg.test.cpp:29
static void prove_and_verify(const OpeningPair< Curve > &opening_pair, bb::Polynomial< Fr > &witness)
Definition kzg.test.cpp:39
static constexpr size_t n
Definition kzg.test.cpp:23
static void SetUpTestSuite()
Definition kzg.test.cpp:33
static constexpr Commitment g1_identity
Definition kzg.test.cpp:31
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:53
Opening pair (r,v) for some witness polynomial p(X) such that p(r) = v.
Definition claim.hpp:19
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
Fr evaluate(const Fr &z, size_t target_size) const
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
bool is_zero() const
Check whether or not a polynomial is identically zero.
An efficient verifier for the evaluation proofs of multilinear polynomials and their shifts.
Shplonk Prover.
Definition shplonk.hpp:36
Shplonk Verifier.
Definition shplonk.hpp:343
static Univariate get_random()
typename Group::affine_element AffineElement
Definition grumpkin.hpp:56
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:33
Entry point for Barretenberg command-line interface.
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:123
CommitmentKey< Curve > ck
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Curve::ScalarField Fr
Constructs random polynomials, computes commitments and corresponding evaluations.
static field random_element(numeric::RNG *engine=nullptr) noexcept
static constexpr field zero()