Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
groth16_snark.tcc
Go to the documentation of this file.
1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
2 //
3 // SPDX-License-Identifier: LGPL-3.0+
4 
5 #ifndef __ZETH_SNARKS_GROTH16_GROTH16_SNARK_TCC__
6 #define __ZETH_SNARKS_GROTH16_GROTH16_SNARK_TCC__
7 
8 #include "libzeth/core/group_element_utils.hpp"
9 #include "libzeth/core/utils.hpp"
10 #include "libzeth/serialization/r1cs_serialization.hpp"
11 #include "libzeth/snarks/groth16/groth16_snark.hpp"
12 
13 namespace libzeth
14 {
15 
16 template<typename ppT> const std::string groth16_snark<ppT>::name("GROTH16");
17 
18 template<typename ppT>
19 typename groth16_snark<ppT>::keypair groth16_snark<ppT>::generate_setup(
20  const libsnark::protoboard<libff::Fr<ppT>> &pb)
21 {
22  // Generate verification and proving key from the R1CS
23  return libsnark::r1cs_gg_ppzksnark_generator<ppT>(
24  pb.get_constraint_system(), true);
25 }
26 
27 template<typename ppT>
28 typename groth16_snark<ppT>::proof groth16_snark<ppT>::generate_proof(
29  const typename groth16_snark<ppT>::proving_key &proving_key,
30  const libsnark::protoboard<libff::Fr<ppT>> &pb)
31 {
32  return generate_proof(
33  proving_key, pb.primary_input(), pb.auxiliary_input());
34 }
35 
36 template<typename ppT>
37 typename groth16_snark<ppT>::proof groth16_snark<ppT>::generate_proof(
38  const proving_key &proving_key,
39  const libsnark::r1cs_primary_input<libff::Fr<ppT>> &primary_input,
40  const libsnark::r1cs_auxiliary_input<libff::Fr<ppT>> auxiliary_input)
41 {
42  // Generate proof from public input, auxiliary input and proving key.
43  // For now, force a pow2 domain, in case the key came from the MPC.
44  return libsnark::r1cs_gg_ppzksnark_prover(
45  proving_key, primary_input, auxiliary_input, true);
46 }
47 
48 template<typename ppT>
49 bool groth16_snark<ppT>::verify(
50  const libsnark::r1cs_primary_input<libff::Fr<ppT>> &primary_inputs,
51  const groth16_snark<ppT>::proof &proof,
52  const groth16_snark<ppT>::verification_key &verification_key)
53 {
54  return libsnark::r1cs_gg_ppzksnark_verifier_strong_IC<ppT>(
55  verification_key, primary_inputs, proof);
56 }
57 
58 template<typename ppT>
59 void groth16_snark<ppT>::verification_key_write_json(
60  const verification_key &vk, std::ostream &out_s)
61 {
62  const size_t abc_length = vk.ABC_g1.rest.indices.size() + 1;
63  out_s << "{"
64  << "\n"
65  << " \"alpha\": " << group_element_to_json(vk.alpha_g1) << ",\n"
66  << " \"beta\": " << group_element_to_json(vk.beta_g2) << ",\n"
67  << " \"delta\": " << group_element_to_json(vk.delta_g2) << ",\n"
68  << " \"ABC\": [\n " << group_element_to_json(vk.ABC_g1.first);
69  for (size_t i = 1; i < abc_length; ++i) {
70  out_s << ",\n "
71  << group_element_to_json(vk.ABC_g1.rest.values[i - 1]);
72  }
73  out_s << "\n ]\n}";
74 }
75 
76 template<typename ppT>
77 void groth16_snark<ppT>::verification_key_write_bytes(
78  const verification_key &vk, std::ostream &out_s)
79 {
80  using G1 = libff::G1<ppT>;
81 
82  if (!is_well_formed<ppT>(vk)) {
83  throw std::invalid_argument("verification key (write) not well-formed");
84  }
85 
86  group_element_write_bytes(vk.alpha_g1, out_s);
87  group_element_write_bytes(vk.beta_g2, out_s);
88  group_element_write_bytes(vk.delta_g2, out_s);
89  accumulation_vector_write_bytes<G1, group_element_write_bytes<G1>>(
90  vk.ABC_g1, out_s);
91 }
92 
93 template<typename ppT>
94 void groth16_snark<ppT>::proving_key_write_bytes(
95  const proving_key &pk, std::ostream &out_s)
96 {
97  if (!is_well_formed<ppT>(pk)) {
98  throw std::invalid_argument("proving key (write) not well-formed");
99  }
100 
101  group_element_write_bytes(pk.alpha_g1, out_s);
102  group_element_write_bytes(pk.beta_g1, out_s);
103  group_element_write_bytes(pk.beta_g2, out_s);
104  group_element_write_bytes(pk.delta_g1, out_s);
105  group_element_write_bytes(pk.delta_g2, out_s);
106  group_elements_write_bytes(pk.A_query, out_s);
107  knowledge_commitment_vector_write_bytes(pk.B_query, out_s);
108  group_elements_write_bytes(pk.H_query, out_s);
109  group_elements_write_bytes(pk.L_query, out_s);
110  r1cs_write_bytes(pk.constraint_system, out_s);
111 }
112 
113 template<typename ppT>
114 void groth16_snark<ppT>::verification_key_read_bytes(
115  groth16_snark<ppT>::verification_key &vk, std::istream &in_s)
116 {
117  using G1 = libff::G1<ppT>;
118 
119  group_element_read_bytes(vk.alpha_g1, in_s);
120  group_element_read_bytes(vk.beta_g2, in_s);
121  group_element_read_bytes(vk.delta_g2, in_s);
122  accumulation_vector_read_bytes<G1, group_element_read_bytes<G1>>(
123  vk.ABC_g1, in_s);
124 
125  if (!is_well_formed<ppT>(vk)) {
126  throw std::invalid_argument("verification key (read) not well-formed");
127  }
128 }
129 
130 template<typename ppT>
131 void groth16_snark<ppT>::proving_key_read_bytes(
132  groth16_snark<ppT>::proving_key &pk, std::istream &in_s)
133 {
134  group_element_read_bytes(pk.alpha_g1, in_s);
135  group_element_read_bytes(pk.beta_g1, in_s);
136  group_element_read_bytes(pk.beta_g2, in_s);
137  group_element_read_bytes(pk.delta_g1, in_s);
138  group_element_read_bytes(pk.delta_g2, in_s);
139  group_elements_read_bytes(pk.A_query, in_s);
140  knowledge_commitment_vector_read_bytes(pk.B_query, in_s);
141  group_elements_read_bytes(pk.H_query, in_s);
142  group_elements_read_bytes(pk.L_query, in_s);
143  r1cs_read_bytes(pk.constraint_system, in_s);
144 
145  if (!is_well_formed<ppT>(pk)) {
146  throw std::invalid_argument("proving key (read) not well-formed");
147  }
148 }
149 
150 template<typename ppT>
151 void groth16_snark<ppT>::proof_write_json(
152  const typename groth16_snark<ppT>::proof &proof, std::ostream &out_s)
153 {
154  out_s << "{\n \"a\": " << group_element_to_json(proof.g_A)
155  << ",\n \"b\": " << group_element_to_json(proof.g_B)
156  << ",\n \"c\": " << group_element_to_json(proof.g_C) << "\n}";
157 }
158 
159 template<typename ppT>
160 void groth16_snark<ppT>::proof_write_bytes(
161  const typename groth16_snark<ppT>::proof &proof, std::ostream &out_s)
162 {
163  group_element_write_bytes(proof.g_A, out_s);
164  group_element_write_bytes(proof.g_B, out_s);
165  group_element_write_bytes(proof.g_C, out_s);
166 }
167 
168 template<typename ppT>
169 void groth16_snark<ppT>::proof_read_bytes(
170  typename groth16_snark<ppT>::proof &proof, std::istream &in_s)
171 {
172  group_element_read_bytes(proof.g_A, in_s);
173  group_element_read_bytes(proof.g_B, in_s);
174  group_element_read_bytes(proof.g_C, in_s);
175 }
176 
177 template<typename ppT>
178 void groth16_snark<ppT>::keypair_write_bytes(
179  const typename groth16_snark<ppT>::keypair &keypair, std::ostream &out_s)
180 {
181  proving_key_write_bytes(keypair.pk, out_s);
182  verification_key_write_bytes(keypair.vk, out_s);
183 }
184 
185 template<typename ppT>
186 void groth16_snark<ppT>::keypair_read_bytes(
187  typename groth16_snark<ppT>::keypair &keypair, std::istream &in_s)
188 {
189  proving_key_read_bytes(keypair.pk, in_s);
190  verification_key_read_bytes(keypair.vk, in_s);
191 }
192 
193 template<typename ppT>
194 bool is_well_formed(const typename groth16_snark<ppT>::proving_key &pk)
195 {
196  if (!pk.alpha_g1.is_well_formed() || !pk.beta_g1.is_well_formed() ||
197  !pk.beta_g2.is_well_formed() || !pk.delta_g1.is_well_formed() ||
198  !pk.delta_g2.is_well_formed() ||
199  !container_is_well_formed(pk.A_query) ||
200  !container_is_well_formed(pk.L_query)) {
201  return false;
202  }
203 
204  using knowledge_commitment =
205  libsnark::knowledge_commitment<libff::G2<ppT>, libff::G1<ppT>>;
206  for (const knowledge_commitment &b : pk.B_query.values) {
207  if (!b.g.is_well_formed() || !b.h.is_well_formed()) {
208  return false;
209  }
210  }
211 
212  return true;
213 }
214 
215 template<typename ppT>
216 bool is_well_formed(const typename groth16_snark<ppT>::verification_key &vk)
217 {
218  if (!vk.alpha_g1.is_well_formed() || !vk.beta_g2.is_well_formed() ||
219  !vk.delta_g2.is_well_formed() || !vk.ABC_g1.first.is_well_formed()) {
220  return false;
221  }
222 
223  return container_is_well_formed(vk.ABC_g1.rest.values);
224 }
225 
226 } // namespace libzeth
227 
228 #endif // __ZETH_SNARKS_GROTH16_GROTH16_SNARK_TCC__