2#include "barretenberg/commitment_schemes/claim.hpp"
3#include "barretenberg/commitment_schemes/verification_key.hpp"
4#include "barretenberg/common/assert.hpp"
5#include "barretenberg/ecc/scalar_multiplication/scalar_multiplication.hpp"
6#include "barretenberg/transcript/transcript.hpp"
18template <
typename Curve>
class IPA {
19 using Fr =
typename Curve::ScalarField;
20 using GroupElement =
typename Curve::Element;
21 using Commitment =
typename Curve::AffineElement;
39 const std::shared_ptr<BaseTranscript>& transcript)
41 ASSERT(opening_pair.challenge != 0 &&
"The challenge point should not be zero");
42 auto poly_degree =
static_cast<size_t>(
polynomial.size());
43 transcript->send_to_verifier(
"IPA:poly_degree",
static_cast<uint64_t
>(poly_degree));
44 const Fr generator_challenge = transcript->get_challenge(
"IPA:generator_challenge");
45 auto aux_generator = Commitment::one() * generator_challenge;
49 ASSERT((poly_degree > 0) && (!(poly_degree & (poly_degree - 1))) &&
50 "The poly_degree should be positive and a power of two");
53 auto srs_elements = ck->srs->get_monomial_points();
54 std::vector<Commitment> G_vec_local(poly_degree);
58 for (
size_t i = 0; i < poly_degree * 2; i += 2) {
59 G_vec_local[i >> 1] = srs_elements[i];
61 std::vector<Fr> b_vec(poly_degree);
63 for (
size_t i = 0; i < poly_degree; i++) {
65 b_power *= opening_pair.challenge;
68 auto log_poly_degree =
static_cast<size_t>(numeric::get_msb(poly_degree));
69 std::vector<GroupElement> L_elements(log_poly_degree);
70 std::vector<GroupElement> R_elements(log_poly_degree);
71 std::size_t round_size = poly_degree;
77 for (
size_t i = 0; i < log_poly_degree; i++) {
80 Fr inner_prod_L = Fr::zero();
81 Fr inner_prod_R = Fr::zero();
82 for (
size_t j = 0; j < round_size; j++) {
83 inner_prod_L += a_vec[j] * b_vec[round_size + j];
84 inner_prod_R += a_vec[round_size + j] * b_vec[j];
89 barretenberg::scalar_multiplication::pippenger_without_endomorphism_basis_points<Curve>(
90 &a_vec[0], &G_vec_local[round_size], round_size, ck->pippenger_runtime_state);
91 L_elements[i] += aux_generator * inner_prod_L;
95 R_elements[i] = barretenberg::scalar_multiplication::pippenger_without_endomorphism_basis_points<Curve>(
96 &a_vec[round_size], &G_vec_local[0], round_size, ck->pippenger_runtime_state);
97 R_elements[i] += aux_generator * inner_prod_R;
99 std::string index = std::to_string(i);
100 transcript->send_to_verifier(
"IPA:L_" + index, Commitment(L_elements[i]));
101 transcript->send_to_verifier(
"IPA:R_" + index, Commitment(R_elements[i]));
104 const Fr round_challenge = transcript->get_challenge(
"IPA:round_challenge_" + index);
105 const Fr round_challenge_inv = round_challenge.invert();
107 std::vector<Commitment> G_lo(G_vec_local.begin(), G_vec_local.begin() +
static_cast<long>(round_size));
108 std::vector<Commitment> G_hi(G_vec_local.begin() +
static_cast<long>(round_size), G_vec_local.end());
109 G_lo = GroupElement::batch_mul_with_endomorphism(G_lo, round_challenge_inv);
110 G_hi = GroupElement::batch_mul_with_endomorphism(G_hi, round_challenge);
116 for (
size_t j = 0; j < round_size; j++) {
117 a_vec[j] *= round_challenge;
118 a_vec[j] += round_challenge_inv * a_vec[round_size + j];
119 b_vec[j] *= round_challenge_inv;
120 b_vec[j] += round_challenge * b_vec[round_size + j];
122 G_vec_local[j] = G_lo[j] + G_hi[j];
126 transcript->send_to_verifier(
"IPA:a_0", a_vec[0]);
138 static bool verify(
const std::shared_ptr<VK>& vk,
140 const std::shared_ptr<BaseTranscript>& transcript)
142 auto poly_degree =
static_cast<size_t>(transcript->template receive_from_prover<uint64_t>(
"IPA:poly_degree"));
143 const Fr generator_challenge = transcript->get_challenge(
"IPA:generator_challenge");
144 auto aux_generator = Commitment::one() * generator_challenge;
146 auto log_poly_degree =
static_cast<size_t>(numeric::get_msb(poly_degree));
149 GroupElement C_prime = opening_claim.commitment + (aux_generator * opening_claim.opening_pair.evaluation);
152 auto pippenger_size = 2 * log_poly_degree;
153 std::vector<Fr> round_challenges(log_poly_degree);
154 std::vector<Fr> round_challenges_inv(log_poly_degree);
155 std::vector<Commitment> msm_elements(pippenger_size);
156 std::vector<Fr> msm_scalars(pippenger_size);
157 for (
size_t i = 0; i < log_poly_degree; i++) {
158 std::string index = std::to_string(i);
159 auto element_L = transcript->template receive_from_prover<Commitment>(
"IPA:L_" + index);
160 auto element_R = transcript->template receive_from_prover<Commitment>(
"IPA:R_" + index);
161 round_challenges[i] = transcript->get_challenge(
"IPA:round_challenge_" + index);
162 round_challenges_inv[i] = round_challenges[i].invert();
164 msm_elements[2 * i] = element_L;
165 msm_elements[2 * i + 1] = element_R;
166 msm_scalars[2 * i] = round_challenges[i].sqr();
167 msm_scalars[2 * i + 1] = round_challenges_inv[i].sqr();
170 GroupElement LR_sums = barretenberg::scalar_multiplication::pippenger_without_endomorphism_basis_points<Curve>(
171 &msm_scalars[0], &msm_elements[0], pippenger_size, vk->pippenger_runtime_state);
172 GroupElement C_zero = C_prime + LR_sums;
181 Fr b_zero = Fr::one();
182 for (
size_t i = 0; i < log_poly_degree; i++) {
183 auto exponent =
static_cast<uint64_t
>(Fr(2).pow(i));
184 b_zero *= round_challenges_inv[log_poly_degree - 1 - i] +
185 (round_challenges[log_poly_degree - 1 - i] * opening_claim.opening_pair.challenge.pow(exponent));
190 std::vector<Fr> s_vec(poly_degree);
191 for (
size_t i = 0; i < poly_degree; i++) {
192 Fr s_vec_scalar = Fr::one();
193 for (
size_t j = (log_poly_degree - 1); j != size_t(-1); j--) {
194 auto bit = (i >> j) & 1;
195 bool b =
static_cast<bool>(bit);
197 s_vec_scalar *= round_challenges[log_poly_degree - 1 - j];
199 s_vec_scalar *= round_challenges_inv[log_poly_degree - 1 - j];
202 s_vec[i] = s_vec_scalar;
204 auto srs_elements = vk->srs->get_monomial_points();
206 std::vector<Commitment> G_vec_local(poly_degree);
210 for (
size_t i = 0; i < poly_degree * 2; i += 2) {
211 G_vec_local[i >> 1] = srs_elements[i];
214 auto G_zero = barretenberg::scalar_multiplication::pippenger_without_endomorphism_basis_points<Curve>(
215 &s_vec[0], &G_vec_local[0], poly_degree, vk->pippenger_runtime_state);
217 auto a_zero = transcript->template receive_from_prover<Fr>(
"IPA:a_0");
219 GroupElement right_hand_side = G_zero * a_zero + aux_generator * a_zero * b_zero;
221 return (C_zero.normalize() == right_hand_side.normalize());
Definition: polynomial.hpp:12
CommitmentKey object over a pairing group 𝔾₁.
Definition: commitment_key.hpp:35
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition: claim.hpp:43
Opening pair (r,v) for some witness polynomial p(X) such that p(r) = v.
Definition: claim.hpp:12
Definition: verification_key.hpp:25
static bool verify(const std::shared_ptr< VK > &vk, const OpeningClaim< Curve > &opening_claim, const std::shared_ptr< BaseTranscript > &transcript)
Verify the correctness of a Proof.
Definition: ipa.hpp:138
static void compute_opening_proof(const std::shared_ptr< CK > &ck, const OpeningPair< Curve > &opening_pair, const Polynomial &polynomial, const std::shared_ptr< BaseTranscript > &transcript)
Compute an inner product argument proof for opening a single polynomial at a single evaluation point.
Definition: ipa.hpp:36
IPA (inner-product argument) commitment scheme class. Conforms to the specification https://hackmd....
Definition: ipa.hpp:17