loose_multiplexing.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_BLUEPRINT_LOOSE_MULTIPLEXING_COMPONENT_HPP
27 #define CRYPTO3_ZK_BLUEPRINT_LOOSE_MULTIPLEXING_COMPONENT_HPP
28 
29 #include <cassert>
30 #include <memory>
31 
35 
36 #include <nil/crypto3/multiprecision/number.hpp>
38 
39 namespace nil {
40  namespace crypto3 {
41  namespace zk {
42  namespace components {
43 
44  /*
45  loose_multiplexing implements loose multiplexer:
46  index not in bounds -> success_flag = 0
47  index in bounds && success_flag = 1 -> result is correct
48  however if index is in bounds we can also set success_flag to 0 (and then result will be forced to
49  be 0)
50  */
51  template<typename FieldType>
52  class loose_multiplexing : public component<FieldType> {
53  public:
55 
56  private:
57  std::shared_ptr<inner_product<FieldType>> compute_result;
58 
59  public:
64 
70  component<FieldType>(bp),
72  alpha.allocate(bp, arr.size());
73  compute_result.reset(new inner_product<FieldType>(bp, alpha, arr, result));
74  };
75 
77  /* \alpha_i (index - i) = 0 */
78  for (std::size_t i = 0; i < arr.size(); ++i) {
79  this->bp.add_r1cs_constraint(snark::r1cs_constraint<FieldType>(alpha[i], index - i, 0));
80  }
81 
82  /* 1 * (\sum \alpha_i) = success_flag */
85  for (std::size_t i = 0; i < arr.size(); ++i) {
86  b.add_term(alpha[i]);
87  }
89  this->bp.add_r1cs_constraint(snark::r1cs_constraint<FieldType>(a, b, c));
90 
91  /* now success_flag is constrained to either 0 (if index is out of
92  range) or \alpha_i. constrain it and \alpha_i to zero */
93  generate_boolean_r1cs_constraint<FieldType>(this->bp, success_flag);
94 
95  /* compute result */
96  compute_result->generate_r1cs_constraints();
97  }
98 
100 
101  /* assumes that idx can be fit in ulong; true for our purposes for now */
102  const typename FieldType::value_type valint = this->bp.val(index);
103 
104  unsigned long idx = static_cast<unsigned long>(typename FieldType::integral_type(valint.data));
105 
106  if (idx >= arr.size() || typename FieldType::integral_type(valint.data) >= arr.size()) {
107  for (std::size_t i = 0; i < arr.size(); ++i) {
108  this->bp.val(alpha[i]) = FieldType::value_type::zero();
109  }
110 
111  this->bp.val(success_flag) = FieldType::value_type::zero();
112  } else {
113  for (std::size_t i = 0; i < arr.size(); ++i) {
114  this->bp.val(alpha[i]) =
115  (i == idx ? FieldType::value_type::one() : FieldType::value_type::zero());
116  }
117 
118  this->bp.val(success_flag) = FieldType::value_type::one();
119  }
120 
121  compute_result->generate_r1cs_witness();
122  }
123  };
124 
125  } // namespace components
126  } // namespace zk
127  } // namespace crypto3
128 } // namespace nil
129 #endif // CRYPTO3_ZK_BLUEPRINT_LOOSE_MULTIPLEXING_COMPONENT_HPP
Definition: blueprint_linear_combination.hpp:115
Definition: blueprint_linear_combination.hpp:47
Definition: blueprint_variable.hpp:57
Definition: blueprint_variable.hpp:46
Definition: blueprint.hpp:46
Definition: component.hpp:37
blueprint< FieldType > & bp
Definition: component.hpp:39
Definition: blueprint/include/nil/crypto3/zk/components/inner_product.hpp:51
Definition: loose_multiplexing.hpp:52
void generate_r1cs_constraints()
Definition: loose_multiplexing.hpp:76
loose_multiplexing(blueprint< FieldType > &bp, const blueprint_linear_combination_vector< FieldType > &arr, const blueprint_variable< FieldType > &index, const blueprint_variable< FieldType > &result, const blueprint_variable< FieldType > &success_flag)
Definition: loose_multiplexing.hpp:65
void generate_r1cs_witness()
Definition: loose_multiplexing.hpp:99
blueprint_variable_vector< FieldType > alpha
Definition: loose_multiplexing.hpp:54
const blueprint_variable< FieldType > result
Definition: loose_multiplexing.hpp:62
const blueprint_linear_combination_vector< FieldType > arr
Definition: loose_multiplexing.hpp:60
const blueprint_variable< FieldType > index
Definition: loose_multiplexing.hpp:61
const blueprint_variable< FieldType > success_flag
Definition: loose_multiplexing.hpp:63
Definition: pair.hpp:31
void add_term(const variable< FieldType > &var)
Definition: variable.hpp:277