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
20
21 static constexpr size_t n = 16;
22 static constexpr size_t log_n = 4;
23
26 static CK ck;
27 static VK vk;
28
29 static constexpr Commitment g1_identity = Commitment::one();
30
31 static void SetUpTestSuite()
32 {
33 ck = create_commitment_key<CK>(n);
34 vk = create_verifier_commitment_key<VK>();
35 }
36
37 static void prove_and_verify(const OpeningPair<Curve>& opening_pair, bb::Polynomial<Fr>& witness)
38 {
39 const Commitment commitment = ck.commit(witness);
40
41 auto opening_claim = OpeningClaim<Curve>{ opening_pair, commitment };
42
43 auto prover_transcript = NativeTranscript::prover_init_empty();
44
45 PCS::compute_opening_proof(ck, { witness, opening_pair }, prover_transcript);
46
47 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
48 const auto pairing_points = PCS::reduce_verify(opening_claim, verifier_transcript);
49
50 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
51 }
52};
53
55{
56
57 auto witness = bb::Polynomial<Fr>::random(n);
58 const Fr challenge = Fr::random_element();
59 const Fr evaluation = witness.evaluate(challenge);
60
61 prove_and_verify({ challenge, evaluation }, witness);
62}
63
64TEST_F(KZGTest, ZeroEvaluation)
65{
66
67 auto witness = bb::Polynomial<Fr>::random(n);
68 const Fr challenge = Fr::random_element();
69 const Fr evaluation = witness.evaluate(challenge);
70
71 // Modify witness to achieve zero evaluation
72 witness.at(0) -= evaluation;
73
74 prove_and_verify({ challenge, Fr::zero() }, witness);
75}
76
77TEST_F(KZGTest, ZeroPolynomial)
78{
79 static constexpr size_t POLY_SIZE = 10;
80 bb::Polynomial<Fr> zero(POLY_SIZE);
81 for (size_t idx = 0; idx < POLY_SIZE; ++idx) {
82 zero.at(idx) = 0;
83 }
84
85 // Sanity check
86 ASSERT_TRUE(zero.is_zero());
87
88 const Fr challenge = Fr::random_element();
89 const Fr evaluation = zero.evaluate(challenge);
90
91 prove_and_verify({ challenge, evaluation }, zero);
92}
93
94TEST_F(KZGTest, ConstantPolynomial)
95{
96 auto constant = bb::Polynomial<Fr>::random(1);
97 const Fr challenge = Fr::random_element();
98 const Fr evaluation = constant.evaluate(challenge);
99
100 prove_and_verify({ challenge, evaluation }, constant);
101}
102
103TEST_F(KZGTest, EmptyPolynomial)
104{
105 bb::Polynomial<Fr> empty_poly;
106 const Fr challenge = Fr::random_element();
107 const Fr evaluation = empty_poly.evaluate(challenge);
108
109 prove_and_verify({ challenge, evaluation }, empty_poly);
110}
111
117TEST_F(KZGTest, SingleInLagrangeBasis)
118{
119 const size_t n = 4;
120
121 // create a random univariate (coefficients are in Lagrange basis)
122 auto witness = bb::Univariate<Fr, n>::get_random();
123 // define the interpolation domain
124 std::array<Fr, 4> eval_points = { Fr(0), Fr(1), Fr(2), Fr(3) };
125 // compute the monomial coefficients
126 bb::Polynomial<Fr> witness_polynomial(std::span<Fr>(eval_points), std::span<Fr>(witness), n);
127 // commit to the polynomial in the monomial form
128 g1::element commitment = ck.commit(witness_polynomial);
129
130 const Fr challenge = Fr::random_element();
131 // evaluate the original univariate
132 const Fr evaluation = witness.evaluate(challenge);
133 auto opening_pair = OpeningPair<Curve>{ challenge, evaluation };
134 auto opening_claim = OpeningClaim<Curve>{ opening_pair, commitment };
135
136 auto prover_transcript = NativeTranscript::prover_init_empty();
137
138 PCS::compute_opening_proof(ck, { witness_polynomial, opening_pair }, prover_transcript);
139
140 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
141 auto pairing_points = PCS::reduce_verify(opening_claim, verifier_transcript);
142
143 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
144}
145TEST_F(KZGTest, ShpleminiKzgWithShift)
146{
147 // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random
148 // point.
149 std::vector<Fr> mle_opening_point = random_evaluation_point(log_n); // sometimes denoted 'u'
150
151 MockClaimGenerator mock_claims(n,
152 /*num_polynomials*/ 4,
153 /*num_to_be_shifted*/ 2,
154 mle_opening_point,
155 ck);
156
157 auto prover_transcript = NativeTranscript::prover_init_empty();
158
159 // Run the full prover PCS protocol:
160
161 // Compute:
162 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
163 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
164 auto prover_opening_claims =
165 GeminiProver::prove(n, mock_claims.polynomial_batcher, mle_opening_point, ck, prover_transcript);
166
167 // Shplonk prover output:
168 // - opening pair: (z_challenge, 0)
169 // - witness: polynomial Q - Q_z
170 const auto opening_claim = ShplonkProver::prove(ck, prover_opening_claims, prover_transcript);
171
172 // KZG prover:
173 // - Adds commitment [W] to transcript
174 PCS::compute_opening_proof(ck, opening_claim, prover_transcript);
175
176 // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation)
177
178 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
179
180 // Gemini verifier output:
181 // - 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
182 std::array<Fr, log_n> padding_indicator_array;
183 std::ranges::fill(padding_indicator_array, Fr{ 1 });
184
185 auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array,
186 mock_claims.claim_batcher,
187 mle_opening_point,
189 verifier_transcript);
190
191 const auto pairing_points =
192 PCS::reduce_verify_batch_opening_claim(std::move(batch_opening_claim), verifier_transcript);
193 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
194
195 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
196}
197
198TEST_F(KZGTest, ShpleminiKzgWithShiftAndInterleaving)
199{
200 std::vector<Fr> mle_opening_point = random_evaluation_point(log_n); // sometimes denoted 'u'
201 // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random
202 // point.
203 MockClaimGenerator mock_claims(n,
204 /*num_polynomials*/ 4,
205 /*num_to_be_shifted*/ 2,
206 mle_opening_point,
207 ck,
208 /*num_interleaved*/ 3,
209 /*num_to_be_interleaved*/ 2);
210
211 auto prover_transcript = NativeTranscript::prover_init_empty();
212
213 // Run the full prover PCS protocol:
214
215 // Compute:
216 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
217 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
218 auto prover_opening_claims =
219 GeminiProver::prove(n, mock_claims.polynomial_batcher, mle_opening_point, ck, prover_transcript);
220
221 // Shplonk prover output:
222 // - opening pair: (z_challenge, 0)
223 // - witness: polynomial Q - Q_z
224 const auto opening_claim = ShplonkProver::prove(ck, prover_opening_claims, prover_transcript);
225
226 // KZG prover:
227 // - Adds commitment [W] to transcript
228 PCS::compute_opening_proof(ck, opening_claim, prover_transcript);
229
230 // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation)
231
232 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
233
234 // Gemini verifier output:
235 // - 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
236 std::array<Fr, log_n> padding_indicator_array;
237 std::ranges::fill(padding_indicator_array, Fr{ 1 });
238
239 auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array,
240 mock_claims.claim_batcher,
241 mle_opening_point,
243 verifier_transcript,
244 /* repeated commitments= */ {},
245 /* has zk = */ {},
246 nullptr,
247 /* libra commitments = */ {},
248 /* libra evaluations = */ {},
249 {},
250 {});
251 const auto pairing_points =
252 PCS::reduce_verify_batch_opening_claim(std::move(batch_opening_claim), verifier_transcript);
253 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
254
255 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
256}
257TEST_F(KZGTest, ShpleminiKzgShiftsRemoval)
258{
259 std::vector<Fr> mle_opening_point = random_evaluation_point(log_n); // sometimes denoted 'u'
260 // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random
261 // point.
262 MockClaimGenerator mock_claims(n,
263 /*num_polynomials*/ 4,
264 /*num_to_be_shifted*/ 2,
265 mle_opening_point,
266 ck);
267
268 auto prover_transcript = NativeTranscript::prover_init_empty();
269
270 // Run the full prover PCS protocol:
271
272 // Compute:
273 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
274 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
275 auto prover_opening_claims =
276 GeminiProver::prove(n, mock_claims.polynomial_batcher, mle_opening_point, ck, prover_transcript);
277
278 // Shplonk prover output:
279 // - opening pair: (z_challenge, 0)
280 // - witness: polynomial Q - Q_z
281 const auto opening_claim = ShplonkProver::prove(ck, prover_opening_claims, prover_transcript);
282
283 // KZG prover:
284 // - Adds commitment [W] to transcript
285 PCS::compute_opening_proof(ck, opening_claim, prover_transcript);
286
287 // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation)
288
289 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
290 // the index of the first commitment to a polynomial to be shifted in the union of unshifted_commitments and
291 // shifted_commitments. in our case, it is poly2
292 const size_t to_be_shifted_commitments_start = 2;
293 // the index of the first commitment to a shifted polynomial in the union of unshifted_commitments and
294 // shifted_commitments. in our case, it is the second occurence of poly2
295 const size_t shifted_commitments_start = 4;
296 // number of shifted polynomials
297 const size_t num_shifted_commitments = 2;
298 // since commitments to poly2, poly3 and their shifts are the same group elements, we simply combine the scalar
299 // multipliers of commitment2 and commitment3 in one place and remove the entries of the commitments and scalars
300 // vectors corresponding to the "shifted" commitment
301 const RepeatedCommitmentsData repeated_commitments =
302 RepeatedCommitmentsData(to_be_shifted_commitments_start, shifted_commitments_start, num_shifted_commitments);
303
304 // Gemini verifier output:
305 // - 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
306 std::array<Fr, log_n> padding_indicator_array;
307 std::ranges::fill(padding_indicator_array, Fr{ 1 });
308
309 auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array,
310 mock_claims.claim_batcher,
311 mle_opening_point,
313 verifier_transcript,
314 repeated_commitments);
315
316 const auto pairing_points =
317 PCS::reduce_verify_batch_opening_claim(std::move(batch_opening_claim), verifier_transcript);
318
319 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
320 EXPECT_EQ(vk.pairing_check(pairing_points[0], pairing_points[1]), true);
321}
322
323} // namespace bb
static std::shared_ptr< BaseTranscript > prover_init_empty()
For testing: initializes transcript with some arbitrary data so that a challenge can be generated aft...
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...
CommitmentKey object over a pairing group 𝔾₁.
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
static PairingPointsType 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:82
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:43
typename Curve::ScalarField Fr
Definition kzg.test.cpp:13
static constexpr size_t log_n
Definition kzg.test.cpp:22
typename Curve::AffineElement Commitment
Definition kzg.test.cpp:14
static CK ck
Definition kzg.test.cpp:26
static VK vk
Definition kzg.test.cpp:27
static void prove_and_verify(const OpeningPair< Curve > &opening_pair, bb::Polynomial< Fr > &witness)
Definition kzg.test.cpp:37
static constexpr size_t n
Definition kzg.test.cpp:21
static void SetUpTestSuite()
Definition kzg.test.cpp:31
static constexpr Commitment g1_identity
Definition kzg.test.cpp:29
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 .....
static Polynomial random(size_t size, size_t start_index=0)
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
static Univariate get_random()
typename Group::affine_element AffineElement
Definition grumpkin.hpp:63
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:33
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
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()