2 *****************************************************************************
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").
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 RAM_TO_R1CS_TCC_
16 #define RAM_TO_R1CS_TCC_
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)
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>(
36 boot_trace_size_bound,
40 main_protoboard.set_input_sizes(r1cs_input_size);
43 template<typename ramT> void ram_to_r1cs<ramT>::instance_map()
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");
50 template<typename ramT>
51 r1cs_constraint_system<ram_base_field<ramT>> ram_to_r1cs<
52 ramT>::get_constraint_system() const
54 return main_protoboard.get_constraint_system();
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)
62 libff::enter_block("Call to witness_map of ram_to_r1cs");
63 universal_gadget->generate_r1cs_witness(boot_trace, auxiliary_input);
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);
72 libff::leave_block("Call to witness_map of ram_to_r1cs");
73 return main_protoboard.auxiliary_input();
76 template<typename ramT> void ram_to_r1cs<ramT>::print_execution_trace() const
78 universal_gadget->print_execution_trace();
81 template<typename ramT> void ram_to_r1cs<ramT>::print_memory_trace() const
83 universal_gadget->print_memory_trace();
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)
91 typedef ram_base_field<ramT> FieldT;
93 const size_t address = av.first;
94 const size_t contents = av.second;
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());
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());
109 const std::vector<FieldT> trace_element =
110 libff::pack_bit_vector_into_field_element_vector<FieldT>(
113 return trace_element;
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)
122 typedef ram_base_field<ramT> FieldT;
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));
130 std::set<size_t> bound_input_locations;
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;
136 assert(input_pos < boot_trace_size_bound);
138 bound_input_locations.find(input_pos) ==
139 bound_input_locations.end());
141 const std::vector<FieldT> packed_input_element =
142 ram_to_r1cs<ramT>::pack_primary_input_address_and_value(ap, av);
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));
149 bound_input_locations.insert(input_pos);
155 } // namespace libsnark
157 #endif // RAM_TO_R1CS_TCC_