bacs.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 // @file Declaration of interfaces for:
26 // - a BACS variable assignment,
27 // - a BACS gate,
28 // - a BACS primary input,
29 // - a BACS auxiliary input,
30 // - a BACS circuit.
31 //
32 // Above, BACS stands for "Bilinear Arithmetic Circuit Satisfiability".
33 //---------------------------------------------------------------------------//
34 
35 #ifndef CRYPTO3_ZK_BACS_HPP
36 #define CRYPTO3_ZK_BACS_HPP
37 
38 #include <vector>
39 
41 
42 namespace nil {
43  namespace crypto3 {
44  namespace zk {
45  namespace snark {
46 
47  /*********************** BACS variable assignment ****************************/
48 
52  template<typename FieldType>
53  using bacs_variable_assignment = std::vector<typename FieldType::value_type>;
54 
55  /**************************** BACS gate **************************************/
56 
63  template<typename FieldType>
64  struct bacs_gate {
65  typedef FieldType field_type;
66 
69 
72 
73  typename FieldType::value_type evaluate(const bacs_variable_assignment<FieldType> &input) const {
74  return lhs.evaluate(input) * rhs.evaluate(input);
75  }
76 
77  bool operator==(const bacs_gate<FieldType> &other) const {
78  return (this->lhs == other.lhs && this->rhs == other.rhs && this->output == other.output &&
79  this->is_circuit_output == other.is_circuit_output);
80  }
81  };
82 
83  /****************************** BACS inputs **********************************/
84 
88  template<typename FieldType>
90 
94  template<typename FieldType>
96 
97  /************************** BACS circuit *************************************/
98 
109  template<typename FieldType>
110  struct bacs_circuit {
111  typedef FieldType field_type;
112 
113  std::size_t primary_input_size;
114  std::size_t auxiliary_input_size;
115  std::vector<bacs_gate<FieldType>> gates;
116 
118  }
119 
120  std::size_t num_inputs() const {
122  }
123 
124  std::size_t num_gates() const {
125  return gates.size();
126  }
127 
128  std::size_t num_wires() const {
129  return num_inputs() + num_gates();
130  }
131 
132  std::vector<std::size_t> wire_depths() const {
133  std::vector<std::size_t> depths;
134  depths.emplace_back(0);
135  depths.resize(num_inputs() + 1, 1);
136 
137  for (auto &g : gates) {
138  std::size_t max_depth = 0;
139  for (auto &t : g.lhs) {
140  max_depth = std::max(max_depth, depths[t.index]);
141  }
142 
143  for (auto &t : g.rhs) {
144  max_depth = std::max(max_depth, depths[t.index]);
145  }
146 
147  depths.emplace_back(max_depth + 1);
148  }
149 
150  return depths;
151  }
152 
153  std::size_t depth() const {
154  std::vector<std::size_t> all_depths = this->wire_depths();
155  return *(std::max_element(all_depths.begin(), all_depths.end()));
156  }
157 
158  bool is_valid() const {
159  for (std::size_t i = 0; i < num_gates(); ++i) {
164  if (gates[i].output.index != 1 + num_inputs() + i) {
165  return false;
166  }
167 
171  if (!gates[i].lhs.is_valid(gates[i].output.index) ||
172  !gates[i].rhs.is_valid(gates[i].output.index)) {
173  return false;
174  }
175  }
176 
177  return true;
178  }
179 
180  bool is_satisfied(const bacs_primary_input<FieldType> &primary_input,
181  const bacs_auxiliary_input<FieldType> &auxiliary_input) const {
182  const bacs_variable_assignment<FieldType> all_outputs =
183  get_all_outputs(primary_input, auxiliary_input);
184 
185  for (std::size_t i = 0; i < all_outputs.size(); ++i) {
186  if (!all_outputs[i].is_zero()) {
187  return false;
188  }
189  }
190 
191  return true;
192  }
193 
196  const bacs_auxiliary_input<FieldType> &auxiliary_input) const {
197  const bacs_variable_assignment<FieldType> all_wires =
198  get_all_wires(primary_input, auxiliary_input);
199 
201 
202  for (auto &g : gates) {
203  if (g.is_circuit_output) {
204  all_outputs.emplace_back(all_wires[g.output.index - 1]);
205  }
206  }
207 
208  return all_outputs;
209  }
210 
213  const bacs_auxiliary_input<FieldType> &auxiliary_input) const {
214  assert(primary_input.size() == primary_input_size);
215  assert(auxiliary_input.size() == auxiliary_input_size);
216 
218  result.insert(result.end(), primary_input.begin(), primary_input.end());
219  result.insert(result.end(), auxiliary_input.begin(), auxiliary_input.end());
220 
221  assert(result.size() == num_inputs());
222 
223  for (auto &g : gates) {
224  const typename FieldType::value_type gate_output = g.evaluate(result);
225  result.emplace_back(gate_output);
226  }
227 
228  return result;
229  }
230 
232  assert(g.output.index == num_wires() + 1);
233  gates.emplace_back(g);
234  }
235 
236  void add_gate(const bacs_gate<FieldType> &g, const std::string &annotation) {
237  assert(g.output.index == num_wires() + 1);
238  gates.emplace_back(g);
239  }
240 
241  bool operator==(const bacs_circuit<FieldType> &other) const {
242  return (this->primary_input_size == other.primary_input_size &&
243  this->auxiliary_input_size == other.auxiliary_input_size && this->gates == other.gates);
244  }
245  };
246  } // namespace snark
247  } // namespace zk
248  } // namespace crypto3
249 } // namespace nil
250 
251 #endif // CRYPTO3_BACS_HPP
constexpr T max(const vector< T, N > &v)
computes the maximum valued element
Definition: algebra/include/nil/crypto3/algebra/vector/math.hpp:146
bool is_zero(const Range &a)
Definition: basic_operations.hpp:43
bacs_variable_assignment< FieldType > bacs_auxiliary_input
Definition: bacs.hpp:95
bacs_variable_assignment< FieldType > bacs_primary_input
Definition: bacs.hpp:89
std::vector< typename FieldType::value_type > bacs_variable_assignment
Definition: bacs.hpp:53
Definition: pair.hpp:31
bacs_variable_assignment< FieldType > get_all_wires(const bacs_primary_input< FieldType > &primary_input, const bacs_auxiliary_input< FieldType > &auxiliary_input) const
Definition: bacs.hpp:212
std::size_t depth() const
Definition: bacs.hpp:153
std::size_t num_gates() const
Definition: bacs.hpp:124
bool is_valid() const
Definition: bacs.hpp:158
void add_gate(const bacs_gate< FieldType > &g, const std::string &annotation)
Definition: bacs.hpp:236
std::size_t num_wires() const
Definition: bacs.hpp:128
std::vector< std::size_t > wire_depths() const
Definition: bacs.hpp:132
std::size_t primary_input_size
Definition: bacs.hpp:113
std::size_t auxiliary_input_size
Definition: bacs.hpp:114
FieldType field_type
Definition: bacs.hpp:111
std::size_t num_inputs() const
Definition: bacs.hpp:120
bool operator==(const bacs_circuit< FieldType > &other) const
Definition: bacs.hpp:241
std::vector< bacs_gate< FieldType > > gates
Definition: bacs.hpp:115
bacs_circuit()
Definition: bacs.hpp:117
void add_gate(const bacs_gate< FieldType > &g)
Definition: bacs.hpp:231
bacs_variable_assignment< FieldType > get_all_outputs(const bacs_primary_input< FieldType > &primary_input, const bacs_auxiliary_input< FieldType > &auxiliary_input) const
Definition: bacs.hpp:195
bool is_satisfied(const bacs_primary_input< FieldType > &primary_input, const bacs_auxiliary_input< FieldType > &auxiliary_input) const
Definition: bacs.hpp:180
Definition: bacs.hpp:64
linear_combination< FieldType > lhs
Definition: bacs.hpp:67
bool is_circuit_output
Definition: bacs.hpp:71
bool operator==(const bacs_gate< FieldType > &other) const
Definition: bacs.hpp:77
FieldType::value_type evaluate(const bacs_variable_assignment< FieldType > &input) const
Definition: bacs.hpp:73
variable< FieldType > output
Definition: bacs.hpp:70
linear_combination< FieldType > rhs
Definition: bacs.hpp:68
FieldType field_type
Definition: bacs.hpp:65
Definition: variable.hpp:66