Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
knowledge_commitment.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of interfaces for:
5  - a knowledge commitment, and
6  - a knowledge commitment vector.
7 
8  See knowledge_commitment.hpp .
9 
10  *****************************************************************************
11  * @author This file is part of libsnark, developed by SCIPR Lab
12  * and contributors (see AUTHORS).
13  * @copyright MIT license (see LICENSE file)
14  *****************************************************************************/
15 
16 #ifndef KNOWLEDGE_COMMITMENT_TCC_
17 #define KNOWLEDGE_COMMITMENT_TCC_
18 
19 namespace libsnark
20 {
21 
22 template<typename T1, typename T2>
23 knowledge_commitment<T1, T2>::knowledge_commitment(const T1 &g, const T2 &h)
24  : g(g), h(h)
25 {
26 }
27 
28 template<typename T1, typename T2>
29 knowledge_commitment<T1, T2> knowledge_commitment<T1, T2>::add(
30  const knowledge_commitment<T1, T2> &other) const
31 {
32  return knowledge_commitment<T1, T2>(
33  this->g.add(other.g), this->h.add(other.h));
34 }
35 
36 template<typename T1, typename T2>
37 knowledge_commitment<T1, T2> knowledge_commitment<T1, T2>::mixed_add(
38  const knowledge_commitment<T1, T2> &other) const
39 {
40  return knowledge_commitment<T1, T2>(
41  this->g.mixed_add(other.g), this->h.mixed_add(other.h));
42 }
43 
44 template<typename T1, typename T2>
45 knowledge_commitment<T1, T2> knowledge_commitment<T1, T2>::dbl() const
46 {
47  return knowledge_commitment<T1, T2>(this->g.dbl(), this->h.dbl());
48 }
49 
50 template<typename T1, typename T2>
51 knowledge_commitment<T1, T2> knowledge_commitment<T1, T2>::operator+(
52  const knowledge_commitment<T1, T2> &other) const
53 {
54  return add(other);
55 }
56 
57 template<typename T1, typename T2>
58 knowledge_commitment<T1, T2> knowledge_commitment<T1, T2>::operator-() const
59 {
60  return knowledge_commitment<T1, T2>(-(this->g), -(this->h));
61 }
62 
63 template<typename T1, typename T2>
64 void knowledge_commitment<T1, T2>::to_special()
65 {
66  this->g.to_special();
67  this->h.to_special();
68 }
69 
70 template<typename T1, typename T2>
71 bool knowledge_commitment<T1, T2>::is_special() const
72 {
73  return this->g->is_special() && this->h->is_special();
74 }
75 
76 template<typename T1, typename T2>
77 bool knowledge_commitment<T1, T2>::is_zero() const
78 {
79  return (g.is_zero() && h.is_zero());
80 }
81 
82 template<typename T1, typename T2>
83 bool knowledge_commitment<T1, T2>::operator==(
84  const knowledge_commitment<T1, T2> &other) const
85 {
86  return (this->g == other.g && this->h == other.h);
87 }
88 
89 template<typename T1, typename T2>
90 bool knowledge_commitment<T1, T2>::operator!=(
91  const knowledge_commitment<T1, T2> &other) const
92 {
93  return !((*this) == other);
94 }
95 
96 template<typename T1, typename T2>
97 knowledge_commitment<T1, T2> knowledge_commitment<T1, T2>::zero()
98 {
99  return knowledge_commitment<T1, T2>(T1::zero(), T2::zero());
100 }
101 
102 template<typename T1, typename T2>
103 knowledge_commitment<T1, T2> knowledge_commitment<T1, T2>::one()
104 {
105  return knowledge_commitment<T1, T2>(T1::one(), T2::one());
106 }
107 
108 template<typename T1, typename T2, mp_size_t m>
109 knowledge_commitment<T1, T2> operator*(
110  const libff::bigint<m> &lhs, const knowledge_commitment<T1, T2> &rhs)
111 {
112  return knowledge_commitment<T1, T2>(lhs * rhs.g, lhs * rhs.h);
113 }
114 
115 template<
116  typename T1,
117  typename T2,
118  mp_size_t m,
119  const libff::bigint<m> &modulus_p>
120 knowledge_commitment<T1, T2> operator*(
121  const libff::Fp_model<m, modulus_p> &lhs,
122  const knowledge_commitment<T1, T2> &rhs)
123 {
124  return (lhs.as_bigint()) * rhs;
125 }
126 
127 template<typename T1, typename T2>
128 void knowledge_commitment<T1, T2>::print() const
129 {
130  printf("knowledge_commitment.g:\n");
131  g.print();
132  printf("knowledge_commitment.h:\n");
133  h.print();
134 }
135 
136 template<typename T1, typename T2>
137 size_t knowledge_commitment<T1, T2>::size_in_bits()
138 {
139  return T1::size_in_bits() + T2::size_in_bits();
140 }
141 
142 template<typename T1, typename T2>
143 std::ostream &operator<<(
144  std::ostream &out, const knowledge_commitment<T1, T2> &kc)
145 {
146  out << kc.g << OUTPUT_SEPARATOR << kc.h;
147  return out;
148 }
149 
150 template<typename T1, typename T2>
151 std::istream &operator>>(std::istream &in, knowledge_commitment<T1, T2> &kc)
152 {
153  in >> kc.g;
154  libff::consume_OUTPUT_SEPARATOR(in);
155  in >> kc.h;
156  return in;
157 }
158 
159 template<typename T1, typename T2>
160 void knowledge_commitment<T1, T2>::batch_to_special_all_non_zeros(
161  std::vector<knowledge_commitment<T1, T2>> &vec)
162 {
163  // it is guaranteed that every vec[i] is non-zero,
164  // but, for any i, *one* of vec[i].g and vec[i].h might still be zero,
165  // so we still have to handle zeros separately
166 
167  // we separately process g's first, then h's
168  // to lower memory consumption
169  std::vector<T1> g_vec;
170  g_vec.reserve(vec.size());
171 
172  for (size_t i = 0; i < vec.size(); ++i) {
173  if (!vec[i].g.is_zero()) {
174  g_vec.emplace_back(vec[i].g);
175  }
176  }
177 
178  T1::batch_to_special_all_non_zeros(g_vec);
179  auto g_it = g_vec.begin();
180  T1 T1_zero_special = T1::zero();
181  T1_zero_special.to_special();
182 
183  for (size_t i = 0; i < vec.size(); ++i) {
184  if (!vec[i].g.is_zero()) {
185  vec[i].g = *g_it;
186  ++g_it;
187  } else {
188  vec[i].g = T1_zero_special;
189  }
190  }
191 
192  g_vec.clear();
193 
194  // exactly the same thing, but for h:
195  std::vector<T2> h_vec;
196  h_vec.reserve(vec.size());
197 
198  for (size_t i = 0; i < vec.size(); ++i) {
199  if (!vec[i].h.is_zero()) {
200  h_vec.emplace_back(vec[i].h);
201  }
202  }
203 
204  T2::batch_to_special_all_non_zeros(h_vec);
205  auto h_it = h_vec.begin();
206  T2 T2_zero_special = T2::zero();
207  T2_zero_special.to_special();
208 
209  for (size_t i = 0; i < vec.size(); ++i) {
210  if (!vec[i].h.is_zero()) {
211  vec[i].h = *h_it;
212  ++h_it;
213  } else {
214  vec[i].h = T2_zero_special;
215  }
216  }
217 
218  h_vec.clear();
219 }
220 
221 } // namespace libsnark
222 
223 #endif // KNOWLEDGE_COMMITMENT_TCC_