Skip to content

Commit 32ba8d9

Browse files
committed
Refactor multi-polynomial-2-eval-points commitment scheme of [GWC19]
1 parent 2d1cb0e commit 32ba8d9

File tree

3 files changed

+147
-129
lines changed

3 files changed

+147
-129
lines changed

libsnark/polynomial_commitments/kzg10_batched.hpp

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -39,72 +39,71 @@ template<typename ppT> class kzg10_batched_2_point
3939

4040
using commitment = typename kzg10<ppT>::commitment;
4141

42-
using witness = typename kzg10<ppT>::witness;
43-
44-
/// The values chosen by the verifier in the interactive
45-
/// protocol. Namely, the points at which to evaluate each set of
46-
/// polynomials, and the randomness to use in witness generation.
47-
class multi_point_evaluation_challenge
42+
/// Claimed evaluations of 2 groups of polynomials, fs and gs, at 2 points
43+
/// z_1 and z_2. f_s are evaluated at z_1 and g_s are evaluated at z_2.
44+
class evaluations
4845
{
4946
public:
50-
const Field z_1;
51-
const Field z_2;
52-
const Field gamma_1;
53-
const Field gamma_2;
54-
55-
multi_point_evaluation_challenge(
56-
const Field &z_1,
57-
const Field &z_2,
58-
const Field &gamma_1,
59-
const Field &gamma_2);
47+
std::vector<Field> s_1s;
48+
std::vector<Field> s_2s;
49+
50+
evaluations(std::vector<Field> &&fs, std::vector<Field> &&gs);
6051
};
6152

6253
/// The evaluation witness created by the prover in the interactive
63-
/// protocol. Given a multi_point_evaluation_challenge for 2 sets of
64-
/// polynomials, return their evaluations (at z_1 for the first set, at z_2
65-
/// for the second set), and a witness proving the correctness of these
66-
/// evaluations to a verifier holding the commitments for the polynomials
67-
/// in the 2 sets..
68-
class multi_point_evaluation_witness
54+
/// protocol. Given a challenge (gamma_1 and gamma_2) and the claimed
55+
/// evaluation of 2 sets of polynomials, the prover returns this witness,
56+
/// proving the correctness of the evaluations. A verifier holding the
57+
/// commitments for all polynomials in the 2 sets can then verify this
58+
/// witness.
59+
class evaluation_witness
6960
{
7061
public:
71-
// Evaluation of polynomials f_1s at z_1.
72-
const std::vector<Field> s_1s;
73-
// Evaluation of polynomials f_2s at z_2.
74-
const std::vector<Field> s_2s;
7562
// Part of witness corresponding to evaluations of f_1s.
7663
const libff::G1<ppT> W_1;
7764
// Part of witness corresponding to evaluations of f_2s.
7865
const libff::G1<ppT> W_2;
7966

80-
multi_point_evaluation_witness(
81-
const std::vector<Field> &&s_1s,
82-
const std::vector<Field> &&s_2s,
83-
const libff::G1<ppT> &W_1,
84-
const libff::G1<ppT> &W_2);
67+
evaluation_witness(
68+
const libff::G1<ppT> &W_1, const libff::G1<ppT> &W_2);
8569
};
8670

87-
/// Evaluate the polynomials fs and gs at the points z_1 and z_2
88-
/// respectively, and generate a witness to prove the correctness of these
89-
/// evaluations. Returns a `multi_point_evaluation_witness` object holding
90-
/// this data.
91-
static multi_point_evaluation_witness create_witness(
92-
const srs &srs,
93-
const multi_point_evaluation_challenge &challenge,
71+
/// Evaluate the polynomials and return an evaluation object. f_s are
72+
/// evaluated at z_1 and g_s are evaluated at z_2.
73+
static evaluations evaluate_polynomials(
9474
const std::vector<polynomial<Field>> &fs,
95-
const std::vector<polynomial<Field>> &gs);
75+
const std::vector<polynomial<Field>> &gs,
76+
const Field &z_1,
77+
const Field &z_2);
9678

