1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
3 // SPDX-License-Identifier: LGPL-3.0+
5 #ifndef __ZETH_SERIALIZATION_R1CS_SERIALIZATION_TCC__
6 #define __ZETH_SERIALIZATION_R1CS_SERIALIZATION_TCC__
8 #include "libzeth/core/field_element_utils.hpp"
9 #include "libzeth/core/group_element_utils.hpp"
10 #include "libzeth/serialization/r1cs_serialization.hpp"
11 #include "libzeth/serialization/stream_utils.hpp"
19 template<typename FieldT>
20 void constraints_write_json(
21 const libsnark::linear_combination<FieldT> &constraints,
26 for (const libsnark::linear_term<FieldT> < : constraints.terms) {
32 out_s << "\"index\":" << lt.index << ",";
34 << "\"" + base_field_element_to_hex(lt.coeff) << "\"";
41 } // namespace internal
43 template<typename FieldT>
44 std::ostream &primary_inputs_write_json(
45 const std::vector<FieldT> &public_inputs, std::ostream &out_s)
48 for (size_t i = 0; i < public_inputs.size(); ++i) {
49 out_s << field_element_to_json(public_inputs[i]);
50 if (i < public_inputs.size() - 1) {
58 template<typename FieldT>
59 std::istream &primary_inputs_read_json(
60 std::vector<FieldT> &public_inputs, std::istream &in_s)
65 if ('[' != separator && ',' != separator) {
70 field_element_read_json(element, in_s);
71 public_inputs.push_back(element);
76 template<typename ppT>
77 std::string accumulation_vector_to_json(
78 const libsnark::accumulation_vector<libff::G1<ppT>> &acc_vector)
81 unsigned vect_length = acc_vector.rest.indices.size() + 1;
82 ss << "[" << group_element_to_json(acc_vector.first);
83 for (size_t i = 0; i < vect_length - 1; ++i) {
84 ss << ", " << group_element_to_json(acc_vector.rest.values[i]);
87 std::string vect_json_str = ss.str();
92 template<typename ppT>
93 libsnark::accumulation_vector<libff::G1<ppT>> accumulation_vector_from_json(
94 const std::string &acc_vector_str)
96 static const char prefix[] = "[\"";
97 static const char suffix[] = "\"]";
99 if (acc_vector_str.length() < (sizeof(prefix) - 1 + sizeof(suffix) - 1)) {
100 throw std::invalid_argument("invalid accumulation vector string");
103 size_t start_idx = acc_vector_str.find(prefix);
104 if (start_idx == std::string::npos) {
105 throw std::invalid_argument("invalid accumulation vector string");
108 // TODO: Remove the temporary string.
110 // Allocate once and reuse.
111 std::string element_str;
113 // Extract first element
114 size_t end_idx = acc_vector_str.find(suffix, start_idx);
115 if (end_idx == std::string::npos) {
116 throw std::invalid_argument("invalid accumulation vector string");
119 // Extract the string '["....", "...."]'
123 element_str = acc_vector_str.substr(start_idx, end_idx + 2 - start_idx);
124 libff::G1<ppT> front = group_element_from_json<libff::G1<ppT>>(element_str);
125 start_idx = acc_vector_str.find(prefix, end_idx);
127 // Extract remaining elements
128 std::vector<libff::G1<ppT>> rest;
130 end_idx = acc_vector_str.find(suffix, start_idx);
131 if (end_idx == std::string::npos) {
132 throw std::invalid_argument("invalid accumulation vector string");
135 element_str = acc_vector_str.substr(start_idx, end_idx + 2 - start_idx);
136 rest.push_back(group_element_from_json<libff::G1<ppT>>(element_str));
137 start_idx = acc_vector_str.find(prefix, end_idx);
138 } while (start_idx != std::string::npos);
140 return libsnark::accumulation_vector<libff::G1<ppT>>(
141 std::move(front), std::move(rest));
144 template<typename FieldT>
145 std::ostream &r1cs_write_json(
146 const libsnark::r1cs_constraint_system<FieldT> &r1cs, std::ostream &out_s)
148 // output inputs, right now need to compile with debug flag so that the
149 // `variable_annotations` exists. Having trouble setting that up so will
153 out_s << "\"scalar_field_characteristic\":"
154 << "\"" + libff::bigint_to_hex(FieldT::field_char(), true) << "\",\n";
155 out_s << "\"num_variables\":" << r1cs.num_variables() << ",\n";
156 out_s << "\"num_constraints\":" << r1cs.num_constraints() << ",\n";
157 out_s << "\"num_inputs\": " << r1cs.num_inputs() << ",\n";
158 out_s << "\"variables_annotations\":[";
159 for (size_t i = 0; i < r1cs.num_variables(); ++i) {
161 out_s << "\"index\":" << i << ",";
162 out_s << "\"annotation\":"
163 << "\"" << r1cs.variable_annotations.at(i).c_str() << "\"";
164 if (i == r1cs.num_variables() - 1) {
171 out_s << "\"constraints\":[";
172 for (size_t c = 0; c < r1cs.num_constraints(); ++c) {
174 out_s << "\"constraint_id\": " << c << ",";
175 out_s << "\"constraint_annotation\": "
176 << "\"" << r1cs.constraint_annotations.at(c).c_str() << "\",";
177 out_s << "\"linear_combination\":";
180 internal::constraints_write_json(r1cs.constraints[c].a, out_s);
183 internal::constraints_write_json(r1cs.constraints[c].b, out_s);
186 internal::constraints_write_json(r1cs.constraints[c].c, out_s);
188 if (c == r1cs.num_constraints() - 1) {
199 template<typename FieldT>
200 void linear_combination_read_bytes(
201 libsnark::linear_combination<FieldT> &linear_combination,
204 const uint32_t num_terms = read_bytes<uint32_t>(in_s);
206 linear_combination.terms.clear();
207 linear_combination.terms.reserve(num_terms);
208 for (uint32_t i = 0; i < num_terms; ++i) {
209 const libsnark::var_index_t idx =
210 read_bytes<libsnark::var_index_t>(in_s);
212 field_element_read_bytes(coeff, in_s);
213 linear_combination.terms.emplace_back(idx, coeff);
217 template<typename FieldT>
218 void linear_combination_write_bytes(
219 const libsnark::linear_combination<FieldT> &linear_combination,
222 // Write the number of terms as a uint32_t to save space. If this assert
223 // fires (a single linear combination contains 2^32 terms), change to
226 linear_combination.terms.size() <=
227 (size_t)std::numeric_limits<uint32_t>::max);
228 const uint32_t num_terms = (uint32_t)linear_combination.terms.size();
229 write_bytes(num_terms, out_s);
231 for (const libsnark::linear_term<FieldT> &term : linear_combination.terms) {
232 write_bytes(term.index, out_s);
233 field_element_write_bytes(term.coeff, out_s);
237 template<typename FieldT>
238 void r1cs_constraint_read_bytes(
239 libsnark::r1cs_constraint<FieldT> &constraint, std::istream &in_s)
241 linear_combination_read_bytes(constraint.a, in_s);
242 linear_combination_read_bytes(constraint.b, in_s);
243 linear_combination_read_bytes(constraint.c, in_s);
246 template<typename FieldT>
247 void r1cs_constraint_write_bytes(
248 const libsnark::r1cs_constraint<FieldT> &constraint, std::ostream &out_s)
250 linear_combination_write_bytes(constraint.a, out_s);
251 linear_combination_write_bytes(constraint.b, out_s);
252 linear_combination_write_bytes(constraint.c, out_s);
255 template<typename FieldT>
256 void r1cs_read_bytes(
257 libsnark::r1cs_constraint_system<FieldT> &r1cs, std::istream &in_s)
259 read_bytes(r1cs.primary_input_size, in_s);
260 read_bytes(r1cs.auxiliary_input_size, in_s);
261 collection_read_bytes<
262 std::vector<libsnark::r1cs_constraint<FieldT>>,
263 r1cs_constraint_read_bytes>(r1cs.constraints, in_s);
266 template<typename FieldT>
267 void r1cs_write_bytes(
268 const libsnark::r1cs_constraint_system<FieldT> &r1cs, std::ostream &out_s)
270 write_bytes(r1cs.primary_input_size, out_s);
271 write_bytes(r1cs.auxiliary_input_size, out_s);
272 collection_write_bytes<
273 std::vector<libsnark::r1cs_constraint<FieldT>>,
274 r1cs_constraint_write_bytes>(r1cs.constraints, out_s);
277 } // namespace libzeth
279 #endif // __ZETH_SERIALIZATION_R1CS_SERIALIZATION_TCC__