2#include "barretenberg/ecc/curves/bn254/fq.hpp"
3#include "barretenberg/numeric/random/engine.hpp"
4#include "barretenberg/numeric/uint256/uint256.hpp"
5#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp"
6#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp"
7#pragma clang diagnostic push
9#pragma clang diagnostic ignored "-Wc99-designator"
12bool circuit_should_fail =
false;
16#include "barretenberg/common/fuzzer.hpp"
23#ifdef SHOW_INFORMATION
24#define PRINT_SINGLE_ARG_INSTRUCTION(first_index, vector, operation_name, preposition) \
26 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
27 << vector[first_index].bigfield.get_value() << ") at " << first_index << " " << preposition \
31#define PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, vector, operation_name, preposition) \
33 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
34 << vector[first_index].bigfield.get_value() << ") at " << first_index << " " << preposition << " " \
35 << (vector[second_index].bigfield.is_constant() ? "constant(" : "witness(") \
36 << vector[second_index].bigfield.get_value() << ") at " << second_index << std::flush; \
39#define PRINT_THREE_ARG_INSTRUCTION( \
40 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2) \
42 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
43 << vector[first_index].bigfield.get_value() << ") at " << first_index << " " << preposition1 << " " \
44 << (vector[second_index].bigfield.is_constant() ? "constant(" : "witness(") \
45 << vector[second_index].bigfield.get_value() << ") at " << second_index << " " << preposition2 \
46 << " " << (vector[third_index].bigfield.is_constant() ? "constant(" : "witness(") \
47 << vector[third_index].bigfield.get_value() << ") at " << third_index << std::flush; \
49#define PRINT_TWO_ARG_ONE_VALUE_INSTRUCTION( \
50 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2) \
52 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
53 << vector[first_index].bigfield.get_value() << ":" << vector[first_index].suint.current_max \
54 << ") at " << first_index << " " << preposition1 << " " \
55 << (vector[second_index].bigfield.is_constant() ? "constant(" : "witness(") \
56 << vector[second_index].bigfield.get_value() << ":" << vector[second_index].suint.current_max \
57 << ") at " << second_index << " " << preposition2 << " " << third_index << std::flush; \
60#define PRINT_TWO_ARG_TWO_VALUES_INSTRUCTION( \
61 first_index, second_index, value1, value2, vector, operation_name, preposition1, preposition2, preposition3) \
63 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
64 << vector[first_index].bigfield.get_value() << ") at " << first_index << " " << preposition1 << " " \
65 << (vector[second_index].bigfield.is_constant() ? "constant(" : "witness(") \
66 << vector[second_index].bigfield.get_value() << ") at " << second_index << " " << preposition2 \
67 << " " << value1 << preposition3 << value2 << std::flush; \
70#define PRINT_SLICE(first_index, lsb, msb, vector) \
72 std::cout << "Slice:" \
73 << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
74 << vector[first_index].bigfield.get_value() << ":" << vector[first_index].suint.current_max \
75 << ") at " << first_index << " " \
76 << "(" << (size_t)lsb << ":" << (size_t)msb << ")" << std::flush; \
79#define PRINT_RESULT(prefix, action, index, value) \
81 std::cout << " result(" << value.bigfield.get_value() << ")" << action << index << std::endl << std::flush; \
86#define PRINT_SINGLE_ARG_INSTRUCTION(first_index, vector, operation_name, preposition)
87#define PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, vector, operation_name, preposition)
89#define PRINT_TWO_ARG_ONE_VALUE_INSTRUCTION( \
90 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2)
91#define PRINT_TWO_ARG_TWO_VALUES_INSTRUCTION( \
92 first_index, second_index, value1, value2, vector, operation_name, preposition1, preposition2, preposition3)
94#define PRINT_THREE_ARG_INSTRUCTION( \
95 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2)
96#define PRINT_RESULT(prefix, action, index, value)
98#define PRINT_SLICE(first_index, lsb, msb, vector)
101#define OPERATION_TYPE_SIZE 1
103#define ELEMENT_SIZE (sizeof(fq) + 1)
104#define TWO_IN_ONE_OUT 3
105#define THREE_IN_ONE_OUT 4
106#define SLICE_ARGS_SIZE 6
108#define MSUB_DIV_MINIMUM_MUL_PAIRS 1
109#define MSUB_DIV_MAXIMUM_MUL_PAIRS 8
110#define MSUB_DIV_MINIMUM_SUBTRACTED_ELEMENTS 0
111#define MSUB_DIV_MAXIMUM_SUBTRACTED_ELEMENTS 8
112#define MULT_MADD_MINIMUM_MUL_PAIRS 1
113#define MULT_MADD_MAXIMUM_MUL_PAIRS 8
114#define MULT_MADD_MINIMUM_ADDED_ELEMENTS 0
115#define MULT_MADD_MAXIMUM_ADDED_ELEMENTS 8
116#define SQR_ADD_MINIMUM_ADDED_ELEMENTS 0
117#define SQR_ADD_MAXIMUM_ADDED_ELEMENTS 8
144#ifndef DISABLE_DIVISION
191 uint8_t add_elements[MULT_MADD_MAXIMUM_ADDED_ELEMENTS];
192 uint8_t add_elements_count = 0;
194 uint8_t output_index;
197 uint8_t mult_pairs[MULT_MADD_MAXIMUM_MUL_PAIRS * 2];
198 uint8_t add_elements[MULT_MADD_MAXIMUM_ADDED_ELEMENTS];
199 uint8_t mult_pairs_count = 1;
200 uint8_t add_elements_count = 0;
201 uint8_t divisor_index;
202 uint8_t output_index;
239 template <
typename T>
244 OPCODE instruction_opcode =
static_cast<OPCODE
>(rng.next() % (OPCODE::_LAST));
245 uint8_t in1, in2, in3, out, mask_size, mult_size, add_size;
248 uint8_t mult_pairs[MULT_MADD_MAXIMUM_MUL_PAIRS * 2] = { 0 };
249 uint8_t add_elements[MULT_MADD_MAXIMUM_ADDED_ELEMENTS > SQR_ADD_MAXIMUM_ADDED_ELEMENTS
250 ? MULT_MADD_MAXIMUM_ADDED_ELEMENTS
251 : SQR_ADD_MAXIMUM_ADDED_ELEMENTS] = { 0 };
254 switch (instruction_opcode) {
255 case OPCODE::CONSTANT:
256 case OPCODE::WITNESS:
257 case OPCODE::CONSTANT_WITNESS:
260 for (
size_t i = 0; i < (
sizeof(
uint256_t) >> 1); i++) {
261 *(((uint16_t*)&temp) + i) =
static_cast<uint16_t
>(rng.next() & 0xffff);
265 mask_size =
static_cast<uint8_t
>(rng.next() & 0xff);
269 return { .id = instruction_opcode, .arguments.element =
Element(
static_cast<uint64_t
>(temp & mask)) };
272 case OPCODE::RANDOMSEED:
273 return { .id = instruction_opcode, .arguments.randomseed = rng.next() };
276 case OPCODE::ASSERT_EQUAL:
277 case OPCODE::ASSERT_NOT_EQUAL:
279 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
280 out =
static_cast<uint8_t
>(rng.next() & 0xff);
281 return { .id = instruction_opcode, .arguments.twoArgs = { .in = in1, .out = out } };
284 case OPCODE::SUBTRACT:
285 case OPCODE::MULTIPLY:
286#ifndef DISABLE_DIVISION
289 case OPCODE::COND_NEGATE:
292 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
293 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
294 out =
static_cast<uint8_t
>(rng.next() & 0xff);
295 return { .id = instruction_opcode, .arguments.threeArgs = { .in1 = in1, .in2 = in2, .out = out } };
297 case OPCODE::ADD_TWO:
299 case OPCODE::COND_SELECT:
302 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
303 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
304 in3 =
static_cast<uint8_t
>(rng.next() & 0xff);
305 out =
static_cast<uint8_t
>(rng.next() & 0xff);
306 return { .id = instruction_opcode,
307 .arguments.fourArgs{ .in1 = in1, .in2 = in2, .in3 = in3, .out = out } };
309 case OPCODE::MSUB_DIV:
310 instr.arguments.multOpArgs.divisor_index =
static_cast<uint8_t
>(rng.next() & 0xff);
311 case OPCODE::MULT_MADD:
313 MULT_MADD_MINIMUM_MUL_PAIRS +
314 static_cast<uint8_t
>(rng.next() % (MULT_MADD_MAXIMUM_MUL_PAIRS - MULT_MADD_MINIMUM_MUL_PAIRS));
315 add_size = MULT_MADD_MINIMUM_ADDED_ELEMENTS +
316 static_cast<uint8_t
>(rng.next() %
317 (MULT_MADD_MAXIMUM_ADDED_ELEMENTS - MULT_MADD_MINIMUM_ADDED_ELEMENTS));
319 for (
size_t i = 0; i < mult_size; i++) {
320 mult_pairs[i * 2] =
static_cast<uint8_t
>(rng.next() & 0xff);
321 mult_pairs[i * 2 + 1] =
static_cast<uint8_t
>(rng.next() & 0xff);
323 for (
size_t i = 0; i < add_size; i++) {
324 add_elements[i] =
static_cast<uint8_t
>(rng.next() & 0xff);
326 instr.id = instruction_opcode;
327 memcpy(instr.arguments.multOpArgs.mult_pairs, mult_pairs, 2 * MULT_MADD_MAXIMUM_MUL_PAIRS);
328 memcpy(instr.arguments.multOpArgs.add_elements, add_elements, MULT_MADD_MAXIMUM_ADDED_ELEMENTS);
329 instr.arguments.multOpArgs.add_elements_count = add_size;
330 instr.arguments.multOpArgs.mult_pairs_count = mult_size;
332 instr.arguments.multOpArgs.output_index =
static_cast<uint8_t
>(rng.next() & 0xff);
335 case OPCODE::SQR_ADD:
336 add_size = SQR_ADD_MINIMUM_ADDED_ELEMENTS +
337 static_cast<uint8_t
>(rng.next() %
338 (SQR_ADD_MAXIMUM_ADDED_ELEMENTS - SQR_ADD_MINIMUM_ADDED_ELEMENTS));
340 for (
size_t i = 0; i < add_size; i++) {
341 add_elements[i] =
static_cast<uint8_t
>(rng.next() & 0xff);
343 instr.id = instruction_opcode;
344 memcpy(instr.arguments.multAddArgs.add_elements, add_elements, SQR_ADD_MAXIMUM_ADDED_ELEMENTS);
345 instr.arguments.multAddArgs.add_elements_count = add_size;
347 instr.arguments.multAddArgs.input_index =
static_cast<uint8_t
>(rng.next() & 0xff);
348 instr.arguments.multAddArgs.output_index =
static_cast<uint8_t
>(rng.next() & 0xff);
366 template <
typename T>
373 bool convert_to_montgomery = (rng.next() % (havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY +
374 havoc_config.VAL_MUT_NON_MONTGOMERY_PROBABILITY)) <
375 havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY;
378#define MONT_CONVERSION \
379 if (convert_to_montgomery) { \
380 value_data = uint256_t(e.to_montgomery_form()); \
382 value_data = uint256_t(e); \
385#define INV_MONT_CONVERSION \
386 if (convert_to_montgomery) { \
387 e = fq(value_data).from_montgomery_form(); \
389 e = fq(value_data); \
393 const size_t mutation_type_count = havoc_config.value_mutation_distribution.size();
395 const size_t choice = rng.next() % havoc_config.value_mutation_distribution[mutation_type_count - 1];
396 if (choice < havoc_config.value_mutation_distribution[0]) {
401 }
else if (choice < havoc_config.value_mutation_distribution[1]) {
403 if (convert_to_montgomery) {
404 e = e.to_montgomery_form();
406 if (rng.next() & 1) {
407 value_data = e +
fq(rng.next() & 0xff);
409 value_data = e -
fq(rng.next() & 0xff);
411 if (convert_to_montgomery) {
412 e = e.from_montgomery_form();
417 switch (rng.next() % 9) {
428 e = fq::one().sqrt().second;
431 e = fq::one().sqrt().second.invert();
434 e = fq::get_root_of_unity(8);
440 e =
fq((fq::modulus - 1) / 2);
443 e =
fq((fr::modulus));
463 template <
typename T>
467#define PUT_RANDOM_BYTE_IF_LUCKY(variable) \
468 if (rng.next() & 1) { \
469 variable = rng.next() & 0xff; \
472 switch (instruction.id) {
473 case OPCODE::CONSTANT:
474 case OPCODE::WITNESS:
475 case OPCODE::CONSTANT_WITNESS:
478 if (rng.next() & 1) {
479 instruction.arguments.element.value =
484 case OPCODE::ASSERT_EQUAL:
485 case OPCODE::ASSERT_NOT_EQUAL:
487 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.twoArgs.in)
488 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.twoArgs.out)
491#ifndef DISABLE_DIVISION
494 case OPCODE::MULTIPLY:
495 case OPCODE::SUBTRACT:
496 case OPCODE::COND_NEGATE:
498 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.threeArgs.in1)
499 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.threeArgs.in2)
500 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.threeArgs.out)
502 case OPCODE::ADD_TWO:
504 case OPCODE::COND_SELECT:
506 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fourArgs.in1)
507 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fourArgs.in2)
508 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fourArgs.in3)
509 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fourArgs.out)
511 case OPCODE::MSUB_DIV:
512 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.multOpArgs.divisor_index)
513 case OPCODE::MULT_MADD:
514 if (rng.next() & 1) {
516 instruction.arguments.multOpArgs.mult_pairs_count =
517 MULT_MADD_MINIMUM_MUL_PAIRS +
518 static_cast<uint8_t
>(rng.next() % (MULT_MADD_MAXIMUM_MUL_PAIRS - MULT_MADD_MINIMUM_MUL_PAIRS));
520 if (rng.next() & 1) {
522 instruction.arguments.multOpArgs.add_elements_count =
523 MULT_MADD_MINIMUM_ADDED_ELEMENTS +
524 static_cast<uint8_t
>(rng.next() %
525 (MULT_MADD_MAXIMUM_ADDED_ELEMENTS - MULT_MADD_MINIMUM_ADDED_ELEMENTS));
527 if (instruction.arguments.multOpArgs.mult_pairs_count && rng.next() & 1) {
529 size_t mut_count =
static_cast<uint8_t
>(
530 rng.next() % (2 * (size_t)instruction.arguments.multOpArgs.mult_pairs_count));
532 for (
size_t i = 0; i < mut_count; i++) {
533 auto ind = rng.next() % (2 * (size_t)instruction.arguments.multOpArgs.mult_pairs_count);
534 instruction.arguments.multOpArgs.mult_pairs[ind] =
static_cast<uint8_t
>(rng.next() & 0xff);
537 if (instruction.arguments.multOpArgs.add_elements_count && rng.next() & 1) {
539 size_t add_mut_count =
static_cast<uint8_t
>(
540 rng.next() % ((size_t)instruction.arguments.multOpArgs.add_elements_count));
542 for (
size_t i = 0; i < add_mut_count; i++) {
543 instruction.arguments.multOpArgs
544 .add_elements[rng.next() % ((size_t)instruction.arguments.multOpArgs.add_elements_count)] =
545 static_cast<uint8_t
>(rng.next() & 0xff);
548 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.multOpArgs.output_index)
550 case OPCODE::SQR_ADD:
551 if (rng.next() & 1) {
553 instruction.arguments.multAddArgs.add_elements_count =
554 SQR_ADD_MINIMUM_ADDED_ELEMENTS +
555 static_cast<uint8_t
>(rng.next() %
556 (SQR_ADD_MAXIMUM_ADDED_ELEMENTS - SQR_ADD_MINIMUM_ADDED_ELEMENTS));
559 if (instruction.arguments.multAddArgs.add_elements_count && rng.next() & 1) {
561 size_t add_mut_count =
static_cast<uint8_t
>(
562 rng.next() % ((size_t)instruction.arguments.multAddArgs.add_elements_count));
564 for (
size_t i = 0; i < add_mut_count; i++) {
565 instruction.arguments.multAddArgs
566 .add_elements[rng.next() % ((size_t)instruction.arguments.multAddArgs.add_elements_count)] =
567 static_cast<uint8_t
>(rng.next() & 0xff);
570 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.multAddArgs.input_index)
571 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.multAddArgs.output_index)
573 case OPCODE::RANDOMSEED:
574 instruction.arguments.randomseed = rng.next();
588 static constexpr size_t CONSTANT =
sizeof(
fq);
589 static constexpr size_t WITNESS =
sizeof(
fq);
590 static constexpr size_t CONSTANT_WITNESS =
sizeof(
fq);
591 static constexpr size_t SQR = 2;
592 static constexpr size_t ASSERT_EQUAL = 2;
593 static constexpr size_t ASSERT_NOT_EQUAL = 2;
594 static constexpr size_t ADD = 3;
595 static constexpr size_t SUBTRACT = 3;
596 static constexpr size_t MULTIPLY = 3;
597 static constexpr size_t ADD_TWO =
static_cast<size_t>(-1);
598#ifndef DISABLE_DIVISION
599 static constexpr size_t DIVIDE = 3;
601 static constexpr size_t DIVIDE =
static_cast<size_t>(-1);
603 static constexpr size_t MADD = 4;
607 static constexpr size_t SUBTRACT_WITH_CONSTRAINT =
static_cast<size_t>(-1);
608 static constexpr size_t DIVIDE_WITH_CONSTRAINTS =
static_cast<size_t>(-1);
609 static constexpr size_t SLICE =
static_cast<size_t>(-1);
610 static constexpr size_t COND_NEGATE = 3;
611 static constexpr size_t COND_SELECT = 4;
612 static constexpr size_t SET = 2;
613 static constexpr size_t RANDOMSEED =
sizeof(uint32_t);
623 static constexpr size_t CONSTANT = 1;
624 static constexpr size_t WITNESS = 1;
625 static constexpr size_t CONSTANT_WITNESS = 1;
626 static constexpr size_t ADD = 1;
627 static constexpr size_t SUBTRACT = 1;
628 static constexpr size_t MULTIPLY = 2;
629 static constexpr size_t SQR = 2;
630 static constexpr size_t ASSERT_EQUAL = 2;
631 static constexpr size_t ASSERT_NOT_EQUAL = 2;
632 static constexpr size_t ADD_TWO = 0;
633#ifndef DISABLE_DIVISION
634 static constexpr size_t DIVIDE = 16;
636 static constexpr size_t MADD = 2;
637 static constexpr size_t MULT_MADD = 3;
638 static constexpr size_t MSUB_DIV = 3;
639 static constexpr size_t SQR_ADD = 2;
640 static constexpr size_t SUBTRACT_WITH_CONSTRAINT = 0;
641 static constexpr size_t DIVIDE_WITH_CONSTRAINTS = 0;
642 static constexpr size_t SLICE = 0;
643 static constexpr size_t COND_NEGATE = 0;
644 static constexpr size_t COND_SELECT = 0;
645 static constexpr size_t SET = 0;
646 static constexpr size_t RANDOMSEED = 0;
647 static constexpr size_t _LIMIT = 64;
664 if constexpr (opcode == Instruction::OPCODE::CONSTANT || opcode == Instruction::OPCODE::WITNESS ||
665 opcode == Instruction::OPCODE::CONSTANT_WITNESS) {
667 instr.id =
static_cast<typename Instruction::OPCODE
>(opcode);
668 instr.arguments.element.value = fq::serialize_from_buffer(Data);
671 if constexpr (opcode == Instruction::OPCODE::RANDOMSEED) {
673 instr.id =
static_cast<typename Instruction::OPCODE
>(opcode);
674 memcpy(&instr.arguments.randomseed, Data,
sizeof(uint32_t));
677 if constexpr (opcode == Instruction::OPCODE::SQR || opcode == Instruction::OPCODE::ASSERT_EQUAL ||
678 opcode == Instruction::OPCODE::ASSERT_NOT_EQUAL || opcode == Instruction::OPCODE::SET) {
679 return { .id =
static_cast<typename Instruction::OPCODE
>(opcode),
680 .arguments.twoArgs = { .in = *Data, .out = *(Data + 1) } };
682 if constexpr (opcode == Instruction::OPCODE::ADD || opcode == Instruction::OPCODE::MULTIPLY ||
683#ifndef DISABLE_DIVISION
684 opcode == Instruction::OPCODE::DIVIDE ||
686 opcode == Instruction::OPCODE::SUBTRACT || opcode == Instruction::OPCODE::COND_NEGATE) {
687 return { .id =
static_cast<typename Instruction::OPCODE
>(opcode),
688 .arguments.threeArgs = { .in1 = *Data, .in2 = *(Data + 1), .out = *(Data + 2) } };
690 if constexpr (opcode == Instruction::OPCODE::MADD || opcode == Instruction::OPCODE::ADD_TWO ||
691 opcode == Instruction::OPCODE::COND_SELECT) {
693 return { .id =
static_cast<typename Instruction::OPCODE
>(opcode),
694 .arguments.fourArgs = {
695 .in1 = *Data, .in2 = *(Data + 1), .in3 = *(Data + 2), .out = *(Data + 3) } };
697 if constexpr (opcode == Instruction::OPCODE::MULT_MADD || opcode == Instruction::OPCODE::MSUB_DIV) {
698 Instruction mult_madd_or_div;
699 mult_madd_or_div.id =
static_cast<typename Instruction::OPCODE
>(opcode);
700 memcpy(&mult_madd_or_div.arguments.multOpArgs, Data,
sizeof(
typename Instruction::MultOpArgs));
701 mult_madd_or_div.arguments.multOpArgs.add_elements_count =
702 mult_madd_or_div.arguments.multOpArgs.add_elements_count % MULT_MADD_MAXIMUM_ADDED_ELEMENTS;
704 if (mult_madd_or_div.arguments.multOpArgs.add_elements_count < MULT_MADD_MINIMUM_ADDED_ELEMENTS) {
706 mult_madd_or_div.arguments.multOpArgs.add_elements_count = MULT_MADD_MINIMUM_ADDED_ELEMENTS;
708 mult_madd_or_div.arguments.multOpArgs.mult_pairs_count =
709 mult_madd_or_div.arguments.multOpArgs.mult_pairs_count % MULT_MADD_MAXIMUM_MUL_PAIRS;
711 if (mult_madd_or_div.arguments.multOpArgs.mult_pairs_count < MULT_MADD_MINIMUM_MUL_PAIRS) {
712 mult_madd_or_div.arguments.multOpArgs.mult_pairs_count = MULT_MADD_MINIMUM_MUL_PAIRS;
714 return mult_madd_or_div;
716 if constexpr (opcode == Instruction::OPCODE::SQR_ADD) {
718 sqr_add.id =
static_cast<typename Instruction::OPCODE
>(opcode);
719 memcpy(&sqr_add.arguments.multAddArgs, Data,
sizeof(
typename Instruction::MultAddArgs));
720 sqr_add.arguments.multAddArgs.add_elements_count =
721 sqr_add.arguments.multAddArgs.add_elements_count % SQR_ADD_MAXIMUM_ADDED_ELEMENTS;
723 if (sqr_add.arguments.multOpArgs.add_elements_count < SQR_ADD_MINIMUM_ADDED_ELEMENTS) {
725 sqr_add.arguments.multOpArgs.add_elements_count = SQR_ADD_MINIMUM_ADDED_ELEMENTS;
737 template <
typename Instruction::OPCODE instruction_opcode>
740 if constexpr (instruction_opcode == Instruction::OPCODE::CONSTANT ||
741 instruction_opcode == Instruction::OPCODE::WITNESS ||
742 instruction_opcode == Instruction::OPCODE::CONSTANT_WITNESS) {
743 *Data = instruction.id;
745 &instruction.arguments.element.value.data[0],
746 sizeof(instruction.arguments.element.value.data));
749 if constexpr (instruction_opcode == Instruction::OPCODE::SQR ||
750 instruction_opcode == Instruction::OPCODE::ASSERT_EQUAL ||
751 instruction_opcode == Instruction::OPCODE::ASSERT_NOT_EQUAL ||
752 instruction_opcode == Instruction::OPCODE::SET) {
753 *Data = instruction.id;
754 *(Data + 1) = instruction.arguments.twoArgs.in;
755 *(Data + 2) = instruction.arguments.twoArgs.out;
757 if constexpr (instruction_opcode == Instruction::OPCODE::ADD ||
758#ifndef DISABLE_DIVISION
759 instruction_opcode == Instruction::OPCODE::DIVIDE ||
761 instruction_opcode == Instruction::OPCODE::MULTIPLY ||
762 instruction_opcode == Instruction::OPCODE::SUBTRACT ||
763 instruction_opcode == Instruction::OPCODE::COND_NEGATE) {
764 *Data = instruction.id;
765 *(Data + 1) = instruction.arguments.threeArgs.in1;
766 *(Data + 2) = instruction.arguments.threeArgs.in2;
767 *(Data + 3) = instruction.arguments.threeArgs.out;
769 if constexpr (instruction_opcode == Instruction::OPCODE::ADD_TWO ||
770 instruction_opcode == Instruction::OPCODE::MADD ||
771 instruction_opcode == Instruction::OPCODE::COND_SELECT) {
772 *Data = instruction.id;
773 *(Data + 1) = instruction.arguments.fourArgs.in1;
774 *(Data + 2) = instruction.arguments.fourArgs.in2;
775 *(Data + 3) = instruction.arguments.fourArgs.in3;
776 *(Data + 4) = instruction.arguments.fourArgs.out;
778 if constexpr (instruction_opcode == Instruction::OPCODE::MULT_MADD ||
779 instruction_opcode == Instruction::OPCODE::MSUB_DIV) {
781 *Data = instruction.id;
784 if constexpr (instruction_opcode == Instruction::OPCODE::SQR_ADD) {
786 *Data = instruction.id;
789 if constexpr (instruction_opcode == Instruction::OPCODE::RANDOMSEED) {
791 *Data = instruction.id;
792 memcpy(Data + 1, &instruction.arguments.randomseed,
sizeof(uint32_t));
802 static bool_t construct_predicate(
Builder* builder,
const bool predicate)
808 const bool predicate_has_ctx =
static_cast<bool>(VarianceRNG.next() % 2);
810 return bool_t(predicate_has_ctx ? builder :
nullptr, predicate);
814 const bool reconstruct =
static_cast<bool>(VarianceRNG.next() % 2);
817 return this->bigfield;
824 return static_cast<uint256_t>((this->bigfield.get_value() % uint512_t(fq::modulus)).lo);
835 if (b.get_context() ==
nullptr) {
838 if (b.get_value() > b.get_maximum_value()) {
841 for (
auto& limb : b.binary_basis_limbs) {
842 if (limb.maximum_value < limb.element.get_value()) {
851 if (b.get_context() ==
nullptr) {
854 if (b.get_value() > b.get_maximum_value()) {
857 for (
auto& limb : b.binary_basis_limbs) {
858 if (limb.maximum_value < limb.element.get_value()) {
867 if (b.get_context() ==
nullptr) {
870 if (b.get_value() > b.get_maximum_value()) {
873 for (
auto& limb : b.binary_basis_limbs) {
874 if (limb.maximum_value < limb.element.get_value()) {
894 if (other.bf().get_value() == 0) {
895 circuit_should_fail =
true;
898 const auto divisor = other.base != 0 ? other.base : 1;
899 switch (VarianceRNG.next() % 3) {
904 bigfield_t::div_check_denominator_nonzero({ this->bf() }, other.bf()));
909 std::vector<bigfield_t> numerators;
910 while (v != this->base) {
912 static_cast<uint256_t>(fq::random_element()) % (
static_cast<uint256_t>(this->base - v) + 1);
913 numerators.push_back(
bigfield_t(this->bigfield.context,
fq(add)));
919 bigfield_t::div_check_denominator_nonzero(numerators, other.bf()));
930 this->bf().madd(other1.bigfield, { other2.bigfield }));
934 std::vector<bigfield_t> to_add_bf;
935 fq accumulator = this->base.
sqr();
936 for (
size_t i = 0; i < to_add.size(); i++) {
937 to_add_bf.push_back(to_add[i].bigfield);
938 accumulator += to_add[i].base;
943 static ExecutionHandler mult_madd(
const std::vector<ExecutionHandler>& input_left,
944 const std::vector<ExecutionHandler>& input_right,
945 const std::vector<ExecutionHandler>& to_add)
947 std::vector<bigfield_t> input_left_bf;
948 std::vector<bigfield_t> input_right_bf;
949 std::vector<bigfield_t> to_add_bf;
950 fq accumulator = fq::zero();
951 for (
size_t i = 0; i < input_left.size(); i++) {
952 input_left_bf.push_back(input_left[i].bigfield);
953 input_right_bf.push_back(input_right[i].bigfield);
954 accumulator += input_left[i].base * input_right[i].base;
956 for (
size_t i = 0; i < to_add.size(); i++) {
957 to_add_bf.push_back(to_add[i].bigfield);
958 accumulator += to_add[i].base;
960 return ExecutionHandler(accumulator, bigfield_t::mult_madd(input_left_bf, input_right_bf, to_add_bf));
962 static ExecutionHandler msub_div(
const std::vector<ExecutionHandler>& input_left,
963 const std::vector<ExecutionHandler>& input_right,
965 const std::vector<ExecutionHandler>& to_sub)
967 std::vector<bigfield_t> input_left_bf;
968 std::vector<bigfield_t> input_right_bf;
969 std::vector<bigfield_t> to_sub_bf;
970 fq accumulator = fq::zero();
971 for (
size_t i = 0; i < input_left.size(); i++) {
972 input_left_bf.push_back(input_left[i].bigfield);
973 input_right_bf.push_back(input_right[i].bigfield);
974 accumulator -= input_left[i].base * input_right[i].base;
976 for (
size_t i = 0; i < to_sub.size(); i++) {
977 to_sub_bf.push_back(to_sub[i].bigfield);
978 accumulator -= to_sub[i].base;
981 if (divisor.base != 0) {
982 accumulator /= divisor.base;
984 const bool enable_divisor_nz_check =
static_cast<bool>(VarianceRNG.next() % 2);
987 bigfield_t::msub_div(
988 input_left_bf, input_right_bf, divisor.bigfield, to_sub_bf, enable_divisor_nz_check));
993 if (other.bf().is_constant()) {
994 if (this->bf().is_constant()) {
1004 this->bigfield.assert_is_in_field();
1006 this->bigfield.assert_equal(other.bf() + to_add);
1009 if (this->bf().is_constant()) {
1011 auto new_el = other.bf() + to_add;
1012 new_el.assert_is_in_field();
1013 this->bf().assert_equal(new_el);
1016 this->bf().assert_equal(other.bf() + to_add);
1023 if (this->base == other.base) {
1026 this->bf().assert_is_not_equal(other.bf());
1033 this->bf().conditional_negate(construct_predicate(builder, predicate)));
1039 this->bf().conditional_select(other.bf(), construct_predicate(builder, predicate)));
1045 if (this->bigfield.get_value() > this->bigfield.get_maximum_value()) {
1046 std::cerr <<
"bigfield value is larger than its maximum" << std::endl;
1050 switch (VarianceRNG.next() % 6) {
1066 const uint256_t u256_lo = u256.
slice(0, bigfield_t::NUM_LIMB_BITS * 2);
1067 const uint256_t u256_hi = u256.
slice(bigfield_t::NUM_LIMB_BITS * 2, bigfield_t::NUM_LIMB_BITS * 4);
1068 const field_t field_lo(builder, u256_lo);
1069 const field_t field_hi(builder, u256_hi);
1084 auto bf_copy = bf();
1102 std::vector<ExecutionHandler>& stack,
1107 bigfield_t(builder, instruction.arguments.element.value)));
1108#ifdef SHOW_INFORMATION
1109 std::cout <<
"Pushed constant value " << instruction.arguments.element.value <<
" to position "
1110 << stack.size() - 1 << std::endl;
1124 std::vector<ExecutionHandler>& stack,
1131 bigfield_t::from_witness(builder,
fq(instruction.arguments.element.value))));
1136#ifdef SHOW_INFORMATION
1137 std::cout <<
"Pushed witness value " << instruction.arguments.element.value <<
" to position "
1138 << stack.size() - 1 << std::endl;
1153 std::vector<ExecutionHandler>& stack,
1157 instruction.arguments.element.value,
1158 bigfield_t::create_from_u512_as_witness(builder,
uint256_t(instruction.arguments.element.value))));
1159#ifdef SHOW_INFORMATION
1160 std::cout <<
"Pushed constant witness value " << instruction.arguments.element.value <<
" to position "
1161 << stack.size() - 1 << std::endl;
1174 std::vector<ExecutionHandler>& stack,
1179 if (stack.size() == 0) {
1182 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
1183 size_t second_index = instruction.arguments.threeArgs.in2 % stack.size();
1184 size_t output_index = instruction.arguments.threeArgs.out;
1186 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"Multiplying",
"*")
1189 result = stack[first_index] * stack[second_index];
1191 if (output_index >= stack.size()) {
1192 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1193 stack.push_back(result);
1196 PRINT_RESULT(
"",
"saved to ", output_index, result)
1197 stack[output_index] = result;
1210 std::vector<ExecutionHandler>& stack,
1214 if (stack.size() == 0) {
1217 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
1218 size_t second_index = instruction.arguments.threeArgs.in2 % stack.size();
1219 size_t output_index = instruction.arguments.threeArgs.out;
1221 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"Adding",
"+")
1224 result = stack[first_index] + stack[second_index];
1226 if (output_index >= stack.size()) {
1227 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1228 stack.push_back(result);
1231 PRINT_RESULT(
"",
"saved to ", output_index, result)
1232 stack[output_index] = result;
1246 std::vector<ExecutionHandler>& stack,
1250 if (stack.size() == 0) {
1253 size_t first_index = instruction.arguments.twoArgs.in % stack.size();
1254 size_t output_index = instruction.arguments.twoArgs.out;
1256 PRINT_SINGLE_ARG_INSTRUCTION(first_index, stack,
"Squaring",
"squared")
1259 result = stack[first_index].sqr();
1261 if (output_index >= stack.size()) {
1262 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1263 stack.push_back(result);
1266 PRINT_RESULT(
"",
"saved to ", output_index, result)
1267 stack[output_index] = result;
1281 std::vector<ExecutionHandler>& stack,
1285 if (stack.size() == 0) {
1288 size_t first_index = instruction.arguments.twoArgs.in % stack.size();
1289 size_t second_index = instruction.arguments.twoArgs.out % stack.size();
1291 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"ASSERT_EQUAL",
"== something + ")
1292#ifdef SHOW_INFORMATION
1293 std::cout << std::endl;
1296 stack[first_index].assert_equal(stack[second_index]);
1309 std::vector<ExecutionHandler>& stack,
1313 if (stack.size() == 0) {
1316 size_t first_index = instruction.arguments.twoArgs.in % stack.size();
1317 size_t second_index = instruction.arguments.twoArgs.out % stack.size();
1319 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"ASSERT_NOT_EQUAL",
"!=")
1320#ifdef SHOW_INFORMATION
1321 std::cout << std::endl;
1325 if (stack[first_index].bigfield.is_constant() && stack[second_index].bigfield.is_constant()) {
1328 stack[first_index].assert_not_equal(stack[second_index]);
1341 std::vector<ExecutionHandler>& stack,
1345 if (stack.size() == 0) {
1348 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
1349 size_t second_index = instruction.arguments.threeArgs.in2 % stack.size();
1350 size_t output_index = instruction.arguments.threeArgs.out;
1352 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"Subtracting",
"-")
1355 result = stack[first_index] - stack[second_index];
1357 if (output_index >= stack.size()) {
1358 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1359 stack.push_back(result);
1362 PRINT_RESULT(
"",
"saved to ", output_index, result)
1363 stack[output_index] = result;
1376 std::vector<ExecutionHandler>& stack,
1380 if (stack.size() == 0) {
1383 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
1384 size_t second_index = instruction.arguments.threeArgs.in2 % stack.size();
1385 size_t output_index = instruction.arguments.threeArgs.out;
1387 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"Dividing",
"/")
1390 if (
fq((stack[second_index].bigfield.get_value() % fq::modulus).lo) == 0) {
1397 result = stack[first_index] / stack[second_index];
1399 if (output_index >= stack.size()) {
1400 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1401 stack.push_back(result);
1404 PRINT_RESULT(
"",
"saved to ", output_index, result)
1405 stack[output_index] = result;
1419 std::vector<ExecutionHandler>& stack,
1423 if (stack.size() == 0) {
1426 size_t first_index = instruction.arguments.fourArgs.in1 % stack.size();
1427 size_t second_index = instruction.arguments.fourArgs.in2 % stack.size();
1428 size_t third_index = instruction.arguments.fourArgs.in3 % stack.size();
1429 size_t output_index = instruction.arguments.fourArgs.out;
1430 PRINT_THREE_ARG_INSTRUCTION(first_index, second_index, third_index, stack,
"MADD:",
"*",
"+")
1433 result = stack[first_index].madd(stack[second_index], stack[third_index]);
1435 if (output_index >= stack.size()) {
1436 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1437 stack.push_back(result);
1440 PRINT_RESULT(
"",
"saved to ", output_index, result)
1441 stack[output_index] = result;
1455 std::vector<ExecutionHandler>& stack,
1459 if (stack.size() == 0) {
1462 std::vector<ExecutionHandler> input_left;
1463 std::vector<ExecutionHandler> input_right;
1464 std::vector<ExecutionHandler> to_add;
1465#ifdef SHOW_INFORMATION
1466 std::cout <<
"MULT_MADD:" << std::endl;
1467 for (
size_t i = 0; i < instruction.arguments.multOpArgs.mult_pairs_count; i++) {
1468 size_t index_left = (size_t)instruction.arguments.multOpArgs.mult_pairs[2 * i] % stack.size();
1469 size_t index_right = (size_t)instruction.arguments.multOpArgs.mult_pairs[2 * i + 1] % stack.size();
1470 std::cout << (stack[index_left].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1471 << stack[index_left].bigfield.get_value() <<
") at " << index_left <<
" * ";
1472 std::cout << (stack[index_right].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1473 << stack[index_right].bigfield.get_value() <<
") at " << index_right;
1474 if (i == (instruction.arguments.multOpArgs.mult_pairs_count - 1) &&
1475 instruction.arguments.multOpArgs.add_elements_count == 0) {
1476 std::cout << std::endl;
1478 std::cout <<
" + " << std::endl;
1481 for (
size_t i = 0; i < instruction.arguments.multOpArgs.add_elements_count; i++) {
1482 size_t add_index = (size_t)instruction.arguments.multOpArgs.add_elements[i] % stack.size();
1483 std::cout << (stack[add_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1484 << stack[add_index].bigfield.get_value() <<
") at " << add_index;
1485 if (i == (instruction.arguments.multOpArgs.add_elements_count - 1)) {
1486 std::cout << std::endl;
1488 std::cout <<
" + " << std::endl;
1492 for (
size_t i = 0; i < instruction.arguments.multOpArgs.mult_pairs_count; i++) {
1493 input_left.push_back(stack[(
size_t)instruction.arguments.multOpArgs.mult_pairs[2 * i] % stack.size()]);
1494 input_right.push_back(
1495 stack[(
size_t)instruction.arguments.multOpArgs.mult_pairs[2 * i + 1] % stack.size()]);
1498 for (
size_t i = 0; i < instruction.arguments.multOpArgs.add_elements_count; i++) {
1499 auto element_index = (size_t)instruction.arguments.multOpArgs.add_elements[i] % stack.size();
1500 to_add.push_back(stack[element_index]);
1502 size_t output_index = (size_t)instruction.arguments.multOpArgs.output_index;
1505 result = ExecutionHandler::mult_madd(input_left, input_right, to_add);
1507 if (output_index >= stack.size()) {
1508 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1509 stack.push_back(result);
1512 PRINT_RESULT(
"",
"saved to ", output_index, result)
1513 stack[output_index] = result;
1528 std::vector<ExecutionHandler>& stack,
1532 if (stack.size() == 0) {
1535 std::vector<ExecutionHandler> input_left;
1536 std::vector<ExecutionHandler> input_right;
1537 std::vector<ExecutionHandler> to_sub;
1538 size_t divisor_index = instruction.arguments.multOpArgs.divisor_index % stack.size();
1539#ifdef SHOW_INFORMATION
1541 std::cout <<
"MSUB_DIV:" << std::endl;
1543 for (
size_t i = 0; i < instruction.arguments.multOpArgs.mult_pairs_count; i++) {
1544 size_t index_left = (size_t)instruction.arguments.multOpArgs.mult_pairs[2 * i] % stack.size();
1545 size_t index_right = (size_t)instruction.arguments.multOpArgs.mult_pairs[2 * i + 1] % stack.size();
1546 std::cout << (stack[index_left].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1547 << stack[index_left].bigfield.get_value() <<
") at " << index_left <<
" * ";
1548 std::cout << (stack[index_right].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1549 << stack[index_right].bigfield.get_value() <<
") at " << index_right;
1550 if (i == (instruction.arguments.multOpArgs.mult_pairs_count - 1) &&
1551 instruction.arguments.multOpArgs.add_elements_count == 0) {
1552 std::cout << std::endl;
1554 std::cout <<
" + " << std::endl;
1557 for (
size_t i = 0; i < instruction.arguments.multOpArgs.add_elements_count; i++) {
1558 size_t add_index = (size_t)instruction.arguments.multOpArgs.add_elements[i] % stack.size();
1559 std::cout << (stack[add_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1560 << stack[add_index].bigfield.get_value() <<
") at " << add_index;
1561 if (i == (instruction.arguments.multOpArgs.add_elements_count - 1)) {
1562 std::cout << std::endl;
1564 std::cout <<
" + " << std::endl;
1567 std::cout <<
") / " << std::endl;
1568 std::cout << (stack[divisor_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1569 << stack[divisor_index].bigfield.get_value() <<
") at " << divisor_index << std::endl;
1572 if (
fq((stack[divisor_index].bigfield.get_value() % fq::modulus).lo) == 0) {
1575 for (
size_t i = 0; i < instruction.arguments.multOpArgs.mult_pairs_count; i++) {
1576 input_left.push_back(stack[(
size_t)instruction.arguments.multOpArgs.mult_pairs[2 * i] % stack.size()]);
1577 input_right.push_back(
1578 stack[(
size_t)instruction.arguments.multOpArgs.mult_pairs[2 * i + 1] % stack.size()]);
1581 for (
size_t i = 0; i < instruction.arguments.multOpArgs.add_elements_count; i++) {
1582 auto element_index = (size_t)instruction.arguments.multOpArgs.add_elements[i] % stack.size();
1583 to_sub.push_back(stack[element_index]);
1585 size_t output_index = (size_t)instruction.arguments.multOpArgs.output_index;
1588 result = ExecutionHandler::msub_div(input_left, input_right, stack[divisor_index], to_sub);
1590 if (output_index >= stack.size()) {
1591 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1592 stack.push_back(result);
1595 PRINT_RESULT(
"",
"saved to ", output_index, result)
1596 stack[output_index] = result;
1611 std::vector<ExecutionHandler>& stack,
1615 if (stack.size() == 0) {
1618 std::vector<ExecutionHandler> to_add;
1620 size_t input_index = (size_t)instruction.arguments.multAddArgs.input_index % stack.size();
1621#ifdef SHOW_INFORMATION
1622 std::cout <<
"SQR_ADD:" << std::endl;
1623 std::cout << (stack[input_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1624 << stack[input_index].bigfield.get_value() <<
") at " << input_index <<
" squared ";
1625 if (instruction.arguments.multAddArgs.add_elements_count == 0) {
1626 std::cout << std::endl;
1628 std::cout <<
"+" << std::endl;
1631 for (
size_t i = 0; i < instruction.arguments.multAddArgs.add_elements_count; i++) {
1632 size_t add_index = (size_t)instruction.arguments.multAddArgs.add_elements[i] % stack.size();
1633 std::cout << (stack[add_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1634 << stack[add_index].bigfield.get_value() <<
") at " << add_index;
1635 if (i == (instruction.arguments.multOpArgs.add_elements_count - 1)) {
1636 std::cout << std::endl;
1638 std::cout <<
" + " << std::endl;
1643 for (
size_t i = 0; i < instruction.arguments.multAddArgs.add_elements_count; i++) {
1644 auto element_index = (size_t)instruction.arguments.multAddArgs.add_elements[i] % stack.size();
1645 to_add.push_back(stack[element_index]);
1647 size_t output_index = (size_t)instruction.arguments.multAddArgs.output_index;
1650 result = stack[input_index].sqr_add(to_add);
1652 if (output_index >= stack.size()) {
1653 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1654 stack.push_back(result);
1657 PRINT_RESULT(
"",
"saved to ", output_index, result)
1658 stack[output_index] = result;
1671 std::vector<ExecutionHandler>& stack,
1675 if (stack.size() == 0) {
1678 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
1679 size_t output_index = instruction.arguments.threeArgs.out % stack.size();
1680 bool predicate = instruction.arguments.threeArgs.in2 % 2;
1682 result = stack[first_index].conditional_negate(builder, predicate);
1684 if (output_index >= stack.size()) {
1685 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1686 stack.push_back(result);
1689 PRINT_RESULT(
"",
"saved to ", output_index, result)
1690 stack[output_index] = result;
1704 std::vector<ExecutionHandler>& stack,
1708 if (stack.size() == 0) {
1711 size_t first_index = instruction.arguments.fourArgs.in1 % stack.size();
1712 size_t second_index = instruction.arguments.fourArgs.in2 % stack.size();
1713 size_t output_index = instruction.arguments.fourArgs.out % stack.size();
1714 bool predicate = instruction.arguments.fourArgs.in3 % 2;
1717 result = stack[first_index].conditional_select(builder, stack[second_index], predicate);
1719 if (output_index >= stack.size()) {
1720 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1721 stack.push_back(result);
1724 PRINT_RESULT(
"",
"saved to ", output_index, result)
1725 stack[output_index] = result;
1738 std::vector<ExecutionHandler>& stack,
1742 if (stack.size() == 0) {
1745 size_t first_index = instruction.arguments.twoArgs.in % stack.size();
1746 size_t output_index = instruction.arguments.twoArgs.out;
1748 result = stack[first_index].set(builder);
1750 if (output_index >= stack.size()) {
1751 stack.push_back(result);
1753 stack[output_index] = result;
1766 std::vector<ExecutionHandler>& stack,
1772 VarianceRNG.reseed(instruction.arguments.randomseed);
1793 for (
size_t i = 0; i < stack.size(); i++) {
1794 auto element = stack[i];
1795 if (
fq((element.bigfield.get_value() % uint512_t(fq::modulus)).lo) != element.base) {
1796 std::cerr <<
"Failed at " << i <<
" with actual value " << element.base <<
" and value in bigfield "
1797 << element.bigfield.get_value() << std::endl;
1807extern "C" int LLVMFuzzerInitialize(
int* argc,
char*** argv)
1814 .GEN_LLVM_POST_MUTATION_PROB = 30,
1815 .GEN_MUTATION_COUNT_LOG = 5,
1816 .GEN_STRUCTURAL_MUTATION_PROBABILITY = 300,
1817 .GEN_VALUE_MUTATION_PROBABILITY = 700,
1818 .ST_MUT_DELETION_PROBABILITY = 100,
1819 .ST_MUT_DUPLICATION_PROBABILITY = 80,
1820 .ST_MUT_INSERTION_PROBABILITY = 120,
1821 .ST_MUT_MAXIMUM_DELETION_LOG = 6,
1822 .ST_MUT_MAXIMUM_DUPLICATION_LOG = 2,
1823 .ST_MUT_SWAP_PROBABILITY = 50,
1824 .VAL_MUT_LLVM_MUTATE_PROBABILITY = 250,
1825 .VAL_MUT_MONTGOMERY_PROBABILITY = 130,
1826 .VAL_MUT_NON_MONTGOMERY_PROBABILITY = 50,
1827 .VAL_MUT_SMALL_ADDITION_PROBABILITY = 110,
1828 .VAL_MUT_SPECIAL_VALUE_PROBABILITY = 130
1901 std::vector<size_t> structural_mutation_distribution;
1902 std::vector<size_t> value_mutation_distribution;
1904 temp += fuzzer_havoc_settings.ST_MUT_DELETION_PROBABILITY;
1905 structural_mutation_distribution.push_back(temp);
1906 temp += fuzzer_havoc_settings.ST_MUT_DUPLICATION_PROBABILITY;
1907 structural_mutation_distribution.push_back(temp);
1908 temp += fuzzer_havoc_settings.ST_MUT_INSERTION_PROBABILITY;
1909 structural_mutation_distribution.push_back(temp);
1910 temp += fuzzer_havoc_settings.ST_MUT_SWAP_PROBABILITY;
1911 structural_mutation_distribution.push_back(temp);
1912 fuzzer_havoc_settings.structural_mutation_distribution = structural_mutation_distribution;
1915 temp += fuzzer_havoc_settings.VAL_MUT_LLVM_MUTATE_PROBABILITY;
1916 value_mutation_distribution.push_back(temp);
1917 temp += fuzzer_havoc_settings.VAL_MUT_SMALL_ADDITION_PROBABILITY;
1918 value_mutation_distribution.push_back(temp);
1920 temp += fuzzer_havoc_settings.VAL_MUT_SPECIAL_VALUE_PROBABILITY;
1921 value_mutation_distribution.push_back(temp);
1922 fuzzer_havoc_settings.value_mutation_distribution = value_mutation_distribution;
1926#ifndef DISABLE_CUSTOM_MUTATORS
1931extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* Data,
size_t Size,
size_t MaxSize,
unsigned int Seed)
1936 if ((fast_random.next() % 200) < fuzzer_havoc_settings.GEN_LLVM_POST_MUTATION_PROB) {
1937 size_occupied = LLVMFuzzerMutate(Data, size_occupied, MaxSize);
1939 return size_occupied;
1946extern "C" size_t LLVMFuzzerCustomCrossOver(
const uint8_t* Data1,
1948 const uint8_t* Data2,
1968extern "C" size_t LLVMFuzzerTestOneInput(
const uint8_t* Data,
size_t Size)
1970 RunWithBuilders<BigFieldBase, FuzzerCircuitTypes>(Data, Size, VarianceRNG);
1974#pragma clang diagnostic pop
static size_t writeInstructionsToBuffer(std::vector< typename T::Instruction > &instructions, uint8_t *Data, size_t MaxSize)
Write instructions into the buffer until there are no instructions left or there is no more space.
Definition: fuzzer.hpp:561
static std::vector< typename T::Instruction > parseDataIntoInstructions(const uint8_t *Data, size_t Size)
Parses a given data buffer into a vector of instructions for testing the arithmetic.
Definition: fuzzer.hpp:520
static size_t MutateInstructionBuffer(uint8_t *Data, size_t Size, size_t MaxSize, FastRandom &rng)
Interpret the data buffer as a series of arithmetic instructions and mutate it accordingly.
Definition: fuzzer.hpp:670
static std::vector< typename T::Instruction > crossoverInstructionVector(const std::vector< typename T::Instruction > &vecA, const std::vector< typename T::Instruction > &vecB, FastRandom &rng)
Splice two instruction vectors into one randomly.
Definition: fuzzer.hpp:458
Definition: bigfield.fuzzer.hpp:586
This class implements the execution of safeuint with an oracle to detect discrepancies.
Definition: bigfield.fuzzer.hpp:800
static size_t execute_CONSTANT_WITNESS(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the constant_witness instruction (push a safeuint witness equal to the constant to the stack)
Definition: bigfield.fuzzer.hpp:1152
static size_t execute_SET(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SET instruction.
Definition: bigfield.fuzzer.hpp:1737
static size_t execute_RANDOMSEED(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the RANDOMSEED instruction.
Definition: bigfield.fuzzer.hpp:1765
static size_t execute_WITNESS(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the witness instruction (push witness safeuit to the stack)
Definition: bigfield.fuzzer.hpp:1123
static size_t execute_SUBTRACT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the subtraction operator instruction.
Definition: bigfield.fuzzer.hpp:1340
static size_t execute_MADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the MADD instruction.
Definition: bigfield.fuzzer.hpp:1418
static size_t execute_MSUB_DIV(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the MSUB_DIV instruction.
Definition: bigfield.fuzzer.hpp:1527
static size_t execute_CONSTANT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the constant instruction (push constant safeuint to the stack)
Definition: bigfield.fuzzer.hpp:1101
static size_t execute_DIVIDE(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the division operator instruction.
Definition: bigfield.fuzzer.hpp:1375
static size_t execute_ADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the addition operator instruction.
Definition: bigfield.fuzzer.hpp:1209
static size_t execute_ASSERT_NOT_EQUAL(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the ASSERT_NOT_EQUAL instruction.
Definition: bigfield.fuzzer.hpp:1308
static size_t execute_COND_NEGATE(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the COND_NEGATE instruction.
Definition: bigfield.fuzzer.hpp:1670
static size_t execute_ASSERT_EQUAL(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the ASSERT_EQUAL instruction.
Definition: bigfield.fuzzer.hpp:1280
static size_t execute_SQR(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SQR instruction.
Definition: bigfield.fuzzer.hpp:1245
static size_t execute_SQR_ADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SQR_ADD instruction.
Definition: bigfield.fuzzer.hpp:1610
static size_t execute_COND_SELECT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the COND_SELECT instruction.
Definition: bigfield.fuzzer.hpp:1703
static size_t execute_MULT_MADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the MULT_MADD instruction.
Definition: bigfield.fuzzer.hpp:1454
static size_t execute_MULTIPLY(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the multiply instruction.
Definition: bigfield.fuzzer.hpp:1173
Optional subclass that governs limits on the use of certain instructions, since some of them can be t...
Definition: bigfield.fuzzer.hpp:621
A class representing a single fuzzing instruction.
Definition: bigfield.fuzzer.hpp:135
static fq mutateFieldElement(fq e, T &rng, HavocSettings &havoc_config)
Mutate the value of a field element.
Definition: bigfield.fuzzer.hpp:367
static Instruction generateRandom(T &rng)
Generate a random instruction.
Definition: bigfield.fuzzer.hpp:240
static Instruction mutateInstruction(Instruction instruction, T &rng, HavocSettings &havoc_config)
Mutate a single instruction.
Definition: bigfield.fuzzer.hpp:464
Parser class handles the parsing and writing the instructions back to data buffer.
Definition: bigfield.fuzzer.hpp:653
static Instruction parseInstructionArgs(uint8_t *Data)
Parse a single instruction from data.
Definition: bigfield.fuzzer.hpp:662
static void writeInstruction(Instruction &instruction, uint8_t *Data)
Write a single instruction to buffer.
Definition: bigfield.fuzzer.hpp:738
The class parametrizing Bigfield fuzzing instructions, execution, etc.
Definition: bigfield.fuzzer.hpp:122
std::vector< ExecutionHandler > ExecutionState
Definition: bigfield.fuzzer.hpp:1780
static bool postProcess(Builder *builder, std::vector< BigFieldBase::ExecutionHandler > &stack)
Check that the resulting values are equal to expected.
Definition: bigfield.fuzzer.hpp:1790
Class for quickly deterministically creating new random values. We don't care about distribution much...
Definition: fuzzer.hpp:64
Definition: uint256.hpp:25
constexpr uint256_t slice(uint64_t start, uint64_t end) const
Definition: uint256_impl.hpp:157
Definition: standard_circuit_builder.hpp:12
Definition: bigfield.hpp:17
Definition: witness.hpp:51
Definition: witness.hpp:10
Concept for a simple PRNG which returns a uint32_t when next is called.
Definition: fuzzer.hpp:91
Definition: bigfield.fuzzer.hpp:162
Definition: bigfield.fuzzer.hpp:183
Definition: bigfield.fuzzer.hpp:177
Definition: bigfield.fuzzer.hpp:190
Definition: bigfield.fuzzer.hpp:196
Definition: bigfield.fuzzer.hpp:205
Definition: bigfield.fuzzer.hpp:172
Definition: bigfield.fuzzer.hpp:168
Definition: fuzzer.hpp:27
BBERG_INLINE constexpr field sqr() const noexcept
Definition: field_impl.hpp:61
Definition: bigfield.fuzzer.hpp:213