40#pragma clang diagnostic push
47#pragma clang diagnostic ignored "-Wc99-designator"
49#ifdef FUZZING_SHOW_INFORMATION
67template <
typename Stack>
68inline FormattedArgs format_single_arg(
const Stack& stack,
size_t first_index,
size_t output_index)
70 std::string
rhs = stack[first_index].cycle_group.is_constant() ?
"c" :
"w";
71 std::string out =
rhs;
73 out +=
std::to_string(output_index >= stack.size() ? stack.size() : output_index);
74 out = (output_index >= stack.size() ?
"auto " :
"") + out;
75 return FormattedArgs{ .lhs =
"", .rhs =
rhs, .out = out };
86template <
typename Stack>
87inline FormattedArgs format_two_arg(
const Stack& stack,
size_t first_index,
size_t second_index,
size_t output_index)
89 std::string lhs = stack[first_index].cycle_group.is_constant() ?
"c" :
"w";
90 std::string
rhs = stack[second_index].cycle_group.is_constant() ?
"c" :
"w";
92 (stack[first_index].cycle_group.is_constant() && stack[second_index].cycle_group.is_constant()) ?
"c" :
"w";
95 out +=
std::to_string(output_index >= stack.size() ? stack.size() : output_index);
96 out = (output_index >= stack.size() ?
"auto " :
"") + out;
97 return FormattedArgs{ .lhs = lhs, .rhs =
rhs, .out = out };
208#ifndef DISABLE_MULTIPLICATION
211#ifndef DISABLE_BATCH_MUL
282 template <
typename T>
287 uint8_t in, in1, in2, in3, out;
290 switch (instruction_opcode) {
294 auto scalar =
ScalarField(
static_cast<uint64_t
>(fast_log_distributed_uint256(rng)));
295 auto el = GroupElement::one() * scalar;
296 return { .id = instruction_opcode, .arguments.element =
Element(scalar, el) };
302 in =
static_cast<uint8_t
>(rng.next() & 0xff);
303 out =
static_cast<uint8_t
>(rng.next() & 0xff);
304 return { .id = instruction_opcode, .arguments.twoArgs = { .in = in, .out = out } };
307 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
308 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
309 out =
static_cast<uint8_t
>(rng.next() & 0xff);
310 return { .id = instruction_opcode,
311 .arguments.threeArgs.in1 = in1,
312 .arguments.threeArgs.in2 = in2,
313 .arguments.threeArgs.out = out };
315 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
316 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
317 in3 =
static_cast<uint8_t
>(rng.next() & 0xff);
318 out =
static_cast<uint8_t
>(rng.next() & 0xff);
319 return { .id = instruction_opcode,
320 .arguments.fourArgs.in1 = in1,
321 .arguments.fourArgs.in2 = in2,
322 .arguments.fourArgs.in3 = in3,
323 .arguments.fourArgs.out = out };
324#ifndef DISABLE_MULTIPLICATION
326 in =
static_cast<uint8_t
>(rng.next() & 0xff);
327 out =
static_cast<uint8_t
>(rng.next() & 0xff);
328 return { .id = instruction_opcode,
330 .arguments.mulArgs.in = in,
331 .arguments.mulArgs.out = out };
333#ifndef DISABLE_BATCH_MUL
344 instr.
id = instruction_opcode;
346 for (
size_t i = 0; i < mult_size; i++) {
349 for (
size_t i = 0; i < mult_size; i++) {
357 return { .
id = instruction_opcode, .arguments.randomseed = rng.next() * rng.next() };
380 if (from_montgomery) {
395 template <
typename T>
406 bool convert_to_montgomery = (rng.next() % (havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY +
407 havoc_config.VAL_MUT_NON_MONTGOMERY_PROBABILITY)) <
408 havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY;
409 bool normalize = (rng.next() % (havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY +
410 havoc_config.VAL_MUT_NON_MONTGOMERY_PROBABILITY)) <
411 havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY;
415 const size_t mutation_type_count = havoc_config.value_mutation_distribution.size();
417 const size_t choice = rng.next() % havoc_config.value_mutation_distribution[mutation_type_count - 1];
418 if (choice < havoc_config.value_mutation_distribution[0]) {
422 e.scalar = from_uint256_montgomery<ScalarField>(value_data, convert_to_montgomery);
423 e.value = GroupElement::one() * e.scalar;
424 }
else if (choice < havoc_config.value_mutation_distribution[1]) {
426 if (convert_to_montgomery) {
427 e.scalar = e.scalar.to_montgomery_form();
432 if (rng.next() & 1) {
433 auto switch_sign =
static_cast<bool>(rng.next() & 1);
436 e.value += GroupElement::one() * extra;
439 e.value -= GroupElement::one() * extra;
447 e.value = e.value.normalize();
449 if (convert_to_montgomery) {
450 e.scalar = e.scalar.from_montgomery_form();
452 }
else if (choice < havoc_config.value_mutation_distribution[2]) {
453 if (convert_to_montgomery) {
454 e.scalar = e.scalar.to_montgomery_form();
458 e.scalar = get_special_scalar_value<ScalarField>(special_value);
459 if (convert_to_montgomery) {
460 e.scalar = e.scalar.to_montgomery_form();
462 e.value = GroupElement::one() * e.scalar;
476 template <
typename T>
484 bool convert_to_montgomery = (rng.next() % (havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY +
485 havoc_config.VAL_MUT_NON_MONTGOMERY_PROBABILITY)) <
486 havoc_config.VAL_MUT_MONTGOMERY_PROBABILITY;
490 const size_t mutation_type_count = havoc_config.value_mutation_distribution.size();
492 const size_t choice = rng.next() % havoc_config.value_mutation_distribution[mutation_type_count - 1];
493 if (choice < havoc_config.value_mutation_distribution[0]) {
497 e = from_uint256_montgomery<ScalarField>(value_data, convert_to_montgomery);
498 }
else if (choice < havoc_config.value_mutation_distribution[1]) {
500 if (convert_to_montgomery) {
501 e = e.to_montgomery_form();
506 if (rng.next() & 1) {
507 auto switch_sign =
static_cast<bool>(rng.next() & 1);
517 if (convert_to_montgomery) {
518 e = e.from_montgomery_form();
520 }
else if (choice < havoc_config.value_mutation_distribution[2]) {
521 if (convert_to_montgomery) {
522 e = e.to_montgomery_form();
527 e = get_special_scalar_value<ScalarField>(special_value);
528 if (convert_to_montgomery) {
529 e = e.to_montgomery_form();
544 template <
typename T>
548#define PUT_RANDOM_BYTE_IF_LUCKY(variable) \
549 if (rng.next() & 1) { \
550 variable = rng.next() & 0xff; \
559 if (rng.next() & 1) {
572#ifndef DISABLE_MULTIPLICATION
576 if (rng.next() & 1) {
594#ifndef DISABLE_BATCH_MUL
596 if (rng.next() & 1) {
606 instruction.arguments.batchMulArgs.add_elements_count = mult_size;
608 if (
instruction.arguments.batchMulArgs.add_elements_count && (rng.next() & 1)) {
610 static_cast<uint8_t
>(rng.next() % (
instruction.arguments.batchMulArgs.add_elements_count));
611 for (
size_t i = 0; i < mut_count; i++) {
613 rng.next() %
static_cast<size_t>(
instruction.arguments.batchMulArgs.add_elements_count);
617 if (
instruction.arguments.batchMulArgs.add_elements_count && (rng.next() & 1)) {
619 static_cast<uint8_t
>(rng.next() % (
instruction.arguments.batchMulArgs.add_elements_count));
620 for (
size_t i = 0; i < mut_count; i++) {
622 rng.next() %
static_cast<size_t>(
instruction.arguments.batchMulArgs.add_elements_count);
647 static constexpr size_t DBL = 2;
648 static constexpr size_t NEG = 2;
650 static constexpr size_t SET = 2;
651 static constexpr size_t ADD = 3;
654#ifndef DISABLE_MULTIPLICATION
657#ifndef DISABLE_BATCH_MUL
670 static constexpr size_t SET = 0;
676 static constexpr size_t ADD = 1;
678 static constexpr size_t DBL = 1;
679 static constexpr size_t NEG = 1;
682#ifndef DISABLE_MULTIPLICATION
687#ifndef DISABLE_BATCH_MUL
713 auto scalar = ScalarField::serialize_from_buffer(Data);
714 auto el = GroupElement::one() * scalar;
729 instr.
arguments.
fourArgs = { .
in1 = *Data, .in2 = *(Data + 1), .in3 = *(Data + 2), .out = *(Data + 3) };
732#ifndef DISABLE_MULTIPLICATION
739#ifndef DISABLE_BATCH_MUL
752 for (
size_t i = 0; i < n; i++) {
774 template <
typename Instruction::OPCODE instruction_opcode>
778 switch (instruction_opcode) {
782 ScalarField::serialize_to_buffer(
instruction.arguments.element.scalar, Data + 1);
803#ifndef DISABLE_MULTIPLICATION
807 ScalarField::serialize_to_buffer(
instruction.arguments.mulArgs.scalar, Data + 3);
810#ifndef DISABLE_BATCH_MUL
812 *(Data + 1) =
instruction.arguments.batchMulArgs.add_elements_count;
813 *(Data + 2) =
instruction.arguments.batchMulArgs.output_index;
815 size_t n =
instruction.arguments.batchMulArgs.add_elements_count;
817 memcpy(Data + 3,
instruction.arguments.batchMulArgs.inputs, n);
819 for (
size_t i = 0; i < n; i++) {
820 ScalarField::serialize_to_buffer(
instruction.arguments.batchMulArgs.scalars[i], Data +
offset);
827 memcpy(Data + 1, &
instruction.arguments.randomseed,
sizeof(uint32_t));
847 const bool predicate_is_const =
static_cast<bool>(
VarianceRNG.
next() & 1);
848 if (predicate_is_const) {
849 const bool predicate_has_ctx =
static_cast<bool>(
VarianceRNG.
next() % 2);
850 debug_log(
"bool_t(", (predicate_has_ctx ?
"&builder," :
"nullptr,"), (predicate ?
"true)" :
"false)"));
851 return bool_t(predicate_has_ctx ?
builder :
nullptr, predicate);
853 debug_log(
"bool_t(witness_t(&builder, ", (predicate ?
"true));" :
"false))"));
942 bool smth_inf = this->cycle_group.is_point_at_infinity().get_value() ||
943 other.
cycle_group.is_point_at_infinity().get_value();
946 switch (add_option) {
948 debug_log(
"left.unconditional_add(right);",
"\n");
951 debug_log(
"right.unconditional_add(left);",
"\n");
952 return ExecutionHandler(base_scalar_res, base_res, other.
cg().unconditional_add(this->cg()));
954 debug_log(
"left.checked_unconditional_add(right);",
"\n");
955 return ExecutionHandler(base_scalar_res, base_res, this->
cg().checked_unconditional_add(other.
cg()));
957 debug_log(
"right.checked_unconditional_add(left);",
"\n");
958 return ExecutionHandler(base_scalar_res, base_res, other.
cg().checked_unconditional_add(this->cg()));
974 if (other.
cg().get_value() == this->cg().get_value()) {
979 if (other.
cg().get_value() == -this->cg().get_value()) {
1028 bool smth_inf = this->cycle_group.is_point_at_infinity().get_value() ||
1029 other.
cycle_group.is_point_at_infinity().get_value();
1032 switch (add_option) {
1034 debug_log(
"left.unconditional_subtract(right);",
"\n");
1035 return ExecutionHandler(base_scalar_res, base_res, this->
cg().unconditional_subtract(other.
cg()));
1037 debug_log(
"left.checked_unconditional_subtract(right);",
"\n");
1039 base_scalar_res, base_res, this->
cg().checked_unconditional_subtract(other.
cg()));
1055 if (other.
cg().get_value() == -this->cg().get_value()) {
1058 if (other.
cg().get_value() == this->cg().get_value()) {
1068 (is_witness ?
"::from_witness(&builder, " :
"("),
1072 auto scalar = is_witness ? cycle_scalar_t::from_witness(
builder, multiplier) :
cycle_scalar_t(multiplier);
1073 return ExecutionHandler(this->base_scalar * multiplier, this->base * multiplier, this->
cg() * scalar);
1078 const std::vector<ScalarField>& to_mul)
1081 to_add_cg.reserve(to_add.size());
1083 to_mul_cs.reserve(to_mul.size());
1088 for (
size_t i = 0; i < to_add.size(); i++) {
1093 (is_witness ?
"::from_witness(&builder, " :
"("),
1097 auto scalar = is_witness ? cycle_scalar_t::from_witness(
builder, to_mul[i]) :
cycle_scalar_t(to_mul[i]);
1098 to_mul_cs.push_back(scalar);
1100 accumulator_cg += to_add[i].base * to_mul[i];
1101 accumulator_cs += to_add[i].base_scalar * to_mul[i];
1103 accumulator_cg -= GroupElement::one();
1107 if (accumulator_cg.is_point_at_infinity()) {
1110 accumulator_cg += GroupElement::one();
1111 accumulator_cs += ScalarField::one();
1122 return ExecutionHandler(this->base_scalar + this->base_scalar, this->base.dbl(), this->cg().dbl());
1136 if (other.
cg().is_constant()) {
1137 if (this->
cg().is_constant()) {
1143 auto to_ae = other.
cg() + to_add;
1144 this->
cg().assert_equal(to_ae);
1151 switch (switch_case) {
1158 (this->cycle_group.is_constant() ?
"" :
"_constant"),
1159 "_witness(&builder, e.get_value());");
1162 if (this->cycle_group.is_constant()) {
1170 debug_log(
"res = cycle_group_t(tmp);",
"\n");
1173 cg_new = this->
cg();
1178 debug_log(
"res = cycle_group_t(std::move(tmp));",
"\n");
1206 "auto c", stack.size() - 1,
" = cycle_group_t(ae(\"",
instruction.arguments.element.scalar,
"\"));\n");
1229 " = cycle_group_t::from_witness(&builder, ae(\"",
1256 " = cycle_group_t::from_constant_witness(&builder, ae(\"",
1275 if (stack.size() == 0) {
1278 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
1279 size_t output_index =
instruction.arguments.twoArgs.out;
1282 auto args = format_single_arg(stack, first_index, output_index);
1283 debug_log(args.out,
" = ", args.rhs,
".dbl();",
"\n");
1287 if (output_index >= stack.size()) {
1288 stack.push_back(result);
1290 stack[output_index] = result;
1308 if (stack.size() == 0) {
1311 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
1312 size_t output_index =
instruction.arguments.twoArgs.out;
1315 auto args = format_single_arg(stack, first_index, output_index);
1316 debug_log(args.out,
" = -", args.rhs,
";",
"\n");
1320 if (output_index >= stack.size()) {
1321 stack.push_back(result);
1323 stack[output_index] = result;
1340 if (stack.size() == 0) {
1343 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
1344 size_t second_index =
instruction.arguments.twoArgs.out % stack.size();
1347 auto args = format_two_arg(stack, first_index, second_index, 0);
1348 debug_log(
"assert_equal(", args.lhs,
", ", args.rhs,
", builder);",
"\n");
1350 stack[first_index].assert_equal(
builder, stack[second_index]);
1367 if (stack.size() == 0) {
1370 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
1371 size_t output_index =
instruction.arguments.twoArgs.out;
1375 auto args = format_single_arg(stack, first_index, output_index);
1384 if (output_index >= stack.size()) {
1385 stack.push_back(result);
1387 stack[output_index] = result;
1405 if (stack.size() == 0) {
1408 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
1409 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
1410 size_t output_index =
instruction.arguments.threeArgs.out;
1413 auto args = format_two_arg(stack, first_index, second_index, output_index);
1414 debug_log(args.out,
" = ", args.lhs,
" + ", args.rhs,
";",
"\n");
1418 if (output_index >= stack.size()) {
1419 stack.push_back(result);
1421 stack[output_index] = result;
1439 if (stack.size() == 0) {
1442 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
1443 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
1444 size_t output_index =
instruction.arguments.threeArgs.out;
1447 auto args = format_two_arg(stack, first_index, second_index, output_index);
1448 debug_log(args.out,
" = ", args.lhs,
" - ", args.rhs,
";",
"\n");
1452 if (output_index >= stack.size()) {
1453 stack.push_back(result);
1455 stack[output_index] = result;
1473 if (stack.size() == 0) {
1476 size_t first_index =
instruction.arguments.fourArgs.in1 % stack.size();
1477 size_t second_index =
instruction.arguments.fourArgs.in2 % stack.size();
1478 size_t output_index =
instruction.arguments.fourArgs.out % stack.size();
1479 bool predicate =
instruction.arguments.fourArgs.in3 % 2;
1483 auto args = format_two_arg(stack, first_index, second_index, output_index);
1484 debug_log(args.out,
" = cycle_group_t::conditional_assign(");
1487 debug_log(args.rhs,
", ", args.lhs,
");",
"\n");
1493 if (output_index >= stack.size()) {
1494 stack.push_back(result);
1496 stack[output_index] = result;
1514 if (stack.size() == 0) {
1517 size_t first_index =
instruction.arguments.mulArgs.in % stack.size();
1518 size_t output_index =
instruction.arguments.mulArgs.out;
1522 auto args = format_single_arg(stack, first_index, output_index);
1527 if (output_index >= stack.size()) {
1528 stack.push_back(result);
1530 stack[output_index] = result;
1548 if (stack.size() == 0) {
1552 std::vector<ScalarField> to_mul;
1553 for (
size_t i = 0; i <
instruction.arguments.batchMulArgs.add_elements_count; i++) {
1554 to_add.push_back(stack[(
size_t)
instruction.arguments.batchMulArgs.inputs[i] % stack.size()]);
1555 to_mul.push_back(
instruction.arguments.batchMulArgs.scalars[i]);
1557 size_t output_index = (size_t)
instruction.arguments.batchMulArgs.output_index;
1561 std::string res =
"";
1562 bool is_const =
true;
1563 for (
size_t i = 0; i <
instruction.arguments.batchMulArgs.add_elements_count; i++) {
1564 size_t idx =
instruction.arguments.batchMulArgs.inputs[i] % stack.size();
1565 std::string el = stack[idx].
cycle_group.is_constant() ?
"c" :
"w";
1568 is_const &= stack[idx].cycle_group.is_constant();
1570 std::string out = is_const ?
"c" :
"w";
1571 out = ((output_index >= stack.size()) ?
"auto " :
"") + out;
1572 out +=
std::to_string(output_index >= stack.size() ? stack.size() : output_index);
1573 debug_log(out,
" = cycle_group_t::batch_mul({", res,
"}, {");
1581 if (output_index >= stack.size()) {
1582 stack.push_back(result);
1584 stack[output_index] = result;
1626 for (
size_t i = 0; i < stack.size(); i++) {
1627 auto element = stack[i];
1628 if (element.cycle_group.get_value() !=
AffineElement(element.base)) {
1630 <<
" and value in CycleGroup " << element.cycle_group.get_value() <<
std::endl;
1633 if ((AffineElement::one() * element.base_scalar) !=
AffineElement(element.base)) {
1634 std::cerr <<
"Failed at " << i <<
" with actual mul value " << element.base
1635 <<
" and value in scalar * CG " << element.cycle_group.get_value() * element.base_scalar
1653 .GEN_MUTATION_COUNT_LOG = 5,
1654 .GEN_STRUCTURAL_MUTATION_PROBABILITY = 300,
1655 .GEN_VALUE_MUTATION_PROBABILITY = 700,
1656 .ST_MUT_DELETION_PROBABILITY = 100,
1657 .ST_MUT_DUPLICATION_PROBABILITY = 80,
1658 .ST_MUT_INSERTION_PROBABILITY = 120,
1659 .ST_MUT_MAXIMUM_DELETION_LOG = 6,
1660 .ST_MUT_MAXIMUM_DUPLICATION_LOG = 2,
1661 .ST_MUT_SWAP_PROBABILITY = 50,
1662 .VAL_MUT_LLVM_MUTATE_PROBABILITY = 250,
1663 .VAL_MUT_MONTGOMERY_PROBABILITY = 130,
1664 .VAL_MUT_NON_MONTGOMERY_PROBABILITY = 50,
1665 .VAL_MUT_SMALL_ADDITION_PROBABILITY = 110,
1666 .VAL_MUT_SPECIAL_VALUE_PROBABILITY = 130,
1667 .structural_mutation_distribution = {},
1668 .value_mutation_distribution = {} };
1739 std::vector<size_t> structural_mutation_distribution;
1740 std::vector<size_t> value_mutation_distribution;
1742 temp += fuzzer_havoc_settings.ST_MUT_DELETION_PROBABILITY;
1743 structural_mutation_distribution.push_back(temp);
1744 temp += fuzzer_havoc_settings.ST_MUT_DUPLICATION_PROBABILITY;
1745 structural_mutation_distribution.push_back(temp);
1746 temp += fuzzer_havoc_settings.ST_MUT_INSERTION_PROBABILITY;
1747 structural_mutation_distribution.push_back(temp);
1748 temp += fuzzer_havoc_settings.ST_MUT_SWAP_PROBABILITY;
1749 structural_mutation_distribution.push_back(temp);
1750 fuzzer_havoc_settings.structural_mutation_distribution = structural_mutation_distribution;
1753 temp += fuzzer_havoc_settings.VAL_MUT_LLVM_MUTATE_PROBABILITY;
1754 value_mutation_distribution.push_back(temp);
1755 temp += fuzzer_havoc_settings.VAL_MUT_SMALL_ADDITION_PROBABILITY;
1756 value_mutation_distribution.push_back(temp);
1757 temp += fuzzer_havoc_settings.VAL_MUT_SPECIAL_VALUE_PROBABILITY;
1758 value_mutation_distribution.push_back(temp);
1760 fuzzer_havoc_settings.value_mutation_distribution = value_mutation_distribution;
1771 RunWithBuilders<CycleGroupBase, FuzzerCircuitTypes>(Data, Size,
VarianceRNG);
1775#pragma clang diagnostic pop
bb::field< bb::Bn254FrParams > FF
SpecialScalarValue
Special scalar field values used for mutation testing.
static constexpr size_t CONSTANT_WITNESS
static constexpr size_t ADD
static constexpr size_t CONSTANT
static constexpr size_t MULTIPLY
static constexpr size_t COND_ASSIGN
static constexpr size_t ASSERT_EQUAL
static constexpr size_t RANDOMSEED
static constexpr size_t DBL
static constexpr size_t BATCH_MUL
static constexpr size_t SET
static constexpr size_t WITNESS
static constexpr size_t NEG
static constexpr size_t SUBTRACT
This class implements the execution of cycle group with an oracle to detect discrepancies.
ExecutionHandler operator-()
static size_t execute_SUBTRACT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the subtraction operator instruction.
static size_t execute_COND_ASSIGN(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the COND_ASSIGN instruction.
ExecutionHandler()=default
static size_t execute_DBL(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the DBL instruction.
ExecutionHandler(ScalarField s, GroupElement g, cycle_group_t w_g)
ExecutionHandler handle_add_doubling_case(Builder *builder, const ExecutionHandler &other, const ScalarField &base_scalar_res, const GroupElement &base_res)
Handle addition when points are equal (requires doubling)
static bool_t construct_predicate(Builder *builder, const bool predicate)
ExecutionHandler handle_sub_normal_case(const ExecutionHandler &other, const ScalarField &base_scalar_res, const GroupElement &base_res)
Handle normal subtraction case (no special edge cases)
static size_t execute_NEG(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the NEG instruction.
static size_t execute_WITNESS(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the witness instruction (push witness cycle group to the stack)
ExecutionHandler handle_sub_doubling_case(Builder *builder, const ExecutionHandler &other, const ScalarField &base_scalar_res, const GroupElement &base_res)
Handle subtraction when points are negations: x - (-x) = 2x (doubling case)
static size_t execute_BATCH_MUL(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the BATCH_MUL instruction.
static size_t execute_RANDOMSEED(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the RANDOMSEED instruction.
static size_t execute_ASSERT_EQUAL(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the ASSERT_EQUAL instruction.
static size_t execute_SET(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SET instruction.
static size_t execute_CONSTANT_WITNESS(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the constant_witness instruction (push a cycle group witness equal to the constant to the sta...
static size_t execute_ADD(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the addition operator instruction.
ExecutionHandler mul(Builder *builder, const ScalarField &multiplier)
static ExecutionHandler batch_mul(Builder *builder, const std::vector< ExecutionHandler > &to_add, const std::vector< ScalarField > &to_mul)
ExecutionHandler handle_sub_infinity_case(const ExecutionHandler &other, const ScalarField &base_scalar_res, const GroupElement &base_res)
Handle subtraction when points are equal: x - x = 0 (point at infinity)
ExecutionHandler operator_sub(Builder *builder, const ExecutionHandler &other)
Subtract two ExecutionHandlers, exploring different code paths for edge cases.
static size_t execute_MULTIPLY(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the multiply instruction.
void assert_equal(Builder *builder, ExecutionHandler &other)
ExecutionHandler handle_add_infinity_case(const ExecutionHandler &other, const ScalarField &base_scalar_res, const GroupElement &base_res)
Handle addition when points are negations (result is point at infinity)
cycle_group_t cycle_group
ExecutionHandler handle_add_normal_case(const ExecutionHandler &other, const ScalarField &base_scalar_res, const GroupElement &base_res)
Handle normal addition (no special edge cases)
static size_t execute_CONSTANT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the constant instruction (push constant cycle group to the stack)
ExecutionHandler operator_add(Builder *builder, const ExecutionHandler &other)
ExecutionHandler conditional_assign(Builder *builder, ExecutionHandler &other, const bool predicate)
ExecutionHandler set(Builder *builder)
ArgumentContents arguments
static uint256_t to_uint256_montgomery(const FF &value, bool as_montgomery)
Convert a scalar field element to uint256_t, optionally using Montgomery form.
static Instruction generateRandom(T &rng)
Generates a random instruction.
static Instruction mutateInstruction(Instruction instruction, T &rng, HavocSettings &havoc_config)
Mutate a single instruction.
static FF from_uint256_montgomery(const uint256_t &data, bool from_montgomery)
Convert uint256_t back to scalar field element, optionally from Montgomery form.
static ScalarField mutateScalarElement(ScalarField e, T &rng, HavocSettings &havoc_config)
Mutate the value of a scalar element.
static Element mutateGroupElement(Element e, T &rng, HavocSettings &havoc_config)
Mutate the value of a group element.
Optional subclass that governs limits on the use of certain instructions, since some of them can be t...
static constexpr size_t RANDOMSEED
static constexpr size_t SET
static constexpr size_t BATCH_MUL
static constexpr size_t COND_ASSIGN
static constexpr size_t WITNESS
static constexpr size_t DBL
static constexpr size_t _LIMIT
static constexpr size_t SUBTRACT
static constexpr size_t ASSERT_EQUAL
static constexpr size_t CONSTANT_WITNESS
static constexpr size_t CONSTANT
static constexpr size_t MULTIPLY
static constexpr size_t NEG
static constexpr size_t ADD
Parser class handles the parsing and writing the instructions back to data buffer.
static void writeInstruction(Instruction &instruction, uint8_t *Data)
Write a single instruction to buffer.
static Instruction parseInstructionArgs(uint8_t *Data)
Parse a single instruction from data.
The class parametrizing CycleGroup fuzzing instructions, execution, etc.
typename bb::stdlib::witness_t< Builder > witness_t
typename bb::stdlib::cycle_group< Builder >::Curve Curve
typename bb::stdlib::cycle_group< Builder > cycle_group_t
typename bb::stdlib::field_t< Builder > field_t
static bool postProcess(Builder *builder, std::vector< CycleGroupBase::ExecutionHandler > &stack)
Check that the resulting values are equal to expected.
std::vector< ExecutionHandler > ExecutionState
typename bb::stdlib::bool_t< Builder > bool_t
typename cycle_group_t::cycle_scalar cycle_scalar_t
typename Curve::Element GroupElement
typename Curve::AffineElement AffineElement
typename Curve::ScalarField ScalarField
typename Curve::BaseField BaseField
Class for quickly deterministically creating new random values. We don't care about distribution much...
void reseed(uint32_t seed)
typename Group::element Element
typename Group::affine_element AffineElement
Implements boolean logic in-circuit.
cycle_group represents a group Element of the proving system's embedded curve, i.e....
static cycle_group from_constant_witness(Builder *_context, const AffineElement &_in)
Converts a native AffineElement into a witness, but constrains the witness values to be known constan...
static cycle_group conditional_assign(const bool_t &predicate, const cycle_group &lhs, const cycle_group &rhs)
static cycle_group from_witness(Builder *_context, const AffineElement &_in)
Converts an AffineElement into a circuit witness.
::bb::stdlib::cycle_scalar< Builder > cycle_scalar
static cycle_group batch_mul(const std::vector< cycle_group > &base_points, const std::vector< BigScalarField > &scalars, GeneratorContext context={})
Concept for a simple PRNG which returns a uint32_t when next is called.
const std::vector< MemoryValue > data
constexpr size_t MINIMUM_MUL_ELEMENTS
constexpr uint8_t SPECIAL_VALUE_COUNT_NO_ZERO
constexpr size_t MAXIMUM_MUL_ELEMENTS
constexpr uint8_t SPECIAL_VALUE_COUNT
SpecialScalarValue
Special scalar field values used for mutation testing.
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize)
FastRandom VarianceRNG(0)
int LLVMFuzzerInitialize(int *argc, char ***argv)
FF get_special_scalar_value(SpecialScalarValue type)
Generate a special scalar field value for testing.
size_t LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Fuzzer entry function.
#define PUT_RANDOM_BYTE_IF_LUCKY(variable)
void debug_log(Args &&... args)
Compile-time debug logging helper.
constexpr bool SHOW_FUZZING_INFO
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
BatchMulArgs batchMulArgs
uint8_t inputs[MAXIMUM_MUL_ELEMENTS]
ScalarField scalars[MAXIMUM_MUL_ELEMENTS]
uint8_t add_elements_count
Element(ScalarField s=ScalarField::one(), GroupElement g=GroupElement::one())
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 to_montgomery_form() const noexcept
constexpr std::pair< bool, field > sqrt() const noexcept
Compute square root of the field element.
BB_INLINE constexpr field from_montgomery_form() const noexcept
static constexpr field zero()