2 *****************************************************************************
4 Implementation of functions to sample R1CS examples with prescribed parameters
5 (according to some distribution).
7 See r1cs_examples.hpp .
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 *****************************************************************************/
15 #ifndef R1CS_EXAMPLES_TCC_
16 #define R1CS_EXAMPLES_TCC_
19 #include <libff/common/utils.hpp>
24 template<typename FieldT>
25 r1cs_example<FieldT> generate_r1cs_example_with_field_input(
26 const size_t num_constraints, const size_t num_inputs)
28 libff::enter_block("Call to generate_r1cs_example_with_field_input");
30 assert(num_inputs <= num_constraints + 2);
32 r1cs_constraint_system<FieldT> cs;
33 cs.primary_input_size = num_inputs;
35 cs.auxiliary_input_size = 2 + num_constraints - num_inputs;
37 r1cs_variable_assignment<FieldT> full_variable_assignment;
38 FieldT a = FieldT::random_element();
39 FieldT b = FieldT::random_element();
40 full_variable_assignment.push_back(a);
41 full_variable_assignment.push_back(b);
43 for (size_t i = 0; i < num_constraints - 1; ++i) {
44 linear_combination<FieldT> A, B, C;
52 full_variable_assignment.push_back(tmp);
62 full_variable_assignment.push_back(tmp);
67 cs.add_constraint(r1cs_constraint<FieldT>(A, B, C));
70 linear_combination<FieldT> A, B, C;
71 FieldT fin = FieldT::zero();
72 for (size_t i = 1; i < cs.num_variables(); ++i) {
75 fin = fin + full_variable_assignment[i - 1];
77 C.add_term(cs.num_variables(), 1);
78 cs.add_constraint(r1cs_constraint<FieldT>(A, B, C));
79 full_variable_assignment.push_back(fin.squared());
81 /* split variable assignment */
82 r1cs_primary_input<FieldT> primary_input(
83 full_variable_assignment.begin(),
84 full_variable_assignment.begin() + num_inputs);
85 r1cs_primary_input<FieldT> auxiliary_input(
86 full_variable_assignment.begin() + num_inputs,
87 full_variable_assignment.end());
90 assert(cs.num_variables() == full_variable_assignment.size());
91 assert(cs.num_variables() >= num_inputs);
92 assert(cs.num_inputs() == num_inputs);
93 assert(cs.num_constraints() == num_constraints);
94 assert(cs.is_satisfied(primary_input, auxiliary_input));
96 libff::leave_block("Call to generate_r1cs_example_with_field_input");
98 return r1cs_example<FieldT>(
99 std::move(cs), std::move(primary_input), std::move(auxiliary_input));
102 template<typename FieldT>
103 r1cs_example<FieldT> generate_r1cs_example_with_binary_input(
104 const size_t num_constraints, const size_t num_inputs)
106 libff::enter_block("Call to generate_r1cs_example_with_binary_input");
108 assert(num_inputs >= 1);
110 r1cs_constraint_system<FieldT> cs;
111 cs.primary_input_size = num_inputs;
112 // we will add one auxiliary variable per constraint
113 cs.auxiliary_input_size = num_constraints;
115 r1cs_variable_assignment<FieldT> full_variable_assignment;
116 for (size_t i = 0; i < num_inputs; ++i) {
117 full_variable_assignment.push_back(FieldT(std::rand() % 2));
120 size_t lastvar = num_inputs - 1;
121 for (size_t i = 0; i < num_constraints; ++i) {
123 const size_t u = (i == 0 ? std::rand() % num_inputs : std::rand() % i);
124 const size_t v = (i == 0 ? std::rand() % num_inputs : std::rand() % i);
126 /* chose two random bits and XOR them together:
127 res = u + v - 2 * u * v
128 2 * u * v = u + v - res
130 linear_combination<FieldT> A, B, C;
131 A.add_term(u + 1, 2);
132 B.add_term(v + 1, 1);
134 C.add_term(u + 1, 2);
136 C.add_term(u + 1, 1);
137 C.add_term(v + 1, 1);
139 C.add_term(lastvar + 1, -FieldT::one());
141 cs.add_constraint(r1cs_constraint<FieldT>(A, B, C));
142 full_variable_assignment.push_back(
143 full_variable_assignment[u] + full_variable_assignment[v] -
144 full_variable_assignment[u] * full_variable_assignment[v] -
145 full_variable_assignment[u] * full_variable_assignment[v]);
148 /* split variable assignment */
149 r1cs_primary_input<FieldT> primary_input(
150 full_variable_assignment.begin(),
151 full_variable_assignment.begin() + num_inputs);
152 r1cs_primary_input<FieldT> auxiliary_input(
153 full_variable_assignment.begin() + num_inputs,
154 full_variable_assignment.end());
157 assert(cs.num_variables() == full_variable_assignment.size());
158 assert(cs.num_variables() >= num_inputs);
159 assert(cs.num_inputs() == num_inputs);
160 assert(cs.num_constraints() == num_constraints);
161 assert(cs.is_satisfied(primary_input, auxiliary_input));
163 libff::leave_block("Call to generate_r1cs_example_with_binary_input");
165 return r1cs_example<FieldT>(
166 std::move(cs), std::move(primary_input), std::move(auxiliary_input));
169 } // namespace libsnark
171 #endif // R1CS_EXAMPLES_TCC