1#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
2#include "barretenberg/numeric/random/engine.hpp"
3#include "barretenberg/numeric/uint256/uint256.hpp"
4#include "barretenberg/stdlib/primitives/safe_uint/safe_uint.hpp"
5#pragma clang diagnostic push
6#pragma clang diagnostic ignored "-Wc99-designator"
10bool circuit_should_fail =
false;
15#include "barretenberg/common/fuzzer.hpp"
21#ifdef SHOW_INFORMATION
22#define PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, vector, operation_name, preposition) \
24 std::cout << operation_name << " " << (vector[first_index].suint.is_constant() ? "constant(" : "witness(") \
25 << vector[first_index].suint.get_value() << ":" << vector[first_index].suint.current_max << ") at " \
26 << first_index << " " << preposition << " " \
27 << (vector[second_index].suint.is_constant() ? "constant(" : "witness(") \
28 << vector[second_index].suint.get_value() << ":" << vector[second_index].suint.current_max \
29 << ") at " << second_index << std::flush; \
32#define PRINT_THREE_ARG_INSTRUCTION( \
33 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2) \
35 std::cout << operation_name << " " << (vector[first_index].suint.is_constant() ? "constant(" : "witness(") \
36 << vector[first_index].suint.get_value() << ":" << vector[first_index].suint.current_max << ") at " \
37 << first_index << " " << preposition1 << " " \
38 << (vector[second_index].suint.is_constant() ? "constant(" : "witness(") \
39 << vector[second_index].suint.get_value() << ":" << vector[second_index].suint.current_max \
40 << ") at " << second_index << " " << preposition2 << " " \
41 << (vector[third_index].suint.is_constant() ? "constant(" : "witness(") \
42 << vector[third_index].suint.get_value() << ":" << vector[third_index].suint.current_max << ") at " \
43 << third_index << std::flush; \
45#define PRINT_TWO_ARG_ONE_VALUE_INSTRUCTION( \
46 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2) \
48 std::cout << operation_name << " " << (vector[first_index].suint.is_constant() ? "constant(" : "witness(") \
49 << vector[first_index].suint.get_value() << ":" << vector[first_index].suint.current_max << ") at " \
50 << first_index << " " << preposition1 << " " \
51 << (vector[second_index].suint.is_constant() ? "constant(" : "witness(") \
52 << vector[second_index].suint.get_value() << ":" << vector[second_index].suint.current_max \
53 << ") at " << second_index << " " << preposition2 << " " << third_index << std::flush; \
56#define PRINT_TWO_ARG_TWO_VALUES_INSTRUCTION( \
57 first_index, second_index, value1, value2, vector, operation_name, preposition1, preposition2, preposition3) \
59 std::cout << operation_name << " " << (vector[first_index].suint.is_constant() ? "constant(" : "witness(") \
60 << vector[first_index].suint.get_value() << ":" << vector[first_index].suint.current_max << ") at " \
61 << first_index << " " << preposition1 << " " \
62 << (vector[second_index].suint.is_constant() ? "constant(" : "witness(") \
63 << vector[second_index].suint.get_value() << ":" << vector[second_index].suint.current_max \
64 << ") at " << second_index << " " << preposition2 << " " << value1 << preposition3 << value2 \
68#define PRINT_SLICE(first_index, lsb, msb, vector) \
70 std::cout << "Slice:" \
71 << " " << (vector[first_index].suint.is_constant() ? "constant(" : "witness(") \
72 << vector[first_index].suint.get_value() << ":" << vector[first_index].suint.current_max << ") at " \
73 << first_index << " " \
74 << "(" << (size_t)lsb << ":" << (size_t)msb << ")" << std::flush; \
77#define PRINT_RESULT(prefix, action, index, value) \
79 std::cout << " result(" << value.suint.get_value() << " : " << value.suint.current_max << ") " << action \
80 << index << std::endl \
86#define PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, vector, operation_name, preposition)
88#define PRINT_TWO_ARG_ONE_VALUE_INSTRUCTION( \
89 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2)
90#define PRINT_TWO_ARG_TWO_VALUES_INSTRUCTION( \
91 first_index, second_index, value1, value2, vector, operation_name, preposition1, preposition2, preposition3)
93#define PRINT_THREE_ARG_INSTRUCTION( \
94 first_index, second_index, third_index, vector, operation_name, preposition1, preposition2)
95#define PRINT_RESULT(prefix, action, index, value)
97#define PRINT_SLICE(first_index, lsb, msb, vector)
100#define OPERATION_TYPE_SIZE 1
102#define ELEMENT_SIZE (sizeof(fr) + 1)
103#define TWO_IN_ONE_OUT 3
104#define THREE_IN_ONE_OUT 4
105#define SLICE_ARGS_SIZE 6
136 SUBTRACT_WITH_CONSTRAINT,
137 DIVIDE_WITH_CONSTRAINTS,
192 template <
typename T>
197 OPCODE instruction_opcode =
static_cast<OPCODE
>(rng.next() % (OPCODE::_LAST));
198 uint8_t in1, in2, in3, lsb, msb, out, out1, out2, out3, mask_size, bit_range;
201 switch (instruction_opcode) {
202 case OPCODE::CONSTANT:
203 case OPCODE::WITNESS:
204 case OPCODE::CONSTANT_WITNESS:
207 for (
size_t i = 0; i < (
sizeof(
uint256_t) >> 1); i++) {
208 *(((uint16_t*)&temp) + i) =
static_cast<uint16_t
>(rng.next() & 0xffff);
212 mask_size =
static_cast<uint8_t
>(rng.next() & 0xff);
215 bit_range =
static_cast<uint8_t
>(rng.next() & 0xff);
217 return { .id = instruction_opcode,
218 .arguments.element = { .value =
fr(temp & mask), .bit_range = bit_range } };
222 case OPCODE::SUBTRACT:
223 case OPCODE::MULTIPLY:
227 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
228 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
229 out =
static_cast<uint8_t
>(rng.next() & 0xff);
230 return { .id = instruction_opcode, .arguments.threeArgs = { .in1 = in1, .in2 = in2, .out = out } };
232 case OPCODE::ADD_TWO:
234 case OPCODE::SUBTRACT_WITH_CONSTRAINT:
237 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
238 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
239 in3 =
static_cast<uint8_t
>(rng.next() & 0xff);
240 out =
static_cast<uint8_t
>(rng.next() & 0xff);
241 return { .id = instruction_opcode,
242 .arguments.fourArgs = { .in1 = in1, .in2 = in2, .in3 = in3, .out = out } };
245 case OPCODE::DIVIDE_WITH_CONSTRAINTS:
248 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
249 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
250 in3 =
static_cast<uint8_t
>(rng.next() & 0xff);
251 lsb =
static_cast<uint8_t
>(rng.next() & 0xff);
252 out =
static_cast<uint8_t
>(rng.next() & 0xff);
253 return { .id = instruction_opcode,
254 .arguments.fiveArgs = { .in1 = in1, .in2 = in2, .qbs = in3, .rbs = lsb, .out = out } };
260 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
261 lsb =
static_cast<uint8_t
>(rng.next() & 0xff);
262 msb =
static_cast<uint8_t
>(rng.next() & 0xff);
263 out1 =
static_cast<uint8_t
>(rng.next() & 0xff);
264 out2 =
static_cast<uint8_t
>(rng.next() & 0xff);
265 out3 =
static_cast<uint8_t
>(rng.next() & 0xff);
266 return { .id = instruction_opcode,
267 .arguments.sliceArgs = {
268 .in1 = in1, .lsb = lsb, .msb = msb, .out1 = out1, .out2 = out2, .out3 = out3 } };
270 case OPCODE::RANDOMSEED:
271 return { .id = instruction_opcode, .arguments.randomseed = rng.next() };
288 template <
typename T>
295 bool convert_to_montgomery = (rng.next() % (havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY +
296 havoc_config.VAL_MUT_NON_MONTGOMERY_PROBABILITY)) <
297 havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY;
300#define MONT_CONVERSION \
301 if (convert_to_montgomery) { \
302 value_data = uint256_t(e.to_montgomery_form()); \
304 value_data = uint256_t(e); \
307#define INV_MONT_CONVERSION \
308 if (convert_to_montgomery) { \
309 e = fr(value_data).from_montgomery_form(); \
311 e = fr(value_data); \
315 const size_t mutation_type_count = havoc_config.value_mutation_distribution.size();
317 const size_t choice = rng.next() % havoc_config.value_mutation_distribution[mutation_type_count - 1];
318 if (choice < havoc_config.value_mutation_distribution[0]) {
323 }
else if (choice < havoc_config.value_mutation_distribution[1]) {
325 if (convert_to_montgomery) {
326 e = e.to_montgomery_form();
328 if (rng.next() & 1) {
329 value_data = e +
fr(rng.next() & 0xff);
331 value_data = e -
fr(rng.next() & 0xff);
333 if (convert_to_montgomery) {
334 e = e.from_montgomery_form();
339 switch (rng.next() % 8) {
350 e = fr::one().sqrt().second;
353 e = fr::one().sqrt().second.invert();
356 e = fr::get_root_of_unity(8);
362 e =
fr((fr::modulus - 1) / 2);
382 template <
typename T>
386#define PUT_RANDOM_BYTE_IF_LUCKY(variable) \
387 if (rng.next() & 1) { \
388 variable = rng.next() & 0xff; \
391 switch (instruction.id) {
392 case OPCODE::CONSTANT:
393 case OPCODE::WITNESS:
394 case OPCODE::CONSTANT_WITNESS:
396 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.element.bit_range);
398 if (rng.next() & 1) {
399 instruction.arguments.element.value =
405 case OPCODE::MULTIPLY:
406 case OPCODE::SUBTRACT:
408 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.threeArgs.in1)
409 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.threeArgs.in2)
410 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.threeArgs.out)
412 case OPCODE::ADD_TWO:
414 case OPCODE::SUBTRACT_WITH_CONSTRAINT:
416 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fourArgs.in1)
417 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fourArgs.in2)
418 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fourArgs.in3)
419 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fourArgs.out)
421 case OPCODE::DIVIDE_WITH_CONSTRAINTS:
423 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fiveArgs.in1)
424 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fiveArgs.in2)
425 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fiveArgs.qbs)
426 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fiveArgs.rbs)
427 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.fiveArgs.out)
431 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.sliceArgs.in1)
432 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.sliceArgs.lsb)
433 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.sliceArgs.msb)
434 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.sliceArgs.out1)
435 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.sliceArgs.out2)
436 PUT_RANDOM_BYTE_IF_LUCKY(instruction.arguments.sliceArgs.out3)
438 case OPCODE::RANDOMSEED:
439 instruction.arguments.randomseed = rng.next();
453 static constexpr size_t CONSTANT =
sizeof(
uint256_t) + 1;
454 static constexpr size_t WITNESS =
sizeof(
uint256_t) + 1;
455 static constexpr size_t CONSTANT_WITNESS =
sizeof(
uint256_t) + 1;
456 static constexpr size_t ADD = 3;
457 static constexpr size_t SUBTRACT = 3;
458 static constexpr size_t MULTIPLY = 3;
459 static constexpr size_t ADD_TWO = 4;
460 static constexpr size_t DIVIDE = 3;
461 static constexpr size_t MADD = 4;
462 static constexpr size_t SUBTRACT_WITH_CONSTRAINT = 4;
463 static constexpr size_t DIVIDE_WITH_CONSTRAINTS = 5;
464 static constexpr size_t SLICE = 6;
465 static constexpr size_t RANDOMSEED =
sizeof(uint32_t);
482 if constexpr (opcode == Instruction::OPCODE::CONSTANT || opcode == Instruction::OPCODE::WITNESS ||
483 opcode == Instruction::OPCODE::CONSTANT_WITNESS) {
484 return Instruction{ .id =
static_cast<typename Instruction::OPCODE
>(opcode),
485 .arguments.element = { .value = fr::serialize_from_buffer(Data + 1),
486 .bit_range = *Data } };
488 if constexpr (opcode == Instruction::OPCODE::ADD || opcode == Instruction::OPCODE::MULTIPLY ||
489 opcode == Instruction::OPCODE::DIVIDE || opcode == Instruction::OPCODE::SUBTRACT) {
490 return Instruction{ .id =
static_cast<typename Instruction::OPCODE
>(opcode),
491 .arguments.threeArgs = { .in1 = *Data, .in2 = *(Data + 1), .out = *(Data + 2) } };
493 if constexpr (opcode == Instruction::OPCODE::MADD || opcode == Instruction::OPCODE::ADD_TWO ||
494 opcode == Instruction::OPCODE::SUBTRACT_WITH_CONSTRAINT) {
495 return Instruction{ .id =
static_cast<typename Instruction::OPCODE
>(opcode),
496 .arguments.fourArgs = {
497 .in1 = *Data, .in2 = *(Data + 1), .in3 = *(Data + 2), .out = *(Data + 3) } };
499 if constexpr (opcode == Instruction::OPCODE::DIVIDE_WITH_CONSTRAINTS) {
500 return Instruction{ .id =
static_cast<typename Instruction::OPCODE
>(opcode),
501 .arguments.fiveArgs = { .in1 = *Data,
505 .out = *(Data + 4) } };
507 if constexpr (opcode == Instruction::OPCODE::SLICE) {
508 return Instruction{ .id =
static_cast<typename Instruction::OPCODE
>(opcode),
509 .arguments.sliceArgs = { .in1 = *Data,
514 .out3 = *(Data + 5) } };
516 if constexpr (opcode == Instruction::OPCODE::RANDOMSEED) {
518 memcpy(&randomseed, Data,
sizeof(uint32_t));
519 return Instruction{ .id =
static_cast<typename Instruction::OPCODE
>(opcode),
520 .arguments.randomseed = randomseed };
530 template <
typename Instruction::OPCODE instruction_opcode>
533 if constexpr (instruction_opcode == Instruction::OPCODE::CONSTANT ||
534 instruction_opcode == Instruction::OPCODE::WITNESS ||
535 instruction_opcode == Instruction::OPCODE::CONSTANT_WITNESS) {
536 *Data = instruction.id;
537 *(Data + 1) = instruction.arguments.element.bit_range;
538 fr::serialize_to_buffer(instruction.arguments.element.value, Data + 2);
541 if constexpr (instruction_opcode == Instruction::OPCODE::ADD ||
542 instruction_opcode == Instruction::OPCODE::DIVIDE ||
543 instruction_opcode == Instruction::OPCODE::MULTIPLY ||
544 instruction_opcode == Instruction::OPCODE::SUBTRACT) {
545 *Data = instruction.id;
546 *(Data + 1) = instruction.arguments.threeArgs.in1;
547 *(Data + 2) = instruction.arguments.threeArgs.in2;
548 *(Data + 3) = instruction.arguments.threeArgs.out;
550 if constexpr (instruction_opcode == Instruction::OPCODE::ADD_TWO ||
551 instruction_opcode == Instruction::OPCODE::MADD ||
552 instruction_opcode == Instruction::OPCODE::SUBTRACT_WITH_CONSTRAINT) {
553 *Data = instruction.id;
554 *(Data + 1) = instruction.arguments.fourArgs.in1;
555 *(Data + 2) = instruction.arguments.fourArgs.in2;
556 *(Data + 3) = instruction.arguments.fourArgs.in3;
557 *(Data + 4) = instruction.arguments.fourArgs.out;
559 if constexpr (instruction_opcode == Instruction::OPCODE::DIVIDE_WITH_CONSTRAINTS) {
560 *Data = instruction.id;
561 *(Data + 1) = instruction.arguments.fiveArgs.in1;
562 *(Data + 2) = instruction.arguments.fiveArgs.in2;
563 *(Data + 3) = instruction.arguments.fiveArgs.qbs;
564 *(Data + 4) = instruction.arguments.fiveArgs.rbs;
565 *(Data + 5) = instruction.arguments.fiveArgs.out;
567 if constexpr (instruction_opcode == Instruction::OPCODE::SLICE) {
568 *Data = instruction.id;
569 *(Data + 1) = instruction.arguments.sliceArgs.in1;
570 *(Data + 2) = instruction.arguments.sliceArgs.lsb;
571 *(Data + 3) = instruction.arguments.sliceArgs.msb;
572 *(Data + 4) = instruction.arguments.sliceArgs.out1;
573 *(Data + 5) = instruction.arguments.sliceArgs.out2;
574 *(Data + 6) = instruction.arguments.sliceArgs.out3;
576 if constexpr (instruction_opcode == Instruction::OPCODE::RANDOMSEED) {
578 *Data = instruction.id;
579 memcpy(Data + 1, &instruction.arguments.randomseed,
sizeof(uint32_t));
590 const bool reconstruct =
static_cast<bool>(VarianceRNG.next() % 2);
602 uint512_t reference_value;
611 if (r >=
static_cast<uint512_t
>(fr::modulus)) {
612 circuit_should_fail =
true;
621 if (r >=
static_cast<uint512_t
>(fr::modulus)) {
623 circuit_should_fail =
true;
627 : reference_value(s.get_value())
632 return ExecutionHandler(this->reference_value + other.reference_value, this->s() + other.s());
636 if ((this->reference_value - other.reference_value) >= (uint512_t(1) << difference_bit_size)) {
637 circuit_should_fail =
true;
640 this->s().subtract(other.s(), difference_bit_size));
644 return ExecutionHandler(this->reference_value - other.reference_value, this->s() - other.s());
648 return ExecutionHandler(this->reference_value * other.reference_value, this->s() * other.s());
652 if (other.s().get_value() == 0) {
653 circuit_should_fail =
true;
655 auto quotient =
static_cast<uint512_t
>(this->reference_value.lo / other.reference_value.lo);
656 auto remainder = this->reference_value.lo - quotient.lo * other.reference_value.lo;
657 if ((quotient.lo >= (
uint256_t(1) << quotient_bit_size)) ||
658 (remainder >= (
uint256_t(1) << remainder_bit_size))) {
659 circuit_should_fail =
true;
661 return ExecutionHandler(quotient, this->s().divide(other.s(), quotient_bit_size, remainder_bit_size));
665 if (other.s().get_value() == 0) {
666 circuit_should_fail =
true;
668 return ExecutionHandler(
static_cast<uint512_t
>(this->reference_value.lo / other.reference_value.lo),
669 this->s() / other.s());
675 return ExecutionHandler(this->reference_value + other1.reference_value + other2.reference_value,
676 this->s().add_two(other1.s(), other2.s()));
682 return ExecutionHandler(this->reference_value * other1.reference_value + other2.reference_value,
683 this->s().madd(other1.s(), other2.s()));
686 std::array<ExecutionHandler, 3> slice(uint8_t lsb, uint8_t msb)
688 const auto msb_plus_one = uint32_t(msb) + 1;
689 const auto hi_mask = ((
uint256_t(1) << (256 - uint32_t(msb))) - 1);
690 const auto hi_reference = (this->reference_value.lo >> msb_plus_one) & hi_mask;
692 const auto lo_mask = (
uint256_t(1) << lsb) - 1;
693 const auto lo_reference = this->reference_value.lo & lo_mask;
695 const auto slice_mask = ((
uint256_t(1) << (uint32_t(msb - lsb) + 1)) - 1);
696 const auto slice_reference = (this->reference_value.lo >> lsb) & slice_mask;
698 auto lo_slice_hi_suint_array = this->s().slice(msb, lsb);
699 return std::array<ExecutionHandler, 3>{
ExecutionHandler(lo_reference, lo_slice_hi_suint_array[0]),
713 std::vector<ExecutionHandler>& stack,
717 stack.push_back(
suint_t(instruction.arguments.element.value));
718#ifdef SHOW_INFORMATION
719 std::cout <<
"Pushed constant value " << instruction.arguments.element.value <<
" to position "
720 << stack.size() - 1 << std::endl;
734 std::vector<ExecutionHandler>& stack,
737 size_t bit_range =
static_cast<size_t>(instruction.arguments.element.bit_range);
739 if ((bit_range > suint_t::MAX_BIT_NUM) ||
740 (bit_range > 0 && (
uint256_t(instruction.arguments.element.value) >= (
uint256_t(1) << bit_range)))) {
744 if (bit_range == 0 && instruction.arguments.element.value != 0) {
745 circuit_should_fail =
true;
748 stack.push_back(
suint_t(
witness_t(builder, instruction.arguments.element.value),
749 instruction.arguments.element.bit_range));
750#ifdef SHOW_INFORMATION
751 std::cout <<
"Pushed witness value " << instruction.arguments.element.value <<
" < 2^" << (size_t)bit_range
752 <<
" to position " << stack.size() - 1 << std::endl;
766 std::vector<ExecutionHandler>& stack,
769 stack.push_back(suint_t::create_constant_witness(builder, instruction.arguments.element.value));
770#ifdef SHOW_INFORMATION
771 std::cout <<
"Pushed constant witness value " << instruction.arguments.element.value <<
" to position "
772 << stack.size() - 1 << std::endl;
785 std::vector<ExecutionHandler>& stack,
790 if (stack.size() == 0) {
793 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
794 size_t second_index = instruction.arguments.threeArgs.in2 % stack.size();
795 size_t output_index = instruction.arguments.threeArgs.out;
797 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"Multiplying",
"*")
800 if ((
static_cast<uint512_t
>(stack[first_index].suint.current_max) *
801 static_cast<uint512_t
>(stack[second_index].suint.current_max))
808 result = stack[first_index] * stack[second_index];
809 }
catch (std::runtime_error& err) {
810 if (!strncmp(err.what(),
811 "exceeded modulus in safe_uint class",
812 sizeof(
"exceeded modulus in safe_uint class"))) {
818 if (output_index >= stack.size()) {
819 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
820 stack.push_back(result);
823 PRINT_RESULT(
"",
"saved to ", output_index, result)
824 stack[output_index] = result;
837 std::vector<ExecutionHandler>& stack,
841 if (stack.size() == 0) {
844 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
845 size_t second_index = instruction.arguments.threeArgs.in2 % stack.size();
846 size_t output_index = instruction.arguments.threeArgs.out;
848 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"Adding",
"+")
852 result = stack[first_index] + stack[second_index];
853 }
catch (std::runtime_error& err) {
854 if (!strncmp(err.what(),
855 "exceeded modulus in safe_uint class",
856 sizeof(
"exceeded modulus in safe_uint class"))) {
862 if (output_index >= stack.size()) {
863 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
864 stack.push_back(result);
867 PRINT_RESULT(
"",
"saved to ", output_index, result)
868 stack[output_index] = result;
881 std::vector<ExecutionHandler>& stack,
885 if (stack.size() == 0) {
888 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
889 size_t second_index = instruction.arguments.threeArgs.in2 % stack.size();
890 size_t output_index = instruction.arguments.threeArgs.out;
892 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"Subtracting",
"-")
895 if ((
static_cast<uint512_t
>(1 << (stack[first_index].suint.current_max.get_msb() + 1)) +
896 static_cast<uint512_t
>(stack[second_index].suint.current_max)) > suint_t::MAX_VALUE) {
901 if (stack[first_index].suint.is_constant() && stack[second_index].suint.is_constant() &&
902 (
static_cast<uint256_t>(stack[first_index].suint.get_value()) <
903 static_cast<uint256_t>(stack[second_index].suint.get_value()))) {
909 if ((stack[first_index].suint.current_max.get_msb() + 1) > suint_t::MAX_BIT_NUM) {
914 result = stack[first_index] - stack[second_index];
915 }
catch (std::runtime_error& err) {
916 if (!strncmp(err.what(),
917 "exceeded modulus in safe_uint class",
918 sizeof(
"exceeded modulus in safe_uint class"))) {
921 if (!strncmp(err.what(),
922 "maximum value exceeded in safe_uint minus operator",
923 sizeof(
"maximum value exceeded in safe_uint minus operator"))) {
929 if (output_index >= stack.size()) {
930 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
931 stack.push_back(result);
934 PRINT_RESULT(
"",
"saved to ", output_index, result)
935 stack[output_index] = result;
948 std::vector<ExecutionHandler>& stack,
952 if (stack.size() == 0) {
955 size_t first_index = instruction.arguments.threeArgs.in1 % stack.size();
956 size_t second_index = instruction.arguments.threeArgs.in2 % stack.size();
957 size_t output_index = instruction.arguments.threeArgs.out;
959 PRINT_TWO_ARG_INSTRUCTION(first_index, second_index, stack,
"Dividing",
"/")
961 if (stack[first_index].suint.value.is_constant()) {
966 if ((((uint512_t(1) << (stack[first_index].suint.current_max.get_msb() + 1)) - 1) *
967 stack[second_index].suint.current_max)
973 result = stack[first_index] / stack[second_index];
974 }
catch (std::runtime_error& err) {
975 if (!strncmp(err.what(),
976 "exceeded modulus in safe_uint class",
977 sizeof(
"exceeded modulus in safe_uint class"))) {
980 if (!strncmp(err.what(),
981 "maximum value exceeded in safe_uint minus operator",
982 sizeof(
"maximum value exceeded in safe_uint minus operator"))) {
988 if (stack[first_index].suint.get_value().is_zero() && stack[second_index].suint.get_value().is_zero()) {
989 circuit_should_fail =
true;
992 if (output_index >= stack.size()) {
993 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
994 stack.push_back(result);
997 PRINT_RESULT(
"",
"saved to ", output_index, result)
998 stack[output_index] = result;
1012 std::vector<ExecutionHandler>& stack,
1016 if (stack.size() == 0) {
1019 size_t first_index = instruction.arguments.fourArgs.in1 % stack.size();
1020 size_t second_index = instruction.arguments.fourArgs.in2 % stack.size();
1021 size_t third_index = instruction.arguments.fourArgs.in3 % stack.size();
1022 size_t output_index = instruction.arguments.fourArgs.out;
1023 PRINT_THREE_ARG_INSTRUCTION(first_index, second_index, third_index, stack,
"ADD_TWO:",
"+",
"+")
1025 if ((
static_cast<uint512_t
>(stack[first_index].suint.current_max) +
1026 static_cast<uint512_t
>(stack[second_index].suint.current_max) +
1027 static_cast<uint512_t
>(stack[third_index].suint.current_max)) >
1028 static_cast<uint512_t
>(suint_t::MAX_VALUE)) {
1033 result = stack[first_index].add_two(stack[second_index], stack[third_index]);
1034 }
catch (std::runtime_error& err) {
1035 if (!strncmp(err.what(),
1036 "exceeded modulus in safe_uint class",
1037 sizeof(
"exceeded modulus in safe_uint class"))) {
1043 if (output_index >= stack.size()) {
1044 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1045 stack.push_back(result);
1048 PRINT_RESULT(
"",
"saved to ", output_index, result)
1049 stack[output_index] = result;
1063 std::vector<ExecutionHandler>& stack,
1067 if (stack.size() == 0) {
1070 size_t first_index = instruction.arguments.fourArgs.in1 % stack.size();
1071 size_t second_index = instruction.arguments.fourArgs.in2 % stack.size();
1072 size_t third_index = instruction.arguments.fourArgs.in3 % stack.size();
1073 size_t output_index = instruction.arguments.fourArgs.out;
1074 PRINT_THREE_ARG_INSTRUCTION(first_index, second_index, third_index, stack,
"MADD:",
"*",
"+")
1077 if ((
static_cast<uint512_t
>(stack[first_index].suint.current_max) *
1078 static_cast<uint512_t
>(stack[second_index].suint.current_max) +
1079 static_cast<uint512_t
>(stack[third_index].suint.current_max)) >
1080 static_cast<uint512_t
>(suint_t::MAX_VALUE)) {
1085 result = stack[first_index].madd(stack[second_index], stack[third_index]);
1086 }
catch (std::runtime_error& err) {
1087 if (!strncmp(err.what(),
1088 "exceeded modulus in safe_uint class",
1089 sizeof(
"exceeded modulus in safe_uint class"))) {
1095 if (output_index >= stack.size()) {
1096 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1097 stack.push_back(result);
1100 PRINT_RESULT(
"",
"saved to ", output_index, result)
1101 stack[output_index] = result;
1116 std::vector<ExecutionHandler>& stack,
1120 if (stack.size() == 0) {
1123 size_t first_index = instruction.arguments.fourArgs.in1 % stack.size();
1124 size_t second_index = instruction.arguments.fourArgs.in2 % stack.size();
1125 size_t difference_bit_size = instruction.arguments.fourArgs.in3;
1126 size_t output_index = instruction.arguments.fourArgs.out;
1127 PRINT_TWO_ARG_ONE_VALUE_INSTRUCTION(
1128 first_index, second_index, difference_bit_size, stack,
"SUBTRACT_WITH_CONSTRAINT:",
"-",
"<= 2**")
1131 if (difference_bit_size > suint_t::MAX_BIT_NUM) {
1135 if (stack[first_index].suint.is_constant() && stack[second_index].suint.is_constant()) {
1140 result = stack[first_index].subtract(stack[second_index], difference_bit_size);
1141 }
catch (std::runtime_error& err) {
1142 if (!strncmp(err.what(),
1143 "maximum value exceeded in safe_uint subtract",
1144 sizeof(
"maximum value exceeded in safe_uint subtract"))) {
1150 if (output_index >= stack.size()) {
1151 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1152 stack.push_back(result);
1155 PRINT_RESULT(
"",
"saved to ", output_index, result)
1156 stack[output_index] = result;
1171 std::vector<ExecutionHandler>& stack,
1175 if (stack.size() == 0) {
1178 size_t first_index = instruction.arguments.fiveArgs.in1 % stack.size();
1179 size_t second_index = instruction.arguments.fiveArgs.in2 % stack.size();
1180 size_t quotient_bit_size = instruction.arguments.fiveArgs.qbs;
1181 size_t remainder_bit_size = instruction.arguments.fiveArgs.rbs;
1182 size_t output_index = instruction.arguments.fiveArgs.out;
1183 PRINT_TWO_ARG_TWO_VALUES_INSTRUCTION(first_index,
1188 "DIVIDE_WITH_CONSTRAINTS:",
1194 if ((quotient_bit_size > suint_t::MAX_BIT_NUM) || (remainder_bit_size > suint_t::MAX_BIT_NUM)) {
1198 if (stack[first_index].suint.is_constant()) {
1203 result = stack[first_index].divide(stack[second_index], quotient_bit_size, remainder_bit_size);
1204 }
catch (std::runtime_error& err) {
1205 if (!strncmp(err.what(),
1206 "exceeded modulus in safe_uint class",
1207 sizeof(
"exceeded modulus in safe_uint class"))) {
1210 if (!strncmp(err.what(),
1211 "maximum value exceeded in safe_uint minus operator",
1212 sizeof(
"maximum value exceeded in safe_uint minus operator"))) {
1218 if (output_index >= stack.size()) {
1219 PRINT_RESULT(
"",
"pushed to ", stack.size(), result)
1220 stack.push_back(result);
1223 PRINT_RESULT(
"",
"saved to ", output_index, result)
1224 stack[output_index] = result;
1238 std::vector<ExecutionHandler>& stack,
1242 if (stack.size() == 0) {
1245 size_t first_index = instruction.arguments.sliceArgs.in1 % stack.size();
1246 uint8_t lsb = instruction.arguments.sliceArgs.lsb;
1247 uint8_t msb = instruction.arguments.sliceArgs.msb;
1248 size_t second_index = instruction.arguments.sliceArgs.out1;
1249 size_t third_index = instruction.arguments.sliceArgs.out2;
1250 size_t output_index = instruction.arguments.sliceArgs.out3;
1251 PRINT_SLICE(first_index, lsb, msb, stack)
1253 if ((lsb > msb) || (msb > 252) ||
1254 (
static_cast<uint256_t>(stack[first_index].suint.get_value()) >=
1255 (
static_cast<uint256_t>(1) << grumpkin::MAX_NO_WRAP_INTEGER_BIT_LENGTH))) {
1258 PRINT_SLICE(first_index, lsb, msb, stack)
1259 auto slices = stack[first_index].slice(lsb, msb);
1260 std::array<std::pair<ExecutionHandler, size_t>, 3> what_where = { std::make_pair(slices[0], second_index),
1261 std::make_pair(slices[1], third_index),
1262 std::make_pair(slices[2], output_index) };
1263 for (
auto& x : what_where) {
1264 auto suints_count = stack.size();
1265 if (x.second >= suints_count) {
1267 PRINT_RESULT(
"\t",
"pushed to ", stack.size(), x.first)
1268 stack.push_back(x.first);
1271 PRINT_RESULT(
"\t",
"saved to ", x.second, x.first)
1272 stack[x.second] = x.first;
1287 std::vector<ExecutionHandler>& stack,
1293 VarianceRNG.reseed(instruction.arguments.randomseed);
1298 typedef std::vector<ExecutionHandler> ExecutionState;
1303extern "C" int LLVMFuzzerInitialize(
int* argc,
char*** argv)
1310 .GEN_LLVM_POST_MUTATION_PROB = 30,
1311 .GEN_MUTATION_COUNT_LOG = 5,
1312 .GEN_STRUCTURAL_MUTATION_PROBABILITY = 300,
1313 .GEN_VALUE_MUTATION_PROBABILITY = 700,
1314 .ST_MUT_DELETION_PROBABILITY = 100,
1315 .ST_MUT_DUPLICATION_PROBABILITY = 80,
1316 .ST_MUT_INSERTION_PROBABILITY = 120,
1317 .ST_MUT_MAXIMUM_DELETION_LOG = 6,
1318 .ST_MUT_MAXIMUM_DUPLICATION_LOG = 2,
1319 .ST_MUT_SWAP_PROBABILITY = 50,
1320 .VAL_MUT_LLVM_MUTATE_PROBABILITY = 250,
1321 .VAL_MUT_MONTGOMERY_PROBABILITY = 130,
1322 .VAL_MUT_NON_MONTGOMERY_PROBABILITY = 50,
1323 .VAL_MUT_SMALL_ADDITION_PROBABILITY = 110,
1324 .VAL_MUT_SPECIAL_VALUE_PROBABILITY = 130
1391 std::vector<size_t> structural_mutation_distribution;
1392 std::vector<size_t> value_mutation_distribution;
1394 temp += fuzzer_havoc_settings.ST_MUT_DELETION_PROBABILITY;
1395 structural_mutation_distribution.push_back(temp);
1396 temp += fuzzer_havoc_settings.ST_MUT_DUPLICATION_PROBABILITY;
1397 structural_mutation_distribution.push_back(temp);
1398 temp += fuzzer_havoc_settings.ST_MUT_INSERTION_PROBABILITY;
1399 structural_mutation_distribution.push_back(temp);
1400 temp += fuzzer_havoc_settings.ST_MUT_SWAP_PROBABILITY;
1401 structural_mutation_distribution.push_back(temp);
1402 fuzzer_havoc_settings.structural_mutation_distribution = structural_mutation_distribution;
1405 temp += fuzzer_havoc_settings.VAL_MUT_LLVM_MUTATE_PROBABILITY;
1406 value_mutation_distribution.push_back(temp);
1407 temp += fuzzer_havoc_settings.VAL_MUT_SMALL_ADDITION_PROBABILITY;
1408 value_mutation_distribution.push_back(temp);
1410 temp += fuzzer_havoc_settings.VAL_MUT_SPECIAL_VALUE_PROBABILITY;
1411 value_mutation_distribution.push_back(temp);
1412 fuzzer_havoc_settings.value_mutation_distribution = value_mutation_distribution;
1416#ifndef DISABLE_CUSTOM_MUTATORS
1421extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* Data,
size_t Size,
size_t MaxSize,
unsigned int Seed)
1426 if ((fast_random.next() % 200) < fuzzer_havoc_settings.GEN_LLVM_POST_MUTATION_PROB) {
1427 size_occupied = LLVMFuzzerMutate(Data, size_occupied, MaxSize);
1429 return size_occupied;
1436extern "C" size_t LLVMFuzzerCustomCrossOver(
const uint8_t* Data1,
1438 const uint8_t* Data2,
1458extern "C" size_t LLVMFuzzerTestOneInput(
const uint8_t* Data,
size_t Size)
1460 RunWithBuilders<SafeUintFuzzBase, FuzzerCircuitTypes>(Data, Size, VarianceRNG);
1464#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
Class for quickly deterministically creating new random values. We don't care about distribution much...
Definition: fuzzer.hpp:64
Definition: safe_uint.fuzzer.hpp:451
This class implements the execution of safeuint with an oracle to detect discrepancies.
Definition: safe_uint.fuzzer.hpp:587
static size_t execute_SUBTRACT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the subtraction operator instruction.
Definition: safe_uint.fuzzer.hpp:880
static size_t execute_MULTIPLY(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the multiply instruction.
Definition: safe_uint.fuzzer.hpp:784
static size_t execute_SLICE(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the slice instruction.
Definition: safe_uint.fuzzer.hpp:1237
static size_t execute_SUBTRACT_WITH_CONSTRAINT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SUBTRACT_WITH_CONSTRAINT instruction.
Definition: safe_uint.fuzzer.hpp:1115
static size_t execute_MADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the MADD instruction.
Definition: safe_uint.fuzzer.hpp:1062
static size_t execute_CONSTANT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the constant instruction (push constant safeuint to the stack)
Definition: safe_uint.fuzzer.hpp:712
static size_t execute_DIVIDE_WITH_CONSTRAINTS(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Definition: safe_uint.fuzzer.hpp:1170
static size_t execute_DIVIDE(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the division operator instruction.
Definition: safe_uint.fuzzer.hpp:947
static size_t execute_ADD_TWO(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the ADD_TWO instruction.
Definition: safe_uint.fuzzer.hpp:1011
static size_t execute_RANDOMSEED(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the RANDOMSEED instruction.
Definition: safe_uint.fuzzer.hpp:1286
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: safe_uint.fuzzer.hpp:765
static size_t execute_WITNESS(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the witness instruction (push witness safeuit to the stack)
Definition: safe_uint.fuzzer.hpp:733
static size_t execute_ADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the addition operator instruction.
Definition: safe_uint.fuzzer.hpp:836
A class representing a single fuzzing instruction.
Definition: safe_uint.fuzzer.hpp:124
static Instruction generateRandom(T &rng)
Generate a random instruction.
Definition: safe_uint.fuzzer.hpp:193
static Instruction mutateInstruction(Instruction instruction, T &rng, HavocSettings &havoc_config)
Mutate a single instruction.
Definition: safe_uint.fuzzer.hpp:383
static fr mutateFieldElement(fr e, T &rng, HavocSettings &havoc_config)
Mutate the value of a field element.
Definition: safe_uint.fuzzer.hpp:289
Parser class handles the parsing and writing the instructions back to data buffer.
Definition: safe_uint.fuzzer.hpp:471
static void writeInstruction(Instruction &instruction, uint8_t *Data)
Write a single instruction to buffer.
Definition: safe_uint.fuzzer.hpp:531
static Instruction parseInstructionArgs(uint8_t *Data)
Parse a single instruction from data.
Definition: safe_uint.fuzzer.hpp:480
The class parametrizing SafeUint fuzzing instructions, execution, etc.
Definition: safe_uint.fuzzer.hpp:111
Definition: uint256.hpp:25
Definition: standard_circuit_builder.hpp:12
Definition: witness.hpp:51
Definition: safe_uint.hpp:17
Definition: witness.hpp:10
Concept for a simple PRNG which returns a uint32_t when next is called.
Definition: fuzzer.hpp:91
Definition: fuzzer.hpp:27
Definition: safe_uint.fuzzer.hpp:142
Definition: safe_uint.fuzzer.hpp:157
Definition: safe_uint.fuzzer.hpp:151
Definition: safe_uint.fuzzer.hpp:165
Definition: safe_uint.fuzzer.hpp:146
Definition: safe_uint.fuzzer.hpp:173