51bool solve_witnesses(std::vector<Acir::Expression>& expressions,
52 uint32_t num_witnesses,
63 for (
const auto& expr : expressions) {
65 for (
const auto& [coeff_bytes, w1, w2] : expr.mul_terms) {
66 witness_has_nonlinear[w1.value] =
true;
67 witness_has_nonlinear[w2.value] =
true;
72 for (
const auto& expr : expressions) {
73 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
75 if (!witness_has_nonlinear.contains(w.value)) {
76 linear_only_witnesses.insert(w.value);
83 for (
auto& expr : expressions) {
87 for (
const auto& [coeff_bytes, w1, w2] : expr.mul_terms) {
89 value += coeff * witnesses[w1.value] * witnesses[w2.value];
92 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
94 value += coeff * witnesses[w.value];
104 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
105 if (linear_only_witnesses.contains(w.value)) {
107 linear_witness_coeffs[w.value] += coeff;
112 for (
const auto& [w_idx, total_coeff] : linear_witness_coeffs) {
117 for (
const auto& [coeff_bytes, w1, w2] : expr.mul_terms) {
119 value_without_witness += coeff * witnesses[w1.value] * witnesses[w2.value];
121 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
122 if (w.value != w_idx) {
124 value_without_witness += coeff * witnesses[w.value];
130 witnesses[w_idx] = -value_without_witness / total_coeff;
146 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
147 linear_only_witnesses.erase(w.value);
167 for (
const auto& [coeff_bytes, w1, w2] : expr.mul_terms) {
175 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
193 for (
size_t i = 0; i <
acir_format.quad_constraints.size(); ++i) {
194 const auto& gate =
acir_format.quad_constraints[i];
196 std::cerr <<
" a=" << gate.a <<
", b=" << gate.b <<
", c=" << gate.c <<
", d=" << gate.d <<
std::endl;
204 std::cerr <<
" Represents: " << gate.mul_scaling <<
"*w" << gate.a <<
"*w" << gate.b <<
" + " << gate.a_scaling
205 <<
"*w" << gate.a <<
" + " << gate.b_scaling <<
"*w" << gate.b <<
" + " << gate.c_scaling <<
"*w"
206 << gate.c <<
" + " << gate.d_scaling <<
"*w" << gate.d <<
" + " << gate.const_scaling <<
" = 0"
211 for (
size_t expr_idx = 0; expr_idx <
acir_format.big_quad_constraints.size(); ++expr_idx) {
212 const auto& gates =
acir_format.big_quad_constraints[expr_idx];
213 std::cerr <<
"\nBig Expression " << expr_idx <<
" (" << gates.size() <<
" gates):" <<
std::endl;
214 for (
size_t i = 0; i < gates.size(); ++i) {
215 const auto& gate = gates[i];
216 std::cerr <<
" Gate " << i <<
": " << gate.mul_scaling <<
"*w" << gate.a <<
"*w" << gate.b <<
" + "
217 << gate.a_scaling <<
"*w" << gate.a <<
" + " << gate.b_scaling <<
"*w" << gate.b <<
" + "
218 << gate.c_scaling <<
"*w" << gate.c <<
" + " << gate.d_scaling <<
"*w" << gate.d <<
" + "
219 << gate.const_scaling <<
" = 0" <<
std::endl;
229void print_expressions_and_witnesses(
const std::vector<Acir::Expression>& expressions,
236 for (
const auto& [idx,
value] : witnesses) {
242 for (
size_t i = 0; i < expressions.size(); ++i) {
243 const auto& expr = expressions[i];
253 for (
const auto& [coeff_bytes, w1, w2] : expr.mul_terms) {
262 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
270 for (
const auto& [coeff_bytes, w1, w2] : expr.mul_terms) {
272 auto it1 = witnesses.find(w1.value);
273 auto it2 = witnesses.find(w2.value);
274 if (it1 != witnesses.end() && it2 != witnesses.end()) {
275 value += coeff * it1->second * it2->second;
278 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
280 auto it = witnesses.find(w.value);
281 if (it != witnesses.end()) {
282 value += coeff * it->second;
303bool validate_witnesses(
const std::vector<Acir::Expression>& expressions,
305 bool expect_satisfied =
true)
307 (void)expect_satisfied;
308 size_t unsatisfied_count = 0;
310 for (
size_t i = 0; i < expressions.size(); ++i) {
311 const auto& expr = expressions[i];
316 for (
const auto& [coeff_bytes, w1, w2] : expr.mul_terms) {
318 auto it1 = witnesses.find(w1.value);
319 auto it2 = witnesses.find(w2.value);
320 if (it1 != witnesses.end() && it2 != witnesses.end()) {
321 value += coeff * it1->second * it2->second;
325 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
327 auto it = witnesses.find(w.value);
328 if (it != witnesses.end()) {
329 value += coeff * it->second;
341 return unsatisfied_count == 0;
347struct LogicConstraintInfo {
349 bool lhs_is_constant;
350 bool rhs_is_constant;
351 uint32_t lhs_witness;
352 uint32_t rhs_witness;
355 uint32_t output_witness;
363fr compute_and(
const fr& lhs,
const fr& rhs, uint32_t num_bits)
368 uint256_t result = (lhs_int & rhs_int) & mask;
375fr compute_xor(
const fr& lhs,
const fr& rhs, uint32_t num_bits)
380 uint256_t result = ((lhs_int ^ rhs_int) & mask);
393 input.
value = witness_input;
404 constant_input.
value.resize(32);
406 std::copy(value_bytes.begin(), value_bytes.end(), constant_input.
value.begin());
409 input.
value = constant_input;
420bool test_acir_circuit(
const uint8_t*
data,
size_t size)
432 bool disable_sanitization =
false;
433#ifdef ENABLE_UNSANITIZED_FUZZING
435 disable_sanitization = (
data[0] % 10) == 0;
446 uint32_t scale_factor = 1;
449 size_t temp_size = size / 64;
450 while (temp_size > 1 && scale_factor < 10) {
456 uint32_t max_witnesses = std::min(10u * scale_factor, 100u);
457 uint32_t max_expressions = std::min(3u * scale_factor, 20u);
458 uint32_t max_vm_steps = std::min(10u * scale_factor, 50u);
460 uint32_t num_witnesses = (
data[0] % max_witnesses) + 2;
461 uint32_t num_expressions = (
data[1] % max_expressions) + 1;
462 size_t coeff_vm_steps = (
data[2] % max_vm_steps) + 3;
463 size_t witness_vm_steps = (
data[3] % max_vm_steps) + 3;
464 uint8_t range_constraint_byte =
data[4];
465 uint8_t logic_constraint_byte =
data[5];
467 const uint8_t* vm_data =
data + 6;
468 size_t vm_data_size = size - 6;
472 size_t coeff_consumed = coeff_vm.run(vm_data, vm_data_size,
false);
473 const auto& coeff_state = coeff_vm.field_internal_state;
476 const uint8_t* witness_vm_data = vm_data + coeff_consumed;
477 size_t witness_vm_data_size = (coeff_consumed < vm_data_size) ? (vm_data_size - coeff_consumed) : 0;
479 if (witness_vm_data_size < 10)
483 size_t witness_consumed = witness_vm.run(witness_vm_data, witness_vm_data_size,
false);
484 const auto& witness_state = witness_vm.field_internal_state;
487 const uint8_t* ptr = witness_vm_data + witness_consumed;
488 size_t remaining = (witness_consumed < witness_vm_data_size) ? (witness_vm_data_size - witness_consumed) : 0;
494 std::vector<Acir::Expression> expressions;
495 for (uint32_t e = 0; e < num_expressions && remaining > 2; ++e) {
501 uint8_t max_mul_terms =
static_cast<uint8_t
>(std::min(1u + scale_factor / 2, 5u));
502 uint8_t max_lin_terms =
static_cast<uint8_t
>(std::min(3u + scale_factor, 10u));
504 uint8_t num_mul = (ptr[0] %
std::max(max_mul_terms,
static_cast<uint8_t
>(1)));
505 uint8_t num_lin = 1 + (ptr[1] %
std::max(max_lin_terms,
static_cast<uint8_t
>(1)));
510 for (uint8_t m = 0; m < num_mul && remaining >= 3; ++m) {
513 disable_sanitization ? *
reinterpret_cast<const uint16_t*
>(ptr + 1) : ptr[1] % num_witnesses;
515 disable_sanitization ? *
reinterpret_cast<const uint16_t*
>(ptr + 1) : ptr[2] % num_witnesses;
519 std::vector<uint8_t> coeff(32);
520 coeff = coeff_state[coeff_reg].
to_buffer();
524 expr.
mul_terms.push_back(std::make_tuple(coeff, w1, w2));
528 bool force_duplicate = (num_lin > 1) && (remaining > 0) && ((ptr[0] % 3) == 0);
529 uint32_t prev_witness = 0;
531 for (uint8_t l = 0; l < num_lin && remaining >= 2; ++l) {
533 uint32_t w_idx = disable_sanitization ? ptr[1] : ptr[1] % num_witnesses;
538 if (force_duplicate && l > 0 && l < 3) {
539 w_idx = prev_witness;
541 prev_witness = w_idx;
543 std::vector<uint8_t> coeff(32);
544 coeff = coeff_state[coeff_reg].
to_buffer();
555 expr.
q_c = coeff_state[const_reg].to_buffer();
557 expr.
q_c = std::vector<uint8_t>(32, 0);
560 expressions.push_back(expr);
563 if (expressions.empty())
567 std::vector<Acir::Expression> non_trivial_expressions;
568 for (
const auto& expr : expressions) {
569 if (!is_trivial_expression(expr)) {
570 non_trivial_expressions.push_back(expr);
575 if (non_trivial_expressions.empty()) {
580 expressions = non_trivial_expressions;
584 for (uint32_t i = 0; i < num_witnesses; ++i) {
590 solve_witnesses(expressions, num_witnesses, solved_witnesses);
601 bool witnesses_corrupted =
false;
602 std::vector<uint32_t> corrupted_witness_indices;
606 if (size > 4 && (
data[size - 1] % 5) == 0) {
607 witnesses_corrupted =
true;
608 uint32_t num_to_corrupt = 1 + (
data[size - 2] % 3);
609 bool actually_corrupted =
false;
611 for (uint32_t i = 0; i < num_to_corrupt && i < num_witnesses; ++i) {
612 size_t byte_idx = size - 3 - i;
614 uint32_t witness_to_corrupt = disable_sanitization ?
data[byte_idx] :
data[byte_idx] % num_witnesses;
617 if (already_corrupted.count(witness_to_corrupt) > 0) {
620 already_corrupted.insert(witness_to_corrupt);
622 fr original_value = solved_witnesses[witness_to_corrupt];
626 size_t mode_idx = (byte_idx > 1) ? byte_idx - 1 : 0;
627 size_t value_idx = (byte_idx > 2) ? byte_idx - 2 : 0;
628 uint8_t corruption_mode = (mode_idx >= 6) ? (
data[mode_idx] & 0x07) : 0;
629 uint8_t corruption_seed = (value_idx >= 6) ?
data[value_idx] : 1;
632 switch (corruption_mode) {
635 corruption_value =
fr(corruption_seed);
639 corruption_value = original_value +
fr(corruption_seed);
643 corruption_value = original_value -
fr(corruption_seed);
651 corruption_value =
fr(
uint256_t(corruption_seed) << 128);
655 corruption_value = -original_value;
663 corruption_value =
fr(
uint256_t(corruption_seed) << 64);
668 if (corruption_value == original_value) {
669 corruption_value = original_value +
fr::one();
671 if (corruption_value == original_value) {
672 corruption_value = original_value -
fr::one();
676 if (corruption_value != original_value) {
677 solved_witnesses[witness_to_corrupt] = corruption_value;
678 corrupted_witness_indices.push_back(witness_to_corrupt);
679 actually_corrupted =
true;
685 if (actually_corrupted) {
691 bool corrupted_witnesses_satisfy_constraints = validate_witnesses(expressions, solved_witnesses,
false);
693 if (corrupted_witnesses_satisfy_constraints) {
698 solved_witnesses = original_witnesses;
699 witnesses_corrupted =
false;
712 for (
const auto& expr : expressions) {
716 if (is_assert_equal_pattern) {
719 if (coeff1 == -coeff2 && coeff1 !=
fr::zero()) {
723 assert_equal_only_witnesses.insert(w1);
724 assert_equal_only_witnesses.insert(w2);
728 for (
const auto& [coeff_bytes, w1, w2] : expr.mul_terms) {
729 constrained_in_other_expressions.insert(w1.value);
730 constrained_in_other_expressions.insert(w2.value);
732 for (
const auto& [coeff_bytes, w] : expr.linear_combinations) {
733 constrained_in_other_expressions.insert(w.
value);
739 for (uint32_t w : constrained_in_other_expressions) {
740 assert_equal_only_witnesses.erase(w);
744 bool all_corrupted_are_assert_equal_only =
true;
745 for (uint32_t w : corrupted_witness_indices) {
746 if (assert_equal_only_witnesses.count(w) == 0) {
747 all_corrupted_are_assert_equal_only =
false;
752 if (all_corrupted_are_assert_equal_only && !assert_equal_only_witnesses.empty()) {
757 solved_witnesses = original_witnesses;
758 witnesses_corrupted =
false;
765 witnesses_corrupted =
false;
774 bool should_violate_range =
false;
775 uint32_t violated_witness_idx = 0;
776 uint32_t violated_range_bits = 0;
779 auto satisfies_range = [](
const fr&
value, uint32_t num_bits) ->
bool {
780 if (num_bits >= 254) {
789 return value_int == 0;
793 size_t msb = value_int.
get_msb();
794 return msb < num_bits;
798 if ((range_constraint_byte & 0x80) != 0 && num_witnesses > 1) {
800 uint32_t num_range_constraints = ((range_constraint_byte >> 5) & 0x3) + 1;
801 num_range_constraints = std::min(num_range_constraints, num_witnesses - 1);
805 for (uint32_t i = 0; i < num_range_constraints; ++i) {
807 size_t param_offset = i * 2;
810 uint8_t witness_byte = (param_offset < vm_data_size) ? vm_data[param_offset] : 0;
811 uint8_t bit_selector_byte = (param_offset + 1 < vm_data_size) ? vm_data[param_offset + 1] : 0;
813 uint32_t witness_idx = disable_sanitization ? witness_byte : witness_byte % num_witnesses;
814 uint8_t bit_selector = bit_selector_byte & 0x1F;
825 uint32_t num_bits = 0;
826 if (bit_selector < 8) {
828 }
else if (bit_selector < 14) {
830 }
else if (bit_selector < 18) {
832 }
else if (bit_selector < 21) {
834 }
else if (bit_selector < 24) {
836 }
else if (bit_selector < 28) {
838 }
else if (bit_selector < 30) {
845 auto it = minimal_range.find(witness_idx);
846 if (it == minimal_range.end() || num_bits < it->second) {
847 minimal_range[witness_idx] = num_bits;
854 bool has_accidental_violation =
false;
855 for (
const auto& [witness_idx, min_bits] : minimal_range) {
856 range_constraints.push_back({ witness_idx, min_bits });
858 auto it = solved_witnesses.find(witness_idx);
859 if (it != solved_witnesses.end()) {
860 if (!satisfies_range(it->second, min_bits)) {
861 has_accidental_violation =
true;
869 if (!has_accidental_violation && (range_constraint_byte & 0x10) != 0 && !minimal_range.empty()) {
872 size_t violate_idx = range_constraint_byte % minimal_range.size();
873 auto it = minimal_range.begin();
875 uint32_t candidate_witness = it->first;
876 uint32_t candidate_bits = it->second;
880 if (candidate_bits < 254) {
881 should_violate_range =
true;
882 violated_witness_idx = candidate_witness;
883 violated_range_bits = candidate_bits;
886 fr violation_value =
fr(1);
887 for (uint32_t
b = 0;
b < violated_range_bits; ++
b) {
888 violation_value = violation_value + violation_value;
890 solved_witnesses[violated_witness_idx] = violation_value;
893 }
else if (has_accidental_violation) {
897 for (
const auto& [witness_idx, min_bits] : minimal_range) {
898 auto it = solved_witnesses.find(witness_idx);
899 if (it != solved_witnesses.end() && min_bits < 254) {
900 if (!satisfies_range(it->second, min_bits)) {
901 should_violate_range =
true;
902 violated_witness_idx = witness_idx;
903 violated_range_bits = min_bits;
915 bool should_violate_logic =
false;
916 uint32_t violated_logic_idx = 0;
919 if ((logic_constraint_byte & 0x80) != 0 && num_witnesses >= 3) {
921 uint32_t num_logic_constraints = ((logic_constraint_byte >> 5) & 0x3) + 1;
922 num_logic_constraints = std::min(num_logic_constraints, (num_witnesses - 1) / 3 + 1);
925 uint32_t next_witness = num_witnesses;
927 for (uint32_t i = 0; i < num_logic_constraints; ++i) {
931 size_t param_offset = i * 3;
934 uint8_t control_byte = (param_offset < vm_data_size) ? vm_data[param_offset] : 0;
935 uint8_t lhs_byte = (param_offset + 1 < vm_data_size) ? vm_data[param_offset + 1] : 0;
936 uint8_t rhs_byte = (param_offset + 2 < vm_data_size) ? vm_data[param_offset + 2] : 0;
939 uint8_t bit_selector = control_byte & 0x3;
940 uint32_t num_bits = 8;
941 switch (bit_selector) {
962 bool is_xor = (control_byte & 0x04) != 0;
963 bool lhs_is_const = (control_byte & 0x08) != 0;
964 bool rhs_is_const = (control_byte & 0x10) != 0;
967 uint32_t lhs_idx = lhs_byte % num_witnesses;
968 uint32_t rhs_idx = rhs_byte % num_witnesses;
979 lhs_const =
fr(const_int);
985 rhs_const =
fr(const_int);
989 uint32_t out_idx = next_witness++;
991 logic_constraints.push_back(LogicConstraintInfo{ .lhs_is_constant = lhs_is_const,
992 .rhs_is_constant = rhs_is_const,
993 .lhs_witness = lhs_idx,
994 .rhs_witness = rhs_idx,
995 .lhs_constant = lhs_const,
996 .rhs_constant = rhs_const,
997 .output_witness = out_idx,
998 .num_bits = num_bits,
1003 num_witnesses = next_witness;
1008 for (
auto& lc : logic_constraints) {
1009 max_val_mask = (
uint256_t(1) << lc.num_bits) - 1;
1013 if (lc.lhs_is_constant) {
1014 lhs_val = lc.lhs_constant;
1016 lhs_val = solved_witnesses[lc.lhs_witness];
1018 lhs_val =
fr(lhs_int);
1020 solved_witnesses[lc.lhs_witness] = lhs_val;
1025 if (lc.rhs_is_constant) {
1026 rhs_val = lc.rhs_constant;
1028 rhs_val = solved_witnesses[lc.rhs_witness];
1030 rhs_val =
fr(rhs_int);
1032 solved_witnesses[lc.rhs_witness] = rhs_val;
1038 output_val = compute_xor(lhs_val, rhs_val, lc.num_bits);
1040 output_val = compute_and(lhs_val, rhs_val, lc.num_bits);
1042 solved_witnesses[lc.output_witness] = output_val;
1046 if ((logic_constraint_byte & 0x08) != 0 && !logic_constraints.empty()) {
1047 should_violate_logic =
true;
1048 violated_logic_idx = logic_constraint_byte %
static_cast<uint32_t
>(logic_constraints.size());
1050 const auto& violated_lc = logic_constraints[violated_logic_idx];
1051 fr correct_output = solved_witnesses[violated_lc.output_witness];
1055 size_t violation_offset = num_logic_constraints * 3;
1056 uint8_t violation_mode =
1057 (violation_offset < vm_data_size) ? (vm_data[violation_offset] & 0x07) : 0;
1058 uint8_t violation_value =
1059 (violation_offset + 1 < vm_data_size) ? vm_data[violation_offset + 1] : 1;
1061 fr corrupted_output;
1062 switch (violation_mode) {
1065 corrupted_output = correct_output +
fr(violation_value);
1069 corrupted_output = correct_output -
fr(violation_value);
1077 corrupted_output =
fr(violation_value);
1081 corrupted_output =
fr(
uint256_t(violation_value) << 8);
1085 corrupted_output = -correct_output;
1086 if (corrupted_output == correct_output) {
1093 if (!violated_lc.lhs_is_constant) {
1096 solved_witnesses[violated_lc.lhs_witness] =
fr(over_limit);
1099 corrupted_output = correct_output +
fr::one();
1103 if (!violated_lc.rhs_is_constant) {
1105 solved_witnesses[violated_lc.rhs_witness] =
fr(over_limit);
1107 corrupted_output = correct_output +
fr::one();
1112 if (corrupted_output == correct_output) {
1113 corrupted_output = correct_output +
fr::one();
1115 solved_witnesses[violated_lc.output_witness] = corrupted_output;
1131 for (
const auto& expr : expressions) {
1133 assert_zero.
value = expr;
1136 opcode.
value = assert_zero;
1137 circuit.
opcodes.push_back(opcode);
1141 for (
const auto& [witness_idx, num_bits] : range_constraints) {
1147 input.
value = witness_input;
1151 range_op.
input = input;
1156 bb_call.
value = range_op;
1160 bb_opcode.
value = bb_call;
1163 opcode.
value = bb_opcode;
1164 circuit.
opcodes.push_back(opcode);
1168 for (
const auto& lc : logic_constraints) {
1171 lc.lhs_is_constant ? make_constant_input(lc.lhs_constant) : make_witness_input(lc.lhs_witness);
1175 lc.rhs_is_constant ? make_constant_input(lc.rhs_constant) : make_witness_input(lc.rhs_witness);
1180 xor_op.
lhs = lhs_input;
1181 xor_op.
rhs = rhs_input;
1186 bb_call.
value = xor_op;
1189 bb_opcode.
value = bb_call;
1192 opcode.
value = bb_opcode;
1193 circuit.
opcodes.push_back(opcode);
1197 and_op.
lhs = lhs_input;
1198 and_op.
rhs = rhs_input;
1203 bb_call.
value = and_op;
1206 bb_opcode.
value = bb_call;
1209 opcode.
value = bb_opcode;
1210 circuit.
opcodes.push_back(opcode);
1222 witness_vec.reserve(num_witnesses);
1223 for (uint32_t i = 0; i < num_witnesses; ++i) {
1224 auto it = solved_witnesses.find(i);
1225 if (it != solved_witnesses.end()) {
1226 witness_vec.push_back(it->second);
1241#ifndef FUZZING_DISABLE_WARNINGS
1242 info(
"Circuit builder is in a failed state: ",
builder.err());
1251 if (should_violate_range) {
1252 fr actual_value = solved_witnesses[violated_witness_idx];
1253 if (satisfies_range(actual_value, violated_range_bits)) {
1255 should_violate_range =
false;
1262 if (witnesses_corrupted) {
1264 bool corruption_still_effective =
false;
1265 for (uint32_t corrupted_w : corrupted_witness_indices) {
1266 if (solved_witnesses[corrupted_w] != original_witnesses[corrupted_w]) {
1267 corruption_still_effective =
true;
1272 if (!corruption_still_effective) {
1274 witnesses_corrupted =
false;
1277 bool expressions_still_broken = !validate_witnesses(expressions, solved_witnesses,
false);
1278 if (!expressions_still_broken) {
1280 witnesses_corrupted =
false;
1286 if (witnesses_corrupted || should_violate_range || should_violate_logic) {
1287 if (circuit_valid) {
1289 if (witnesses_corrupted) {
1292 if (should_violate_range) {
1293 std::cerr <<
"Range constraint violation passed CircuitChecker verification!" <<
std::endl;
1294 std::cerr <<
"Violated witness: w" << violated_witness_idx <<
" (range: " << violated_range_bits
1296 std::cerr <<
"Witness value: " << solved_witnesses[violated_witness_idx] <<
std::endl;
1298 if (should_violate_logic) {
1299 std::cerr <<
"Logic constraint violation passed CircuitChecker verification!" <<
std::endl;
1300 const auto& violated_lc = logic_constraints[violated_logic_idx];
1301 std::cerr <<
"Violated logic op: " << (violated_lc.is_xor ?
"XOR" :
"AND") <<
std::endl;
1302 std::cerr <<
"LHS witness w" << violated_lc.lhs_witness <<
" = "
1303 << solved_witnesses[violated_lc.lhs_witness] <<
std::endl;
1304 std::cerr <<
"RHS witness w" << violated_lc.rhs_witness <<
" = "
1305 << solved_witnesses[violated_lc.rhs_witness] <<
std::endl;
1306 std::cerr <<
"Output witness w" << violated_lc.output_witness <<
" = "
1307 << solved_witnesses[violated_lc.output_witness] <<
std::endl;
1310 std::cerr <<
"Num witnesses: " << num_witnesses <<
", Num expressions: " << expressions.size()
1312 print_expressions_and_witnesses(expressions, solved_witnesses);
1320 if (!circuit_valid) {
1323 std::cerr <<
"Num witnesses: " << num_witnesses <<
", Num expressions: " << expressions.size() <<
std::endl;
1324 print_expressions_and_witnesses(expressions, solved_witnesses);
1329 return circuit_valid;
1331 }
catch (
const std::exception& e) {
1353 test_acir_circuit(
data, size);
1363 if (size < 10 || max_size < 50) {
1368 int strategy =
static_cast<int>(
static_cast<unsigned>(
std::rand()) % 100u);
1370 if (strategy < 30) {
1373 size_t vm_section_start = 6;
1374 size_t vm_section_end = size / 2;
1375 if (vm_section_end > vm_section_start) {
1376 size_t pos = vm_section_start + (
static_cast<unsigned>(
std::rand()) %
1377 static_cast<unsigned>(vm_section_end - vm_section_start));
1378 data[pos] =
static_cast<uint8_t
>(
static_cast<unsigned>(
std::rand()) % 256u);
1381 }
else if (strategy < 55) {
1384 size_t expr_section_start = size / 2;
1385 size_t expr_section_end = size - 10;
1386 if (expr_section_end > expr_section_start) {
1387 size_t pos = expr_section_start + (
static_cast<unsigned>(
std::rand()) %
1388 static_cast<unsigned>(expr_section_end - expr_section_start));
1389 data[pos] =
static_cast<uint8_t
>(
static_cast<unsigned>(
std::rand()) % 256u);
1392 }
else if (strategy < 70) {
1396 static_cast<uint8_t
>(
static_cast<unsigned>(
std::rand()) % 256u);
1398 }
else if (strategy < 80) {
1400 if (size < max_size && max_size - size >= 32) {
1401 size_t grow_by = std::min(
static_cast<size_t>(32), max_size - size);
1403 for (
size_t i = 0; i < grow_by; ++i) {
1404 data[size + i] =
static_cast<uint8_t
>(
static_cast<unsigned>(
std::rand()) % 256u);
1406 return size + grow_by;
1408 }
else if (strategy < 85) {
1411 size_t shrink_by = std::min(
static_cast<size_t>(32), size - 50);
1412 return size - shrink_by;
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize)
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
LibFuzzer entry point.
size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t max_size, unsigned int seed)
Custom mutator for structure-aware mutations with size scaling.
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
constexpr uint64_t get_msb() const
const std::vector< MemoryValue > data
Field arithmetic fuzzer for testing cryptographic field operations.
Entry point for Barretenberg command-line interface.
const size_t INTERNAL_STATE_SIZE
Constant defining the number of elements in the VM's internal state.
field< Bn254FrParams > fr
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::vector< uint8_t > to_buffer(T const &value)
Acir::FunctionInput input
std::variant< AES128Encrypt, AND, XOR, RANGE, Blake2s, Blake3, EcdsaSecp256k1, EcdsaSecp256r1, MultiScalarMul, EmbeddedCurveAdd, Keccakf1600, RecursiveAggregation, Poseidon2Permutation, Sha256Compression > value
Acir::PublicInputs return_values
std::vector< Acir::Opcode > opcodes
uint32_t current_witness_index
std::vector< Acir::Witness > private_parameters
Acir::PublicInputs public_parameters
std::string function_name
std::vector< std::tuple< Acir::OpcodeLocation, Acir::AssertionPayload > > assert_messages
std::vector< std::tuple< std::vector< uint8_t >, Acir::Witness > > linear_combinations
std::vector< uint8_t > q_c
std::vector< std::tuple< std::vector< uint8_t >, Acir::Witness, Acir::Witness > > mul_terms
Acir::BlackBoxFuncCall value
std::variant< AssertZero, BlackBoxFuncCall, MemoryOp, MemoryInit, BrilligCall, Call > value
Virtual machine for field arithmetic operations.
static constexpr field one()
static field serialize_from_buffer(const uint8_t *buffer)
BB_INLINE std::vector< uint8_t > to_buffer() const
static constexpr field zero()