barretenberg
Loading...
Searching...
No Matches
gemini.hpp
1#pragma once
2
3#include "../claim.hpp"
4#include "barretenberg/polynomials/polynomial.hpp"
5#include "barretenberg/transcript/transcript.hpp"
6
7#include <vector>
8
46
60template <typename Curve> struct ProverOutput {
61 std::vector<OpeningPair<Curve>> opening_pairs;
62 std::vector<barretenberg::Polynomial<typename Curve::ScalarField>> witnesses;
63};
64
73template <class Fr> inline std::vector<Fr> powers_of_rho(const Fr rho, const size_t num_powers)
74{
75 std::vector<Fr> rhos = { Fr(1), rho };
76 rhos.reserve(num_powers);
77 for (size_t j = 2; j < num_powers; j++) {
78 rhos.emplace_back(rhos[j - 1] * rho);
79 }
80 return rhos;
81};
82
90template <class Fr> inline std::vector<Fr> squares_of_r(const Fr r, const size_t num_squares)
91{
92 std::vector<Fr> squares = { r };
93 squares.reserve(num_squares);
94 for (size_t j = 1; j < num_squares; j++) {
95 squares.emplace_back(squares[j - 1].sqr());
96 }
97 return squares;
98};
99
100template <typename Curve> class GeminiProver_ {
101 using Fr = typename Curve::ScalarField;
103
104 public:
105 static std::vector<Polynomial> compute_gemini_polynomials(std::span<const Fr> mle_opening_point,
106 Polynomial&& batched_unshifted,
107 Polynomial&& batched_to_be_shifted);
108
109 static ProverOutput<Curve> compute_fold_polynomial_evaluations(std::span<const Fr> mle_opening_point,
110 std::vector<Polynomial>&& gemini_polynomials,
111 const Fr& r_challenge);
112}; // namespace proof_system::honk::pcs::gemini
113
114template <typename Curve> class GeminiVerifier_ {
115 using Fr = typename Curve::ScalarField;
116 using GroupElement = typename Curve::Element;
117 using Commitment = typename Curve::AffineElement;
118
119 public:
132 static std::vector<OpeningClaim<Curve>> reduce_verification(std::span<const Fr> mle_opening_point, /* u */
133 const Fr batched_evaluation, /* all */
134 GroupElement& batched_f, /* unshifted */
135 GroupElement& batched_g, /* to-be-shifted */
136 auto& transcript)
137 {
138 const size_t num_variables = mle_opening_point.size();
139
140 // Get polynomials Fold_i, i = 1,...,m-1 from transcript
141 std::vector<Commitment> commitments;
142 commitments.reserve(num_variables - 1);
143 for (size_t i = 0; i < num_variables - 1; ++i) {
144 auto commitment =
145 transcript->template receive_from_prover<Commitment>("Gemini:FOLD_" + std::to_string(i + 1));
146 commitments.emplace_back(commitment);
147 }
148
149 // compute vector of powers of random evaluation point r
150 const Fr r = transcript->get_challenge("Gemini:r");
151 std::vector<Fr> r_squares = squares_of_r(r, num_variables);
152
153 // Get evaluations a_i, i = 0,...,m-1 from transcript
154 std::vector<Fr> evaluations;
155 evaluations.reserve(num_variables);
156 for (size_t i = 0; i < num_variables; ++i) {
157 auto eval = transcript->template receive_from_prover<Fr>("Gemini:a_" + std::to_string(i));
158 evaluations.emplace_back(eval);
159 }
160
161 // Compute evaluation A₀(r)
162 auto a_0_pos = compute_eval_pos(batched_evaluation, mle_opening_point, r_squares, evaluations);
163
164 // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ]
165 // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ]
166 auto [c0_r_pos, c0_r_neg] = compute_simulated_commitments(batched_f, batched_g, r);
167
168 std::vector<OpeningClaim<Curve>> fold_polynomial_opening_claims;
169 fold_polynomial_opening_claims.reserve(num_variables + 1);
170
171 // ( [A₀₊], r, A₀(r) )
172 fold_polynomial_opening_claims.emplace_back(OpeningClaim<Curve>{ { r, a_0_pos }, c0_r_pos });
173 // ( [A₀₋], -r, A₀(-r) )
174 fold_polynomial_opening_claims.emplace_back(OpeningClaim<Curve>{ { -r, evaluations[0] }, c0_r_neg });
175 for (size_t l = 0; l < num_variables - 1; ++l) {
176 // ([A₀₋], −r^{2ˡ}, Aₗ(−r^{2ˡ}) )
177 fold_polynomial_opening_claims.emplace_back(
178 OpeningClaim<Curve>{ { -r_squares[l + 1], evaluations[l + 1] }, commitments[l] });
179 }
180
181 return fold_polynomial_opening_claims;
182 }
183
184 private:
194 static Fr compute_eval_pos(const Fr batched_mle_eval,
195 std::span<const Fr> mle_vars,
196 std::span<const Fr> r_squares,
197 std::span<const Fr> fold_polynomial_evals)
198 {
199 const size_t num_variables = mle_vars.size();
200
201 const auto& evals = fold_polynomial_evals;
202
203 // Initialize eval_pos with batched MLE eval v = ∑ⱼ ρʲ vⱼ + ∑ⱼ ρᵏ⁺ʲ v↺ⱼ
204 Fr eval_pos = batched_mle_eval;
205 for (size_t l = num_variables; l != 0; --l) {
206 const Fr r = r_squares[l - 1]; // = rₗ₋₁ = r^{2ˡ⁻¹}
207 const Fr eval_neg = evals[l - 1]; // = Aₗ₋₁(−r^{2ˡ⁻¹})
208 const Fr u = mle_vars[l - 1]; // = uₗ₋₁
209
210 // The folding property ensures that
211 // Aₗ₋₁(r^{2ˡ⁻¹}) + Aₗ₋₁(−r^{2ˡ⁻¹}) Aₗ₋₁(r^{2ˡ⁻¹}) - Aₗ₋₁(−r^{2ˡ⁻¹})
212 // Aₗ(r^{2ˡ}) = (1-uₗ₋₁) ----------------------------- + uₗ₋₁ -----------------------------
213 // 2 2r^{2ˡ⁻¹}
214 // We solve the above equation in Aₗ₋₁(r^{2ˡ⁻¹}), using the previously computed Aₗ(r^{2ˡ}) in eval_pos
215 // and using Aₗ₋₁(−r^{2ˡ⁻¹}) sent by the prover in the proof.
216 eval_pos = ((r * eval_pos * 2) - eval_neg * (r * (Fr(1) - u) - u)) / (r * (Fr(1) - u) + u);
217 }
218
219 return eval_pos; // return A₀(r)
220 }
221
230 static std::pair<GroupElement, GroupElement> compute_simulated_commitments(GroupElement& batched_f,
231 GroupElement& batched_g,
232 Fr r)
233 {
234 // C₀ᵣ₊ = [F] + r⁻¹⋅[G]
235 GroupElement C0_r_pos;
236 // C₀ᵣ₋ = [F] - r⁻¹⋅[G]
237 GroupElement C0_r_neg;
238 Fr r_inv = r.invert(); // r⁻¹
239
240 // If in a recursive setting, perform a batch mul. Otherwise, accumulate directly.
241 // TODO(#673): The following if-else represents the stldib/native code paths. Once the "native" verifier is
242 // achieved through a builder Simulator, the stdlib codepath should become the only codepath.
243 if constexpr (Curve::is_stdlib_type) {
244 std::vector<GroupElement> commitments = { batched_f, batched_g };
245 auto builder = r.get_context();
246 auto one = Fr(builder, 1);
247 // TODO(#707): these batch muls include the use of 1 as a scalar. This is handled appropriately as a non-mul
248 // (add-accumulate) in the goblin batch_mul but is done inefficiently as a scalar mul in the conventional
249 // emulated batch mul.
250 C0_r_pos = GroupElement::batch_mul(commitments, { one, r_inv });
251 C0_r_neg = GroupElement::batch_mul(commitments, { one, -r_inv });
252 } else {
253 C0_r_pos = batched_f;
254 C0_r_neg = batched_f;
255 if (!batched_g.is_point_at_infinity()) {
256 batched_g = batched_g * r_inv;
257 C0_r_pos += batched_g;
258 C0_r_neg -= batched_g;
259 }
260 }
261
262 return { C0_r_pos, C0_r_neg };
263 }
264
265}; // namespace proof_system::honk::pcs::gemini
266
267} // namespace proof_system::honk::pcs::gemini
Definition: polynomial.hpp:12
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition: claim.hpp:43
static ProverOutput< Curve > compute_fold_polynomial_evaluations(std::span< const Fr > mle_opening_point, std::vector< Polynomial > &&gemini_polynomials, const Fr &r_challenge)
Computes/aggragates d+1 Fold polynomials and their opening pairs (challenge, evaluation)
Definition: gemini.cpp:146
static std::vector< Polynomial > compute_gemini_polynomials(std::span< const Fr > mle_opening_point, Polynomial &&batched_unshifted, Polynomial &&batched_to_be_shifted)
Computes d-1 fold polynomials Fold_i, i = 1, ..., d-1.
Definition: gemini.cpp:57
static std::vector< OpeningClaim< Curve > > reduce_verification(std::span< const Fr > mle_opening_point, const Fr batched_evaluation, GroupElement &batched_f, GroupElement &batched_g, auto &transcript)
Returns univariate opening claims for the Fold polynomials to be checked later.
Definition: gemini.hpp:132
Protocol for opening several multi-linear polynomials at the same point.
Definition: gemini.cpp:45
std::vector< Fr > powers_of_rho(const Fr rho, const size_t num_powers)
Compute powers of challenge ρ
Definition: gemini.hpp:73
std::vector< Fr > squares_of_r(const Fr r, const size_t num_squares)
Compute squares of folding challenge r.
Definition: gemini.hpp:90
Prover output (evalutation pair, witness) that can be passed on to Shplonk batch opening.
Definition: gemini.hpp:60