Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
bacs_examples.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of functions to sample BACS examples with prescribed parameters
5  (according to some distribution).
6 
7  See bacs_examples.hpp .
8 
9  *****************************************************************************
10  * @author This file is part of libsnark, developed by SCIPR Lab
11  * and contributors (see AUTHORS).
12  * @copyright MIT license (see LICENSE file)
13  *****************************************************************************/
14 
15 #ifndef BACS_EXAMPLES_TCC_
16 #define BACS_EXAMPLES_TCC_
17 
18 #include <cassert>
19 #include <libff/common/utils.hpp>
20 
21 namespace libsnark
22 {
23 
24 template<typename FieldT>
25 linear_combination<FieldT> random_linear_combination(const size_t num_variables)
26 {
27  const size_t terms = 1 + (std::rand() % 3);
28  linear_combination<FieldT> result;
29 
30  for (size_t i = 0; i < terms; ++i) {
31  const FieldT coeff =
32  FieldT(std::rand()); // TODO: replace with FieldT::random_element(),
33  // when it becomes faster...
34  result = result +
35  coeff * variable<FieldT>(std::rand() % (num_variables + 1));
36  }
37 
38  return result;
39 }
40 
41 template<typename FieldT>
42 bacs_example<FieldT> generate_bacs_example(
43  const size_t primary_input_size,
44  const size_t auxiliary_input_size,
45  const size_t num_gates,
46  const size_t num_outputs)
47 {
48  bacs_example<FieldT> example;
49  for (size_t i = 0; i < primary_input_size; ++i) {
50  example.primary_input.emplace_back(FieldT::random_element());
51  }
52 
53  for (size_t i = 0; i < auxiliary_input_size; ++i) {
54  example.auxiliary_input.emplace_back(FieldT::random_element());
55  }
56 
57  example.circuit.primary_input_size = primary_input_size;
58  example.circuit.auxiliary_input_size = auxiliary_input_size;
59 
60  bacs_variable_assignment<FieldT> all_vals;
61  all_vals.insert(
62  all_vals.end(),
63  example.primary_input.begin(),
64  example.primary_input.end());
65  all_vals.insert(
66  all_vals.end(),
67  example.auxiliary_input.begin(),
68  example.auxiliary_input.end());
69 
70  for (size_t i = 0; i < num_gates; ++i) {
71  const size_t num_variables =
72  primary_input_size + auxiliary_input_size + i;
73  bacs_gate<FieldT> gate;
74  gate.lhs = random_linear_combination<FieldT>(num_variables);
75  gate.rhs = random_linear_combination<FieldT>(num_variables);
76  gate.output = variable<FieldT>(num_variables + 1);
77 
78  if (i >= num_gates - num_outputs) {
79  /* make gate a circuit output and fix */
80  gate.is_circuit_output = true;
81  const var_index_t var_idx =
82  std::rand() %
83  (1 + primary_input_size + std::min(num_gates - num_outputs, i));
84  const FieldT var_val =
85  (var_idx == 0 ? FieldT::one() : all_vals[var_idx - 1]);
86 
87  if (std::rand() % 2 == 0) {
88  const FieldT lhs_val = gate.lhs.evaluate(all_vals);
89  const FieldT coeff = -(lhs_val * var_val.inverse());
90  gate.lhs = gate.lhs + coeff * variable<FieldT>(var_idx);
91  } else {
92  const FieldT rhs_val = gate.rhs.evaluate(all_vals);
93  const FieldT coeff = -(rhs_val * var_val.inverse());
94  gate.rhs = gate.rhs + coeff * variable<FieldT>(var_idx);
95  }
96 
97  assert(gate.evaluate(all_vals).is_zero());
98  } else {
99  gate.is_circuit_output = false;
100  }
101 
102  example.circuit.add_gate(gate);
103  all_vals.emplace_back(gate.evaluate(all_vals));
104  }
105 
106  assert(example.circuit.is_satisfied(
107  example.primary_input, example.auxiliary_input));
108 
109  return example;
110 }
111 
112 } // namespace libsnark
113 
114 #endif // BACS_EXAMPLES_TCC