Skip to content

Commit cdcbc8d

Browse files
authored
Remove gamma from the groth16 snark (#1383)
This PR removes gamma from the Groth16 implementation (or put another way, it sets gamma equal to one). The benefit is that it makes the verification key one G2 element smaller, which is a big win from the point of view of proof composition. I opened a PR on libsnark [here](scipr-lab/libsnark#137) so hopefully that eventually makes it in upstream, but I want to get this through here first.
1 parent 3f1b854 commit cdcbc8d

File tree

2 files changed

+42
-54
lines changed

2 files changed

+42
-54
lines changed

src/lib/snarky/src/camlsnark_c/libsnark-caml/libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/r1cs_gg_ppzksnark.hpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -168,30 +168,27 @@ template<typename ppT>
168168
class r1cs_gg_ppzksnark_verification_key {
169169
public:
170170
libff::GT<ppT> alpha_g1_beta_g2;
171-
libff::G2<ppT> gamma_g2;
172171
libff::G2<ppT> delta_g2;
173172

174-
accumulation_vector<libff::G1<ppT> > gamma_ABC_g1;
173+
accumulation_vector<libff::G1<ppT> > ABC_g1;
175174

176175
r1cs_gg_ppzksnark_verification_key() = default;
177176
r1cs_gg_ppzksnark_verification_key(const libff::GT<ppT> &alpha_g1_beta_g2,
178-
const libff::G2<ppT> &gamma_g2,
179177
const libff::G2<ppT> &delta_g2,
180-
const accumulation_vector<libff::G1<ppT> > &gamma_ABC_g1) :
178+
const accumulation_vector<libff::G1<ppT> > &ABC_g1) :
181179
alpha_g1_beta_g2(alpha_g1_beta_g2),
182-
gamma_g2(gamma_g2),
183180
delta_g2(delta_g2),
184-
gamma_ABC_g1(gamma_ABC_g1)
181+
ABC_g1(ABC_g1)
185182
{};
186183

187184
size_t G1_size() const
188185
{
189-
return gamma_ABC_g1.size();
186+
return ABC_g1.size();
190187
}
191188

192189
size_t G2_size() const
193190
{
194-
return 2;
191+
return 1;
195192
}
196193

197194
size_t GT_size() const
@@ -202,7 +199,7 @@ class r1cs_gg_ppzksnark_verification_key {
202199
size_t size_in_bits() const
203200
{
204201
// TODO: include GT size
205-
return (gamma_ABC_g1.size_in_bits() + 2 * libff::G2<ppT>::size_in_bits());
202+
return (ABC_g1.size_in_bits() + 2 * libff::G2<ppT>::size_in_bits());
206203
}
207204

208205
void print_size() const
@@ -243,10 +240,10 @@ template<typename ppT>
243240
class r1cs_gg_ppzksnark_processed_verification_key {
244241
public:
245242
libff::GT<ppT> vk_alpha_g1_beta_g2;
246-
libff::G2_precomp<ppT> vk_gamma_g2_precomp;
243+
libff::G2_precomp<ppT> vk_generator_g2_precomp;
247244
libff::G2_precomp<ppT> vk_delta_g2_precomp;
248245

249-
accumulation_vector<libff::G1<ppT> > gamma_ABC_g1;
246+
accumulation_vector<libff::G1<ppT> > ABC_g1;
250247

251248
bool operator==(const r1cs_gg_ppzksnark_processed_verification_key &other) const;
252249
friend std::ostream& operator<< <ppT>(std::ostream &out, const r1cs_gg_ppzksnark_processed_verification_key<ppT> &pvk);

src/lib/snarky/src/camlsnark_c/libsnark-caml/libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/r1cs_gg_ppzksnark.tcc

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,16 @@ template<typename ppT>
9191
bool r1cs_gg_ppzksnark_verification_key<ppT>::operator==(const r1cs_gg_ppzksnark_verification_key<ppT> &other) const
9292
{
9393
return (this->alpha_g1_beta_g2 == other.alpha_g1_beta_g2 &&
94-
this->gamma_g2 == other.gamma_g2 &&
9594
this->delta_g2 == other.delta_g2 &&
96-
this->gamma_ABC_g1 == other.gamma_ABC_g1);
95+
this->ABC_g1 == other.ABC_g1);
9796
}
9897

9998
template<typename ppT>
10099
std::ostream& operator<<(std::ostream &out, const r1cs_gg_ppzksnark_verification_key<ppT> &vk)
101100
{
102101
out << vk.alpha_g1_beta_g2 << OUTPUT_NEWLINE;
103-
out << vk.gamma_g2 << OUTPUT_NEWLINE;
104102
out << vk.delta_g2 << OUTPUT_NEWLINE;
105-
out << vk.gamma_ABC_g1 << OUTPUT_NEWLINE;
103+
out << vk.ABC_g1 << OUTPUT_NEWLINE;
106104

107105
return out;
108106
}
@@ -112,11 +110,9 @@ std::istream& operator>>(std::istream &in, r1cs_gg_ppzksnark_verification_key<pp
112110
{
113111
in >> vk.alpha_g1_beta_g2;
114112
libff::consume_OUTPUT_NEWLINE(in);
115-
in >> vk.gamma_g2;
116-
libff::consume_OUTPUT_NEWLINE(in);
117113
in >> vk.delta_g2;
118114
libff::consume_OUTPUT_NEWLINE(in);
119-
in >> vk.gamma_ABC_g1;
115+
in >> vk.ABC_g1;
120116
libff::consume_OUTPUT_NEWLINE(in);
121117

122118
return in;
@@ -126,18 +122,18 @@ template<typename ppT>
126122
bool r1cs_gg_ppzksnark_processed_verification_key<ppT>::operator==(const r1cs_gg_ppzksnark_processed_verification_key<ppT> &other) const
127123
{
128124
return (this->vk_alpha_g1_beta_g2 == other.vk_alpha_g1_beta_g2 &&
129-
this->vk_gamma_g2_precomp == other.vk_gamma_g2_precomp &&
125+
this->vk_generator_g2_precomp == other.vk_generator_g2_precomp &&
130126
this->vk_delta_g2_precomp == other.vk_delta_g2_precomp &&
131-
this->gamma_ABC_g1 == other.gamma_ABC_g1);
127+
this->ABC_g1 == other.ABC_g1);
132128
}
133129

134130
template<typename ppT>
135131
std::ostream& operator<<(std::ostream &out, const r1cs_gg_ppzksnark_processed_verification_key<ppT> &pvk)
136132
{
137133
out << pvk.vk_alpha_g1_beta_g2 << OUTPUT_NEWLINE;
138-
out << pvk.vk_gamma_g2_precomp << OUTPUT_NEWLINE;
134+
out << pvk.vk_generator_g2_precomp << OUTPUT_NEWLINE;
139135
out << pvk.vk_delta_g2_precomp << OUTPUT_NEWLINE;
140-
out << pvk.gamma_ABC_g1 << OUTPUT_NEWLINE;
136+
out << pvk.ABC_g1 << OUTPUT_NEWLINE;
141137

142138
return out;
143139
}
@@ -147,11 +143,11 @@ std::istream& operator>>(std::istream &in, r1cs_gg_ppzksnark_processed_verificat
147143
{
148144
in >> pvk.vk_alpha_g1_beta_g2;
149145
libff::consume_OUTPUT_NEWLINE(in);
150-
in >> pvk.vk_gamma_g2_precomp;
146+
in >> pvk.vk_generator_g2_precomp;
151147
libff::consume_OUTPUT_NEWLINE(in);
152148
in >> pvk.vk_delta_g2_precomp;
153149
libff::consume_OUTPUT_NEWLINE(in);
154-
in >> pvk.gamma_ABC_g1;
150+
in >> pvk.ABC_g1;
155151
libff::consume_OUTPUT_NEWLINE(in);
156152

157153
return in;
@@ -193,7 +189,6 @@ r1cs_gg_ppzksnark_verification_key<ppT> r1cs_gg_ppzksnark_verification_key<ppT>:
193189
{
194190
r1cs_gg_ppzksnark_verification_key<ppT> result;
195191
result.alpha_g1_beta_g2 = libff::Fr<ppT>::random_element() * libff::GT<ppT>::random_element();
196-
result.gamma_g2 = libff::G2<ppT>::random_element();
197192
result.delta_g2 = libff::G2<ppT>::random_element();
198193

199194
libff::G1<ppT> base = libff::G1<ppT>::random_element();
@@ -203,7 +198,7 @@ r1cs_gg_ppzksnark_verification_key<ppT> r1cs_gg_ppzksnark_verification_key<ppT>:
203198
v.emplace_back(libff::G1<ppT>::random_element());
204199
}
205200

206-
result.gamma_ABC_g1 = accumulation_vector<libff::G1<ppT> >(std::move(base), std::move(v));
201+
result.ABC_g1 = accumulation_vector<libff::G1<ppT> >(std::move(base), std::move(v));
207202

208203
return result;
209204
}
@@ -221,9 +216,7 @@ r1cs_gg_ppzksnark_keypair<ppT> r1cs_gg_ppzksnark_generator(const r1cs_gg_ppzksna
221216
const libff::Fr<ppT> t = libff::Fr<ppT>::random_element();
222217
const libff::Fr<ppT> alpha = libff::Fr<ppT>::random_element();
223218
const libff::Fr<ppT> beta = libff::Fr<ppT>::random_element();
224-
const libff::Fr<ppT> gamma = libff::Fr<ppT>::random_element();
225219
const libff::Fr<ppT> delta = libff::Fr<ppT>::random_element();
226-
const libff::Fr<ppT> gamma_inverse = gamma.inverse();
227220
const libff::Fr<ppT> delta_inverse = delta.inverse();
228221

229222
/* A quadratic arithmetic program evaluated at t. */
@@ -256,17 +249,17 @@ r1cs_gg_ppzksnark_keypair<ppT> r1cs_gg_ppzksnark_generator(const r1cs_gg_ppzksna
256249
libff::Fr_vector<ppT> Ct = std::move(qap.Ct);
257250
libff::Fr_vector<ppT> Ht = std::move(qap.Ht);
258251

259-
/* The gamma inverse product component: (beta*A_i(t) + alpha*B_i(t) + C_i(t)) * gamma^{-1}. */
260-
libff::enter_block("Compute gamma_ABC for R1CS verification key");
261-
libff::Fr_vector<ppT> gamma_ABC;
262-
gamma_ABC.reserve(qap.num_inputs());
252+
/* The product component: (beta*A_i(t) + alpha*B_i(t) + C_i(t)). */
253+
libff::enter_block("Compute ABC for R1CS verification key");
254+
libff::Fr_vector<ppT> ABC;
255+
ABC.reserve(qap.num_inputs());
263256

264-
const libff::Fr<ppT> gamma_ABC_0 = (beta * At[0] + alpha * Bt[0] + Ct[0]) * gamma_inverse;
257+
const libff::Fr<ppT> ABC_0 = beta * At[0] + alpha * Bt[0] + Ct[0];
265258
for (size_t i = 1; i < qap.num_inputs() + 1; ++i)
266259
{
267-
gamma_ABC.emplace_back((beta * At[i] + alpha * Bt[i] + Ct[i]) * gamma_inverse);
260+
ABC.emplace_back(beta * At[i] + alpha * Bt[i] + Ct[i]);
268261
}
269-
libff::leave_block("Compute gamma_ABC for R1CS verification key");
262+
libff::leave_block("Compute ABC for R1CS verification key");
270263

271264
/* The delta inverse product component: (beta*A_i(t) + alpha*B_i(t) + C_i(t)) * delta^{-1}. */
272265
libff::enter_block("Compute L query for R1CS proving key");
@@ -353,22 +346,20 @@ r1cs_gg_ppzksnark_keypair<ppT> r1cs_gg_ppzksnark_generator(const r1cs_gg_ppzksna
353346

354347
libff::enter_block("Generate R1CS verification key");
355348
libff::GT<ppT> alpha_g1_beta_g2 = ppT::reduced_pairing(alpha_g1, beta_g2);
356-
libff::G2<ppT> gamma_g2 = gamma * G2_gen;
357349

358-
libff::enter_block("Encode gamma_ABC for R1CS verification key");
359-
libff::G1<ppT> gamma_ABC_g1_0 = gamma_ABC_0 * g1_generator;
360-
libff::G1_vector<ppT> gamma_ABC_g1_values = batch_exp(g1_scalar_size, g1_window_size, g1_table, gamma_ABC);
361-
libff::leave_block("Encode gamma_ABC for R1CS verification key");
350+
libff::enter_block("Encode ABC for R1CS verification key");
351+
libff::G1<ppT> ABC_g1_0 = ABC_0 * g1_generator;
352+
libff::G1_vector<ppT> ABC_g1_values = batch_exp(g1_scalar_size, g1_window_size, g1_table, ABC);
353+
libff::leave_block("Encode ABC for R1CS verification key");
362354
libff::leave_block("Generate R1CS verification key");
363355

364356
libff::leave_block("Call to r1cs_gg_ppzksnark_generator");
365357

366-
accumulation_vector<libff::G1<ppT> > gamma_ABC_g1(std::move(gamma_ABC_g1_0), std::move(gamma_ABC_g1_values));
358+
accumulation_vector<libff::G1<ppT> > ABC_g1(std::move(ABC_g1_0), std::move(ABC_g1_values));
367359

368360
r1cs_gg_ppzksnark_verification_key<ppT> vk = r1cs_gg_ppzksnark_verification_key<ppT>(alpha_g1_beta_g2,
369-
gamma_g2,
370361
delta_g2,
371-
gamma_ABC_g1);
362+
ABC_g1);
372363

373364
r1cs_gg_ppzksnark_proving_key<ppT> pk = r1cs_gg_ppzksnark_proving_key<ppT>(std::move(alpha_g1),
374365
std::move(beta_g1),
@@ -511,9 +502,9 @@ r1cs_gg_ppzksnark_processed_verification_key<ppT> r1cs_gg_ppzksnark_verifier_pro
511502

512503
r1cs_gg_ppzksnark_processed_verification_key<ppT> pvk;
513504
pvk.vk_alpha_g1_beta_g2 = vk.alpha_g1_beta_g2;
514-
pvk.vk_gamma_g2_precomp = ppT::precompute_G2(vk.gamma_g2);
505+
pvk.vk_generator_g2_precomp = ppT::precompute_G2(libff::G2<ppT>::one());
515506
pvk.vk_delta_g2_precomp = ppT::precompute_G2(vk.delta_g2);
516-
pvk.gamma_ABC_g1 = vk.gamma_ABC_g1;
507+
pvk.ABC_g1 = vk.ABC_g1;
517508

518509
libff::leave_block("Call to r1cs_gg_ppzksnark_verifier_process_vk");
519510

@@ -526,10 +517,10 @@ bool r1cs_gg_ppzksnark_online_verifier_weak_IC(const r1cs_gg_ppzksnark_processed
526517
const r1cs_gg_ppzksnark_proof<ppT> &proof)
527518
{
528519
libff::enter_block("Call to r1cs_gg_ppzksnark_online_verifier_weak_IC");
529-
assert(pvk.gamma_ABC_g1.domain_size() >= primary_input.size());
520+
assert(pvk.ABC_g1.domain_size() >= primary_input.size());
530521

531522
libff::enter_block("Accumulate input");
532-
const accumulation_vector<libff::G1<ppT> > accumulated_IC = pvk.gamma_ABC_g1.template accumulate_chunk<libff::Fr<ppT> >(primary_input.begin(), primary_input.end(), 0);
523+
const accumulation_vector<libff::G1<ppT> > accumulated_IC = pvk.ABC_g1.template accumulate_chunk<libff::Fr<ppT> >(primary_input.begin(), primary_input.end(), 0);
533524
const libff::G1<ppT> &acc = accumulated_IC.first;
534525
libff::leave_block("Accumulate input");
535526

@@ -555,7 +546,7 @@ bool r1cs_gg_ppzksnark_online_verifier_weak_IC(const r1cs_gg_ppzksnark_processed
555546

556547
const libff::Fqk<ppT> QAP1 = ppT::miller_loop(proof_g_A_precomp, proof_g_B_precomp);
557548
const libff::Fqk<ppT> QAP2 = ppT::double_miller_loop(
558-
acc_precomp, pvk.vk_gamma_g2_precomp,
549+
acc_precomp, pvk.vk_generator_g2_precomp,
559550
proof_g_C_precomp, pvk.vk_delta_g2_precomp);
560551
const libff::GT<ppT> QAP = ppT::final_exponentiation(QAP1 * QAP2.unitary_inverse());
561552

@@ -595,9 +586,9 @@ bool r1cs_gg_ppzksnark_online_verifier_strong_IC(const r1cs_gg_ppzksnark_process
595586
bool result = true;
596587
libff::enter_block("Call to r1cs_gg_ppzksnark_online_verifier_strong_IC");
597588

598-
if (pvk.gamma_ABC_g1.domain_size() != primary_input.size())
589+
if (pvk.ABC_g1.domain_size() != primary_input.size())
599590
{
600-
libff::print_indent(); printf("Input length differs from expected (got %zu, expected %zu).\n", primary_input.size(), pvk.gamma_ABC_g1.domain_size());
591+
libff::print_indent(); printf("Input length differs from expected (got %zu, expected %zu).\n", primary_input.size(), pvk.ABC_g1.domain_size());
601592
result = false;
602593
}
603594
else
@@ -627,13 +618,13 @@ bool r1cs_gg_ppzksnark_affine_verifier_weak_IC(const r1cs_gg_ppzksnark_verificat
627618
const r1cs_gg_ppzksnark_proof<ppT> &proof)
628619
{
629620
libff::enter_block("Call to r1cs_gg_ppzksnark_affine_verifier_weak_IC");
630-
assert(vk.gamma_ABC_g1.domain_size() >= primary_input.size());
621+
assert(vk.ABC_g1.domain_size() >= primary_input.size());
631622

632-
libff::affine_ate_G2_precomp<ppT> pvk_vk_gamma_g2_precomp = ppT::affine_ate_precompute_G2(vk.gamma_g2);
623+
libff::affine_ate_G2_precomp<ppT> pvk_vk_generator_g2_precomp = ppT::affine_ate_precompute_G2(libff::G2<ppT>::one());
633624
libff::affine_ate_G2_precomp<ppT> pvk_vk_delta_g2_precomp = ppT::affine_ate_precompute_G2(vk.delta_g2);
634625

635626
libff::enter_block("Accumulate input");
636-
const accumulation_vector<libff::G1<ppT> > accumulated_IC = vk.gamma_ABC_g1.template accumulate_chunk<libff::Fr<ppT> >(primary_input.begin(), primary_input.end(), 0);
627+
const accumulation_vector<libff::G1<ppT> > accumulated_IC = vk.ABC_g1.template accumulate_chunk<libff::Fr<ppT> >(primary_input.begin(), primary_input.end(), 0);
637628
const libff::G1<ppT> &acc = accumulated_IC.first;
638629
libff::leave_block("Accumulate input");
639630

@@ -657,7 +648,7 @@ bool r1cs_gg_ppzksnark_affine_verifier_weak_IC(const r1cs_gg_ppzksnark_verificat
657648
const libff::affine_ate_G1_precomp<ppT> acc_precomp = ppT::affine_ate_precompute_G1(acc);
658649

659650
const libff::Fqk<ppT> QAP_miller = ppT::affine_ate_e_times_e_over_e_miller_loop(
660-
acc_precomp, pvk_vk_gamma_g2_precomp,
651+
acc_precomp, pvk_vk_generator_g2_precomp,
661652
proof_g_C_precomp, pvk_vk_delta_g2_precomp,
662653
proof_g_A_precomp, proof_g_B_precomp);
663654
const libff::GT<ppT> QAP = ppT::final_exponentiation(QAP_miller.unitary_inverse());

0 commit comments

Comments
 (0)