Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bigint_constraint.cpp
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
12#include <cstddef>
13#include <cstdint>
14
15namespace acir_format {
16
17using namespace bb;
18
20{
24 }
28 }
32 }
36 }
40 }
44 }
45 return ModulusId::UNKNOWN;
46}
47
50 bool has_valid_witness_assignments);
53 bool has_valid_witness_assignments);
68 bool has_valid_witness_assignments);
71 bool has_valid_witness_assignments);
72
73template <typename Builder>
75{
76 switch (dsl_bigint.get_modulus_id(input.lhs)) {
78 auto lhs = dsl_bigint.bn254_fr(input.lhs);
79 auto rhs = dsl_bigint.bn254_fr(input.rhs);
80 dsl_bigint.set_bn254_fr(lhs + rhs, input.result);
81 break;
82 }
84 auto lhs = dsl_bigint.bn254_fq(input.lhs);
85 auto rhs = dsl_bigint.bn254_fq(input.rhs);
86 dsl_bigint.set_bn254_fq(lhs + rhs, input.result);
87 break;
88 }
90 auto lhs = dsl_bigint.secp256k1_fq(input.lhs);
91 auto rhs = dsl_bigint.secp256k1_fq(input.rhs);
92 dsl_bigint.set_secp256k1_fq(lhs + rhs, input.result);
93 break;
94 }
96 auto lhs = dsl_bigint.secp256k1_fr(input.lhs);
97 auto rhs = dsl_bigint.secp256k1_fr(input.rhs);
98 dsl_bigint.set_secp256k1_fr(lhs + rhs, input.result);
99 break;
100 }
102 auto lhs = dsl_bigint.secp256r1_fq(input.lhs);
103 auto rhs = dsl_bigint.secp256r1_fq(input.rhs);
104 dsl_bigint.set_secp256r1_fq(lhs + rhs, input.result);
105 break;
106 }
108 auto lhs = dsl_bigint.secp256r1_fr(input.lhs);
109 auto rhs = dsl_bigint.secp256r1_fr(input.rhs);
110 dsl_bigint.set_secp256r1_fr(lhs + rhs, input.result);
111 break;
112 }
113 default: {
114 throw_or_abort("Unexpected Modulus ID");
115 }
116 }
117}
118
119template <typename Builder>
121{
122 switch (dsl_bigint.get_modulus_id(input.lhs)) {
123 case ModulusId::BN254_FR: {
124 auto lhs = dsl_bigint.bn254_fr(input.lhs);
125 auto rhs = dsl_bigint.bn254_fr(input.rhs);
126 dsl_bigint.set_bn254_fr(lhs - rhs, input.result);
127 break;
128 }
129 case ModulusId::BN254_FQ: {
130 auto lhs = dsl_bigint.bn254_fq(input.lhs);
131 auto rhs = dsl_bigint.bn254_fq(input.rhs);
132 dsl_bigint.set_bn254_fq(lhs - rhs, input.result);
133 break;
134 }
136 auto lhs = dsl_bigint.secp256k1_fq(input.lhs);
137 auto rhs = dsl_bigint.secp256k1_fq(input.rhs);
138 dsl_bigint.set_secp256k1_fq(lhs - rhs, input.result);
139 break;
140 }
142 auto lhs = dsl_bigint.secp256k1_fr(input.lhs);
143 auto rhs = dsl_bigint.secp256k1_fr(input.rhs);
144 dsl_bigint.set_secp256k1_fr(lhs - rhs, input.result);
145 break;
146 }
148 auto lhs = dsl_bigint.secp256r1_fq(input.lhs);
149 auto rhs = dsl_bigint.secp256r1_fq(input.rhs);
150 dsl_bigint.set_secp256r1_fq(lhs - rhs, input.result);
151 break;
152 }
154 auto lhs = dsl_bigint.secp256r1_fr(input.lhs);
155 auto rhs = dsl_bigint.secp256r1_fr(input.rhs);
156 dsl_bigint.set_secp256r1_fr(lhs - rhs, input.result);
157 break;
158 }
159 default: {
160 throw_or_abort("Unexpected Modulus ID");
161 }
162 }
163}
164
165template <typename Builder>
167{
168 switch (dsl_bigint.get_modulus_id(input.lhs)) {
169 case ModulusId::BN254_FR: {
170 auto lhs = dsl_bigint.bn254_fr(input.lhs);
171 auto rhs = dsl_bigint.bn254_fr(input.rhs);
172 dsl_bigint.set_bn254_fr(lhs * rhs, input.result);
173 break;
174 }
175 case ModulusId::BN254_FQ: {
176 auto lhs = dsl_bigint.bn254_fq(input.lhs);
177 auto rhs = dsl_bigint.bn254_fq(input.rhs);
178 dsl_bigint.set_bn254_fq(lhs * rhs, input.result);
179 break;
180 }
182 auto lhs = dsl_bigint.secp256k1_fq(input.lhs);
183 auto rhs = dsl_bigint.secp256k1_fq(input.rhs);
184 dsl_bigint.set_secp256k1_fq(lhs * rhs, input.result);
185 break;
186 }
188 auto lhs = dsl_bigint.secp256k1_fr(input.lhs);
189 auto rhs = dsl_bigint.secp256k1_fr(input.rhs);
190 dsl_bigint.set_secp256k1_fr(lhs * rhs, input.result);
191 break;
192 }
194 auto lhs = dsl_bigint.secp256r1_fq(input.lhs);
195 auto rhs = dsl_bigint.secp256r1_fq(input.rhs);
196 dsl_bigint.set_secp256r1_fq(lhs * rhs, input.result);
197 break;
198 }
200 auto lhs = dsl_bigint.secp256r1_fr(input.lhs);
201 auto rhs = dsl_bigint.secp256r1_fr(input.rhs);
202 dsl_bigint.set_secp256r1_fr(lhs * rhs, input.result);
203 break;
204 }
205 default: {
206 throw_or_abort("Unexpected Modulus ID");
207 }
208 }
209}
210
211template <typename Builder>
213 DSLBigInts<Builder>& dsl_bigint,
214 bool has_valid_witness_assignments)
215{
216 if (!has_valid_witness_assignments) {
217 // Asserts catch the case where the divisor is zero, so we need to provide a different value (1) to avoid the
218 // assert
219 std::array<uint32_t, 5> limbs_idx;
220 dsl_bigint.get_witness_idx_of_limbs(input.rhs, limbs_idx);
221 dsl_bigint.set_value(1, limbs_idx);
222 }
223
224 switch (dsl_bigint.get_modulus_id(input.lhs)) {
225 case ModulusId::BN254_FR: {
226 auto lhs = dsl_bigint.bn254_fr(input.lhs);
227 auto rhs = dsl_bigint.bn254_fr(input.rhs);
228 dsl_bigint.set_bn254_fr(lhs / rhs, input.result);
229 break;
230 }
231 case ModulusId::BN254_FQ: {
232 auto lhs = dsl_bigint.bn254_fq(input.lhs);
233 auto rhs = dsl_bigint.bn254_fq(input.rhs);
234 dsl_bigint.set_bn254_fq(lhs / rhs, input.result);
235 break;
236 }
238 auto lhs = dsl_bigint.secp256k1_fq(input.lhs);
239 auto rhs = dsl_bigint.secp256k1_fq(input.rhs);
240 dsl_bigint.set_secp256k1_fq(lhs / rhs, input.result);
241 break;
242 }
244 auto lhs = dsl_bigint.secp256k1_fr(input.lhs);
245 auto rhs = dsl_bigint.secp256k1_fr(input.rhs);
246 dsl_bigint.set_secp256k1_fr(lhs / rhs, input.result);
247 break;
248 }
250 auto lhs = dsl_bigint.secp256r1_fq(input.lhs);
251 auto rhs = dsl_bigint.secp256r1_fq(input.rhs);
252 dsl_bigint.set_secp256r1_fq(lhs / rhs, input.result);
253 break;
254 }
256 auto lhs = dsl_bigint.secp256r1_fr(input.lhs);
257 auto rhs = dsl_bigint.secp256r1_fr(input.rhs);
258 dsl_bigint.set_secp256r1_fr(lhs / rhs, input.result);
259 break;
260 }
261 default: {
262 throw_or_abort("Unexpected Modulus ID");
263 }
264 }
265}
266
267template <typename Builder>
269 DSLBigInts<Builder>& dsl_bigint,
270 bool has_valid_witness_assignments)
271{
272 switch (input.opcode) {
274 create_bigint_addition_constraint<Builder>(input, dsl_bigint);
275 break;
276 }
278 create_bigint_sub_constraint<Builder>(input, dsl_bigint);
279 break;
280 }
282 create_bigint_mul_constraint<Builder>(input, dsl_bigint);
283 break;
284 }
286 create_bigint_div_constraint<Builder>(input, dsl_bigint, has_valid_witness_assignments);
287 break;
288 }
289 default: {
290 throw_or_abort("Unexpected BigIntOperationType");
291 }
292 }
293}
294
295template <typename Builder>
297 const BigIntFromLeBytes& input,
298 DSLBigInts<Builder>& dsl_bigints)
299{
308
309 // Construct the modulus from its bytes
310 uint64_t modulus_64 = 0;
311 uint64_t base = 1;
312 std::vector<uint64_t> modulus_limbs;
313 for (std::size_t i = 0; i < 32; ++i) {
314 if (i < input.modulus.size()) {
315 modulus_64 += input.modulus[i] * base;
316 base = base * 256;
317 if ((i + 1) % 8 == 0) {
318 modulus_limbs.push_back(modulus_64);
319 modulus_64 = 0;
320 base = 1;
321 }
322 }
323 }
324 auto modulus = ModulusParam{ .modulus_0 = modulus_limbs[0],
325 .modulus_1 = modulus_limbs[1],
326 .modulus_2 = modulus_limbs[2],
327 .modulus_3 = modulus_limbs[3] };
329 for (size_t i = 0; i < 32; ++i) {
330 if (i < input.inputs.size()) {
332 byte_array_ct element_bytes(element, 1);
333 rev_bytes.write_at(element_bytes, i);
334 } else {
335 rev_bytes[i] = 0;
336 }
337 }
338 bb::stdlib::byte_array<Builder> bytes = rev_bytes.reverse();
339
340 auto modulus_id = modulus_param_to_id(modulus);
341
342 switch (modulus_id) {
343 case BN254_FQ: {
344 auto big = big_bn254_fq(bytes);
345 dsl_bigints.set_bn254_fq(big, input.result);
346 break;
347 }
348 case BN254_FR: {
349 auto big = big_bn254_fr(bytes);
350 dsl_bigints.set_bn254_fr(big, input.result);
351 break;
352 }
353 case SECP256K1_FQ: {
354 auto big = big_secp256k1_fq(bytes);
355 dsl_bigints.set_secp256k1_fq(big, input.result);
356 break;
357 }
358 case SECP256K1_FR: {
359 auto big = big_secp256k1_fr(bytes);
360 dsl_bigints.set_secp256k1_fr(big, input.result);
361 break;
362 }
363 case SECP256R1_FQ: {
364 auto big = big_secp256r1_fq(bytes);
365 dsl_bigints.set_secp256r1_fq(big, input.result);
366 break;
367 }
368 case SECP256R1_FR: {
369 auto big = big_secp256r1_fr(bytes);
370 dsl_bigints.set_secp256r1_fr(big, input.result);
371 break;
372 }
373 case UNKNOWN:
374 default:
375 throw_or_abort("Unexpected Modulus ID");
376 break;
377 }
378}
379
380template <typename Builder>
382 const BigIntToLeBytes& input,
383 DSLBigInts<Builder>& dsl_bigints)
384{
391
392 auto modulus_id = dsl_bigints.get_modulus_id(input.input);
394 switch (modulus_id) {
395 case BN254_FQ: {
396 big_bn254_fq big = dsl_bigints.bn254_fq(input.input);
397 big.self_reduce();
398 byte_array = big.to_byte_array();
399
400 break;
401 }
402 case BN254_FR: {
403 big_bn254_fr big = dsl_bigints.bn254_fr(input.input);
404 big.self_reduce();
405 byte_array = big.to_byte_array();
406 break;
407 }
408 case SECP256K1_FQ: {
409 big_secp256k1_fq big = dsl_bigints.secp256k1_fq(input.input);
410 big.self_reduce();
411 byte_array = big.to_byte_array();
412 break;
413 }
414 case SECP256K1_FR: {
415 big_secp256k1_fr big = dsl_bigints.secp256k1_fr(input.input);
416 big.self_reduce();
417 byte_array = big.to_byte_array();
418 break;
419 }
420 case SECP256R1_FQ: {
421 big_secp256r1_fq big = dsl_bigints.secp256r1_fq(input.input);
422 big.self_reduce();
423 byte_array = big.to_byte_array();
424 break;
425 }
426 case SECP256R1_FR: {
427 big_secp256r1_fr big = dsl_bigints.secp256r1_fr(input.input);
428 big.self_reduce();
429 byte_array = big.to_byte_array();
430 break;
431 }
432 case UNKNOWN:
433 default:
434 throw_or_abort("Unexpected Modulus ID");
435 break;
436 }
438 BB_ASSERT_LTE(input.result.size(), byte_array.size());
439 for (size_t i = 0; i < byte_array.size(); ++i) {
440 if (i < input.result.size()) {
441
442 // This should instead use assert_equal: builder.assert_equal(byte_array[i].normalize().witness_index,
443 // input.result[i]); but unit tests require this because they do not constraint the witness, and then if we
444 // use assert_equal in that case, we can generate a proof for non matching values (cf test_assert_equal in
445 // field.test.cpp). We should check that Noir always constraint the results of to_bytes
446 poly_triple assert_equal{
447 .a = byte_array[i].normalize().witness_index,
448 .b = input.result[i],
449 .c = 0,
450 .q_m = 0,
451 .q_l = 1,
452 .q_r = -1,
453 .q_o = 0,
454 .q_c = 0,
455 };
456 builder.create_poly_gate(assert_equal);
457 } else {
458 byte_array[i].normalize().is_zero();
459 }
460 }
461}
462
464 const BigIntFromLeBytes& input,
467 const BigIntFromLeBytes& input,
468 DSLBigInts<MegaCircuitBuilder>& dsl_bigints);
470 const BigIntToLeBytes& input,
472
474 const BigIntToLeBytes& input,
475 DSLBigInts<MegaCircuitBuilder>& dsl_bigints);
476
477} // namespace acir_format
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:129
ModulusId get_modulus_id(uint32_t bigint_id)
big_secp256k1_fr secp256k1_fr(uint32_t bigint_id)
void set_secp256r1_fq(const big_secp256r1_fq &bigint, uint32_t bigint_id)
big_secp256r1_fq secp256r1_fq(uint32_t bigint_id)
big_bn254_fr bn254_fr(uint32_t bigint_id)
void set_secp256k1_fr(const big_secp256k1_fr &bigint, uint32_t bigint_id)
big_secp256r1_fr secp256r1_fr(uint32_t bigint_id)
big_bn254_fq bn254_fq(uint32_t bigint_id)
void set_secp256r1_fr(const big_secp256r1_fr &bigint, uint32_t bigint_id)
void set_value(uint256_t value, const std::array< uint32_t, 5 > limbs_idx)
void get_witness_idx_of_limbs(uint32_t bigint_id, std::array< uint32_t, 5 > &limbs_idx)
void set_bn254_fr(const big_bn254_fr &bigint, uint32_t bigint_id)
big_secp256k1_fq secp256k1_fq(uint32_t bigint_id)
void set_secp256k1_fq(const big_secp256k1_fq &bigint, uint32_t bigint_id)
void set_bn254_fq(const big_bn254_fq &bigint, uint32_t bigint_id)
static constexpr uint64_t modulus_0
Definition fq.hpp:24
static constexpr uint64_t modulus_3
Definition fq.hpp:27
static constexpr uint64_t modulus_1
Definition fq.hpp:25
static constexpr uint64_t modulus_2
Definition fq.hpp:26
static constexpr uint64_t modulus_0
Definition fr.hpp:28
static constexpr uint64_t modulus_3
Definition fr.hpp:31
static constexpr uint64_t modulus_2
Definition fr.hpp:30
static constexpr uint64_t modulus_1
Definition fr.hpp:29
Represents a dynamic array of bytes in-circuit.
byte_array reverse() const
Reverse the bytes in the byte array.
byte_array & write_at(byte_array const &other, size_t index)
Overwrites this byte_array starting at index with the contents of other. Asserts that the write does ...
size_t size() const
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:59
AluTraceBuilder builder
Definition alu.test.cpp:123
template void create_bigint_sub_constraint< UltraCircuitBuilder >(const BigIntOperation &input, DSLBigInts< UltraCircuitBuilder > &dsl_bigint)
template void create_bigint_addition_constraint< UltraCircuitBuilder >(const BigIntOperation &input, DSLBigInts< UltraCircuitBuilder > &dsl_bigint)
void create_bigint_div_constraint(const BigIntOperation &input, DSLBigInts< Builder > &dsl_bigint, bool has_valid_witness_assignments)
ModulusId modulus_param_to_id(ModulusParam param)
template void create_bigint_from_le_bytes_constraint< UltraCircuitBuilder >(UltraCircuitBuilder &builder, const BigIntFromLeBytes &input, DSLBigInts< UltraCircuitBuilder > &dsl_bigints)
void create_bigint_sub_constraint(const BigIntOperation &input, DSLBigInts< Builder > &dsl_bigint)
template void create_bigint_operations_constraint< UltraCircuitBuilder >(const BigIntOperation &input, DSLBigInts< UltraCircuitBuilder > &dsl_bigint, bool has_valid_witness_assignments)
void create_bigint_from_le_bytes_constraint(Builder &builder, const BigIntFromLeBytes &input, DSLBigInts< Builder > &dsl_bigints)
template void create_bigint_div_constraint< UltraCircuitBuilder >(const BigIntOperation &input, DSLBigInts< UltraCircuitBuilder > &dsl_bigint, bool has_valid_witness_assignments)
template void create_bigint_addition_constraint< MegaCircuitBuilder >(const BigIntOperation &input, DSLBigInts< MegaCircuitBuilder > &dsl_bigint)
template void create_bigint_sub_constraint< MegaCircuitBuilder >(const BigIntOperation &input, DSLBigInts< MegaCircuitBuilder > &dsl_bigint)
template void create_bigint_from_le_bytes_constraint< MegaCircuitBuilder >(MegaCircuitBuilder &builder, const BigIntFromLeBytes &input, DSLBigInts< MegaCircuitBuilder > &dsl_bigints)
template void create_bigint_div_constraint< MegaCircuitBuilder >(const BigIntOperation &input, DSLBigInts< MegaCircuitBuilder > &dsl_bigint, bool has_valid_witness_assignments)
void create_bigint_addition_constraint(const BigIntOperation &input, DSLBigInts< Builder > &dsl_bigint)
void create_bigint_to_le_bytes_constraint(Builder &builder, const BigIntToLeBytes &input, DSLBigInts< Builder > &dsl_bigints)
template void create_bigint_mul_constraint< UltraCircuitBuilder >(const BigIntOperation &input, DSLBigInts< UltraCircuitBuilder > &dsl_bigint)
template void create_bigint_operations_constraint< MegaCircuitBuilder >(const BigIntOperation &input, DSLBigInts< MegaCircuitBuilder > &dsl_bigint, bool has_valid_witness_assignments)
template void create_bigint_mul_constraint< MegaCircuitBuilder >(const BigIntOperation &input, DSLBigInts< MegaCircuitBuilder > &dsl_bigint)
template void create_bigint_to_le_bytes_constraint< MegaCircuitBuilder >(MegaCircuitBuilder &builder, const BigIntToLeBytes &input, DSLBigInts< MegaCircuitBuilder > &dsl_bigints)
void create_bigint_mul_constraint(const BigIntOperation &input, DSLBigInts< Builder > &dsl_bigint)
void create_bigint_operations_constraint(const BigIntOperation &input, DSLBigInts< Builder > &dsl_bigint, bool has_valid_witness_assignments)
template void create_bigint_to_le_bytes_constraint< UltraCircuitBuilder >(UltraCircuitBuilder &builder, const BigIntToLeBytes &input, DSLBigInts< UltraCircuitBuilder > &dsl_bigints)
std::conditional_t< IsGoblinBigGroup< C, Fq, Fr, G >, element_goblin::goblin_element< C, goblin_field< C >, Fr, G >, element_default::element< C, Fq, Fr, G > > element
element wraps either element_default::element or element_goblin::goblin_element depending on parametr...
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< uint32_t > modulus
std::vector< uint32_t > result
static constexpr uint64_t modulus_0
Definition secp256k1.hpp:21
static constexpr uint64_t modulus_1
Definition secp256k1.hpp:22
static constexpr uint64_t modulus_2
Definition secp256k1.hpp:23
static constexpr uint64_t modulus_3
Definition secp256k1.hpp:24
static constexpr uint64_t modulus_0
static constexpr uint64_t modulus_3
static constexpr uint64_t modulus_1
static constexpr uint64_t modulus_2
static constexpr uint64_t modulus_3
Definition secp256r1.hpp:19
static constexpr uint64_t modulus_2
Definition secp256r1.hpp:18
static constexpr uint64_t modulus_0
Definition secp256r1.hpp:16
static constexpr uint64_t modulus_1
Definition secp256r1.hpp:17
static constexpr uint64_t modulus_2
static constexpr uint64_t modulus_1
static constexpr uint64_t modulus_3
static constexpr uint64_t modulus_0
void throw_or_abort(std::string const &err)