1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
3 // SPDX-License-Identifier: LGPL-3.0+
5 #ifndef __ZETH_SNARKS_GROTH16_GROTH16_SNARK_TCC__
6 #define __ZETH_SNARKS_GROTH16_GROTH16_SNARK_TCC__
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"
16 template<typename ppT> const std::string groth16_snark<ppT>::name("GROTH16");
18 template<typename ppT>
19 typename groth16_snark<ppT>::keypair groth16_snark<ppT>::generate_setup(
20 const libsnark::protoboard<libff::Fr<ppT>> &pb)
22 // Generate verification and proving key from the R1CS
23 return libsnark::r1cs_gg_ppzksnark_generator<ppT>(
24 pb.get_constraint_system(), true);
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)
32 return generate_proof(
33 proving_key, pb.primary_input(), pb.auxiliary_input());
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)
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);
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)
54 return libsnark::r1cs_gg_ppzksnark_verifier_strong_IC<ppT>(
55 verification_key, primary_inputs, proof);
58 template<typename ppT>
59 void groth16_snark<ppT>::verification_key_write_json(
60 const verification_key &vk, std::ostream &out_s)
62 const size_t abc_length = vk.ABC_g1.rest.indices.size() + 1;
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) {
71 << group_element_to_json(vk.ABC_g1.rest.values[i - 1]);
76 template<typename ppT>
77 void groth16_snark<ppT>::verification_key_write_bytes(
78 const verification_key &vk, std::ostream &out_s)
80 using G1 = libff::G1<ppT>;
82 if (!is_well_formed<ppT>(vk)) {
83 throw std::invalid_argument("verification key (write) not well-formed");
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>>(
93 template<typename ppT>
94 void groth16_snark<ppT>::proving_key_write_bytes(
95 const proving_key &pk, std::ostream &out_s)
97 if (!is_well_formed<ppT>(pk)) {
98 throw std::invalid_argument("proving key (write) not well-formed");
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);
113 template<typename ppT>
114 void groth16_snark<ppT>::verification_key_read_bytes(
115 groth16_snark<ppT>::verification_key &vk, std::istream &in_s)
117 using G1 = libff::G1<ppT>;
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>>(
125 if (!is_well_formed<ppT>(vk)) {
126 throw std::invalid_argument("verification key (read) not well-formed");
130 template<typename ppT>
131 void groth16_snark<ppT>::proving_key_read_bytes(
132 groth16_snark<ppT>::proving_key &pk, std::istream &in_s)
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);
145 if (!is_well_formed<ppT>(pk)) {
146 throw std::invalid_argument("proving key (read) not well-formed");
150 template<typename ppT>
151 void groth16_snark<ppT>::proof_write_json(
152 const typename groth16_snark<ppT>::proof &proof, std::ostream &out_s)
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}";
159 template<typename ppT>
160 void groth16_snark<ppT>::proof_write_bytes(
161 const typename groth16_snark<ppT>::proof &proof, std::ostream &out_s)
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);
168 template<typename ppT>
169 void groth16_snark<ppT>::proof_read_bytes(
170 typename groth16_snark<ppT>::proof &proof, std::istream &in_s)
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);
177 template<typename ppT>
178 void groth16_snark<ppT>::keypair_write_bytes(
179 const typename groth16_snark<ppT>::keypair &keypair, std::ostream &out_s)
181 proving_key_write_bytes(keypair.pk, out_s);
182 verification_key_write_bytes(keypair.vk, out_s);
185 template<typename ppT>
186 void groth16_snark<ppT>::keypair_read_bytes(
187 typename groth16_snark<ppT>::keypair &keypair, std::istream &in_s)
189 proving_key_read_bytes(keypair.pk, in_s);
190 verification_key_read_bytes(keypair.vk, in_s);
193 template<typename ppT>
194 bool is_well_formed(const typename groth16_snark<ppT>::proving_key &pk)
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)) {
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()) {
215 template<typename ppT>
216 bool is_well_formed(const typename groth16_snark<ppT>::verification_key &vk)
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()) {
223 return container_is_well_formed(vk.ABC_g1.rest.values);
226 } // namespace libzeth
228 #endif // __ZETH_SNARKS_GROTH16_GROTH16_SNARK_TCC__