comparison.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_COMPARISON_COMPONENT_HPP
27 #define CRYPTO3_ZK_BLUEPRINT_COMPARISON_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  the components below are Fp specific:
46  I * X = R
47  (1-R) * X = 0
48 
49  if X = 0 then R = 0
50  if X != 0 then R = 1 and I = X^{-1}
51  */
52  template<typename FieldType>
53  class comparison : public component<FieldType> {
54  private:
56  blueprint_variable<FieldType> alpha_packed;
57  std::shared_ptr<packing_component<FieldType>> pack_alpha;
58 
59  std::shared_ptr<disjunction<FieldType>> all_zeros_test;
60  blueprint_variable<FieldType> not_all_zeros;
61 
62  public:
63  const std::size_t n;
68 
70  std::size_t n,
75  component<FieldType>(bp),
76  n(n), A(A), B(B), less(less), less_or_eq(less_or_eq) {
77  alpha.allocate(bp, n);
78  alpha.emplace_back(less_or_eq); // alpha[n] is less_or_eq
79 
80  alpha_packed.allocate(bp);
81  not_all_zeros.allocate(bp);
82 
83  pack_alpha.reset(new packing_component<FieldType>(bp, alpha, alpha_packed));
84 
85  all_zeros_test.reset(new disjunction<FieldType>(
86  bp, blueprint_variable_vector<FieldType>(alpha.begin(), alpha.begin() + n), not_all_zeros));
87  };
88 
90  /*
91  packed(alpha) = 2^n + B - A
92 
93  not_all_zeros = \bigvee_{i=0}^{n-1} alpha_i
94 
95  if B - A > 0, then 2^n + B - A > 2^n,
96  so alpha_n = 1 and not_all_zeros = 1
97  if B - A = 0, then 2^n + B - A = 2^n,
98  so alpha_n = 1 and not_all_zeros = 0
99  if B - A < 0, then 2^n + B - A \in {0, 1, \ldots, 2^n-1},
100  so alpha_n = 0
101 
102  therefore alpha_n = less_or_eq and alpha_n * not_all_zeros = less
103  */
104 
105  /* not_all_zeros to be Boolean, alpha_i are Boolean by packing component */
106  generate_boolean_r1cs_constraint<FieldType>(this->bp, not_all_zeros);
107 
108  /* constraints for packed(alpha) = 2^n + B - A */
109  pack_alpha->generate_r1cs_constraints(true);
110  this->bp.add_r1cs_constraint(snark::r1cs_constraint<FieldType>(
111  1, (typename FieldType::value_type(0x02).pow(n)) + B - A, alpha_packed));
112 
113  /* compute result */
114  all_zeros_test->generate_r1cs_constraints();
115  this->bp.add_r1cs_constraint(
117  }
118 
120  A.evaluate(this->bp);
121  B.evaluate(this->bp);
122 
123  /* unpack 2^n + B - A into alpha_packed */
124  this->bp.val(alpha_packed) =
125  (typename FieldType::value_type(0x02).pow(n)) + this->bp.lc_val(B) - this->bp.lc_val(A);
126  pack_alpha->generate_r1cs_witness_from_packed();
127 
128  /* compute result */
129  all_zeros_test->generate_r1cs_witness();
130  this->bp.val(less) = this->bp.val(less_or_eq) * this->bp.val(not_all_zeros);
131  }
132  };
133 
134  } // namespace components
135  } // namespace zk
136  } // namespace crypto3
137 } // namespace nil
138 #endif // CRYPTO3_ZK_BLUEPRINT_COMPARISON_COMPONENT_HPP
Definition: blueprint_linear_combination.hpp:47
void evaluate(blueprint< field_type > &bp) const
Definition: blueprint_linear_combination.hpp:71
Definition: blueprint_variable.hpp:57
void allocate(blueprint< field_type > &bp, const std::size_t n)
Definition: blueprint_variable.hpp:91
Definition: blueprint_variable.hpp:46
void allocate(blueprint< FieldType > &bp)
Definition: blueprint_variable.hpp:51
Definition: blueprint.hpp:46
Definition: comparison.hpp:53
void generate_r1cs_witness()
Definition: comparison.hpp:119
const blueprint_variable< FieldType > less
Definition: comparison.hpp:66
const std::size_t n
Definition: comparison.hpp:63
comparison(blueprint< FieldType > &bp, std::size_t n, const blueprint_linear_combination< FieldType > &A, const blueprint_linear_combination< FieldType > &B, const blueprint_variable< FieldType > &less, const blueprint_variable< FieldType > &less_or_eq)
Definition: comparison.hpp:69
const blueprint_linear_combination< FieldType > B
Definition: comparison.hpp:65
const blueprint_linear_combination< FieldType > A
Definition: comparison.hpp:64
const blueprint_variable< FieldType > less_or_eq
Definition: comparison.hpp:67
void generate_r1cs_constraints()
Definition: comparison.hpp:89
Definition: component.hpp:37
blueprint< FieldType > & bp
Definition: component.hpp:39
Definition: disjunction.hpp:52
constexpr T pow(T x, U n)
Definition: static_pow.hpp:32
Definition: pair.hpp:31