Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
translator_non_native_field_relation_impl.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Planned, auditors: [], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
9
10namespace bb {
76template <typename FF>
77template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
78void TranslatorNonNativeFieldRelationImpl<FF>::accumulate(ContainerOverSubrelations& accumulators,
79 const AllEntities& in,
80 const Parameters& params,
81 const FF& scaling_factor)
82{
83
85 using View = typename Accumulator::View;
86
87 static constexpr size_t NUM_LIMB_BITS = 68;
88 static const FF shift = FF(uint256_t(1) << NUM_LIMB_BITS);
89 static const FF shiftx2 = FF(uint256_t(1) << (NUM_LIMB_BITS * 2));
90 static const FF shiftx3 = FF(uint256_t(1) << (NUM_LIMB_BITS * 3));
91 static constexpr uint512_t MODULUS_U512 = uint512_t(curve::BN254::BaseField::modulus);
92 static constexpr uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (NUM_LIMB_BITS << 2);
93 static constexpr uint512_t NEGATIVE_PRIME_MODULUS = BINARY_BASIS_MODULUS - MODULUS_U512;
94 static const std::array<FF, 5> NEGATIVE_MODULUS_LIMBS = {
95 FF(NEGATIVE_PRIME_MODULUS.slice(0, NUM_LIMB_BITS).lo),
96 FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2).lo),
97 FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3).lo),
98 FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4).lo),
100 };
101
102 // Limbs of evaluation challenge x
103 const auto& evaluation_input_x_0 = params.evaluation_input_x[0];
104 const auto& evaluation_input_x_1 = params.evaluation_input_x[1];
105 const auto& evaluation_input_x_2 = params.evaluation_input_x[2];
106 const auto& evaluation_input_x_3 = params.evaluation_input_x[3];
107 const auto& evaluation_input_x_4 = params.evaluation_input_x[4];
108
109 // Limbs of batching challenge v
110 const auto& v_0 = params.batching_challenge_v[0][0];
111 const auto& v_1 = params.batching_challenge_v[0][1];
112 const auto& v_2 = params.batching_challenge_v[0][2];
113 const auto& v_3 = params.batching_challenge_v[0][3];
114 const auto& v_4 = params.batching_challenge_v[0][4];
115
116 // Limbs of batching challenge v²
117 const auto& v_sqr_0 = params.batching_challenge_v[1][0];
118 const auto& v_sqr_1 = params.batching_challenge_v[1][1];
119 const auto& v_sqr_2 = params.batching_challenge_v[1][2];
120 const auto& v_sqr_3 = params.batching_challenge_v[1][3];
121 const auto& v_sqr_4 = params.batching_challenge_v[1][4];
122
123 // Limbs of batching challenge v³
124 const auto& v_cube_0 = params.batching_challenge_v[2][0];
125 const auto& v_cube_1 = params.batching_challenge_v[2][1];
126 const auto& v_cube_2 = params.batching_challenge_v[2][2];
127 const auto& v_cube_3 = params.batching_challenge_v[2][3];
128 const auto& v_cube_4 = params.batching_challenge_v[2][4];
129
130 // Limbs of batching challenge v⁴
131 const auto& v_quad_0 = params.batching_challenge_v[3][0];
132 const auto& v_quad_1 = params.batching_challenge_v[3][1];
133 const auto& v_quad_2 = params.batching_challenge_v[3][2];
134 const auto& v_quad_3 = params.batching_challenge_v[3][3];
135 const auto& v_quad_4 = params.batching_challenge_v[3][4];
136
137 // Fetch witness values
138 // Pₓ = (Pₓ,₃ || Pₓ,₂ || Pₓ,₁ || Pₓ,₀)
139 // Pᵧ = (Pᵧ,₃ || Pᵧ,₂ || Pᵧ,₁ || Pᵧ,₀)
140 // z₁ = (z₁,₁ || z₁,₀)
141 // z₂ = (z₂,₁ || z₂,₀)
142 // Q = (q₃ || q₂ || q₁ || q₀)
143 const auto& op = View(in.op);
144 const auto& p_x_limb_0 = View(in.p_x_low_limbs);
145 const auto& p_y_limb_0 = View(in.p_y_low_limbs);
146 const auto& p_x_limb_2 = View(in.p_x_high_limbs);
147 const auto& p_y_limb_2 = View(in.p_y_high_limbs);
148 const auto& accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0);
149 const auto& accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1);
150 const auto& accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2);
151 const auto& accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3);
152 const auto& z_first_limb_0 = View(in.z_low_limbs);
153 const auto& z_first_limb_1 = View(in.z_high_limbs);
154 const auto& quotient_binary_limbs_0 = View(in.quotient_low_binary_limbs);
155 const auto& quotient_binary_limbs_1 = View(in.quotient_low_binary_limbs_shift);
156 const auto& p_x_limb_1 = View(in.p_x_low_limbs_shift);
157 const auto& p_y_limb_1 = View(in.p_y_low_limbs_shift);
158 const auto& p_x_limb_3 = View(in.p_x_high_limbs_shift);
159 const auto& p_y_limb_3 = View(in.p_y_high_limbs_shift);
160 const auto& prev_accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0_shift);
161 const auto& prev_accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1_shift);
162 const auto& prev_accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2_shift);
163 const auto& prev_accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3_shift);
164 const auto& z_second_limb_0 = View(in.z_low_limbs_shift);
165 const auto& z_second_limb_1 = View(in.z_high_limbs_shift);
166 const auto& quotient_binary_limbs_2 = View(in.quotient_high_binary_limbs);
167 const auto& quotient_binary_limbs_3 = View(in.quotient_high_binary_limbs_shift);
168 const auto& relation_wide_limbs_lo = View(in.relation_wide_limbs);
169 const auto& relation_wide_limbs_hi = View(in.relation_wide_limbs_shift);
170 const auto& lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit);
171
180 // clang-format off
181 // T₀: Limb 0 contribution (all products contributing at weight 2⁰)
182 auto tmp = prev_accumulators_binary_limbs_0 * evaluation_input_x_0
183 + op
184 + p_x_limb_0 * v_0
185 + p_y_limb_0 * v_sqr_0
186 + z_first_limb_0 * v_cube_0
187 + z_second_limb_0 * v_quad_0
188 + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[0]
189 - accumulators_binary_limbs_0;
190
191 // T₁: Limb 1 contribution (all cross-products contributing at weight 2⁶⁸)
192 tmp += (prev_accumulators_binary_limbs_1 * evaluation_input_x_0
193 + prev_accumulators_binary_limbs_0 * evaluation_input_x_1
194 + p_x_limb_0 * v_1
195 + p_x_limb_1 * v_0
196 + p_y_limb_0 * v_sqr_1
197 + p_y_limb_1 * v_sqr_0
198 + z_first_limb_0 * v_cube_1
199 + z_first_limb_1 * v_cube_0
200 + z_second_limb_0 * v_quad_1
201 + z_second_limb_1 * v_quad_0
202 + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[1]
203 + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[0]
204 - accumulators_binary_limbs_1)
205 * shift ;
206 // clang-format on
207 // Subtract 2¹³⁶·c_lo: if the result is zero, lower 136 bits are correct
208 tmp -= relation_wide_limbs_lo * shiftx2;
209 tmp *= lagrange_even_in_minicircuit * op;
210 tmp *= scaling_factor;
211 std::get<0>(accumulators) += tmp;
212
222 // clang-format off
223 // T₂: Limb 2 contribution (with carry from lower 136 bits)
224 tmp = relation_wide_limbs_lo
225 + prev_accumulators_binary_limbs_2 * evaluation_input_x_0
226 + prev_accumulators_binary_limbs_1 * evaluation_input_x_1
227 + prev_accumulators_binary_limbs_0 * evaluation_input_x_2
228 + p_x_limb_2 * v_0
229 + p_x_limb_1 * v_1
230 + p_x_limb_0 * v_2
231 + p_y_limb_2 * v_sqr_0
232 + p_y_limb_1 * v_sqr_1
233 + p_y_limb_0 * v_sqr_2
234 + z_first_limb_1 * v_cube_1
235 + z_first_limb_0 * v_cube_2
236 + z_second_limb_1 * v_quad_1
237 + z_second_limb_0 * v_quad_2
238 + quotient_binary_limbs_2 * NEGATIVE_MODULUS_LIMBS[0]
239 + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[1]
240 + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[2]
241 - accumulators_binary_limbs_2;
242
243 // T₃: Limb 3 contribution (all cross-products contributing at weight 2²⁰⁴)
244 tmp += (prev_accumulators_binary_limbs_3 * evaluation_input_x_0
245 + prev_accumulators_binary_limbs_2 * evaluation_input_x_1
246 + prev_accumulators_binary_limbs_1 * evaluation_input_x_2
247 + prev_accumulators_binary_limbs_0 * evaluation_input_x_3
248 + p_x_limb_3 * v_0
249 + p_x_limb_2 * v_1
250 + p_x_limb_1 * v_2
251 + p_x_limb_0 * v_3
252 + p_y_limb_3 * v_sqr_0
253 + p_y_limb_2 * v_sqr_1
254 + p_y_limb_1 * v_sqr_2
255 + p_y_limb_0 * v_sqr_3
256 + z_first_limb_1 * v_cube_2
257 + z_first_limb_0 * v_cube_3
258 + z_second_limb_1 * v_quad_2
259 + z_second_limb_0 * v_quad_3
260 + quotient_binary_limbs_3 * NEGATIVE_MODULUS_LIMBS[0]
261 + quotient_binary_limbs_2 * NEGATIVE_MODULUS_LIMBS[1]
262 + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[2]
263 + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[3]
264 - accumulators_binary_limbs_3)
265 * shift;
266 // clang-format on
267 // Subtract 2¹³⁶·c_hi: if the result is zero, higher 136 bits are correct
268 tmp -= relation_wide_limbs_hi * shiftx2;
269 tmp *= lagrange_even_in_minicircuit * op;
270 tmp *= scaling_factor;
271 std::get<1>(accumulators) += tmp;
272
273 // Helper functions to reconstruct field elements from limbs
274 const auto reconstruct_from_two = [](const auto& l0, const auto& l1) { return l0 + l1 * shift; };
275
276 const auto reconstruct_from_four = [](const auto& l0, const auto& l1, const auto& l2, const auto& l3) {
277 return l0 + l1 * shift + l2 * shiftx2 + l3 * shiftx3;
278 };
279
280 // Reconstruct native 𝔽ᵣ representations from binary limbs
281 auto reconstructed_p_x = reconstruct_from_four(p_x_limb_0, p_x_limb_1, p_x_limb_2, p_x_limb_3);
282 auto reconstructed_p_y = reconstruct_from_four(p_y_limb_0, p_y_limb_1, p_y_limb_2, p_y_limb_3);
283 auto reconstructed_previous_accumulator = reconstruct_from_four(prev_accumulators_binary_limbs_0,
284 prev_accumulators_binary_limbs_1,
285 prev_accumulators_binary_limbs_2,
286 prev_accumulators_binary_limbs_3);
287 auto reconstructed_current_accumulator = reconstruct_from_four(accumulators_binary_limbs_0,
288 accumulators_binary_limbs_1,
289 accumulators_binary_limbs_2,
290 accumulators_binary_limbs_3);
291 auto reconstructed_z1 = reconstruct_from_two(z_first_limb_0, z_first_limb_1);
292 auto reconstructed_z2 = reconstruct_from_two(z_second_limb_0, z_second_limb_1);
293 auto reconstructed_quotient = reconstruct_from_four(
294 quotient_binary_limbs_0, quotient_binary_limbs_1, quotient_binary_limbs_2, quotient_binary_limbs_3);
295
304 // clang-format off
305 // Compute accumulation formula using native 𝔽ᵣ arithmetic (limb index 4)
306 tmp = reconstructed_previous_accumulator * evaluation_input_x_4
307 + op
308 + reconstructed_p_x * v_4
309 + reconstructed_p_y * v_sqr_4
310 + reconstructed_z1 * v_cube_4
311 + reconstructed_z2 * v_quad_4
312 + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4]
313 - reconstructed_current_accumulator;
314 // clang-format on
315 tmp *= lagrange_even_in_minicircuit * op;
316 tmp *= scaling_factor;
317 std::get<2>(accumulators) += tmp;
318};
319} // namespace bb
bb::field< bb::Bn254FrParams > FF
Definition field.cpp:24
static void accumulate(ContainerOverSubrelations &accumulators, const AllEntities &in, const Parameters &params, const FF &scaling_factor)
Expression for the computation of Translator accumulator in integers through 68-bit limbs and native ...
constexpr uintx slice(const uint64_t start, const uint64_t end) const
Definition uintx.hpp:82
uintx< uint256_t > uint512_t
Definition uintx.hpp:307
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr uint256_t modulus