97-
/// Given a `multi_point_evaluation_witness` generated for polynomials with
98-
/// commitments `cm_1s` and `cm_2s`, in response to `challenge`, verify the
99-
/// witnesses, and thereby that the given polynomials attain the claimed
100-
/// values at the evaluation points.
101-
static bool verify_eval(
79+
/// Generate a witness to prove the correctness of these evaluations.
80+
/// Returns a `multi_point_evaluation_witness` object holding this data.
81+
static evaluation_witness create_evaluation_witness(
82+
const std::vector<polynomial<Field>> &fs,
83+
const std::vector<polynomial<Field>> &gs,
84+
const Field &z_1,
85+
const Field &z_2,
86+
const evaluations &evaluations,
87+
const srs &srs,
88+
const Field &gamma_1,
89+
const Field &gamma_2);
90+
91+
/// Given an `evaluation` and `evaluation_witness` generated for
92+
/// polynomials with commitments `cm_1s` and `cm_2s`, verify the witnesses
93+
/// using randomness r. This convinces the verifier that the given
94+
/// polynomials attain the claimed values at the evaluation points z_1 and
95+
/// z_2.
96+
static bool verify_evaluations(
97+
const Field &z_1,
98+
const Field &z_2,
99+
const evaluations &evaluations,
102100
const srs &srs,
103-
const multi_point_evaluation_challenge &challenge,
101+
const Field &gamma_1,
102+
const Field &gamma_2,
103+
const evaluation_witness &witness,
104104
const std::vector<commitment> &cm_1s,
105105
const std::vector<commitment> &cm_2s,
106-
const multi_point_evaluation_witness &witness,
107-
const libff::Fr<ppT> &r);
106+
const Field &r);
108107
};
109108

110109
} // namespace libsnark

libsnark/polynomial_commitments/kzg10_batched.tcc

Lines changed: 72 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -88,42 +88,66 @@ static polynomial<FieldT> polynomial_accumulate_with_power_factors(
8888
} // namespace internal
8989

9090
template<typename ppT>
91-
kzg10_batched_2_point<ppT>::multi_point_evaluation_challenge::
92-
multi_point_evaluation_challenge(
93-
const Field &z_1,
94-
const Field &z_2,
95-
const Field &gamma_1,
96-
const Field &gamma_2)
97-
: z_1(z_1), z_2(z_2), gamma_1(gamma_1), gamma_2(gamma_2)
91+
kzg10_batched_2_point<ppT>::evaluations::evaluations(
92+
std::vector<Field> &&s_1s, std::vector<Field> &&s_2s)
93+
: s_1s(s_1s), s_2s(s_2s)
9894
{
9995
}
10096

10197
template<typename ppT>
102-
kzg10_batched_2_point<ppT>::multi_point_evaluation_witness::
103-
multi_point_evaluation_witness(
104-
const std::vector<Field> &&s_1s,
105-
const std::vector<Field> &&s_2s,
106-
const libff::G1<ppT> &W_1,
107-
const libff::G1<ppT> &W_2)
108-
: s_1s(s_1s), s_2s(s_2s), W_1(W_1), W_2(W_2)
98+
kzg10_batched_2_point<ppT>::evaluation_witness::evaluation_witness(
99+
const libff::G1<ppT> &W_1, const libff::G1<ppT> &W_2)
100+
: W_1(W_1), W_2(W_2)
109101
{
110102
}
111103

