Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
memory_relation.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
10
11namespace bb {
12
13template <typename FF_> class MemoryRelationImpl {
14 public:
15 using FF = FF_;
16
17 static constexpr std::array<size_t, 6> SUBRELATION_PARTIAL_LENGTHS{
18 6, // memory sub-relation;
19 6, // ROM consistency sub-relation 1
20 6, // ROM consistency sub-relation 2
21 6, // RAM consistency sub-relation 1
22 6, // RAM consistency sub-relation 2
23 6 // RAM consistency sub-relation 3
24 };
25
26 static constexpr std::array<size_t, 6> TOTAL_LENGTH_ADJUSTMENTS{
27 1, // memory sub-relation
28 1, // ROM consistency sub-relation 1
29 1, // ROM consistency sub-relation 2
30 1, // RAM consistency sub-relation 1
31 1, // RAM consistency sub-relation 2
32 1 // RAM consistency sub-relation 3
33 };
34
39 template <typename AllEntities> inline static bool skip(const AllEntities& in) { return in.q_memory.is_zero(); }
40
67 template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
68 inline static void accumulate(ContainerOverSubrelations& accumulators,
69 const AllEntities& in,
70 const Parameters& params,
71 const FF& scaling_factor)
72 {
73 // all accumulators are of the same length, so we set our accumulator type to (arbitrarily) be the first one.
74 // if there were one that were shorter, we could also profitably use a `ShortAccumulator` type. however,
75 // that is not the case here.
76 using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
77 using View = typename Accumulator::View;
78 using CoefficientAccumulator = typename Accumulator::CoefficientAccumulator;
79
80 using ParameterView = GetParameterView<Parameters, View>;
81 using ParameterCoefficientAccumulator = typename ParameterView::CoefficientAccumulator;
82
83 const auto& eta_m = ParameterCoefficientAccumulator(params.eta);
84 const auto& eta_two_m = ParameterCoefficientAccumulator(params.eta_two);
85 const auto& eta_three_m = ParameterCoefficientAccumulator(params.eta_three);
86
87 auto w_1_m = CoefficientAccumulator(in.w_l);
88 auto w_2_m = CoefficientAccumulator(in.w_r);
89 auto w_3_m = CoefficientAccumulator(in.w_o);
90 auto w_4_m = CoefficientAccumulator(in.w_4);
91 auto w_1_shift_m = CoefficientAccumulator(in.w_l_shift);
92 auto w_2_shift_m = CoefficientAccumulator(in.w_r_shift);
93 auto w_3_shift_m = CoefficientAccumulator(in.w_o_shift);
94 auto w_4_shift_m = CoefficientAccumulator(in.w_4_shift);
95
96 auto q_1_m = CoefficientAccumulator(in.q_l);
97 auto q_2_m = CoefficientAccumulator(in.q_r);
98 auto q_3_m = CoefficientAccumulator(in.q_o);
99 auto q_4_m = CoefficientAccumulator(in.q_4);
100 auto q_m_m = CoefficientAccumulator(in.q_m);
101 auto q_c_m = CoefficientAccumulator(in.q_c);
102
103 auto q_memory_m = CoefficientAccumulator(in.q_memory);
104
147 // memory_record_check and partial_record_check_m have either deg 1 or 2 (the latter refers to the
148 // functional univariate degree when we use PG as opposed to sumcheck.)
149 auto memory_record_check_m = w_3_m * eta_three_m;
150 memory_record_check_m += w_2_m * eta_two_m;
151 memory_record_check_m += w_1_m * eta_m;
152 memory_record_check_m += q_c_m;
153 auto partial_record_check_m = memory_record_check_m; // used later in RAM consistency check
154 memory_record_check_m = memory_record_check_m - w_4_m;
155
156 auto memory_record_check = Accumulator(memory_record_check_m);
174 auto neg_index_delta_m = w_1_m - w_1_shift_m;
175 auto index_delta_is_zero_m = neg_index_delta_m + FF(1); // deg 1
176 auto record_delta_m = w_4_shift_m - w_4_m;
177
178 Accumulator index_is_monotonically_increasing(neg_index_delta_m.sqr() +
179 neg_index_delta_m); // check if next index minus current index is
180 // 0 or 1. deg 2
181
182 auto adjacent_values_match_if_adjacent_indices_match =
183 Accumulator(index_delta_is_zero_m * record_delta_m); // deg 2
184
185 auto q_memory_by_scaling_m = q_memory_m * scaling_factor; // deg 1
186 auto q_memory_by_scaling = Accumulator(q_memory_by_scaling_m);
187 auto q_one_by_two_m = q_1_m * q_2_m; // deg 2
188 auto q_one_by_two = Accumulator(q_one_by_two_m);
189 auto q_one_by_two_by_memory_by_scaling = q_one_by_two * q_memory_by_scaling; // deg 3
190
191 std::get<1>(accumulators) +=
192 adjacent_values_match_if_adjacent_indices_match * q_one_by_two_by_memory_by_scaling; // deg 5
193 std::get<2>(accumulators) += index_is_monotonically_increasing * q_one_by_two_by_memory_by_scaling; // deg 5
194 auto ROM_consistency_check_identity = memory_record_check * q_one_by_two; // deg 3 or 4
195
214 auto neg_access_type_m = (partial_record_check_m - w_4_m); // will be 0 or 1 for honest Prover; deg 1 or 2
215 Accumulator neg_access_type(neg_access_type_m);
216 auto access_check = neg_access_type.sqr() + neg_access_type; // check value is 0 or 1; deg 2 or 4
217
218 // TODO(https://github.com/AztecProtocol/barretenberg/issues/757): If we sorted in
219 // reverse order we could re-use `partial_record_check` 1 - (w3' * eta_three + w2' * eta_two + w1' *
220 // eta) deg 1 or 2
221 auto neg_next_gate_access_type_m = w_3_shift_m * eta_three_m;
222 neg_next_gate_access_type_m += w_2_shift_m * eta_two_m;
223 neg_next_gate_access_type_m += w_1_shift_m * eta_m;
224 neg_next_gate_access_type_m = neg_next_gate_access_type_m - w_4_shift_m;
225 Accumulator neg_next_gate_access_type(neg_next_gate_access_type_m); // deg 1 or 2
226 auto value_delta_m = w_3_shift_m - w_3_m;
227 auto adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation =
228 Accumulator(index_delta_is_zero_m * value_delta_m) *
229 Accumulator(neg_next_gate_access_type_m + FF(1)); // deg 3 or 4
230
231 // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the
232 // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't
233 // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access
234 // type is correct, to cover this edge case
235 // deg 2 or 4
236 auto next_gate_access_type_is_boolean = neg_next_gate_access_type.sqr() + neg_next_gate_access_type;
237
238 auto q_3_by_memory_and_scaling = Accumulator(q_3_m * q_memory_by_scaling_m);
239 // Putting it all together...
240 std::get<3>(accumulators) +=
241 adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation *
242 q_3_by_memory_and_scaling; // deg 5 or 6
243 std::get<4>(accumulators) += index_is_monotonically_increasing * q_3_by_memory_and_scaling; // deg 4
244 std::get<5>(accumulators) += next_gate_access_type_is_boolean * q_3_by_memory_and_scaling; // deg 4 or 6
245
246 auto RAM_consistency_check_identity = access_check * q_3_by_memory_and_scaling; // deg 3 or 5
247
259 auto timestamp_delta_m = w_2_shift_m - w_2_m; // deg 1
260 auto RAM_timestamp_check_identity_m = index_delta_is_zero_m * timestamp_delta_m - w_3_m; // deg 2
261 Accumulator RAM_timestamp_check_identity(RAM_timestamp_check_identity_m);
266 auto memory_identity = ROM_consistency_check_identity; // deg 3 or 4
267 memory_identity += RAM_timestamp_check_identity * Accumulator(q_4_m * q_1_m); // deg 4
268 memory_identity += memory_record_check * Accumulator(q_m_m * q_1_m); // deg 4 ( = deg 4 + (deg 3 or deg 4))
269
270 // (deg 4) + (deg 4) + (deg 3)
271 memory_identity *= q_memory_by_scaling; // deg 5
272 memory_identity += RAM_consistency_check_identity; // deg 5 ( = deg 5 + (deg 3 or deg 5))
273 std::get<0>(accumulators) += memory_identity; // deg 5
274 };
275};
276
277template <typename FF> using MemoryRelation = Relation<MemoryRelationImpl<FF>>;
278} // namespace bb
static bool skip(const AllEntities &in)
Returns true if the contribution from all subrelations for the provided inputs is identically zero.
static constexpr std::array< size_t, 6 > TOTAL_LENGTH_ADJUSTMENTS
static void accumulate(ContainerOverSubrelations &accumulators, const AllEntities &in, const Parameters &params, const FF &scaling_factor)
RAM/ROM memory relation.
static constexpr std::array< size_t, 6 > SUBRELATION_PARTIAL_LENGTHS
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
Entry point for Barretenberg command-line interface.
std::conditional_t< IsField< typename Params::DataType >, typename Params::DataType, View > GetParameterView
A type to optionally extract a view of a relation parameter in a relation.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13