14#pragma clang diagnostic push
16#pragma clang diagnostic ignored "-Wc99-designator"
30#ifdef FUZZING_SHOW_INFORMATION
31#define PRINT_SINGLE_ARG_INSTRUCTION(first_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 \
38#define PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, vector, operation_name, preposition) \
40 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
41 << vector[first_index].bigfield.get_value() << ") at " << first_index << " " << preposition << " " \
42 << (vector[second_index].bigfield.is_constant() ? "constant(" : "witness(") \
43 << vector[second_index].bigfield.get_value() << ") at " << second_index << std::flush; \
46#define PRINT_THREE_ARG_INSTRUCTION( \
47 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2) \
49 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
50 << vector[first_index].bigfield.get_value() << ") at " << first_index << " " << preposition1 << " " \
51 << (vector[second_index].bigfield.is_constant() ? "constant(" : "witness(") \
52 << vector[second_index].bigfield.get_value() << ") at " << second_index << " " << preposition2 \
53 << " " << (vector[third_index].bigfield.is_constant() ? "constant(" : "witness(") \
54 << vector[third_index].bigfield.get_value() << ") at " << third_index << std::flush; \
56#define PRINT_TWO_ARG_ONE_VALUE_INSTRUCTION( \
57 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2) \
59 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
60 << vector[first_index].bigfield.get_value() << ":" << vector[first_index].suint.current_max \
61 << ") at " << first_index << " " << preposition1 << " " \
62 << (vector[second_index].bigfield.is_constant() ? "constant(" : "witness(") \
63 << vector[second_index].bigfield.get_value() << ":" << vector[second_index].suint.current_max \
64 << ") at " << second_index << " " << preposition2 << " " << third_index << std::flush; \
67#define PRINT_TWO_ARG_TWO_VALUES_INSTRUCTION( \
68 first_index, second_index, value1, value2, vector, operation_name, preposition1, preposition2, preposition3) \
70 std::cout << operation_name << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
71 << vector[first_index].bigfield.get_value() << ") at " << first_index << " " << preposition1 << " " \
72 << (vector[second_index].bigfield.is_constant() ? "constant(" : "witness(") \
73 << vector[second_index].bigfield.get_value() << ") at " << second_index << " " << preposition2 \
74 << " " << value1 << preposition3 << value2 << std::flush; \
77#define PRINT_SLICE(first_index, lsb, msb, vector) \
79 std::cout << "Slice:" \
80 << " " << (vector[first_index].bigfield.is_constant() ? "constant(" : "witness(") \
81 << vector[first_index].bigfield.get_value() << ":" << vector[first_index].suint.current_max \
82 << ") at " << first_index << " " \
83 << "(" << (size_t)lsb << ":" << (size_t)msb << ")" << std::flush; \
86#define PRINT_RESULT(prefix, action, index, value) \
88 std::cout << " result(" << value.bigfield.get_value() << ")" << action << index << std::endl << std::flush; \
93#define PRINT_SINGLE_ARG_INSTRUCTION(first_index, vector, operation_name, preposition)
94#define PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, vector, operation_name, preposition)
96#define PRINT_TWO_ARG_ONE_VALUE_INSTRUCTION( \
97 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2)
98#define PRINT_TWO_ARG_TWO_VALUES_INSTRUCTION( \
99 first_index, second_index, value1, value2, vector, operation_name, preposition1, preposition2, preposition3)
101#define PRINT_THREE_ARG_INSTRUCTION( \
102 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2)
103#define PRINT_RESULT(prefix, action, index, value)
105#define PRINT_SLICE(first_index, lsb, msb, vector)
108#define OPERATION_TYPE_SIZE 1
110#define ELEMENT_SIZE (sizeof(fq) + 1)
111#define TWO_IN_ONE_OUT 3
112#define THREE_IN_ONE_OUT 4
113#define SLICE_ARGS_SIZE 6
115#define MSUB_DIV_MINIMUM_MUL_PAIRS 1
116#define MSUB_DIV_MAXIMUM_MUL_PAIRS 8
117#define MSUB_DIV_MINIMUM_SUBTRACTED_ELEMENTS 0
118#define MSUB_DIV_MAXIMUM_SUBTRACTED_ELEMENTS 8
119#define MULT_MADD_MINIMUM_MUL_PAIRS 1
120#define MULT_MADD_MAXIMUM_MUL_PAIRS 8
121#define MULT_MADD_MINIMUM_ADDED_ELEMENTS 0
122#define MULT_MADD_MAXIMUM_ADDED_ELEMENTS 8
123#define SQR_ADD_MINIMUM_ADDED_ELEMENTS 0
124#define SQR_ADD_MAXIMUM_ADDED_ELEMENTS 8
151#ifndef DISABLE_DIVISION
246 template <
typename T>
252 uint8_t in1, in2, in3, out, mult_size, add_size;
260 switch (instruction_opcode) {
264 auto value =
static_cast<uint64_t
>(fast_log_distributed_uint256(rng));
265 return { .id = instruction_opcode, .arguments.element =
Element(
value) };
269 return { .id = instruction_opcode, .arguments.randomseed = rng.next() };
275 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
276 out =
static_cast<uint8_t
>(rng.next() & 0xff);
277 return { .id = instruction_opcode, .arguments.twoArgs = { .in = in1, .out = out } };
282#ifndef DISABLE_DIVISION
288 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
289 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
290 out =
static_cast<uint8_t
>(rng.next() & 0xff);
291 return { .id = instruction_opcode, .arguments.threeArgs = { .in1 = in1, .in2 = in2, .out = out } };
298 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
299 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
300 in3 =
static_cast<uint8_t
>(rng.next() & 0xff);
301 out =
static_cast<uint8_t
>(rng.next() & 0xff);
302 return { .id = instruction_opcode,
303 .arguments.fourArgs{ .in1 = in1, .in2 = in2, .in3 = in3, .out = out } };
312 static_cast<uint8_t
>(rng.next() %
315 for (
size_t i = 0; i < mult_size; i++) {
316 mult_pairs[i * 2] =
static_cast<uint8_t
>(rng.next() & 0xff);
317 mult_pairs[i * 2 + 1] =
static_cast<uint8_t
>(rng.next() & 0xff);
319 for (
size_t i = 0; i < add_size; i++) {
320 add_elements[i] =
static_cast<uint8_t
>(rng.next() & 0xff);
322 instr.
id = instruction_opcode;
333 static_cast<uint8_t
>(rng.next() %
336 for (
size_t i = 0; i < add_size; i++) {
337 add_elements[i] =
static_cast<uint8_t
>(rng.next() & 0xff);
339 instr.
id = instruction_opcode;
362 template <
typename T>
369 bool convert_to_montgomery = (rng.next() % (havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY +
370 havoc_config.VAL_MUT_NON_MONTGOMERY_PROBABILITY)) <
371 havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY;
374#define MONT_CONVERSION \
375 if (convert_to_montgomery) { \
376 value_data = uint256_t(e.to_montgomery_form()); \
378 value_data = uint256_t(e); \
381#define INV_MONT_CONVERSION \
382 if (convert_to_montgomery) { \
383 e = bb::fq(value_data).from_montgomery_form(); \
385 e = bb::fq(value_data); \
389 const size_t mutation_type_count = havoc_config.value_mutation_distribution.size();
391 const size_t choice = rng.next() % havoc_config.value_mutation_distribution[mutation_type_count - 1];
392 if (choice < havoc_config.value_mutation_distribution[0]) {
397 }
else if (choice < havoc_config.value_mutation_distribution[1]) {
399 if (convert_to_montgomery) {
400 e = e.to_montgomery_form();
402 if (rng.next() & 1) {
403 e +=
bb::fq(rng.next() & 0xff);
405 e -=
bb::fq(rng.next() & 0xff);
407 if (convert_to_montgomery) {
408 e = e.from_montgomery_form();
412 switch (rng.next() % 9) {
444 if (convert_to_montgomery) {
445 e = e.from_montgomery_form();
460 template <
typename T>
464#define PUT_RANDOM_BYTE_IF_LUCKY(variable) \
465 if (rng.next() & 1) { \
466 variable = rng.next() & 0xff; \
475 if (rng.next() & 1) {
488#ifndef DISABLE_DIVISION
511 if (rng.next() & 1) {
513 instruction.arguments.multOpArgs.mult_pairs_count =
517 if (rng.next() & 1) {
519 instruction.arguments.multOpArgs.add_elements_count =
521 static_cast<uint8_t
>(rng.next() %
524 if (
instruction.arguments.multOpArgs.mult_pairs_count && rng.next() & 1) {
526 size_t mut_count =
static_cast<uint8_t
>(
527 rng.next() % (2 * (size_t)
instruction.arguments.multOpArgs.mult_pairs_count));
529 for (
size_t i = 0; i < mut_count; i++) {
530 auto ind = rng.next() % (2 * (size_t)
instruction.arguments.multOpArgs.mult_pairs_count);
531 instruction.arguments.multOpArgs.mult_pairs[ind] =
static_cast<uint8_t
>(rng.next() & 0xff);
534 if (
instruction.arguments.multOpArgs.add_elements_count && rng.next() & 1) {
536 size_t add_mut_count =
static_cast<uint8_t
>(
537 rng.next() % ((size_t)
instruction.arguments.multOpArgs.add_elements_count));
539 for (
size_t i = 0; i < add_mut_count; i++) {
541 .add_elements[rng.next() % ((size_t)
instruction.arguments.multOpArgs.add_elements_count)] =
542 static_cast<uint8_t
>(rng.next() & 0xff);
548 if (rng.next() & 1) {
550 instruction.arguments.multAddArgs.add_elements_count =
552 static_cast<uint8_t
>(rng.next() %
556 if (
instruction.arguments.multAddArgs.add_elements_count && rng.next() & 1) {
558 size_t add_mut_count =
static_cast<uint8_t
>(
559 rng.next() % ((size_t)
instruction.arguments.multAddArgs.add_elements_count));
561 for (
size_t i = 0; i < add_mut_count; i++) {
563 .add_elements[rng.next() % ((size_t)
instruction.arguments.multAddArgs.add_elements_count)] =
564 static_cast<uint8_t
>(rng.next() & 0xff);
588 static constexpr size_t SQR = 2;
591 static constexpr size_t ADD = 3;
595#ifndef DISABLE_DIVISION
598 static constexpr size_t DIVIDE =
static_cast<size_t>(-1);
600 static constexpr size_t MADD = 4;
606 static constexpr size_t SLICE =
static_cast<size_t>(-1);
609 static constexpr size_t SET = 2;
623 static constexpr size_t ADD = 1;
626 static constexpr size_t SQR = 2;
630#ifndef DISABLE_DIVISION
633 static constexpr size_t MADD = 2;
642 static constexpr size_t SET = 0;
677 .arguments.twoArgs = { .in = *Data, .out = *(Data + 1) } };
680#ifndef DISABLE_DIVISION
685 .arguments.threeArgs = { .in1 = *Data, .in2 = *(Data + 1), .out = *(Data + 2) } };
691 .arguments.fourArgs = {
692 .in1 = *Data, .in2 = *(Data + 1), .in3 = *(Data + 2), .out = *(Data + 3) } };
694 if constexpr (opcode == Instruction::OPCODE::MULT_MADD || opcode == Instruction::OPCODE::MSUB_DIV) {
696 mult_madd_or_div.id =
static_cast<typename Instruction::OPCODE
>(opcode);
697 memcpy(&mult_madd_or_div.arguments.multOpArgs, Data,
sizeof(
typename Instruction::MultOpArgs));
698 mult_madd_or_div.arguments.multOpArgs.add_elements_count =
704 mult_madd_or_div.arguments.multOpArgs.mult_pairs_count =
710 return mult_madd_or_div;
712 if constexpr (opcode == Instruction::OPCODE::SQR_ADD) {
714 sqr_add.id =
static_cast<typename Instruction::OPCODE
>(opcode);
715 memcpy(&sqr_add.arguments.multAddArgs, Data,
sizeof(
typename Instruction::MultAddArgs));
716 sqr_add.arguments.multAddArgs.add_elements_count =
733 template <
typename Instruction::OPCODE instruction_opcode>
736 if constexpr (instruction_opcode == Instruction::OPCODE::CONSTANT ||
737 instruction_opcode == Instruction::OPCODE::WITNESS ||
738 instruction_opcode == Instruction::OPCODE::CONSTANT_WITNESS) {
743 if constexpr (instruction_opcode == Instruction::OPCODE::SQR ||
744 instruction_opcode == Instruction::OPCODE::ASSERT_EQUAL ||
745 instruction_opcode == Instruction::OPCODE::ASSERT_NOT_EQUAL ||
746 instruction_opcode == Instruction::OPCODE::SET) {
751 if constexpr (instruction_opcode == Instruction::OPCODE::ADD ||
752#ifndef DISABLE_DIVISION
753 instruction_opcode == Instruction::OPCODE::DIVIDE ||
755 instruction_opcode == Instruction::OPCODE::MULTIPLY ||
756 instruction_opcode == Instruction::OPCODE::SUBTRACT ||
757 instruction_opcode == Instruction::OPCODE::COND_NEGATE) {
763 if constexpr (instruction_opcode == Instruction::OPCODE::ADD_TWO ||
764 instruction_opcode == Instruction::OPCODE::MADD ||
765 instruction_opcode == Instruction::OPCODE::COND_SELECT) {
772 if constexpr (instruction_opcode == Instruction::OPCODE::MULT_MADD ||
773 instruction_opcode == Instruction::OPCODE::MSUB_DIV) {
778 if constexpr (instruction_opcode == Instruction::OPCODE::SQR_ADD) {
783 if constexpr (instruction_opcode == Instruction::OPCODE::RANDOMSEED) {
786 memcpy(Data + 1, &
instruction.arguments.randomseed,
sizeof(uint32_t));
802 const bool predicate_has_ctx =
static_cast<bool>(
VarianceRNG.
next() % 2);
804 return bool_t(predicate_has_ctx ?
builder :
nullptr, predicate);
810#ifdef FUZZING_SHOW_INFORMATION
815 return this->bigfield;
833 if (
b.get_context() ==
nullptr) {
836 if (
b.get_value() >
b.get_maximum_value()) {
839 for (
size_t i = 0; i < 4; i++) {
840 auto limb =
b.binary_basis_limbs[i];
841 if (limb.maximum_value < limb.element.get_value()) {
842 info(
"LIMB ", i,
" VALUE IS NOT PROPERLY RESTRICTED");
852 if (
b.get_context() ==
nullptr) {
855 if (
b.get_value() >
b.get_maximum_value()) {
858 for (
auto& limb :
b.binary_basis_limbs) {
859 if (limb.maximum_value < limb.element.get_value()) {
868 if (
b.get_context() ==
nullptr) {
871 if (
b.get_value() >
b.get_maximum_value()) {
874 for (
auto& limb :
b.binary_basis_limbs) {
875 if (limb.maximum_value < limb.element.get_value()) {
899 const auto divisor = other.
base != 0 ? other.
base : 1;
914 for (
size_t i = 0; i < numerators_size && v != this->base; i++) {
916 if (i == numerators_size - 1) {
917 add = this->base - v;
943 this->bf().madd(other1.
bigfield, { other2.bigfield }));
949 for (
size_t i = 0; i < to_add.size(); i++) {
950 to_add_bf.push_back(to_add[i].bigfield);
951 accumulator += to_add[i].base;
964 for (
size_t i = 0; i < input_left.size(); i++) {
965 input_left_bf.push_back(input_left[i].bigfield);
966 input_right_bf.push_back(input_right[i].bigfield);
967 accumulator += input_left[i].base * input_right[i].base;
969 for (
size_t i = 0; i < to_add.size(); i++) {
970 to_add_bf.push_back(to_add[i].bigfield);
971 accumulator += to_add[i].base;
984 for (
size_t i = 0; i < input_left.size(); i++) {
985 input_left_bf.push_back(input_left[i].bigfield);
986 input_right_bf.push_back(input_right[i].bigfield);
987 accumulator -= input_left[i].base * input_right[i].base;
989 for (
size_t i = 0; i < to_sub.size(); i++) {
990 to_sub_bf.push_back(to_sub[i].bigfield);
991 accumulator -= to_sub[i].base;
994 if (divisor.
base != 0) {
995 accumulator /= divisor.
base;
997 const bool enable_divisor_nz_check =
static_cast<bool>(
VarianceRNG.
next() % 2);
1001 input_left_bf, input_right_bf, divisor.
bigfield, to_sub_bf, enable_divisor_nz_check));
1007 if (this->bf().is_constant()) {
1022 if (this->bf().is_constant()) {
1024 auto new_el = other.
bf() + to_add;
1026 this->bf().assert_equal(new_el);
1029 this->bf().assert_equal(other.
bf() + to_add);
1036 if (this->base == other.
base) {
1039 this->bf().assert_is_not_equal(other.
bf());
1046 this->bf().conditional_negate(construct_predicate(
builder, predicate)));
1052 this->bf().conditional_select(other.
bf(), construct_predicate(
builder, predicate)));
1058 if (this->bigfield.
get_value() > this->bigfield.get_maximum_value()) {
1065#ifdef FUZZING_SHOW_INFORMATION
1068 switch (switch_case) {
1102 auto bf_copy = bf();
1126#ifdef FUZZING_SHOW_INFORMATION
1127 std::cout <<
"Pushed constant value " <<
instruction.arguments.element.value <<
" to position "
1154#ifdef FUZZING_SHOW_INFORMATION
1177#ifdef FUZZING_SHOW_INFORMATION
1178 std::cout <<
"Pushed constant witness value " <<
instruction.arguments.element.value <<
" to position "
1197 if (stack.size() == 0) {
1200 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
1201 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
1202 size_t output_index =
instruction.arguments.threeArgs.out;
1207 result = stack[first_index] * stack[second_index];
1209 if (output_index >= stack.size()) {
1211 stack.push_back(result);
1215 stack[output_index] = result;
1232 if (stack.size() == 0) {
1235 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
1236 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
1237 size_t output_index =
instruction.arguments.threeArgs.out;
1242 result = stack[first_index] + stack[second_index];
1244 if (output_index >= stack.size()) {
1246 stack.push_back(result);
1250 stack[output_index] = result;
1268 if (stack.size() == 0) {
1271 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
1272 size_t output_index =
instruction.arguments.twoArgs.out;
1277 result = stack[first_index].
sqr();
1279 if (output_index >= stack.size()) {
1281 stack.push_back(result);
1285 stack[output_index] = result;
1303 if (stack.size() == 0) {
1306 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
1307 size_t second_index =
instruction.arguments.twoArgs.out % stack.size();
1310#ifdef FUZZING_SHOW_INFORMATION
1314 stack[first_index].assert_equal(stack[second_index]);
1331 if (stack.size() == 0) {
1334 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
1335 size_t second_index =
instruction.arguments.twoArgs.out % stack.size();
1338#ifdef FUZZING_SHOW_INFORMATION
1343 if (stack[first_index].bigfield.
is_constant() && stack[second_index].bigfield.is_constant()) {
1346 stack[first_index].assert_not_equal(stack[second_index]);
1363 if (stack.size() == 0) {
1366 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
1367 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
1368 size_t output_index =
instruction.arguments.threeArgs.out;
1373 result = stack[first_index] - stack[second_index];
1375 if (output_index >= stack.size()) {
1377 stack.push_back(result);
1381 stack[output_index] = result;
1398 if (stack.size() == 0) {
1401 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
1402 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
1403 size_t output_index =
instruction.arguments.threeArgs.out;
1415 result = stack[first_index] / stack[second_index];
1417 if (output_index >= stack.size()) {
1419 stack.push_back(result);
1423 stack[output_index] = result;
1441 if (stack.size() == 0) {
1444 size_t first_index =
instruction.arguments.fourArgs.in1 % stack.size();
1445 size_t second_index =
instruction.arguments.fourArgs.in2 % stack.size();
1446 size_t third_index =
instruction.arguments.fourArgs.in3 % stack.size();
1447 size_t output_index =
instruction.arguments.fourArgs.out;
1451 result = stack[first_index].
add_two(stack[second_index], stack[third_index]);
1453 if (output_index >= stack.size()) {
1455 stack.push_back(result);
1458 stack[output_index] = result;
1477 if (stack.size() == 0) {
1480 size_t first_index =
instruction.arguments.fourArgs.in1 % stack.size();
1481 size_t second_index =
instruction.arguments.fourArgs.in2 % stack.size();
1482 size_t third_index =
instruction.arguments.fourArgs.in3 % stack.size();
1483 size_t output_index =
instruction.arguments.fourArgs.out;
1487 result = stack[first_index].
madd(stack[second_index], stack[third_index]);
1489 if (output_index >= stack.size()) {
1491 stack.push_back(result);
1495 stack[output_index] = result;
1513 if (stack.size() == 0) {
1519#ifdef FUZZING_SHOW_INFORMATION
1521 for (
size_t i = 0; i <
instruction.arguments.multOpArgs.mult_pairs_count; i++) {
1522 size_t index_left = (size_t)
instruction.arguments.multOpArgs.mult_pairs[2 * i] % stack.size();
1523 size_t index_right = (size_t)
instruction.arguments.multOpArgs.mult_pairs[2 * i + 1] % stack.size();
1524 std::cout << (stack[index_left].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1525 << stack[index_left].bigfield.
get_value() <<
") at " << index_left <<
" * ";
1526 std::cout << (stack[index_right].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1527 << stack[index_right].bigfield.
get_value() <<
") at " << index_right;
1528 if (i == (
instruction.arguments.multOpArgs.mult_pairs_count - 1) &&
1529 instruction.arguments.multOpArgs.add_elements_count == 0) {
1535 for (
size_t i = 0; i <
instruction.arguments.multOpArgs.add_elements_count; i++) {
1536 size_t add_index = (size_t)
instruction.arguments.multOpArgs.add_elements[i] % stack.size();
1537 std::cout << (stack[add_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1538 << stack[add_index].bigfield.
get_value() <<
") at " << add_index;
1539 if (i == (
instruction.arguments.multOpArgs.add_elements_count - 1)) {
1546 for (
size_t i = 0; i <
instruction.arguments.multOpArgs.mult_pairs_count; i++) {
1547 input_left.push_back(stack[(
size_t)
instruction.arguments.multOpArgs.mult_pairs[2 * i] % stack.size()]);
1548 input_right.push_back(
1549 stack[(
size_t)
instruction.arguments.multOpArgs.mult_pairs[2 * i + 1] % stack.size()]);
1552 for (
size_t i = 0; i <
instruction.arguments.multOpArgs.add_elements_count; i++) {
1553 auto element_index = (size_t)
instruction.arguments.multOpArgs.add_elements[i] % stack.size();
1554 to_add.push_back(stack[element_index]);
1556 size_t output_index = (size_t)
instruction.arguments.multOpArgs.output_index;
1559 result = ExecutionHandler::mult_madd(input_left, input_right, to_add);
1561 if (output_index >= stack.size()) {
1563 stack.push_back(result);
1567 stack[output_index] = result;
1586 if (stack.size() == 0) {
1592 size_t divisor_index =
instruction.arguments.multOpArgs.divisor_index % stack.size();
1593#ifdef FUZZING_SHOW_INFORMATION
1597 for (
size_t i = 0; i <
instruction.arguments.multOpArgs.mult_pairs_count; i++) {
1598 size_t index_left = (size_t)
instruction.arguments.multOpArgs.mult_pairs[2 * i] % stack.size();
1599 size_t index_right = (size_t)
instruction.arguments.multOpArgs.mult_pairs[2 * i + 1] % stack.size();
1600 std::cout << (stack[index_left].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1601 << stack[index_left].bigfield.
get_value() <<
") at " << index_left <<
" * ";
1602 std::cout << (stack[index_right].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1603 << stack[index_right].bigfield.
get_value() <<
") at " << index_right;
1604 if (i == (
instruction.arguments.multOpArgs.mult_pairs_count - 1) &&
1605 instruction.arguments.multOpArgs.add_elements_count == 0) {
1611 for (
size_t i = 0; i <
instruction.arguments.multOpArgs.add_elements_count; i++) {
1612 size_t add_index = (size_t)
instruction.arguments.multOpArgs.add_elements[i] % stack.size();
1613 std::cout << (stack[add_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1614 << stack[add_index].bigfield.
get_value() <<
") at " << add_index;
1615 if (i == (
instruction.arguments.multOpArgs.add_elements_count - 1)) {
1622 std::cout << (stack[divisor_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1623 << stack[divisor_index].bigfield.
get_value() <<
") at " << divisor_index <<
std::endl;
1629 for (
size_t i = 0; i <
instruction.arguments.multOpArgs.mult_pairs_count; i++) {
1630 input_left.push_back(stack[(
size_t)
instruction.arguments.multOpArgs.mult_pairs[2 * i] % stack.size()]);
1631 input_right.push_back(
1632 stack[(
size_t)
instruction.arguments.multOpArgs.mult_pairs[2 * i + 1] % stack.size()]);
1635 for (
size_t i = 0; i <
instruction.arguments.multOpArgs.add_elements_count; i++) {
1636 auto element_index = (size_t)
instruction.arguments.multOpArgs.add_elements[i] % stack.size();
1637 to_sub.push_back(stack[element_index]);
1639 size_t output_index = (size_t)
instruction.arguments.multOpArgs.output_index;
1642 result = ExecutionHandler::msub_div(input_left, input_right, stack[divisor_index], to_sub);
1644 if (output_index >= stack.size()) {
1646 stack.push_back(result);
1650 stack[output_index] = result;
1669 if (stack.size() == 0) {
1674 size_t input_index = (size_t)
instruction.arguments.multAddArgs.input_index % stack.size();
1675#ifdef FUZZING_SHOW_INFORMATION
1677 std::cout << (stack[input_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1678 << stack[input_index].bigfield.
get_value() <<
") at " << input_index <<
" squared ";
1679 if (
instruction.arguments.multAddArgs.add_elements_count == 0) {
1685 for (
size_t i = 0; i <
instruction.arguments.multAddArgs.add_elements_count; i++) {
1686 size_t add_index = (size_t)
instruction.arguments.multAddArgs.add_elements[i] % stack.size();
1687 std::cout << (stack[add_index].bigfield.is_constant() ?
"Constant( " :
"Witness( ")
1688 << stack[add_index].bigfield.
get_value() <<
") at " << add_index;
1689 if (i == (
instruction.arguments.multOpArgs.add_elements_count - 1)) {
1697 for (
size_t i = 0; i <
instruction.arguments.multAddArgs.add_elements_count; i++) {
1698 auto element_index = (size_t)
instruction.arguments.multAddArgs.add_elements[i] % stack.size();
1699 to_add.push_back(stack[element_index]);
1701 size_t output_index = (size_t)
instruction.arguments.multAddArgs.output_index;
1704 result = stack[input_index].
sqr_add(to_add);
1706 if (output_index >= stack.size()) {
1708 stack.push_back(result);
1712 stack[output_index] = result;
1729 if (stack.size() == 0) {
1732 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
1733 size_t output_index =
instruction.arguments.threeArgs.out % stack.size();
1734 bool predicate =
instruction.arguments.threeArgs.in2 % 2;
1741 if (output_index >= stack.size()) {
1743 stack.push_back(result);
1747 stack[output_index] = result;
1765 if (stack.size() == 0) {
1768 size_t first_index =
instruction.arguments.fourArgs.in1 % stack.size();
1769 size_t second_index =
instruction.arguments.fourArgs.in2 % stack.size();
1770 size_t output_index =
instruction.arguments.fourArgs.out % stack.size();
1771 bool predicate =
instruction.arguments.fourArgs.in3 % 2;
1776 first_index, second_index, stack,
"Selecting #" +
std::to_string(predicate) +
" from",
", ")
1780 if (output_index >= stack.size()) {
1782 stack.push_back(result);
1786 stack[output_index] = result;
1803 if (stack.size() == 0) {
1806 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
1807 size_t output_index =
instruction.arguments.twoArgs.out;
1814 if (output_index >= stack.size()) {
1816 stack.push_back(result);
1819 stack[output_index] = result;
1859 for (
size_t i = 0; i < stack.size(); i++) {
1860 auto element = stack[i];
1862 std::cerr <<
"Failed at " << i <<
" with actual value " << element.base <<
" and value in bigfield "
1863 << element.bigfield.get_value() <<
std::endl;
1880 .GEN_MUTATION_COUNT_LOG = 5,
1881 .GEN_STRUCTURAL_MUTATION_PROBABILITY = 300,
1882 .GEN_VALUE_MUTATION_PROBABILITY = 700,
1883 .ST_MUT_DELETION_PROBABILITY = 100,
1884 .ST_MUT_DUPLICATION_PROBABILITY = 80,
1885 .ST_MUT_INSERTION_PROBABILITY = 120,
1886 .ST_MUT_MAXIMUM_DELETION_LOG = 6,
1887 .ST_MUT_MAXIMUM_DUPLICATION_LOG = 2,
1888 .ST_MUT_SWAP_PROBABILITY = 50,
1889 .VAL_MUT_LLVM_MUTATE_PROBABILITY = 250,
1890 .VAL_MUT_MONTGOMERY_PROBABILITY = 130,
1891 .VAL_MUT_NON_MONTGOMERY_PROBABILITY = 50,
1892 .VAL_MUT_SMALL_ADDITION_PROBABILITY = 110,
1893 .VAL_MUT_SPECIAL_VALUE_PROBABILITY = 130,
1894 .structural_mutation_distribution = {},
1895 .value_mutation_distribution = {} };
1966 std::vector<size_t> structural_mutation_distribution;
1967 std::vector<size_t> value_mutation_distribution;
1969 temp += fuzzer_havoc_settings.ST_MUT_DELETION_PROBABILITY;
1970 structural_mutation_distribution.push_back(temp);
1971 temp += fuzzer_havoc_settings.ST_MUT_DUPLICATION_PROBABILITY;
1972 structural_mutation_distribution.push_back(temp);
1973 temp += fuzzer_havoc_settings.ST_MUT_INSERTION_PROBABILITY;
1974 structural_mutation_distribution.push_back(temp);
1975 temp += fuzzer_havoc_settings.ST_MUT_SWAP_PROBABILITY;
1976 structural_mutation_distribution.push_back(temp);
1977 fuzzer_havoc_settings.structural_mutation_distribution = structural_mutation_distribution;
1980 temp += fuzzer_havoc_settings.VAL_MUT_LLVM_MUTATE_PROBABILITY;
1981 value_mutation_distribution.push_back(temp);
1982 temp += fuzzer_havoc_settings.VAL_MUT_SMALL_ADDITION_PROBABILITY;
1983 value_mutation_distribution.push_back(temp);
1985 temp += fuzzer_havoc_settings.VAL_MUT_SPECIAL_VALUE_PROBABILITY;
1986 value_mutation_distribution.push_back(temp);
1987 fuzzer_havoc_settings.value_mutation_distribution = value_mutation_distribution;
1998 RunWithBuilders<BigFieldBase, FuzzerCircuitTypes>(Data, Size,
VarianceRNG);
2002#pragma clang diagnostic pop
#define BB_ASSERT_EQ(actual, expected,...)
#define PRINT_SINGLE_ARG_INSTRUCTION(first_index, vector, operation_name, preposition)
#define PRINT_THREE_ARG_INSTRUCTION( first_index, second_index, third_index, vector, operation_name, preposition1, preposition2)
#define PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, vector, operation_name, preposition)
#define INV_MONT_CONVERSION
#define SQR_ADD_MINIMUM_ADDED_ELEMENTS
#define MULT_MADD_MINIMUM_MUL_PAIRS
#define MULT_MADD_MAXIMUM_MUL_PAIRS
FastRandom VarianceRNG(0)
#define MULT_MADD_MINIMUM_ADDED_ELEMENTS
int LLVMFuzzerInitialize(int *argc, char ***argv)
#define MULT_MADD_MAXIMUM_ADDED_ELEMENTS
#define PRINT_RESULT(prefix, action, index, value)
size_t LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Fuzzer entry function.
#define SQR_ADD_MAXIMUM_ADDED_ELEMENTS
#define PUT_RANDOM_BYTE_IF_LUCKY(variable)
static constexpr size_t MADD
static constexpr size_t SUBTRACT
static constexpr size_t RANDOMSEED
static constexpr size_t SLICE
static constexpr size_t MULT_MADD
static constexpr size_t ASSERT_NOT_EQUAL
static constexpr size_t WITNESS
static constexpr size_t MULTIPLY
static constexpr size_t CONSTANT
static constexpr size_t ADD_TWO
static constexpr size_t COND_SELECT
static constexpr size_t ADD
static constexpr size_t SQR_ADD
static constexpr size_t CONSTANT_WITNESS
static constexpr size_t ASSERT_EQUAL
static constexpr size_t SQR
static constexpr size_t COND_NEGATE
static constexpr size_t MSUB_DIV
static constexpr size_t SUBTRACT_WITH_CONSTRAINT
static constexpr size_t DIVIDE
static constexpr size_t SET
static constexpr size_t DIVIDE_WITH_CONSTRAINTS
This class implements the execution of safeuint with an oracle to detect discrepancies.
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)
void assert_not_equal(ExecutionHandler &other)
static size_t execute_SET(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SET instruction.
static bool_t construct_predicate(Builder *builder, const bool predicate)
static size_t execute_RANDOMSEED(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the RANDOMSEED instruction.
static size_t execute_WITNESS(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the witness instruction (push witness safeuit to the stack)
static size_t execute_SUBTRACT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the subtraction operator instruction.
static size_t execute_ADD_TWO(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the ADD_TWO instruction.
static size_t execute_MADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the MADD instruction.
static ExecutionHandler msub_div(const std::vector< ExecutionHandler > &input_left, const std::vector< ExecutionHandler > &input_right, const ExecutionHandler &divisor, const std::vector< ExecutionHandler > &to_sub)
static size_t execute_MSUB_DIV(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the MSUB_DIV instruction.
static size_t execute_CONSTANT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the constant instruction (push constant safeuint to the stack)
ExecutionHandler conditional_negate(Builder *builder, const bool predicate)
static size_t execute_DIVIDE(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the division operator instruction.
ExecutionHandler madd(const ExecutionHandler &other1, const ExecutionHandler &other2)
ExecutionHandler(bb::fq a, bigfield_t b)
ExecutionHandler(bb::fq &a, bigfield_t &b)
ExecutionHandler operator+(const ExecutionHandler &other)
static size_t execute_ADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the addition operator instruction.
static size_t execute_ASSERT_NOT_EQUAL(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the ASSERT_NOT_EQUAL instruction.
ExecutionHandler conditional_select(Builder *builder, ExecutionHandler &other, const bool predicate)
ExecutionHandler()=default
static size_t execute_COND_NEGATE(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the COND_NEGATE instruction.
uint256_t bf_u256(void) const
ExecutionHandler operator*(const ExecutionHandler &other)
ExecutionHandler(bb::fq a, bigfield_t &b)
static size_t execute_ASSERT_EQUAL(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the ASSERT_EQUAL instruction.
static size_t execute_SQR(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SQR instruction.
ExecutionHandler operator/(const ExecutionHandler &other)
ExecutionHandler sqr_add(const std::vector< ExecutionHandler > &to_add)
static size_t execute_SQR_ADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SQR_ADD instruction.
static size_t execute_COND_SELECT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the COND_SELECT instruction.
static ExecutionHandler mult_madd(const std::vector< ExecutionHandler > &input_left, const std::vector< ExecutionHandler > &input_right, const std::vector< ExecutionHandler > &to_add)
ExecutionHandler add_two(const ExecutionHandler &other1, const ExecutionHandler &other2)
ExecutionHandler set(Builder *builder)
ExecutionHandler operator-(const ExecutionHandler &other)
void assert_equal(ExecutionHandler &other)
static size_t execute_MULT_MADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the MULT_MADD instruction.
static size_t execute_MULTIPLY(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the multiply instruction.
A class representing a single fuzzing instruction.
ArgumentContents arguments
static Instruction generateRandom(T &rng)
Generate a random instruction.
static Instruction mutateInstruction(Instruction instruction, T &rng, HavocSettings &havoc_config)
Mutate a single instruction.
static bb::fq mutateFieldElement(bb::fq e, T &rng, HavocSettings &havoc_config)
Mutate the value of a field element.
Optional subclass that governs limits on the use of certain instructions, since some of them can be t...
static constexpr size_t ADD
static constexpr size_t SLICE
static constexpr size_t CONSTANT_WITNESS
static constexpr size_t MULTIPLY
static constexpr size_t DIVIDE_WITH_CONSTRAINTS
static constexpr size_t WITNESS
static constexpr size_t MSUB_DIV
static constexpr size_t SUBTRACT
static constexpr size_t COND_NEGATE
static constexpr size_t ADD_TWO
static constexpr size_t SUBTRACT_WITH_CONSTRAINT
static constexpr size_t ASSERT_NOT_EQUAL
static constexpr size_t SET
static constexpr size_t CONSTANT
static constexpr size_t MULT_MADD
static constexpr size_t RANDOMSEED
static constexpr size_t _LIMIT
static constexpr size_t SQR_ADD
static constexpr size_t MADD
static constexpr size_t SQR
static constexpr size_t ASSERT_EQUAL
static constexpr size_t DIVIDE
static constexpr size_t COND_SELECT
Parser class handles the parsing and writing the instructions back to data buffer.
static Instruction parseInstructionArgs(uint8_t *Data)
Parse a single instruction from data.
static void writeInstruction(Instruction &instruction, uint8_t *Data)
Write a single instruction to buffer.
The class parametrizing Bigfield fuzzing instructions, execution, etc.
bb::stdlib::bigfield< Builder, bb::Bn254FqParams > bigfield_t
bb::stdlib::public_witness_t< Builder > public_witness_t
bb::stdlib::field_t< Builder > field_t
std::vector< ExecutionHandler > ExecutionState
bb::stdlib::witness_t< Builder > witness_t
bb::stdlib::bool_t< Builder > bool_t
static bool postProcess(Builder *builder, std::vector< BigFieldBase::ExecutionHandler > &stack)
Check that the resulting values are equal to expected.
Class for quickly deterministically creating new random values. We don't care about distribution much...
void reseed(uint32_t seed)
constexpr uint256_t slice(uint64_t start, uint64_t end) const
static constexpr uint64_t NUM_LIMB_BITS
static bigfield div_check_denominator_nonzero(const std::vector< bigfield > &numerators, const bigfield &denominator)
static bigfield mult_madd(const std::vector< bigfield > &mul_left, const std::vector< bigfield > &mul_right, const std::vector< bigfield > &to_add, bool fix_remainder_to_zero=false)
uint512_t get_value() const
static bigfield msub_div(const std::vector< bigfield > &mul_left, const std::vector< bigfield > &mul_right, const bigfield &divisor, const std::vector< bigfield > &to_sub, bool enable_divisor_nz_check=false)
void assert_equal(const bigfield &other) const
void assert_is_in_field() const
static constexpr size_t MAXIMUM_SUMMAND_COUNT
static bigfield from_witness(Builder *ctx, const bb::field< bb::Bn254FqParams > &input)
bool is_constant() const
Check if the bigfield is constant, i.e. its prime limb is constant.
static bigfield create_from_u512_as_witness(Builder *ctx, const uint512_t &value, const bool can_overflow=false, const size_t maximum_bitlength=0)
Creates a bigfield element from a uint512_t. Bigfield element is constructed as a witness and not a c...
Implements boolean logic in-circuit.
Concept for a simple PRNG which returns a uint32_t when next is called.
StrictMock< MockContext > context
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize)
field< Bn254FqParams > fq
Instruction
Enumeration of VM instructions that can be executed.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
uint8_t add_elements_count
uint8_t add_elements[MULT_MADD_MAXIMUM_ADDED_ELEMENTS]
uint8_t add_elements_count
uint8_t mult_pairs[MULT_MADD_MAXIMUM_MUL_PAIRS *2]
uint8_t add_elements[MULT_MADD_MAXIMUM_ADDED_ELEMENTS]
size_t GEN_LLVM_POST_MUTATION_PROB
static constexpr field get_root_of_unity(size_t subgroup_size) noexcept
static constexpr field one()
static constexpr uint256_t modulus
BB_INLINE constexpr field sqr() const noexcept
static field serialize_from_buffer(const uint8_t *buffer)
static void serialize_to_buffer(const field &value, uint8_t *buffer)
constexpr std::pair< bool, field > sqrt() const noexcept
Compute square root of the field element.
static constexpr field zero()
bb::stdlib::bigfield< Builder, bb::Bn254FqParams > bigfield_t