Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
shplonk.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
14
29namespace bb {
30
36template <typename Curve> class ShplonkProver_ {
37 using Fr = typename Curve::ScalarField;
39
40 public:
49 static Polynomial compute_batched_quotient(const size_t virtual_log_n,
50 std::span<const ProverOpeningClaim<Curve>> opening_claims,
51 const Fr& nu,
52 std::span<Fr> gemini_fold_pos_evaluations,
53 std::span<const ProverOpeningClaim<Curve>> libra_opening_claims,
54 std::span<const ProverOpeningClaim<Curve>> sumcheck_round_claims)
55 {
56 // Find the maximum polynomial size among all claims to determine the dyadic size of the batched polynomial.
57 size_t max_poly_size{ 0 };
58
59 for (const auto& claim_set : { opening_claims, libra_opening_claims, sumcheck_round_claims }) {
60 for (const auto& claim : claim_set) {
61 max_poly_size = std::max(max_poly_size, claim.polynomial.size());
62 }
63 }
64 // The polynomials in Sumcheck Round claims and Libra opening claims are generally not dyadic,
65 // so we round up to the next power of 2.
66 max_poly_size = numeric::round_up_power_2(max_poly_size);
67
68 // Q(X) = ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ )
69 Polynomial Q(max_poly_size);
70 Polynomial tmp(max_poly_size);
71
72 Fr current_nu = Fr::one();
73
74 size_t fold_idx = 0;
75 for (const auto& claim : opening_claims) {
76
77 // Gemini Fold Polynomials have to be opened at -r^{2^j} and r^{2^j}.
78 if (claim.gemini_fold) {
79 tmp = claim.polynomial;
80 tmp.at(0) = tmp[0] - gemini_fold_pos_evaluations[fold_idx++];
81 tmp.factor_roots(-claim.opening_pair.challenge);
82 // Add the claim quotient to the batched quotient polynomial
83 Q.add_scaled(tmp, current_nu);
84 current_nu *= nu;
85 }
86
87 // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ )
88 tmp = claim.polynomial;
89 tmp.at(0) = tmp[0] - claim.opening_pair.evaluation;
90 tmp.factor_roots(claim.opening_pair.challenge);
91 // Add the claim quotient to the batched quotient polynomial
92 Q.add_scaled(tmp, current_nu);
93 current_nu *= nu;
94 }
95 // We use the same batching challenge for Gemini and Libra opening claims. The number of the claims
96 // batched before adding Libra commitments and evaluations is bounded by 2 * `virtual_log_n` + 2, where
97 // 2 * `virtual_log_n` is the number of fold claims including the dummy ones, and +2 is reserved for
98 // interleaving.
99 if (!libra_opening_claims.empty()) {
100 current_nu = nu.pow(2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS);
101 }
102
103 for (const auto& claim : libra_opening_claims) {
104 // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ )
105 tmp = claim.polynomial;
106 tmp.at(0) = tmp[0] - claim.opening_pair.evaluation;
107 tmp.factor_roots(claim.opening_pair.challenge);
108
109 // Add the claim quotient to the batched quotient polynomial
110 Q.add_scaled(tmp, current_nu);
111 current_nu *= nu;
112 }
113
114 for (const auto& claim : sumcheck_round_claims) {
115
116 // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ )
117 tmp = claim.polynomial;
118 tmp.at(0) = tmp[0] - claim.opening_pair.evaluation;
119 tmp.factor_roots(claim.opening_pair.challenge);
120
121 // Add the claim quotient to the batched quotient polynomial
122 Q.add_scaled(tmp, current_nu);
123 current_nu *= nu;
124 }
125 // Return batched quotient polynomial Q(X)
126 return Q;
127 };
128
140 const size_t virtual_log_n,
141 std::span<ProverOpeningClaim<Curve>> opening_claims,
142 Polynomial& batched_quotient_Q,
143 const Fr& nu_challenge,
144 const Fr& z_challenge,
145 std::span<Fr> gemini_fold_pos_evaluations,
146 std::span<ProverOpeningClaim<Curve>> libra_opening_claims = {},
147 std::span<ProverOpeningClaim<Curve>> sumcheck_opening_claims = {})
148 {
149 // Our main use case is the opening of Gemini fold polynomials and each Gemini fold is opened at 2 points.
150 const size_t num_gemini_opening_claims = 2 * opening_claims.size();
151 const size_t num_opening_claims =
152 num_gemini_opening_claims + libra_opening_claims.size() + sumcheck_opening_claims.size();
153
154 // {ẑⱼ(z)}ⱼ , where ẑⱼ(r) = 1/zⱼ(z) = 1/(z - xⱼ)
155 std::vector<Fr> inverse_vanishing_evals;
156 inverse_vanishing_evals.reserve(num_opening_claims);
157 for (const auto& claim : opening_claims) {
158 if (claim.gemini_fold) {
159 inverse_vanishing_evals.emplace_back(z_challenge + claim.opening_pair.challenge);
160 }
161 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
162 }
163
164 // Add the terms (z - uₖ) for k = 0, …, d−1 where d is the number of rounds in Sumcheck
165 for (const auto& claim : libra_opening_claims) {
166 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
167 }
168
169 for (const auto& claim : sumcheck_opening_claims) {
170 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
171 }
172
173 Fr::batch_invert(inverse_vanishing_evals);
174
175 // G(X) = Q(X) - Q_z(X) = Q(X) - ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( z − xⱼ ),
176 // s.t. G(r) = 0
177 Polynomial G(std::move(batched_quotient_Q)); // G(X) = Q(X)
178
179 // G₀ = ∑ⱼ νʲ ⋅ vⱼ / ( z − xⱼ )
180 Fr current_nu = Fr::one();
181 Polynomial tmp(G.size());
182 size_t idx = 0;
183
184 size_t fold_idx = 0;
185 for (auto& claim : opening_claims) {
186
187 if (claim.gemini_fold) {
188 tmp = claim.polynomial;
189 tmp.at(0) = tmp[0] - gemini_fold_pos_evaluations[fold_idx++];
190 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++]; // = νʲ / (z − xⱼ )
191 // G -= νʲ ⋅ ( fⱼ(X) − vⱼ) / ( z − xⱼ )
192 G.add_scaled(tmp, -scaling_factor);
193
194 current_nu *= nu_challenge;
195 }
196 // tmp = νʲ ⋅ ( fⱼ(X) − vⱼ) / ( z − xⱼ )
197 claim.polynomial.at(0) = claim.polynomial[0] - claim.opening_pair.evaluation;
198 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++]; // = νʲ / (z − xⱼ )
199
200 // G -= νʲ ⋅ ( fⱼ(X) − vⱼ) / ( z − xⱼ )
201 G.add_scaled(claim.polynomial, -scaling_factor);
202
203 current_nu *= nu_challenge;
204 }
205
206 // Take into account the constant proof size in Gemini
207 if (!libra_opening_claims.empty()) {
208 current_nu = nu_challenge.pow(2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS);
209 }
210
211 for (auto& claim : libra_opening_claims) {
212 // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ )
213 claim.polynomial.at(0) = claim.polynomial[0] - claim.opening_pair.evaluation;
214 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++]; // = νʲ / (z − xⱼ )
215
216 // Add the claim quotient to the batched quotient polynomial
217 G.add_scaled(claim.polynomial, -scaling_factor);
218 current_nu *= nu_challenge;
219 }
220
221 for (auto& claim : sumcheck_opening_claims) {
222 claim.polynomial.at(0) = claim.polynomial[0] - claim.opening_pair.evaluation;
223 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++]; // = νʲ / (z − xⱼ )
224
225 // Add the claim quotient to the batched quotient polynomial
226 G.add_scaled(claim.polynomial, -scaling_factor);
227 current_nu *= nu_challenge;
228 }
229 // Return opening pair (z, 0) and polynomial G(X) = Q(X) - Q_z(X)
230 return { .polynomial = G, .opening_pair = { .challenge = z_challenge, .evaluation = Fr::zero() } };
231 };
240 std::span<const ProverOpeningClaim<Curve>> opening_claims)
241 {
242 std::vector<Fr> gemini_fold_pos_evaluations;
243 gemini_fold_pos_evaluations.reserve(opening_claims.size());
244
245 for (const auto& claim : opening_claims) {
246 if (claim.gemini_fold) {
247 // -r^{2^i} is stored in the claim
248 const Fr evaluation_point = -claim.opening_pair.challenge;
249 // Compute Fold_i(r^{2^i})
250 const Fr evaluation = claim.polynomial.evaluate(evaluation_point);
251 gemini_fold_pos_evaluations.emplace_back(evaluation);
252 }
253 }
254 return gemini_fold_pos_evaluations;
255 }
256
266 template <typename Transcript>
268 std::span<ProverOpeningClaim<Curve>> opening_claims,
269 const std::shared_ptr<Transcript>& transcript,
270 std::span<ProverOpeningClaim<Curve>> libra_opening_claims = {},
271 std::span<ProverOpeningClaim<Curve>> sumcheck_round_claims = {},
272 const size_t virtual_log_n = 0)
273 {
274 const Fr nu = transcript->template get_challenge<Fr>("Shplonk:nu");
275
276 // Compute the evaluations Fold_i(r^{2^i}) for i>0.
277 std::vector<Fr> gemini_fold_pos_evaluations = compute_gemini_fold_pos_evaluations(opening_claims);
278
279 auto batched_quotient = compute_batched_quotient(virtual_log_n,
280 opening_claims,
281 nu,
282 gemini_fold_pos_evaluations,
283 libra_opening_claims,
284 sumcheck_round_claims);
285 auto batched_quotient_commitment = commitment_key.commit(batched_quotient);
286 transcript->send_to_verifier("Shplonk:Q", batched_quotient_commitment);
287 const Fr z = transcript->template get_challenge<Fr>("Shplonk:z");
288
290 opening_claims,
291 batched_quotient,
292 nu,
293 z,
294 gemini_fold_pos_evaluations,
295 libra_opening_claims,
296 sumcheck_round_claims);
297 }
298};
299
343template <typename Curve> class ShplonkVerifier_ {
344 using Fr = typename Curve::ScalarField;
345 using GroupElement = typename Curve::Element;
348
349 // Random challenges
350 std::vector<Fr> pows_of_nu;
351 size_t pow_idx = 0;
352 // Commitment to quotient polynomial
354 // Partial evaluation challenge
356 // Commitments \f$[f_1], \dots, [f_n]\f$
357 std::vector<Commitment> commitments;
358 // Scalar coefficients of \f$[f_1], \dots, [f_n]\f$ in the MSM needed to compute the commitment to the partially
359 // evaluated quotient
360 std::vector<Fr> scalars;
361 // Coefficient of the identity in partially evaluated quotient
363 // Target evaluation
365
366 public:
367 template <typename Transcript>
368 ShplonkVerifier_(std::vector<Commitment>& polynomial_commitments,
369 std::shared_ptr<Transcript>& transcript,
370 const size_t num_claims)
371 : pows_of_nu({ Fr(1), transcript->template get_challenge<Fr>("Shplonk:nu") })
372 , quotient(transcript->template receive_from_prover<Commitment>("Shplonk:Q"))
373 , z_challenge(transcript->template get_challenge<Fr>("Shplonk:z"))
374 , commitments({ quotient })
375 , scalars{ Fr{ 1 } }
376 {
377 BB_ASSERT_GT(num_claims, 1U, "Using Shplonk with just one claim. Should use batch reduction.");
378 const size_t num_commitments = commitments.size();
379 commitments.reserve(num_commitments);
380 scalars.reserve(num_commitments);
381 pows_of_nu.reserve(num_claims);
382
383 commitments.insert(commitments.end(), polynomial_commitments.begin(), polynomial_commitments.end());
384 scalars.insert(scalars.end(), commitments.size() - 1, Fr(0)); // Initialized as circuit constants
385 // The first two powers of nu have already been initialized, we need another `num_claims - 2` powers to batch
386 // all the claims
387 for (size_t idx = 0; idx < num_claims - 2; idx++) {
388 pows_of_nu.emplace_back(pows_of_nu.back() * pows_of_nu[1]);
389 }
390
391 if constexpr (Curve::is_stdlib_type) {
392 evaluation.convert_constant_to_fixed_witness(pows_of_nu[1].get_context());
393 }
394 }
395
409 // It is composed
411 std::vector<size_t> indices;
412 std::vector<Fr> scalars;
414 };
415
428 void update(const LinearCombinationOfClaims& update_data, const Fr& inverse_vanishing_eval)
429 {
430
431 // Compute \nu^{i-1} / (z - x)
432 auto scalar_factor = pows_of_nu[pow_idx] * inverse_vanishing_eval;
433
434 for (const auto& [index, coefficient] : zip_view(update_data.indices, update_data.scalars)) {
435 // \nu^{i-1} * a_j / (z - x)
436 auto scaling_factor = scalar_factor * coefficient;
437 // s_{i_j} -= \nu^{i-1} * a_j / (z - x)
438 scalars[index + 1] -= scaling_factor;
439 }
440
441 // \theta += \nu^{i-1} * v / (z - x)
442 identity_scalar_coefficient += scalar_factor * update_data.opening_pair.evaluation;
443
444 // Update `pow_idx`
445 pow_idx += 1;
446 }
447
456 OpeningClaim<Curve> finalize(const Commitment& g1_identity)
457 {
458 commitments.emplace_back(g1_identity);
460 GroupElement result;
461 if constexpr (Curve::is_stdlib_type) {
462 result = GroupElement::batch_mul(commitments, scalars);
463 } else {
464 result = GroupElement::zero();
465 for (const auto& [commitment, scalar] : zip_view(commitments, scalars)) {
466 result += commitment * scalar;
467 }
468 }
469
470 return { { z_challenge, evaluation }, result };
471 }
472
487 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1475): Compute g1_identity inside the function body
488 BatchOpeningClaim<Curve> export_batch_opening_claim(const Commitment& g1_identity)
489 {
490 commitments.emplace_back(g1_identity);
492
493 return { commitments, scalars, z_challenge };
494 }
495
503 template <typename Transcript>
504 static ShplonkVerifier_<Curve> reduce_verification_no_finalize(std::span<const OpeningClaim<Curve>> claims,
505 std::shared_ptr<Transcript>& transcript)
506 {
507 // Initialize Shplonk verifier
508 const size_t num_claims = claims.size();
509 std::vector<Commitment> polynomial_commiments;
510 polynomial_commiments.reserve(num_claims);
511 for (const auto& claim : claims) {
512 polynomial_commiments.emplace_back(claim.commitment);
513 }
514 ShplonkVerifier_<Curve> verifier(polynomial_commiments, transcript, num_claims);
515
516 // Compute { 1 / (z - x_i) }
517 std::vector<Fr> inverse_vanishing_evals;
518 inverse_vanishing_evals.reserve(num_claims);
519 if constexpr (Curve::is_stdlib_type) {
520 for (const auto& claim : claims) {
521 inverse_vanishing_evals.emplace_back((verifier.z_challenge - claim.opening_pair.challenge).invert());
522 }
523 } else {
524 for (const auto& claim : claims) {
525 inverse_vanishing_evals.emplace_back(verifier.z_challenge - claim.opening_pair.challenge);
526 }
527 Fr::batch_invert(inverse_vanishing_evals);
528 }
529
530 for (size_t idx = 0; idx < claims.size(); idx++) {
531 verifier.update({ { idx }, { Fr(1) }, claims[idx].opening_pair }, inverse_vanishing_evals[idx]);
532 }
533
534 return verifier;
535 };
536
545 void reduce_verification_vector_claims_no_finalize(std::span<const LinearCombinationOfClaims> claims)
546 {
547 const size_t num_claims = claims.size();
548
549 // Compute { 1 / (z - x_i) }
550 std::vector<Fr> inverse_vanishing_evals;
551 inverse_vanishing_evals.reserve(num_claims);
552 if constexpr (Curve::is_stdlib_type) {
553 for (const auto& claim : claims) {
554 inverse_vanishing_evals.emplace_back((this->z_challenge - claim.opening_pair.challenge).invert());
555 }
556 } else {
557 for (const auto& claim : claims) {
558 inverse_vanishing_evals.emplace_back(this->z_challenge - claim.opening_pair.challenge);
559 }
560 Fr::batch_invert(inverse_vanishing_evals);
561 }
562
563 for (const auto& [claim, inv] : zip_view(claims, inverse_vanishing_evals)) {
564 this->update(claim, inv);
565 }
566 }
567
578 OpeningClaim<Curve> reduce_verification_vector_claims(Commitment g1_identity,
580 {
581 this->reduce_verification_vector_claims_no_finalize(claims);
582 return this->finalize(g1_identity);
583 };
584
595 template <typename Transcript>
596 static OpeningClaim<Curve> reduce_verification(Commitment g1_identity,
597 std::span<const OpeningClaim<Curve>> claims,
598 std::shared_ptr<Transcript>& transcript)
599 {
600 auto verifier = ShplonkVerifier_::reduce_verification_no_finalize(claims, transcript);
601 return verifier.finalize(g1_identity);
602 };
603
613 static std::vector<Fr> compute_inverted_gemini_denominators(const Fr& shplonk_eval_challenge,
614 const std::vector<Fr>& gemini_eval_challenge_powers)
615 {
616 std::vector<Fr> denominators;
617 const size_t virtual_log_n = gemini_eval_challenge_powers.size();
618 const size_t num_gemini_claims = 2 * virtual_log_n;
619 denominators.reserve(num_gemini_claims);
620
621 for (const auto& gemini_eval_challenge_power : gemini_eval_challenge_powers) {
622 // Place 1/(z - r ^ {2^j})
623 denominators.emplace_back(shplonk_eval_challenge - gemini_eval_challenge_power);
624 // Place 1/(z + r ^ {2^j})
625 denominators.emplace_back(shplonk_eval_challenge + gemini_eval_challenge_power);
626 }
627
628 if constexpr (!Curve::is_stdlib_type) {
629 Fr::batch_invert(denominators);
630 } else {
631 for (auto& denominator : denominators) {
632 denominator = denominator.invert();
633 }
634 }
635 return denominators;
636 }
637};
638
644template <typename Fr>
645static std::vector<Fr> compute_shplonk_batching_challenge_powers(const Fr& shplonk_batching_challenge,
646 const size_t virtual_log_n,
647 bool has_zk = false,
648 bool committed_sumcheck = false)
649{
650 // Minimum size of `denominators`
651 size_t num_powers = 2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS;
652 // Each round univariate is opened at 0, 1, and a round challenge.
653 static constexpr size_t NUM_COMMITTED_SUMCHECK_CLAIMS_PER_ROUND = 3;
654
655 // Shplonk evaluation and batching challenges are re-used in SmallSubgroupIPA.
656 if (has_zk) {
657 num_powers += NUM_SMALL_IPA_EVALUATIONS;
658 }
659
660 // Commited sumcheck adds 3 claims per round.
661 if (committed_sumcheck) {
662 num_powers += NUM_COMMITTED_SUMCHECK_CLAIMS_PER_ROUND * virtual_log_n;
663 }
664
665 std::vector<Fr> result;
666 result.reserve(num_powers);
667 result.emplace_back(Fr{ 1 });
668 for (size_t idx = 1; idx < num_powers; idx++) {
669 result.emplace_back(result[idx - 1] * shplonk_batching_challenge);
670 }
671 return result;
672}
673} // namespace bb
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:87
CommitmentKey object over a pairing group 𝔾₁.
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
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 & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
void add_scaled(PolynomialSpan< const Fr > other, Fr scaling_factor) &
adds the polynomial q(X) 'other', multiplied by a scaling factor.
void factor_roots(const Fr &root)
Divides p(X) by (X-r) in-place. Assumes that p(rⱼ)=0 for all j.
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:34
Shplonk Prover.
Definition shplonk.hpp:36
static std::vector< Fr > compute_gemini_fold_pos_evaluations(std::span< const ProverOpeningClaim< Curve > > opening_claims)
Compute evaluations of fold polynomials Fold_i at r^{2^i} for i>0. TODO(https://github....
Definition shplonk.hpp:239
static Polynomial compute_batched_quotient(const size_t virtual_log_n, std::span< const ProverOpeningClaim< Curve > > opening_claims, const Fr &nu, std::span< Fr > gemini_fold_pos_evaluations, std::span< const ProverOpeningClaim< Curve > > libra_opening_claims, std::span< const ProverOpeningClaim< Curve > > sumcheck_round_claims)
Compute batched quotient polynomial Q(X) = ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ )
Definition shplonk.hpp:49
static ProverOpeningClaim< Curve > prove(const CommitmentKey< Curve > &commitment_key, std::span< ProverOpeningClaim< Curve > > opening_claims, const std::shared_ptr< Transcript > &transcript, std::span< ProverOpeningClaim< Curve > > libra_opening_claims={}, std::span< ProverOpeningClaim< Curve > > sumcheck_round_claims={}, const size_t virtual_log_n=0)
Returns a batched opening claim equivalent to a set of opening claims consisting of polynomials,...
Definition shplonk.hpp:267
typename Curve::ScalarField Fr
Definition shplonk.hpp:37
static ProverOpeningClaim< Curve > compute_partially_evaluated_batched_quotient(const size_t virtual_log_n, std::span< ProverOpeningClaim< Curve > > opening_claims, Polynomial &batched_quotient_Q, const Fr &nu_challenge, const Fr &z_challenge, std::span< Fr > gemini_fold_pos_evaluations, std::span< ProverOpeningClaim< Curve > > libra_opening_claims={}, std::span< ProverOpeningClaim< Curve > > sumcheck_opening_claims={})
Compute partially evaluated batched quotient polynomial difference Q(X) - Q_z(X)
Definition shplonk.hpp:139
Shplonk Verifier.
Definition shplonk.hpp:343
std::vector< Fr > pows_of_nu
Definition shplonk.hpp:350
typename Curve::ScalarField Fr
Definition shplonk.hpp:344
ShplonkVerifier_(std::vector< Commitment > &polynomial_commitments, std::shared_ptr< Transcript > &transcript, const size_t num_claims)
Definition shplonk.hpp:368
std::vector< Commitment > commitments
Definition shplonk.hpp:357
typename Curve::AffineElement Commitment
Definition shplonk.hpp:346
typename Curve::Element GroupElement
Definition shplonk.hpp:345
std::vector< Fr > scalars
Definition shplonk.hpp:360
Commitment quotient
Definition shplonk.hpp:353
typename Group::element Element
Definition grumpkin.hpp:55
static constexpr bool is_stdlib_type
Definition grumpkin.hpp:62
typename Group::affine_element AffineElement
Definition grumpkin.hpp:56
typename Flavor::Polynomial Polynomial
#define G(r, i, a, b, c, d)
Definition blake2s.cpp:116
constexpr T round_up_power_2(const T in)
Definition get_msb.hpp:52
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field one()
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
static void batch_invert(std::span< field > coeffs) noexcept
static constexpr field zero()