element_knowledge_commitment.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
4 //
5 // MIT License
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 //---------------------------------------------------------------------------//
25 
26 #ifndef CRYPTO3_ZK_KNOWLEDGE_COMMITMENT_ELEMENT_HPP
27 #define CRYPTO3_ZK_KNOWLEDGE_COMMITMENT_ELEMENT_HPP
28 
30 
31 #include <nil/crypto3/multiprecision/number.hpp>
32 
33 namespace nil {
34  namespace crypto3 {
35  namespace zk {
36  namespace snark {
37  namespace detail {
38 
39  template<typename Type1, typename Type2>
41 
42  /********************** Knowledge commitment *********************************/
43 
53  template<typename Type1, typename Type2>
54  struct element_kc {
55 
56  //using group_type = commitments<Type1, Type2>;
57 
58  typename Type1::value_type g;
59  typename Type2::value_type h;
60 
61  element_kc() = default;
62  element_kc(const element_kc &other) = default;
63  element_kc(element_kc &&other) = default;
64  element_kc(const typename Type1::value_type &g, const typename Type2::value_type &h) :
65  g(g), h(h) {
66  }
67 
68  element_kc &operator=(const element_kc &other) = default;
69  element_kc &operator=(element_kc &&other) noexcept = default;
70  element_kc operator+(const element_kc &other) const {
71  return element_kc(this->g + other.g, this->h + other.h);
72  }
73  element_kc mixed_add(const element_kc &other) const {
74  return element_kc(this->g.mixed_add(other.g), this->h.mixed_add(other.h));
75  }
76  element_kc doubled() const {
77  return element_kc(this->g.doubled(), this->h.doubled());
78  }
79 
81  return element_kc(this->g.to_projective(), this->h.to_projective());
82  }
83  bool is_special() const {
84  return this->g->is_special() && this->h->is_special();
85  }
86 
87  bool is_zero() const {
88  return (g.is_zero() && h.is_zero());
89  }
90  bool operator==(const element_kc &other) const {
91  return (this->g == other.g && this->h == other.h);
92  }
93  bool operator!=(const element_kc &other) const {
94  return !((*this) == other);
95  }
96 
97  static element_kc zero() {
98  return element_kc(Type1::value_type::zero(), Type2::value_type::zero());
99  }
100  static element_kc one() {
101  return element_kc(Type1::value_type::one(), Type2::value_type::one());
102  }
103 
104  static void batch_to_special_all_non_zeros(std::vector<element_kc> &vec) {
105  // it is guaranteed that every vec[i] is non-zero,
106  // but, for any i, *one* of vec[i].g and vec[i].h might still be zero,
107  // so we still have to handle zeros separately
108 
109  // we separately process g's first, then h's
110  // to lower memory consumption
111  std::vector<typename Type1::value_type> g_vec;
112  g_vec.reserve(vec.size());
113 
114  for (std::size_t i = 0; i < vec.size(); ++i) {
115  if (!vec[i].g.is_zero()) {
116  g_vec.emplace_back(vec[i].g);
117  }
118  }
119 
120  Type1::value_type::batch_to_special_all_non_zeros(g_vec);
121  auto g_it = g_vec.begin();
122  typename Type1::value_type Type1_zero_special = Type1::value_type::zero().to_projective();
123 
124  for (std::size_t i = 0; i < vec.size(); ++i) {
125  if (!vec[i].g.is_zero()) {
126  vec[i].g = *g_it;
127  ++g_it;
128  } else {
129  vec[i].g = Type1_zero_special;
130  }
131  }
132 
133  g_vec.clear();
134 
135  // exactly the same thing, but for h:
136  std::vector<typename Type2::value_type> h_vec;
137  h_vec.reserve(vec.size());
138 
139  for (std::size_t i = 0; i < vec.size(); ++i) {
140  if (!vec[i].h.is_zero()) {
141  h_vec.emplace_back(vec[i].h);
142  }
143  }
144 
145  Type2::value_type::batch_to_special_all_non_zeros(h_vec);
146  auto h_it = h_vec.begin();
147  typename Type2::value_type Type2_zero_special = Type2::value_type::zero().to_projective();
148 
149  for (std::size_t i = 0; i < vec.size(); ++i) {
150  if (!vec[i].h.is_zero()) {
151  vec[i].h = *h_it;
152  ++h_it;
153  } else {
154  vec[i].h = Type2_zero_special;
155  }
156  }
157 
158  h_vec.clear();
159  }
160  };
161 
162  template<typename Type1,
163  typename Type2,
164  typename Backend,
165  multiprecision::expression_template_option ExpressionTemplates>
166  element_kc<Type1, Type2> operator*(const multiprecision::number<Backend, ExpressionTemplates> &lhs,
167  const element_kc<Type1, Type2> &rhs) {
168  return element_kc<Type1, Type2>(lhs * rhs.g, lhs * rhs.h);
169  }
170 
171  template<typename Type1,
172  typename Type2,
173  typename Backend,
174  multiprecision::expression_template_option ExpressionTemplates>
175  element_kc<Type1, Type2>
177  const multiprecision::number<Backend, ExpressionTemplates> &rhs) {
178  return element_kc<Type1, Type2>(rhs * lhs.g, rhs * lhs.h);
179  }
180 
181  template<
182  typename Type1,
183  typename Type2,
184  typename FieldValueType,
185  typename = typename std::enable_if<
188  FieldValueType>::type>
189  element_kc<Type1, Type2> operator*(const FieldValueType &lhs, const element_kc<Type1, Type2> &rhs) {
190 
191  return lhs.data * rhs;
192  }
193 
194  template<
195  typename Type1,
196  typename Type2,
197  typename FieldValueType,
198  typename = typename std::enable_if<
201  FieldValueType>::type>
202  element_kc<Type1, Type2> operator*(const element_kc<Type1, Type2> &lhs, const FieldValueType &rhs) {
203 
204  return lhs * rhs.data;
205  }
206  } // namespace detail
207  } // namespace snark
208  } // namespace zk
209  } // namespace crypto3
210 } // namespace nil
211 
212 #endif // CRYPTO3_ZK_KNOWLEDGE_COMMITMENT_ELEMENT_HPP
element_kc< Type1, Type2 > operator*(const multiprecision::number< Backend, ExpressionTemplates > &lhs, const element_kc< Type1, Type2 > &rhs)
Definition: element_knowledge_commitment.hpp:166
Definition: pair.hpp:31
Definition: algebra/include/nil/crypto3/algebra/type_traits.hpp:105
Definition: algebra/include/nil/crypto3/algebra/type_traits.hpp:95
Definition: element_knowledge_commitment.hpp:54
Type1::value_type g
Definition: element_knowledge_commitment.hpp:58
element_kc to_projective()
Definition: element_knowledge_commitment.hpp:80
bool operator==(const element_kc &other) const
Definition: element_knowledge_commitment.hpp:90
element_kc & operator=(element_kc &&other) noexcept=default
element_kc doubled() const
Definition: element_knowledge_commitment.hpp:76
bool is_special() const
Definition: element_knowledge_commitment.hpp:83
element_kc(const typename Type1::value_type &g, const typename Type2::value_type &h)
Definition: element_knowledge_commitment.hpp:64
element_kc & operator=(const element_kc &other)=default
element_kc operator+(const element_kc &other) const
Definition: element_knowledge_commitment.hpp:70
Type2::value_type h
Definition: element_knowledge_commitment.hpp:59
static element_kc zero()
Definition: element_knowledge_commitment.hpp:97
static element_kc one()
Definition: element_knowledge_commitment.hpp:100
bool is_zero() const
Definition: element_knowledge_commitment.hpp:87
element_kc(const element_kc &other)=default
static void batch_to_special_all_non_zeros(std::vector< element_kc > &vec)
Definition: element_knowledge_commitment.hpp:104
bool operator!=(const element_kc &other) const
Definition: element_knowledge_commitment.hpp:93
element_kc(element_kc &&other)=default
element_kc mixed_add(const element_kc &other) const
Definition: element_knowledge_commitment.hpp:73
Definition: element_knowledge_commitment.hpp:40