cp_handler.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 a compliance predicate handler.
26 //
27 // A compliance predicate handler is a base class for creating compliance predicates.
28 // It relies on classes declared in components.
29 //---------------------------------------------------------------------------//
30 
31 #ifndef CRYPTO3_ZK_BLUEPRINT_CP_HANDLER_HPP
32 #define CRYPTO3_ZK_BLUEPRINT_CP_HANDLER_HPP
33 
34 #include <numeric>
35 
38 
39 #include <nil/crypto3/zk/snark/schemes/pcd/r1cs_pcd/compliance_predicate.hpp>
40 
41 namespace nil {
42  namespace crypto3 {
43  namespace zk {
44  namespace snark {
45 
46  /***************************** Message variable ******************************/
47 
51  template<typename FieldType>
53  protected:
55 
56  public:
57  blueprint_variable<FieldType> type;
58 
59  blueprint_variable_vector<FieldType> all_vars;
60 
61  r1cs_pcd_message_variable(blueprint<FieldType> &bp);
62  void update_all_vars();
63 
64  void generate_r1cs_witness(const std::shared_ptr<r1cs_pcd_message<FieldType>> &message);
65  virtual std::shared_ptr<r1cs_pcd_message<FieldType>> get_message() const = 0;
66 
67  virtual ~r1cs_pcd_message_variable() = default;
68  };
69  /*************************** Local data variable *****************************/
70 
74  template<typename FieldType>
76  protected:
78 
79  public:
80  blueprint_variable_vector<FieldType> all_vars;
81 
82  r1cs_pcd_local_data_variable(blueprint<FieldType> &bp);
83  void update_all_vars();
84 
85  void generate_r1cs_witness(const std::shared_ptr<r1cs_pcd_local_data<FieldType>> &local_data);
86 
87  virtual ~r1cs_pcd_local_data_variable() = default;
88  };
89 
90  /*********************** Compliance predicate handler ************************/
91 
95  template<typename FieldType, typename BlueprintType>
97  protected:
98  BlueprintType bp;
99 
100  std::shared_ptr<r1cs_pcd_message_variable<FieldType>> outgoing_message;
101  blueprint_variable<FieldType> arity;
102  std::vector<std::shared_ptr<r1cs_pcd_message_variable<FieldType>>> incoming_messages;
103  std::shared_ptr<r1cs_pcd_local_data_variable<FieldType>> local_data;
104 
105  public:
106  const std::size_t name;
107  const std::size_t type;
108  const std::size_t max_arity;
110  const std::set<std::size_t> accepted_input_types;
111 
113  const BlueprintType &bp,
114  const std::size_t name,
115  const std::size_t type,
116  const std::size_t max_arity,
117  const bool relies_on_same_type_inputs,
118  const std::set<std::size_t> &accepted_input_types = std::set<std::size_t>());
119  virtual void generate_r1cs_constraints() = 0;
120  virtual void generate_r1cs_witness(
121  const std::vector<std::shared_ptr<r1cs_pcd_message<FieldType>>> &incoming_message_values,
122  const std::shared_ptr<r1cs_pcd_local_data<FieldType>> &local_data_value);
123 
126 
127  std::shared_ptr<r1cs_pcd_message<FieldType>> get_outgoing_message() const;
128  std::size_t get_arity() const;
129  std::shared_ptr<r1cs_pcd_message<FieldType>>
130  get_incoming_message(const std::size_t message_idx) const;
131  std::shared_ptr<r1cs_pcd_local_data<FieldType>> get_local_data() const;
133  };
134 
135  template<typename FieldType>
137  components::component<FieldType>(bp) {
138  type.allocate(bp);
139  all_vars.emplace_back(type);
140 
141  num_vars_at_construction = bp.num_variables();
142  }
143 
144  template<typename FieldType>
146  /* NOTE: this assumes that r1cs_pcd_message_variable has been the
147  * only component allocating variables on the protoboard and needs to
148  * be updated, e.g., in multicore variable allocation scenario. */
149 
150  for (std::size_t var_idx = num_vars_at_construction + 1; var_idx <= this->bp.num_variables();
151  ++var_idx) {
152  all_vars.emplace_back(blueprint_variable<FieldType>(var_idx));
153  }
154  }
155 
156  template<typename FieldType>
158  const std::shared_ptr<r1cs_pcd_message<FieldType>> &message) {
159  all_vars.fill_with_field_elements(this->bp, message->as_r1cs_variable_assignment());
160  }
161 
162  template<typename FieldType>
164  components::component<FieldType>(bp) {
165  num_vars_at_construction = bp.num_variables();
166  }
167 
168  template<typename FieldType>
170  /* (the same NOTE as for r1cs_message_variable applies) */
171 
172  for (std::size_t var_idx = num_vars_at_construction + 1; var_idx <= this->bp.num_variables();
173  ++var_idx) {
174  all_vars.emplace_back(blueprint_variable<FieldType>(var_idx));
175  }
176  }
177 
178  template<typename FieldType>
180  const std::shared_ptr<r1cs_pcd_local_data<FieldType>> &local_data) {
181  all_vars.fill_with_field_elements(this->bp, local_data->as_r1cs_variable_assignment());
182  }
183 
184  template<typename FieldType, typename BlueprintType>
186  const BlueprintType &bp,
187  const std::size_t name,
188  const std::size_t type,
189  const std::size_t max_arity,
190  const bool relies_on_same_type_inputs,
191  const std::set<std::size_t> &accepted_input_types) :
192  bp(bp),
193  name(name), type(type), max_arity(max_arity),
194  relies_on_same_type_inputs(relies_on_same_type_inputs), accepted_input_types(accepted_input_types) {
196  }
197 
198  template<typename FieldType, typename BlueprintType>
200  const std::vector<std::shared_ptr<r1cs_pcd_message<FieldType>>> &incoming_message_values,
201  const std::shared_ptr<r1cs_pcd_local_data<FieldType>> &local_data_value) {
202  bp.clear_values();
203  bp.val(outgoing_message->type) = typename FieldType::value_type(type);
204  bp.val(arity) = typename FieldType::value_type(incoming_message_values.size());
205 
206  for (std::size_t i = 0; i < incoming_message_values.size(); ++i) {
207  incoming_messages[i]->generate_r1cs_witness(incoming_message_values[i]);
208  }
209 
210  local_data->generate_r1cs_witness(local_data_value);
211  }
212 
213  template<typename FieldType, typename BlueprintType>
216  assert(incoming_messages.size() == max_arity);
217 
218  const std::size_t outgoing_message_payload_length = outgoing_message->all_vars.size() - 1;
219 
220  std::vector<std::size_t> incoming_message_payload_lengths(max_arity);
221  std::transform(incoming_messages.begin(), incoming_messages.end(),
222  incoming_message_payload_lengths.begin(),
223  [](const std::shared_ptr<r1cs_pcd_message_variable<FieldType>> &msg) {
224  return msg->all_vars.size() - 1;
225  });
226 
227  const std::size_t local_data_length = local_data->all_vars.size();
228 
229  const std::size_t all_but_witness_length =
230  ((1 + outgoing_message_payload_length) + 1 +
231  (max_arity + std::accumulate(incoming_message_payload_lengths.begin(),
232  incoming_message_payload_lengths.end(), 0)) +
233  local_data_length);
234  const std::size_t witness_length = bp.num_variables() - all_but_witness_length;
235 
236  snark::r1cs_constraint_system<FieldType> constraint_system = bp.get_constraint_system();
237  constraint_system.primary_input_size = 1 + outgoing_message_payload_length;
238  constraint_system.auxiliary_input_size = bp.num_variables() - constraint_system.primary_input_size;
239 
241  type,
242  constraint_system,
243  outgoing_message_payload_length,
244  max_arity,
245  incoming_message_payload_lengths,
246  local_data_length,
247  witness_length,
248  relies_on_same_type_inputs,
249  accepted_input_types);
250  }
251 
252  template<typename FieldType, typename BlueprintType>
255  return bp.full_variable_assignment();
256  }
257 
258  template<typename FieldType, typename BlueprintType>
259  std::shared_ptr<r1cs_pcd_message<FieldType>>
261  return outgoing_message->get_message();
262  }
263 
264  template<typename FieldType, typename BlueprintType>
266  return bp.val(arity).as_ulong();
267  }
268 
269  template<typename FieldType, typename BlueprintType>
270  std::shared_ptr<r1cs_pcd_message<FieldType>>
272  const std::size_t message_idx) const {
273  assert(message_idx < max_arity);
274  return incoming_messages[message_idx]->get_message();
275  }
276 
277  template<typename FieldType, typename BlueprintType>
278  std::shared_ptr<r1cs_pcd_local_data<FieldType>>
280  return local_data->get_local_data();
281  }
282 
283  template<typename FieldType, typename BlueprintType>
286  const snark::r1cs_variable_assignment<FieldType> va = bp.full_variable_assignment();
287  // outgoing_message + arity + incoming_messages + local_data
288  const std::size_t witness_pos =
289  (outgoing_message->all_vars.size() + 1 +
291  incoming_messages.begin(), incoming_messages.end(), 0,
292  [](std::size_t acc, const std::shared_ptr<r1cs_pcd_message_variable<FieldType>> &msg) {
293  return acc + msg->all_vars.size();
294  }) +
295  local_data->all_vars.size());
296 
297  return snark::r1cs_variable_assignment<FieldType>(va.begin() + witness_pos, va.end());
298  }
299  } // namespace snark
300  } // namespace zk
301  } // namespace crypto3
302 } // namespace nil
303 
304 #endif // CRYPTO3_ZK_BLUEPRINT_CP_HANDLER_HPP
Definition: component.hpp:37
blueprint< FieldType > & bp
Definition: component.hpp:39
const std::size_t name
Definition: cp_handler.hpp:106
const std::set< std::size_t > accepted_input_types
Definition: cp_handler.hpp:110
const bool relies_on_same_type_inputs
Definition: cp_handler.hpp:109
const std::size_t max_arity
Definition: cp_handler.hpp:108
std::shared_ptr< r1cs_pcd_local_data< FieldType > > get_local_data() const
Definition: cp_handler.hpp:279
std::shared_ptr< r1cs_pcd_message< FieldType > > get_incoming_message(const std::size_t message_idx) const
Definition: cp_handler.hpp:271
r1cs_pcd_compliance_predicate< FieldType > get_compliance_predicate() const
Definition: cp_handler.hpp:215
std::size_t get_arity() const
Definition: cp_handler.hpp:265
std::vector< std::shared_ptr< r1cs_pcd_message_variable< FieldType > > > incoming_messages
Definition: cp_handler.hpp:102
std::shared_ptr< r1cs_pcd_local_data_variable< FieldType > > local_data
Definition: cp_handler.hpp:103
compliance_predicate_handler(const BlueprintType &bp, const std::size_t name, const std::size_t type, const std::size_t max_arity, const bool relies_on_same_type_inputs, const std::set< std::size_t > &accepted_input_types=std::set< std::size_t >())
Definition: cp_handler.hpp:185
snark::r1cs_variable_assignment< FieldType > get_full_variable_assignment() const
Definition: cp_handler.hpp:254
BlueprintType bp
Definition: cp_handler.hpp:98
snark::r1cs_variable_assignment< FieldType > get_witness() const
Definition: cp_handler.hpp:285
blueprint_variable< FieldType > arity
Definition: cp_handler.hpp:101
const std::size_t type
Definition: cp_handler.hpp:107
std::shared_ptr< r1cs_pcd_message< FieldType > > get_outgoing_message() const
Definition: cp_handler.hpp:260
virtual void generate_r1cs_witness(const std::vector< std::shared_ptr< r1cs_pcd_message< FieldType >>> &incoming_message_values, const std::shared_ptr< r1cs_pcd_local_data< FieldType >> &local_data_value)
Definition: cp_handler.hpp:199
std::shared_ptr< r1cs_pcd_message_variable< FieldType > > outgoing_message
Definition: cp_handler.hpp:100
Definition: compliance_predicate.hpp:123
void generate_r1cs_witness(const std::shared_ptr< r1cs_pcd_local_data< FieldType >> &local_data)
Definition: cp_handler.hpp:179
void update_all_vars()
Definition: cp_handler.hpp:169
r1cs_pcd_local_data_variable(blueprint< FieldType > &bp)
Definition: cp_handler.hpp:163
std::size_t num_vars_at_construction
Definition: cp_handler.hpp:77
blueprint_variable_vector< FieldType > all_vars
Definition: cp_handler.hpp:80
virtual std::shared_ptr< r1cs_pcd_message< FieldType > > get_message() const =0
void generate_r1cs_witness(const std::shared_ptr< r1cs_pcd_message< FieldType >> &message)
Definition: cp_handler.hpp:157
blueprint_variable_vector< FieldType > all_vars
Definition: cp_handler.hpp:59
blueprint_variable< FieldType > type
Definition: cp_handler.hpp:57
void update_all_vars()
Definition: cp_handler.hpp:145
std::size_t num_vars_at_construction
Definition: cp_handler.hpp:54
r1cs_pcd_message_variable(blueprint< FieldType > &bp)
Definition: cp_handler.hpp:136
vector(T, U...) -> vector< std::enable_if_t<(std::is_same_v< T, U > &&...), T >, 1+sizeof...(U)>
deduction guide for uniform initialization
constexpr U accumulate(const vector< T, N > &v, U init, F &&f)
accumulates an operation across a vector
Definition: vector/utility.hpp:70
decoded_range< UnaryFunction, SinglePassRange > transform(SinglePassRange &rng, UnaryFunction fn)
Definition: decrypted.hpp:100
std::vector< typename FieldType::value_type > r1cs_pcd_witness
Definition: compliance_predicate.hpp:86
std::vector< typename FieldType::value_type > r1cs_variable_assignment
Definition: r1cs.hpp:107
Definition: pair.hpp:31
std::size_t primary_input_size
Definition: r1cs.hpp:127
std::size_t auxiliary_input_size
Definition: r1cs.hpp:128
Definition: compliance_predicate.hpp:77
Definition: compliance_predicate.hpp:56