Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
ram_to_r1cs.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of interfaces for a RAM-to-R1CS reduction, that is, constructing
5  a R1CS ("Rank-1 Constraint System") from a RAM ("Random-Access Machine").
6 
7  See ram_to_r1cs.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 RAM_TO_R1CS_TCC_
16 #define RAM_TO_R1CS_TCC_
17 
18 #include <set>
19 
20 namespace libsnark
21 {
22 
23 template<typename ramT>
24 ram_to_r1cs<ramT>::ram_to_r1cs(
25  const ram_architecture_params<ramT> &ap,
26  const size_t boot_trace_size_bound,
27  const size_t time_bound)
28  : boot_trace_size_bound(boot_trace_size_bound), main_protoboard(ap)
29 {
30  const size_t r1cs_input_size =
31  ram_universal_gadget<ramT>::packed_input_size(
32  ap, boot_trace_size_bound);
33  r1cs_input.allocate(main_protoboard, r1cs_input_size, "r1cs_input");
34  universal_gadget.reset(new ram_universal_gadget<ramT>(
35  main_protoboard,
36  boot_trace_size_bound,
37  time_bound,
38  r1cs_input,
39  "universal_gadget"));
40  main_protoboard.set_input_sizes(r1cs_input_size);
41 }
42 
43 template<typename ramT> void ram_to_r1cs<ramT>::instance_map()
44 {
45  libff::enter_block("Call to instance_map of ram_to_r1cs");
46  universal_gadget->generate_r1cs_constraints();
47  libff::leave_block("Call to instance_map of ram_to_r1cs");
48 }
49 
50 template<typename ramT>
51 r1cs_constraint_system<ram_base_field<ramT>> ram_to_r1cs<
52  ramT>::get_constraint_system() const
53 {
54  return main_protoboard.get_constraint_system();
55 }
56 
57 template<typename ramT>
58 r1cs_primary_input<ram_base_field<ramT>> ram_to_r1cs<ramT>::auxiliary_input_map(
59  const ram_boot_trace<ramT> &boot_trace,
60  const ram_input_tape<ramT> &auxiliary_input)
61 {
62  libff::enter_block("Call to witness_map of ram_to_r1cs");
63  universal_gadget->generate_r1cs_witness(boot_trace, auxiliary_input);
64 #ifdef DEBUG
65  const r1cs_primary_input<FieldT> primary_input_from_input_map =
66  ram_to_r1cs<ramT>::primary_input_map(
67  main_protoboard.ap, boot_trace_size_bound, boot_trace);
68  const r1cs_primary_input<FieldT> primary_input_from_witness_map =
69  main_protoboard.primary_input();
70  assert(primary_input_from_input_map == primary_input_from_witness_map);
71 #endif
72  libff::leave_block("Call to witness_map of ram_to_r1cs");
73  return main_protoboard.auxiliary_input();
74 }
75 
76 template<typename ramT> void ram_to_r1cs<ramT>::print_execution_trace() const
77 {
78  universal_gadget->print_execution_trace();
79 }
80 
81 template<typename ramT> void ram_to_r1cs<ramT>::print_memory_trace() const
82 {
83  universal_gadget->print_memory_trace();
84 }
85 
86 template<typename ramT>
87 std::vector<ram_base_field<ramT>> ram_to_r1cs<ramT>::
88  pack_primary_input_address_and_value(
89  const ram_architecture_params<ramT> &ap, const address_and_value &av)
90 {
91  typedef ram_base_field<ramT> FieldT;
92 
93  const size_t address = av.first;
94  const size_t contents = av.second;
95 
96  const libff::bit_vector address_bits =
97  libff::convert_field_element_to_bit_vector<FieldT>(
98  FieldT(address, true), ap.address_size());
99  const libff::bit_vector contents_bits =
100  libff::convert_field_element_to_bit_vector<FieldT>(
101  FieldT(contents, true), ap.value_size());
102 
103  libff::bit_vector trace_element_bits;
104  trace_element_bits.insert(
105  trace_element_bits.end(), address_bits.begin(), address_bits.end());
106  trace_element_bits.insert(
107  trace_element_bits.end(), contents_bits.begin(), contents_bits.end());
108 
109  const std::vector<FieldT> trace_element =
110  libff::pack_bit_vector_into_field_element_vector<FieldT>(
111  trace_element_bits);
112 
113  return trace_element;
114 }
115 
116 template<typename ramT>
117 r1cs_primary_input<ram_base_field<ramT>> ram_to_r1cs<ramT>::primary_input_map(
118  const ram_architecture_params<ramT> &ap,
119  const size_t boot_trace_size_bound,
120  const ram_boot_trace<ramT> &boot_trace)
121 {
122  typedef ram_base_field<ramT> FieldT;
123 
124  const size_t packed_input_element_size =
125  ram_universal_gadget<ramT>::packed_input_element_size(ap);
126  r1cs_primary_input<FieldT> result(
127  ram_universal_gadget<ramT>::packed_input_size(
128  ap, boot_trace_size_bound));
129 
130  std::set<size_t> bound_input_locations;
131 
132  for (auto it : boot_trace.get_all_trace_entries()) {
133  const size_t input_pos = it.first;
134  const address_and_value av = it.second;
135 
136  assert(input_pos < boot_trace_size_bound);
137  assert(
138  bound_input_locations.find(input_pos) ==
139  bound_input_locations.end());
140 
141  const std::vector<FieldT> packed_input_element =
142  ram_to_r1cs<ramT>::pack_primary_input_address_and_value(ap, av);
143  std::copy(
144  packed_input_element.begin(),
145  packed_input_element.end(),
146  result.begin() + packed_input_element_size *
147  (boot_trace_size_bound - 1 - input_pos));
148 
149  bound_input_locations.insert(input_pos);
150  }
151 
152  return result;
153 }
154 
155 } // namespace libsnark
156 
157 #endif // RAM_TO_R1CS_TCC_