112104
template<typename ppT>
113-
typename kzg10_batched_2_point<ppT>::multi_point_evaluation_witness
114-
kzg10_batched_2_point<ppT>::create_witness(
115-
const srs &srs,
116-
const multi_point_evaluation_challenge &challenge,
117-
const std::vector<polynomial<Field>> &fs,
118-
const std::vector<polynomial<Field>> &gs)
105+
typename kzg10_batched_2_point<ppT>::evaluations kzg10_batched_2_point<ppT>::
106+
evaluate_polynomials(
107+
const std::vector<polynomial<Field>> &fs,
108+
const std::vector<polynomial<Field>> &gs,
109+
const Field &z_1,
110+
const Field &z_2)
119111
{
120112
// Denote the numbers of polynomials as t1 and t2, consistent with [GWC19].
121113
const size_t t1 = fs.size();
122114
const size_t t2 = gs.size();
123115

124-
// For convenience of variable naming, let $f_i \in fs$ and $g_i in gs$ to
125-
// be the two sets of polynomials. These are denoted $f_i$ and $f^\prime_i$
126-
// in [GWC19]. Similarly, $h_1$ and $h_2$ are used in place of $h$ and
116+
std::vector<Field> s_1s;
117+
s_1s.reserve(t1);
118+
for (const polynomial<Field> &f_i : fs) {
119+
s_1s.push_back(libfqfft::evaluate_polynomial(f_i.size(), f_i, z_1));
120+
}
121+
122+
std::vector<Field> s_2s;
123+
s_2s.reserve(t2);
124+
for (const polynomial<Field> &g_i : gs) {
125+
s_2s.push_back(libfqfft::evaluate_polynomial(g_i.size(), g_i, z_2));
126+
}
127+
128+
return evaluations(std::move(s_1s), std::move(s_2s));
129+
}
130+
131+
template<typename ppT>
132+
typename kzg10_batched_2_point<ppT>::evaluation_witness kzg10_batched_2_point<
133+
ppT>::
134+
create_evaluation_witness(
135+
const std::vector<polynomial<Field>> &fs,
136+
const std::vector<polynomial<Field>> &gs,
137+
const Field &z_1,
138+
const Field &z_2,
139+
const evaluations &evaluations,
140+
const srs &srs,
141+
const Field &gamma_1,
142+
const Field &gamma_2)
143+
{
144+
assert(fs.size() == evaluations.s_1s.size());
145+
assert(gs.size() == evaluations.s_2s.size());
146+
libff::UNUSED(evaluations);
147+
148+
// For convenience of variable naming, let $f_i \in fs$ and $g_i in gs$ be
149+
// the two sets of polynomials. These are denoted $f_i$ and $f^\prime_i$ in
150+
// [GWC19]. Similarly, $h_1$ and $h_2$ are used in place of $h$ and
127151
// $h^\prime$ in the paper, and $\gamma_1$ and $\gamma_2$ in place of
128152
// $\gamma$ and $\gamma^\prime$.
129153
//
@@ -137,71 +161,59 @@ kzg10_batched_2_point<ppT>::create_witness(
137161
//
138162
// W_1 = [h_1(x)]_1
139163
// W_2 = [h_2(x)]_2
140-
// sf_i = f_i(z_1) for i = 1, ..., t1
141-
// sg_i = g_i(z_2) for i = 1, ..., t2
142164

143165
// Compute the sum of $\gamma_1^{i=1} f_i$ polynomials, and pass this
144166
// polynomial into the kzg10 create_witness function, to yield $W_1$ and
145167
// $sf_1$.
146168

147-
// Evaluations
148-
std::vector<Field> s_1s;
149-
s_1s.reserve(t1);
150-
for (const polynomial<Field> &f_i : fs) {
151-
s_1s.push_back(
152-
libfqfft::evaluate_polynomial(f_i.size(), f_i, challenge.z_1));
153-
}
154-
155-
std::vector<Field> s_2s;
156-
s_2s.reserve(t2);
157-
for (const polynomial<Field> &g_i : gs) {
158-
s_2s.push_back(
159-
libfqfft::evaluate_polynomial(g_i.size(), g_i, challenge.z_2));
160-
}
169+
// TODO: Use the evaluations object to compute f_accum_eval and
170+
// g_accum_eval, instead of evaluating the accumulated polynomial.
161171

162172
// Accumulate polynomials and get the witnesses
163173
const polynomial<Field> f_accum =
164-
internal::polynomial_accumulate_with_power_factors(
165-
fs, challenge.gamma_1);
166-
const evaluation_and_witness<ppT, kzg10<ppT>> f_accum_witness =
167-
kzg10<ppT>::create_witness(srs, f_accum, challenge.z_1);
174+
internal::polynomial_accumulate_with_power_factors(fs, gamma_1);
175+
const libff::Fr<ppT> f_accum_eval =
176+
kzg10<ppT>::evaluate_polynomial(f_accum, z_1);
177+
const libff::G1<ppT> f_accum_witness =
178+
kzg10<ppT>::create_evaluation_witness(f_accum, z_1, f_accum_eval, srs);
168179

169180
const polynomial<Field> g_accum =
170-
internal::polynomial_accumulate_with_power_factors(
171-
gs, challenge.gamma_2);
172-
const evaluation_and_witness<ppT, kzg10<ppT>> g_accum_witness =
173-
kzg10<ppT>::create_witness(srs, g_accum, challenge.z_2);
181+
internal::polynomial_accumulate_with_power_factors(gs, gamma_2);
182+
const libff::Fr<ppT> g_accum_eval =
183+
kzg10<ppT>::evaluate_polynomial(g_accum, z_2);
184+
const libff::G1<ppT> g_accum_witness =
185+
kzg10<ppT>::create_evaluation_witness(g_accum, z_2, g_accum_eval, srs);
174186

175-
return multi_point_evaluation_witness(
176-
std::move(s_1s), std::move(s_2s), f_accum_witness.w, g_accum_witness.w);
187+
return evaluation_witness(f_accum_witness, g_accum_witness);
177188
}
178189

179190
template<typename ppT>
180-
bool kzg10_batched_2_point<ppT>::verify_eval(
191+
bool kzg10_batched_2_point<ppT>::verify_evaluations(
192+
const Field &z_1,
193+
const Field &z_2,
194+
const evaluations &evaluations,
181195
const srs &srs,
182-
const multi_point_evaluation_challenge &challenge,
196+
const Field &gamma_1,
197+
const Field &gamma_2,
198+
const evaluation_witness &witness,
183199
const std::vector<commitment> &cm_1s,
184200
const std::vector<commitment> &cm_2s,
185-
const multi_point_evaluation_witness &witness,
186-
const libff::Fr<ppT> &r)
201+
const Field &r)
187202
{
188203
// See Section 3, p13 of [GWC19].
189204

190-
assert(cm_1s.size() == witness.s_1s.size());
191-
assert(cm_2s.size() == witness.s_2s.size());
192-
193205
const size_t t1 = cm_1s.size();
194206
const size_t t2 = cm_2s.size();
207+
assert(t1 == evaluations.s_1s.size());
208+
assert(t2 == evaluations.s_2s.size());
195209

196210
// Compute:
197211
//
198212
// F = \sum_{i=1}^{t1} \gamma_1^{i-1} (cm_1[i] - [s_1[i]]_1) + (G)
199213
// r \sum_{i=1}^{t2} \gamma_2^{i-1} (cm_2[i] - [s_2[i]]_1) (H)
200214

201-
const std::vector<Field> &s_1s = witness.s_1s;
202-
const std::vector<Field> &s_2s = witness.s_2s;
203-
const Field gamma_1 = challenge.gamma_1;
204-
const Field gamma_2 = challenge.gamma_2;
215+
const std::vector<Field> &s_1s = evaluations.s_1s;
216+
const std::vector<Field> &s_2s = evaluations.s_2s;
205217

206218
// Compute:
207219
//
@@ -252,8 +264,6 @@ bool kzg10_batched_2_point<ppT>::verify_eval(
252264

253265
const libff::G1<ppT> &W_1 = witness.W_1;
254266
const libff::G1<ppT> &W_2 = witness.W_2;
255-
const Field &z_1 = challenge.z_1;
256-
const Field &z_2 = challenge.z_2;
257267

258268
const libff::G1<ppT> r_W_2 = r * W_2;
259269
const libff::G1<ppT> A = F + z_1 * W_1 + z_2 * r_W_2;

libsnark/polynomial_commitments/tests/test_polynomial_commitments.cpp

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,6 @@ template<typename ppT> void test_kzg10_batched_2_point()
123123
{{91, 92, 93, 94, 95, 96, 97, 98}},
124124
}};
125125

126-
// Evaluation points
127-
const Field z_1("123");
128-
const Field z_2("456");
129-
130-
// Verifiers random challenges
131-
const Field gamma_1(54321);
132-
const Field gamma_2(98760);
133-
134-
const typename batch_scheme::multi_point_evaluation_challenge challange(
135-
z_1, z_2, gamma_1, gamma_2);
136-
137126
// srs
138127
const typename scheme::srs srs =
139128
scheme::setup_from_secret(MAX_DEGREE_MULTI, secret);
@@ -153,13 +142,24 @@ template<typename ppT> void test_kzg10_batched_2_point()
153142
}
154143
ASSERT_EQ(gs.size(), gs.size());
155144

