2 *****************************************************************************
4 Implementation of interfaces for a QAP ("Quadratic Arithmetic Program").
8 *****************************************************************************
9 * @author This file is part of libsnark, developed by SCIPR Lab
10 * and contributors (see AUTHORS).
11 * @copyright MIT license (see LICENSE file)
12 *****************************************************************************/
17 #include <libff/algebra/scalar_multiplication/multiexp.hpp>
18 #include <libff/common/profiling.hpp>
19 #include <libff/common/utils.hpp>
20 #include <libfqfft/evaluation_domain/evaluation_domain.hpp>
25 template<typename FieldT>
26 qap_instance<FieldT>::qap_instance(
27 const std::shared_ptr<libfqfft::evaluation_domain<FieldT>> &domain,
28 const size_t num_variables,
30 const size_t num_inputs,
31 const std::vector<std::map<size_t, FieldT>> &A_in_Lagrange_basis,
32 const std::vector<std::map<size_t, FieldT>> &B_in_Lagrange_basis,
33 const std::vector<std::map<size_t, FieldT>> &C_in_Lagrange_basis)
34 : num_variables_(num_variables)
36 , num_inputs_(num_inputs)
38 , A_in_Lagrange_basis(A_in_Lagrange_basis)
39 , B_in_Lagrange_basis(B_in_Lagrange_basis)
40 , C_in_Lagrange_basis(C_in_Lagrange_basis)
44 template<typename FieldT>
45 qap_instance<FieldT>::qap_instance(
46 const std::shared_ptr<libfqfft::evaluation_domain<FieldT>> &domain,
47 const size_t num_variables,
49 const size_t num_inputs,
50 std::vector<std::map<size_t, FieldT>> &&A_in_Lagrange_basis,
51 std::vector<std::map<size_t, FieldT>> &&B_in_Lagrange_basis,
52 std::vector<std::map<size_t, FieldT>> &&C_in_Lagrange_basis)
53 : num_variables_(num_variables)
55 , num_inputs_(num_inputs)
57 , A_in_Lagrange_basis(std::move(A_in_Lagrange_basis))
58 , B_in_Lagrange_basis(std::move(B_in_Lagrange_basis))
59 , C_in_Lagrange_basis(std::move(C_in_Lagrange_basis))
63 template<typename FieldT> size_t qap_instance<FieldT>::num_variables() const
65 return num_variables_;
68 template<typename FieldT> size_t qap_instance<FieldT>::degree() const
73 template<typename FieldT> size_t qap_instance<FieldT>::num_inputs() const
78 template<typename FieldT>
79 bool qap_instance<FieldT>::is_satisfied(
80 const qap_witness<FieldT> &witness) const
82 const FieldT t = FieldT::random_element();
84 std::vector<FieldT> At(this->num_variables() + 1, FieldT::zero());
85 std::vector<FieldT> Bt(this->num_variables() + 1, FieldT::zero());
86 std::vector<FieldT> Ct(this->num_variables() + 1, FieldT::zero());
87 std::vector<FieldT> Ht(this->degree() + 1);
89 const FieldT Zt = this->domain->compute_vanishing_polynomial(t);
91 const std::vector<FieldT> u =
92 this->domain->evaluate_all_lagrange_polynomials(t);
94 for (size_t i = 0; i < this->num_variables() + 1; ++i) {
95 for (auto &el : A_in_Lagrange_basis[i]) {
96 At[i] += u[el.first] * el.second;
99 for (auto &el : B_in_Lagrange_basis[i]) {
100 Bt[i] += u[el.first] * el.second;
103 for (auto &el : C_in_Lagrange_basis[i]) {
104 Ct[i] += u[el.first] * el.second;
108 FieldT ti = FieldT::one();
109 for (size_t i = 0; i < this->degree() + 1; ++i) {
114 const qap_instance_evaluation<FieldT> eval_qap_inst(
116 this->num_variables(),
125 return eval_qap_inst.is_satisfied(witness);
128 template<typename FieldT>
129 qap_instance_evaluation<FieldT>::qap_instance_evaluation(
130 const std::shared_ptr<libfqfft::evaluation_domain<FieldT>> &domain,
131 const size_t num_variables,
133 const size_t num_inputs,
135 const std::vector<FieldT> &At,
136 const std::vector<FieldT> &Bt,
137 const std::vector<FieldT> &Ct,
138 const std::vector<FieldT> &Ht,
140 : num_variables_(num_variables)
142 , num_inputs_(num_inputs)
153 template<typename FieldT>
154 qap_instance_evaluation<FieldT>::qap_instance_evaluation(
155 const std::shared_ptr<libfqfft::evaluation_domain<FieldT>> &domain,
156 const size_t num_variables,
158 const size_t num_inputs,
160 std::vector<FieldT> &&At,
161 std::vector<FieldT> &&Bt,
162 std::vector<FieldT> &&Ct,
163 std::vector<FieldT> &&Ht,
165 : num_variables_(num_variables)
167 , num_inputs_(num_inputs)
178 template<typename FieldT>
179 size_t qap_instance_evaluation<FieldT>::num_variables() const
181 return num_variables_;
184 template<typename FieldT> size_t qap_instance_evaluation<FieldT>::degree() const
189 template<typename FieldT>
190 size_t qap_instance_evaluation<FieldT>::num_inputs() const
195 template<typename FieldT>
196 bool qap_instance_evaluation<FieldT>::is_satisfied(
197 const qap_witness<FieldT> &witness) const
200 if (this->num_variables() != witness.num_variables()) {
204 if (this->degree() != witness.degree()) {
208 if (this->num_inputs() != witness.num_inputs()) {
212 if (this->num_variables() != witness.coefficients_for_ABCs.size()) {
216 if (this->degree() + 1 != witness.coefficients_for_H.size()) {
220 if (this->At.size() != this->num_variables() + 1 ||
221 this->Bt.size() != this->num_variables() + 1 ||
222 this->Ct.size() != this->num_variables() + 1) {
226 if (this->Ht.size() != this->degree() + 1) {
230 if (this->Zt != this->domain->compute_vanishing_polynomial(this->t)) {
234 FieldT ans_A = this->At[0] + witness.d1 * this->Zt;
235 FieldT ans_B = this->Bt[0] + witness.d2 * this->Zt;
236 FieldT ans_C = this->Ct[0] + witness.d3 * this->Zt;
237 FieldT ans_H = FieldT::zero();
240 libff::inner_product<FieldT>(
241 this->At.begin() + 1,
242 this->At.begin() + 1 + this->num_variables(),
243 witness.coefficients_for_ABCs.begin(),
244 witness.coefficients_for_ABCs.begin() + this->num_variables());
246 libff::inner_product<FieldT>(
247 this->Bt.begin() + 1,
248 this->Bt.begin() + 1 + this->num_variables(),
249 witness.coefficients_for_ABCs.begin(),
250 witness.coefficients_for_ABCs.begin() + this->num_variables());
252 libff::inner_product<FieldT>(
253 this->Ct.begin() + 1,
254 this->Ct.begin() + 1 + this->num_variables(),
255 witness.coefficients_for_ABCs.begin(),
256 witness.coefficients_for_ABCs.begin() + this->num_variables());
258 ans_H + libff::inner_product<FieldT>(
260 this->Ht.begin() + this->degree() + 1,
261 witness.coefficients_for_H.begin(),
262 witness.coefficients_for_H.begin() + this->degree() + 1);
264 if (ans_A * ans_B - ans_C != ans_H * this->Zt) {
271 template<typename FieldT>
272 qap_witness<FieldT>::qap_witness(
273 const size_t num_variables,
275 const size_t num_inputs,
279 const std::vector<FieldT> &coefficients_for_ABCs,
280 const std::vector<FieldT> &coefficients_for_H)
281 : num_variables_(num_variables)
283 , num_inputs_(num_inputs)
287 , coefficients_for_ABCs(coefficients_for_ABCs)
288 , coefficients_for_H(coefficients_for_H)
292 template<typename FieldT>
293 qap_witness<FieldT>::qap_witness(
294 const size_t num_variables,
296 const size_t num_inputs,
300 const std::vector<FieldT> &coefficients_for_ABCs,
301 std::vector<FieldT> &&coefficients_for_H)
302 : num_variables_(num_variables)
304 , num_inputs_(num_inputs)
308 , coefficients_for_ABCs(coefficients_for_ABCs)
309 , coefficients_for_H(std::move(coefficients_for_H))
313 template<typename FieldT> size_t qap_witness<FieldT>::num_variables() const
315 return num_variables_;
318 template<typename FieldT> size_t qap_witness<FieldT>::degree() const
323 template<typename FieldT> size_t qap_witness<FieldT>::num_inputs() const
328 } // namespace libsnark