259 auto current_mul_term = arg.
mul_terms.begin();
278 std::set<uint32_t> all_mul_terms;
284 std::set<uint32_t> processed_mul_terms;
290 if (current_mul_term != arg.
mul_terms.end()) {
297 if (!processed_mul_terms.contains(mul_gate.
a) || !processed_mul_terms.contains(mul_gate.
b)) {
300 if (w == mul_gate.
a) {
301 if (!processed_mul_terms.contains(mul_gate.
a)) {
303 processed_mul_terms.insert(w);
305 if (mul_gate.
a == mul_gate.
b) {
308 }
else if (w == mul_gate.
b) {
309 if (!processed_mul_terms.contains(mul_gate.
b)) {
311 processed_mul_terms.insert(w);
318 current_mul_term = std::next(current_mul_term);
321 done = current_mul_term == arg.
mul_terms.end();
326 if (!all_mul_terms.contains(w)) {
337 current_linear_term = std::next(current_linear_term);
342 result.push_back(mul_gate);
584 .result = arg.output.
value,
585 .num_bits = arg.num_bits,
586 .is_xor_gate =
false,
596 .result = arg.output.
value,
597 .num_bits = arg.num_bits,
606 .num_bits = arg.num_bits,
619 .iv =
transform::map(*arg.iv, [](
auto& e) { return parse_input(e); }),
620 .key =
transform::map(*arg.key, [](
auto& e) { return parse_input(e); }),
621 .outputs =
transform::map(arg.outputs, [](
auto& e) { return e.value; }),
630 .hash_values =
transform::map(*arg.hash_values, [](
auto& e) { return parse_input(e); }),
631 .result =
transform::map(*arg.outputs, [](
auto& e) { return e.value; }),
642 .blackbox_input = parse_input(e),
656 [](
auto& e) { return Blake3Input{ .blackbox_input = parse_input(e), .num_bits = 8 }; }),
664 af.ecdsa_k1_constraints.push_back(EcdsaConstraint{
666 transform::map(*arg.hashed_message, [](
auto& e) { return get_witness_from_function_input(e); }),
668 transform::map(*arg.signature, [](
auto& e) { return get_witness_from_function_input(e); }),
670 transform::map(*arg.public_key_x, [](
auto& e) { return get_witness_from_function_input(e); }),
672 transform::map(*arg.public_key_y, [](
auto& e) { return get_witness_from_function_input(e); }),
674 .result = arg.output.value,
676 af.constrained_witness.insert(af.ecdsa_k1_constraints.back().result);
677 af.original_opcode_indices.ecdsa_k1_constraints.push_back(opcode_index);
679 af.ecdsa_r1_constraints.push_back(EcdsaConstraint{
681 transform::map(*arg.hashed_message, [](
auto& e) { return get_witness_from_function_input(e); }),
683 transform::map(*arg.signature, [](
auto& e) { return get_witness_from_function_input(e); }),
685 transform::map(*arg.public_key_x, [](
auto& e) { return get_witness_from_function_input(e); }),
687 transform::map(*arg.public_key_y, [](
auto& e) { return get_witness_from_function_input(e); }),
689 .result = arg.output.value,
691 af.constrained_witness.insert(af.ecdsa_r1_constraints.back().result);
692 af.original_opcode_indices.ecdsa_r1_constraints.push_back(opcode_index);
694 af.multi_scalar_mul_constraints.push_back(MultiScalarMul{
695 .points =
transform::map(arg.points, [](
auto& e) { return parse_input(e); }),
696 .scalars =
transform::map(arg.scalars, [](
auto& e) { return parse_input(e); }),
698 .out_point_x = (*arg.outputs)[0].
value,
699 .out_point_y = (*arg.outputs)[1].value,
700 .out_point_is_infinite = (*arg.outputs)[2].
value,
702 af.constrained_witness.insert(af.multi_scalar_mul_constraints.back().out_point_x);
703 af.constrained_witness.insert(af.multi_scalar_mul_constraints.back().out_point_y);
704 af.constrained_witness.insert(af.multi_scalar_mul_constraints.back().out_point_is_infinite);
705 af.original_opcode_indices.multi_scalar_mul_constraints.push_back(opcode_index);
709 auto input_1_infinite =
parse_input((*arg.input1)[2]);
712 auto input_2_infinite =
parse_input((*arg.input2)[2]);
715 af.ec_add_constraints.push_back(EcAdd{
716 .input1_x = input_1_x,
717 .input1_y = input_1_y,
718 .input1_infinite = input_1_infinite,
719 .input2_x = input_2_x,
720 .input2_y = input_2_y,
721 .input2_infinite = input_2_infinite,
722 .predicate = predicate,
723 .result_x = (*arg.outputs)[0].
value,
724 .result_y = (*arg.outputs)[1].value,
725 .result_infinite = (*arg.outputs)[2].
value,
727 af.constrained_witness.insert(af.ec_add_constraints.back().result_x);
728 af.constrained_witness.insert(af.ec_add_constraints.back().result_y);
729 af.constrained_witness.insert(af.ec_add_constraints.back().result_infinite);
730 af.original_opcode_indices.ec_add_constraints.push_back(opcode_index);
732 af.keccak_permutations.push_back(Keccakf1600{
733 .state =
transform::map(*arg.inputs, [](
auto& e) { return parse_input(e); }),
734 .result =
transform::map(*arg.outputs, [](
auto& e) { return e.value; }),
736 for (
auto& output : af.keccak_permutations.back().result) {
737 af.constrained_witness.insert(output);
739 af.original_opcode_indices.keccak_permutations.push_back(opcode_index);
744 auto proof_type_in = arg.proof_type;
746 if (predicate.is_constant && predicate.value.is_zero()) {
750 auto c = RecursionConstraint{
752 [](
auto& e) { return get_witness_from_function_input(e); }),
753 .proof =
transform::map(arg.proof, [](
auto& e) { return get_witness_from_function_input(e); }),
755 transform::map(arg.public_inputs, [](
auto& e) { return get_witness_from_function_input(e); }),
756 .key_hash = input_key,
757 .proof_type = proof_type_in,
758 .predicate = predicate,
762 switch (c.proof_type) {
767 af.honk_recursion_constraints.push_back(c);
768 af.original_opcode_indices.honk_recursion_constraints.push_back(opcode_index);
774 af.pg_recursion_constraints.push_back(c);
775 af.original_opcode_indices.pg_recursion_constraints.push_back(opcode_index);
778 af.avm_recursion_constraints.push_back(c);
779 af.original_opcode_indices.avm_recursion_constraints.push_back(opcode_index);
782 af.civc_recursion_constraints.push_back(c);
783 af.original_opcode_indices.civc_recursion_constraints.push_back(opcode_index);
789 af.poseidon2_constraints.push_back(Poseidon2Constraint{
790 .state =
transform::map(arg.inputs, [](
auto& e) { return parse_input(e); }),
791 .result =
transform::map(arg.outputs, [](
auto& e) { return e.value; }),
793 for (
auto& output : af.poseidon2_constraints.back().result) {
794 af.constrained_witness.insert(output);
796 af.original_opcode_indices.poseidon2_constraints.push_back(opcode_index);