156-
// Evaluation and witness
157-
const typename batch_scheme::multi_point_evaluation_witness witness =
158-
batch_scheme::create_witness(srs, challange, fs, gs);
145+
// Evaluation points
146+
const Field z_1("123");
147+
const Field z_2("456");
148+
149+
// Evaluations
150+
const typename batch_scheme::evaluations evaluations =
151+
batch_scheme::evaluate_polynomials(fs, gs, z_1, z_2);
152+
ASSERT_EQ(fs.size(), evaluations.s_1s.size());
153+
ASSERT_EQ(gs.size(), evaluations.s_2s.size());
154+
155+
// Verifier's random challenges
156+
const Field gamma_1(54321);
157+
const Field gamma_2(98760);
159158

160-
// Check number of evaluations.
161-
ASSERT_EQ(fs.size(), witness.s_1s.size());
162-
ASSERT_EQ(gs.size(), witness.s_2s.size());
159+
// Witness for evaluations
160+
const typename batch_scheme::evaluation_witness witness =
161+
batch_scheme::create_evaluation_witness(
162+
fs, gs, z_1, z_2, evaluations, srs, gamma_1, gamma_2);
163163

164164
// Check evaluations are correct.
165165
{
@@ -183,16 +183,25 @@ template<typename ppT> void test_kzg10_batched_2_point()
183183
const Field g_x_minus_g_z_2 =
184184
libfqfft::evaluate_polynomial(g_i.size(), g_i, secret) -
185185
libfqfft::evaluate_polynomial(g_i.size(), g_i, z_2);
186-
const Field gamma_power = challange.gamma_2 ^ i;
186+
const Field gamma_power = gamma_2 ^ i;
187187
h_2_x += gamma_power * g_x_minus_g_z_2 * ((secret - z_2).inverse());
188188
}
189189
ASSERT_EQ(h_2_x * libff::G1<ppT>::one(), witness.W_2);
190190
}
191191

192192
// Verify the witnesses
193193
const Field r = Field(23546);
194-
ASSERT_TRUE(
195-
batch_scheme::verify_eval(srs, challange, cm_1s, cm_2s, witness, r));
194+
ASSERT_TRUE(batch_scheme::verify_evaluations(
195+
z_1,
196+
z_2,
197+
evaluations,
198+
srs,
199+
gamma_1,
200+
gamma_2,
201+
witness,
202+
cm_1s,
203+
cm_2s,
204+
r));
196205
}
197206

198207
template<typename ppT> void test_for_curve()

0 commit comments

Comments
 (0)