barretenberg
Loading...
Searching...
No Matches
auxiliary_relation.hpp
1#pragma once
2#include "barretenberg/numeric/uint256/uint256.hpp"
3#include "barretenberg/relations/relation_types.hpp"
4
5namespace proof_system {
6
7template <typename FF_> class AuxiliaryRelationImpl {
8 public:
9 using FF = FF_;
10 /*
11 * TODO(https://github.com/AztecProtocol/barretenberg/issues/757): Investigate optimizations.
12 * It seems that we could have:
13 * static constexpr std::array<size_t, 6> SUBRELATION_PARTIAL_LENGTHS{
14 * 5 // auxiliary sub-relation;
15 * 6 // ROM consistency sub-relation 1
16 * 6 // ROM consistency sub-relation 2
17 * 6 // RAM consistency sub-relation 1
18 * 5 // RAM consistency sub-relation 2
19 * 5 // RAM consistency sub-relation 3
20 * };
21 *
22 * and
23 *
24 * static constexpr std::array<size_t, 6> TOTAL_LENGTH_ADJUSTMENTS{
25 * 6, // auxiliary sub-relation
26 * 0, // ROM consistency sub-relation 1
27 * 0, // ROM consistency sub-relation 2
28 * 3, // RAM consistency sub-relation 1
29 * 0, // RAM consistency sub-relation 2
30 * 1 // RAM consistency sub-relation 3
31 * };
32 */
33
34 static constexpr std::array<size_t, 6> SUBRELATION_PARTIAL_LENGTHS{
35 6, // auxiliary sub-relation;
36 6, // ROM consistency sub-relation 1
37 6, // ROM consistency sub-relation 2
38 6, // RAM consistency sub-relation 1
39 6, // RAM consistency sub-relation 2
40 6 // RAM consistency sub-relation 3
41 };
42
43 static constexpr std::array<size_t, 6> TOTAL_LENGTH_ADJUSTMENTS{
44 6, // auxiliary sub-relation
45 6, // ROM consistency sub-relation 1
46 6, // ROM consistency sub-relation 2
47 6, // RAM consistency sub-relation 1
48 6, // RAM consistency sub-relation 2
49 6 // RAM consistency sub-relation 3
50 };
51
86 template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
87 inline static void accumulate(ContainerOverSubrelations& accumulators,
88 const AllEntities& in,
89 const Parameters& params,
90 const FF& scaling_factor)
91 {
92
93 // All subrelations have the same length so we use the same length view for all calculations
94 using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
95 using View = typename Accumulator::View;
96 using ParameterView = GetParameterView<Parameters, View>;
97
98 const auto& eta = ParameterView(params.eta);
99
100 auto w_1 = View(in.w_l);
101 auto w_2 = View(in.w_r);
102 auto w_3 = View(in.w_o);
103 auto w_4 = View(in.w_4);
104 auto w_1_shift = View(in.w_l_shift);
105 auto w_2_shift = View(in.w_r_shift);
106 auto w_3_shift = View(in.w_o_shift);
107 auto w_4_shift = View(in.w_4_shift);
108
109 auto q_1 = View(in.q_l);
110 auto q_2 = View(in.q_r);
111 auto q_3 = View(in.q_o);
112 auto q_4 = View(in.q_4);
113 auto q_m = View(in.q_m);
114 auto q_c = View(in.q_c);
115 auto q_arith = View(in.q_arith);
116 auto q_aux = View(in.q_aux);
117
118 const FF LIMB_SIZE(uint256_t(1) << 68);
119 const FF SUBLIMB_SHIFT(uint256_t(1) << 14);
120
131 auto limb_subproduct = w_1 * w_2_shift + w_1_shift * w_2;
132 auto non_native_field_gate_2 = (w_1 * w_4 + w_2 * w_3 - w_3_shift);
133 non_native_field_gate_2 *= LIMB_SIZE;
134 non_native_field_gate_2 -= w_4_shift;
135 non_native_field_gate_2 += limb_subproduct;
136 non_native_field_gate_2 *= q_4;
137
138 limb_subproduct *= LIMB_SIZE;
139 limb_subproduct += (w_1_shift * w_2_shift);
140 auto non_native_field_gate_1 = limb_subproduct;
141 non_native_field_gate_1 -= (w_3 + w_4);
142 non_native_field_gate_1 *= q_3;
143
144 auto non_native_field_gate_3 = limb_subproduct;
145 non_native_field_gate_3 += w_4;
146 non_native_field_gate_3 -= (w_3_shift + w_4_shift);
147 non_native_field_gate_3 *= q_m;
148
149 auto non_native_field_identity = non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3;
150 non_native_field_identity *= q_2;
151
152 // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm
153 // deg 2
154 auto limb_accumulator_1 = w_2_shift * SUBLIMB_SHIFT;
155 limb_accumulator_1 += w_1_shift;
156 limb_accumulator_1 *= SUBLIMB_SHIFT;
157 limb_accumulator_1 += w_3;
158 limb_accumulator_1 *= SUBLIMB_SHIFT;
159 limb_accumulator_1 += w_2;
160 limb_accumulator_1 *= SUBLIMB_SHIFT;
161 limb_accumulator_1 += w_1;
162 limb_accumulator_1 -= w_4;
163 limb_accumulator_1 *= q_4;
164
165 // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm
166 // deg 2
167 auto limb_accumulator_2 = w_3_shift * SUBLIMB_SHIFT;
168 limb_accumulator_2 += w_2_shift;
169 limb_accumulator_2 *= SUBLIMB_SHIFT;
170 limb_accumulator_2 += w_1_shift;
171 limb_accumulator_2 *= SUBLIMB_SHIFT;
172 limb_accumulator_2 += w_4;
173 limb_accumulator_2 *= SUBLIMB_SHIFT;
174 limb_accumulator_2 += w_3;
175 limb_accumulator_2 -= w_4_shift;
176 limb_accumulator_2 *= q_m;
177
178 auto limb_accumulator_identity = limb_accumulator_1 + limb_accumulator_2;
179 limb_accumulator_identity *= q_3; // deg 3
180
221 auto memory_record_check = w_3 * eta;
222 memory_record_check += w_2;
223 memory_record_check *= eta;
224 memory_record_check += w_1;
225 memory_record_check *= eta;
226 memory_record_check += q_c;
227 auto partial_record_check = memory_record_check; // used in RAM consistency check; deg 1 or 4
228 memory_record_check = memory_record_check - w_4;
229
245 auto index_delta = w_1_shift - w_1;
246 auto record_delta = w_4_shift - w_4;
247
248 auto index_is_monotonically_increasing = index_delta * index_delta - index_delta; // deg 2
249
250 auto adjacent_values_match_if_adjacent_indices_match = (index_delta * FF(-1) + FF(1)) * record_delta; // deg 2
251
252 std::get<1>(accumulators) +=
253 adjacent_values_match_if_adjacent_indices_match * (q_1 * q_2) * (q_aux * scaling_factor); // deg 5
254 std::get<2>(accumulators) +=
255 index_is_monotonically_increasing * (q_1 * q_2) * (q_aux * scaling_factor); // deg 5
256 auto ROM_consistency_check_identity = memory_record_check * (q_1 * q_2); // deg 3 or 7
257
276 auto access_type = (w_4 - partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4
277 auto access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8
278
279 // TODO(https://github.com/AztecProtocol/barretenberg/issues/757): If we sorted in
280 // reverse order we could re-use `partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta
281 // deg 1 or 4
282 auto next_gate_access_type = w_3_shift * eta;
283 next_gate_access_type += w_2_shift;
284 next_gate_access_type *= eta;
285 next_gate_access_type += w_1_shift;
286 next_gate_access_type *= eta;
287 next_gate_access_type = w_4_shift - next_gate_access_type;
288
289 auto value_delta = w_3_shift - w_3;
290 auto adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation =
291 (index_delta * FF(-1) + FF(1)) * value_delta * (next_gate_access_type * FF(-1) + FF(1)); // deg 3 or 6
292
293 // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the
294 // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't
295 // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access
296 // type is correct, to cover this edge case
297 // deg 2 or 4
298 auto next_gate_access_type_is_boolean = next_gate_access_type * next_gate_access_type - next_gate_access_type;
299
300 // Putting it all together...
301 std::get<3>(accumulators) +=
302 adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation * (q_arith) *
303 (q_aux * scaling_factor); // deg 5 or 8
304 std::get<4>(accumulators) += index_is_monotonically_increasing * (q_arith) * (q_aux * scaling_factor); // deg 4
305 std::get<5>(accumulators) +=
306 next_gate_access_type_is_boolean * (q_arith) * (q_aux * scaling_factor); // deg 4 or 6
307 auto RAM_consistency_check_identity = access_check * (q_arith); // deg 3 or 9
308
320 auto timestamp_delta = w_2_shift - w_2;
321 auto RAM_timestamp_check_identity = (index_delta * FF(-1) + FF(1)) * timestamp_delta - w_3; // deg 3
322
327 auto memory_identity = ROM_consistency_check_identity; // deg 3 or 6
328 memory_identity += RAM_timestamp_check_identity * (q_4 * q_1); // deg 4
329 memory_identity += memory_record_check * (q_m * q_1); // deg 3 or 6
330 memory_identity += RAM_consistency_check_identity; // deg 3 or 9
331
332 // (deg 3 or 9) + (deg 4) + (deg 3)
333 auto auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity;
334 auxiliary_identity *= (q_aux * scaling_factor); // deg 4 or 10
335 std::get<0>(accumulators) += auxiliary_identity;
336 };
337};
338
339template <typename FF> using AuxiliaryRelation = Relation<AuxiliaryRelationImpl<FF>>;
340} // namespace proof_system
Definition: uint256.hpp:25
Definition: auxiliary_relation.hpp:7
static void accumulate(ContainerOverSubrelations &accumulators, const AllEntities &in, const Parameters &params, const FF &scaling_factor)
Expression for the generalized permutation sort gate.
Definition: auxiliary_relation.hpp:87