From e82f2b3c549e9019a3e1165244ded84c3cc322cb Mon Sep 17 00:00:00 2001 From: guipublic Date: Tue, 30 Jan 2024 15:01:25 +0000 Subject: [PATCH 01/10] first draft implementation for bigint opcodes --- .../dsl/acir_format/acir_format.cpp | 13 +- .../dsl/acir_format/acir_format.hpp | 2 + .../dsl/acir_format/acir_format.test.cpp | 5 + .../acir_format/acir_to_constraint_buf.hpp | 5 + .../dsl/acir_format/bigint_constraint.cpp | 410 +++++++++++++++++- .../dsl/acir_format/bigint_constraint.hpp | 160 ++++++- .../acir_format/bigint_constraint.test.cpp | 76 ++-- .../dsl/acir_format/ec_operations.test.cpp | 1 + .../dsl/acir_format/ecdsa_secp256k1.test.cpp | 3 + .../dsl/acir_format/ecdsa_secp256r1.test.cpp | 4 + .../acir_format/recursion_constraint.test.cpp | 2 + 11 files changed, 635 insertions(+), 46 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 360d43324e9..09cccb57dac 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -1,10 +1,14 @@ #include "acir_format.hpp" #include "barretenberg/common/log.hpp" +#include "barretenberg/dsl/acir_format/bigint_constraint.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" #include namespace acir_format { +template class DSLBigInts; +template class DSLBigInts; + template void build_constraints(Builder& builder, AcirFormat const& constraint_system, bool has_valid_witness_assignments) { @@ -90,11 +94,12 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo } // Add big_int constraints - for (const auto& constraint : constraint_system.bigint_operations) { - create_bigint_operations_constraint(builder, constraint); - } + DSLBigInts dsl_bigints; for (const auto& constraint : constraint_system.bigint_from_le_bytes_constraints) { - create_bigint_from_le_bytes_constraint(builder, constraint); + create_bigint_from_le_bytes_constraint(builder, constraint, dsl_bigints); + } + for (const auto& constraint : constraint_system.bigint_operations) { + create_bigint_operations_constraint(constraint, dsl_bigints); } // TODO(https://github.com/AztecProtocol/barretenberg/issues/817): disable these for UGH for now since we're not yet diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index f88777038b0..0cde29c1eb9 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -42,6 +42,7 @@ struct AcirFormat { std::vector ec_add_constraints; std::vector recursion_constraints; std::vector bigint_from_le_bytes_constraints; + std::vector bigint_to_le_bytes_constraints; std::vector bigint_operations; // A standard plonk arithmetic constraint, as defined in the poly_triple struct, consists of selector values @@ -74,6 +75,7 @@ struct AcirFormat { constraints, block_constraints, bigint_from_le_bytes_constraints, + bigint_to_le_bytes_constraints, bigint_operations); friend bool operator==(AcirFormat const& lhs, AcirFormat const& rhs) = default; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index 3c85f61d4d1..b4b3a6f7af9 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -47,6 +47,7 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = { constraint }, .block_constraints = {}, @@ -159,6 +160,7 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = { expr_a, expr_b, expr_c, expr_d }, .block_constraints = {} }; @@ -223,6 +225,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = { poly_triple{ .a = schnorr_constraint.result, @@ -315,6 +318,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = { poly_triple{ .a = schnorr_constraint.result, @@ -426,6 +430,7 @@ TEST_F(AcirFormatTests, TestVarKeccak) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = { dummy }, .block_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index 058feb5e6a9..b024540c2b3 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -256,6 +256,11 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .modulus = map(arg.modulus, [](auto& e) -> uint32_t { return e; }), .result = arg.output, }); + } else if constexpr (std::is_same_v) { + af.bigint_to_le_bytes_constraints.push_back(BigIntToLeBytes{ + .input = arg.input, + .result = map(arg.outputs, [](auto& e) { return e.value; }), + }); } else if constexpr (std::is_same_v) { af.bigint_operations.push_back(BigIntOperation{ .lhs = arg.lhs, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp index 4780e5ca36c..d1dc660d464 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp @@ -1,33 +1,413 @@ #include "bigint_constraint.hpp" +#include "barretenberg/common/assert.hpp" #include "barretenberg/dsl/types.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" +#include +#include namespace acir_format { -template void create_bigint_operations_constraint(Builder& builder, const BigIntOperation& input) +ModulusId modulus_param_to_id(ModulusParam param) { - // TODO - (void)builder; - info(input); + if (Bn254FqParams::modulus_0 == param.modulus_0 && Bn254FqParams::modulus_1 == param.modulus_1 && + Bn254FqParams::modulus_2 == param.modulus_2 && Bn254FqParams::modulus_3 == param.modulus_3) { + return ModulusId::BN254_FQ; + } + if (Bn254FrParams::modulus_0 == param.modulus_0 && Bn254FrParams::modulus_1 == param.modulus_1 && + Bn254FrParams::modulus_2 == param.modulus_2 && Bn254FrParams::modulus_3 == param.modulus_3) { + return ModulusId::BN254_FR; + } + if (secp256k1::Secp256k1FqParams::modulus_0 == param.modulus_0 && + secp256k1::Secp256k1FqParams::modulus_1 == param.modulus_1 && + secp256k1::Secp256k1FqParams::modulus_2 == param.modulus_2 && + secp256k1::Secp256k1FqParams::modulus_3 == param.modulus_3) { + return ModulusId::SECP256K1_FQ; + } + if (secp256k1::Secp256k1FrParams::modulus_0 == param.modulus_0 && + secp256k1::Secp256k1FrParams::modulus_1 == param.modulus_1 && + secp256k1::Secp256k1FrParams::modulus_2 == param.modulus_2 && + secp256k1::Secp256k1FrParams::modulus_3 == param.modulus_3) { + return ModulusId::SECP256K1_FR; + } + if (secp256r1::Secp256r1FqParams::modulus_0 == param.modulus_0 && + secp256r1::Secp256r1FqParams::modulus_1 == param.modulus_1 && + secp256r1::Secp256r1FqParams::modulus_2 == param.modulus_2 && + secp256r1::Secp256r1FqParams::modulus_3 == param.modulus_3) { + return ModulusId::SECP256R1_FQ; + } + if (secp256r1::Secp256r1FrParams::modulus_0 == param.modulus_0 && + secp256r1::Secp256r1FrParams::modulus_1 == param.modulus_1 && + secp256r1::Secp256r1FrParams::modulus_2 == param.modulus_2 && + secp256r1::Secp256r1FrParams::modulus_3 == param.modulus_3) { + return ModulusId::SECP256R1_FR; + } + + return ModulusId::UNKNOWN; } -template void create_bigint_operations_constraint(UltraCircuitBuilder& builder, - const BigIntOperation& input); -template void create_bigint_operations_constraint(GoblinUltraCircuitBuilder& builder, - const BigIntOperation& input); +template class DSLBigInts; +template class DSLBigInts; + +template void create_bigint_operations_constraint(const BigIntOperation& input, + DSLBigInts& dsl_bigint); +template void create_bigint_operations_constraint( + const BigIntOperation& input, DSLBigInts& dsl_bigint); +template void create_bigint_addition_constraint(const BigIntOperation& input, + DSLBigInts& dsl_bigint); +template void create_bigint_addition_constraint( + const BigIntOperation& input, DSLBigInts& dsl_bigint); +template void create_bigint_neg_constraint(const BigIntOperation& input, + DSLBigInts& dsl_bigint); +template void create_bigint_neg_constraint( + const BigIntOperation& input, DSLBigInts& dsl_bigint); +template void create_bigint_mul_constraint(const BigIntOperation& input, + DSLBigInts& dsl_bigint); +template void create_bigint_mul_constraint( + const BigIntOperation& input, DSLBigInts& dsl_bigint); +template void create_bigint_div_constraint(const BigIntOperation& input, + DSLBigInts& dsl_bigint); +template void create_bigint_div_constraint( + const BigIntOperation& input, DSLBigInts& dsl_bigint); template -void create_bigint_from_le_bytes_constraint(Builder& builder, const BigIntFromLeBytes& input) +void create_bigint_addition_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint) { - // TODO - (void)builder; - info(input); + switch (dsl_bigint.get_modulus_id(input.lhs)) { + case ModulusId::BN254_FR: { + auto lhs = dsl_bigint.bn254_fr(input.lhs); + auto rhs = dsl_bigint.bn254_fr(input.rhs); + dsl_bigint.set_bn254_fr(lhs + rhs, input.result); + } + case ModulusId::BN254_FQ: { + auto lhs = dsl_bigint.bn254_fq(input.lhs); + auto rhs = dsl_bigint.bn254_fq(input.rhs); + dsl_bigint.set_bn254_fq(lhs + rhs, input.result); + } + case ModulusId::SECP256K1_FQ: { + auto lhs = dsl_bigint.secp256k1_fq(input.lhs); + auto rhs = dsl_bigint.secp256k1_fq(input.rhs); + dsl_bigint.set_secp256k1_fq(lhs + rhs, input.result); + } + case ModulusId::SECP256K1_FR: { + auto lhs = dsl_bigint.secp256k1_fr(input.lhs); + auto rhs = dsl_bigint.secp256k1_fr(input.rhs); + dsl_bigint.set_secp256k1_fr(lhs + rhs, input.result); + } + case ModulusId::SECP256R1_FQ: { + auto lhs = dsl_bigint.secp256r1_fq(input.lhs); + auto rhs = dsl_bigint.secp256r1_fq(input.rhs); + dsl_bigint.set_secp256r1_fq(lhs + rhs, input.result); + } + case ModulusId::SECP256R1_FR: { + auto lhs = dsl_bigint.secp256r1_fr(input.lhs); + auto rhs = dsl_bigint.secp256r1_fr(input.rhs); + dsl_bigint.set_secp256r1_fr(lhs + rhs, input.result); + } + default: { + ASSERT(false); + } + } +} + +template +void create_bigint_neg_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint) +{ + switch (dsl_bigint.get_modulus_id(input.lhs)) { + case ModulusId::BN254_FR: { + auto lhs = dsl_bigint.bn254_fr(input.lhs); + auto rhs = dsl_bigint.bn254_fr(input.rhs); + dsl_bigint.set_bn254_fr(lhs - rhs, input.result); + } + case ModulusId::BN254_FQ: { + auto lhs = dsl_bigint.bn254_fq(input.lhs); + auto rhs = dsl_bigint.bn254_fq(input.rhs); + dsl_bigint.set_bn254_fq(lhs - rhs, input.result); + } + case ModulusId::SECP256K1_FQ: { + auto lhs = dsl_bigint.secp256k1_fq(input.lhs); + auto rhs = dsl_bigint.secp256k1_fq(input.rhs); + dsl_bigint.set_secp256k1_fq(lhs - rhs, input.result); + } + case ModulusId::SECP256K1_FR: { + auto lhs = dsl_bigint.secp256k1_fr(input.lhs); + auto rhs = dsl_bigint.secp256k1_fr(input.rhs); + dsl_bigint.set_secp256k1_fr(lhs - rhs, input.result); + } + case ModulusId::SECP256R1_FQ: { + auto lhs = dsl_bigint.secp256r1_fq(input.lhs); + auto rhs = dsl_bigint.secp256r1_fq(input.rhs); + dsl_bigint.set_secp256r1_fq(lhs - rhs, input.result); + } + case ModulusId::SECP256R1_FR: { + auto lhs = dsl_bigint.secp256r1_fr(input.lhs); + auto rhs = dsl_bigint.secp256r1_fr(input.rhs); + dsl_bigint.set_secp256r1_fr(lhs - rhs, input.result); + } + default: { + ASSERT(false); + } + } +} + +template +void create_bigint_mul_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint) +{ + switch (dsl_bigint.get_modulus_id(input.lhs)) { + case ModulusId::BN254_FR: { + auto lhs = dsl_bigint.bn254_fr(input.lhs); + auto rhs = dsl_bigint.bn254_fr(input.rhs); + dsl_bigint.set_bn254_fr(lhs * rhs, input.result); + } + case ModulusId::BN254_FQ: { + auto lhs = dsl_bigint.bn254_fq(input.lhs); + auto rhs = dsl_bigint.bn254_fq(input.rhs); + dsl_bigint.set_bn254_fq(lhs * rhs, input.result); + } + case ModulusId::SECP256K1_FQ: { + auto lhs = dsl_bigint.secp256k1_fq(input.lhs); + auto rhs = dsl_bigint.secp256k1_fq(input.rhs); + dsl_bigint.set_secp256k1_fq(lhs * rhs, input.result); + } + case ModulusId::SECP256K1_FR: { + auto lhs = dsl_bigint.secp256k1_fr(input.lhs); + auto rhs = dsl_bigint.secp256k1_fr(input.rhs); + dsl_bigint.set_secp256k1_fr(lhs * rhs, input.result); + } + case ModulusId::SECP256R1_FQ: { + auto lhs = dsl_bigint.secp256r1_fq(input.lhs); + auto rhs = dsl_bigint.secp256r1_fq(input.rhs); + dsl_bigint.set_secp256r1_fq(lhs * rhs, input.result); + } + case ModulusId::SECP256R1_FR: { + auto lhs = dsl_bigint.secp256r1_fr(input.lhs); + auto rhs = dsl_bigint.secp256r1_fr(input.rhs); + dsl_bigint.set_secp256r1_fr(lhs * rhs, input.result); + } + default: { + ASSERT(false); + } + } +} + +template +void create_bigint_div_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint) +{ + switch (dsl_bigint.get_modulus_id(input.lhs)) { + case ModulusId::BN254_FR: { + auto lhs = dsl_bigint.bn254_fr(input.lhs); + auto rhs = dsl_bigint.bn254_fr(input.rhs); + dsl_bigint.set_bn254_fr(lhs / rhs, input.result); + } + case ModulusId::BN254_FQ: { + auto lhs = dsl_bigint.bn254_fq(input.lhs); + auto rhs = dsl_bigint.bn254_fq(input.rhs); + dsl_bigint.set_bn254_fq(lhs / rhs, input.result); + } + case ModulusId::SECP256K1_FQ: { + auto lhs = dsl_bigint.secp256k1_fq(input.lhs); + auto rhs = dsl_bigint.secp256k1_fq(input.rhs); + dsl_bigint.set_secp256k1_fq(lhs / rhs, input.result); + } + case ModulusId::SECP256K1_FR: { + auto lhs = dsl_bigint.secp256k1_fr(input.lhs); + auto rhs = dsl_bigint.secp256k1_fr(input.rhs); + dsl_bigint.set_secp256k1_fr(lhs / rhs, input.result); + } + case ModulusId::SECP256R1_FQ: { + auto lhs = dsl_bigint.secp256r1_fq(input.lhs); + auto rhs = dsl_bigint.secp256r1_fq(input.rhs); + dsl_bigint.set_secp256r1_fq(lhs / rhs, input.result); + } + case ModulusId::SECP256R1_FR: { + auto lhs = dsl_bigint.secp256r1_fr(input.lhs); + auto rhs = dsl_bigint.secp256r1_fr(input.rhs); + dsl_bigint.set_secp256r1_fr(lhs / rhs, input.result); + } + default: { + ASSERT(false); + } + } +} + +template +void create_bigint_operations_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint) +{ + switch (input.opcode) { + case BigIntOperationType::Add: { + create_bigint_addition_constraint(input, dsl_bigint); + break; + } + case BigIntOperationType::Neg: { + create_bigint_neg_constraint(input, dsl_bigint); + break; + } + case BigIntOperationType::Mul: { + create_bigint_mul_constraint(input, dsl_bigint); + break; + } + case BigIntOperationType::Div: { + create_bigint_div_constraint(input, dsl_bigint); + break; + } + default: { + ASSERT(false); + } + } +} +// DSLBigInts; + +// template DSLBigInts& DSLBigInts::get(); + +template +void create_bigint_from_le_bytes_constraint(Builder& builder, + const BigIntFromLeBytes& input, + DSLBigInts& dsl_bigints) +{ + using big_bn254_fq = bb::stdlib::bigfield; + using big_bn254_fr = bb::stdlib::bigfield; + using big_secp256k1_fq = bb::stdlib::bigfield; + using big_secp256k1_fr = bb::stdlib::bigfield; + using big_secp256r1_fq = bb::stdlib::bigfield; + using big_secp256r1_fr = bb::stdlib::bigfield; + using field_ct = bb::stdlib::field_t; + using byte_array_ct = bb::stdlib::byte_array; + + // Construct the modulus from its bytes + uint64_t modulus_64 = 0; + uint64_t base = 1; + std::vector modulus_limbs; + for (std::size_t i = 0; i < 32; ++i) { + if (i < input.modulus.size()) { + modulus_64 += input.modulus[i] * base; + base = base * 256; + } + if (i % 8 == 0) { + modulus_limbs.push_back(modulus_64); + modulus_64 = 0; + } + } + auto modulus = ModulusParam{ .modulus_0 = modulus_limbs[0], + .modulus_1 = modulus_limbs[1], + .modulus_2 = modulus_limbs[2], + .modulus_3 = modulus_limbs[3] }; + bb::stdlib::byte_array bytes; + for (auto input : input.inputs) { + field_ct element = field_ct::from_witness_index(&builder, input); + byte_array_ct element_bytes(element, 1); + bytes.write(element_bytes); + } + + auto modulus_id = modulus_param_to_id(modulus); + switch (modulus_id) { + + case BN254_FQ: { + auto big = big_bn254_fq(bytes); + dsl_bigints.set_bn254_fq(big, input.result); + break; + } + case BN254_FR: { + auto big = big_bn254_fr(bytes); + dsl_bigints.set_bn254_fr(big, input.result); + break; + } + case SECP256K1_FQ: { + auto big = big_secp256k1_fq(bytes); + dsl_bigints.set_secp256k1_fq(big, input.result); + break; + } + case SECP256K1_FR: { + auto big = big_secp256k1_fr(bytes); + dsl_bigints.set_secp256k1_fr(big, input.result); + break; + } + case SECP256R1_FQ: { + auto big = big_secp256r1_fq(bytes); + dsl_bigints.set_secp256r1_fq(big, input.result); + break; + } + case SECP256R1_FR: { + auto big = big_secp256r1_fr(bytes); + dsl_bigints.set_secp256r1_fr(big, input.result); + break; + } + case UNKNOWN: + default: + ASSERT(false); + break; + } +} + +template +void create_bigint_to_le_bytes_constraint(Builder& builder, + const BigIntToLeBytes& input, + DSLBigInts& dsl_bigints) +{ + using big_bn254_fq = bb::stdlib::bigfield; + using big_bn254_fr = bb::stdlib::bigfield; + using big_secp256k1_fq = bb::stdlib::bigfield; + using big_secp256k1_fr = bb::stdlib::bigfield; + using big_secp256r1_fq = bb::stdlib::bigfield; + using big_secp256r1_fr = bb::stdlib::bigfield; + + auto modulus_id = dsl_bigints.get_modulus_id(input.input); + bb::stdlib::byte_array byte_array; + switch (modulus_id) { + case BN254_FQ: { + big_bn254_fq big = dsl_bigints.bn254_fq(input.input); + byte_array = big.to_byte_array(); + + break; + } + case BN254_FR: { + big_bn254_fr big = dsl_bigints.bn254_fr(input.input); + byte_array = big.to_byte_array(); + break; + } + case SECP256K1_FQ: { + big_secp256k1_fq big = dsl_bigints.secp256k1_fq(input.input); + byte_array = big.to_byte_array(); + break; + } + case SECP256K1_FR: { + big_secp256k1_fr big = dsl_bigints.secp256k1_fr(input.input); + byte_array = big.to_byte_array(); + break; + } + case SECP256R1_FQ: { + big_secp256r1_fq big = dsl_bigints.secp256r1_fq(input.input); + byte_array = big.to_byte_array(); + break; + } + case SECP256R1_FR: { + big_secp256r1_fr big = dsl_bigints.secp256r1_fr(input.input); + byte_array = big.to_byte_array(); + break; + } + case UNKNOWN: + default: + ASSERT(false); + break; + } + for (size_t i = 0; i < input.result.size(); ++i) { + builder.assert_equal(byte_array[i].normalize().witness_index, input.result[i]); + } } template void create_bigint_from_le_bytes_constraint(UltraCircuitBuilder& builder, - const BigIntFromLeBytes& input); -template void create_bigint_from_le_bytes_constraint(GoblinUltraCircuitBuilder& builder, - const BigIntFromLeBytes& input); + const BigIntFromLeBytes& input, + DSLBigInts& dsl_bigints); +template void create_bigint_from_le_bytes_constraint( + GoblinUltraCircuitBuilder& builder, + const BigIntFromLeBytes& input, + DSLBigInts& dsl_bigints); +template void create_bigint_to_le_bytes_constraint(UltraCircuitBuilder& builder, + const BigIntToLeBytes& input, + DSLBigInts& dsl_bigints); + +template void create_bigint_to_le_bytes_constraint( + GoblinUltraCircuitBuilder& builder, + const BigIntToLeBytes& input, + DSLBigInts& dsl_bigints); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp index 8b21ee5e784..f4981ee90a4 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp @@ -29,7 +29,163 @@ struct BigIntOperation { friend bool operator==(BigIntOperation const& lhs, BigIntOperation const& rhs) = default; }; -template void create_bigint_operations_constraint(Builder& builder, const BigIntOperation& input); +struct BigIntToLeBytes { + uint32_t input; + std::vector result; + + // For serialization, update with any new fields + MSGPACK_FIELDS(input, result); + friend bool operator==(BigIntToLeBytes const& lhs, BigIntToLeBytes const& rhs) = default; +}; + +enum ModulusId { + BN254_FQ = 0, + BN254_FR, + SECP256K1_FQ, + SECP256K1_FR, + SECP256R1_FQ, + SECP256R1_FR, + UNKNOWN, +}; + +class ModulusParam { + public: + uint64_t modulus_0; + uint64_t modulus_1; + uint64_t modulus_2; + uint64_t modulus_3; +}; +template class DSLBigInts { + using big_bn254_fq = bb::stdlib::bigfield; + using big_bn254_fr = bb::stdlib::bigfield; + using big_secp256k1_fq = bb::stdlib::bigfield; + using big_secp256k1_fr = bb::stdlib::bigfield; + using big_secp256r1_fq = bb::stdlib::bigfield; + using big_secp256r1_fr = bb::stdlib::bigfield; + + private: + std::map m_bn254_fq; + std::map m_bn254_fr; + std::map m_secp256k1_fq; + std::map m_secp256k1_fr; + std::map m_secp256r1_fq; + std::map m_secp256r1_fr; + + public: + DSLBigInts(); + + ModulusId get_modulus_id(uint32_t bigint_id) + { + if (this->m_bn254_fq.contains(bigint_id)) { + return ModulusId::BN254_FQ; + } + if (this->m_bn254_fr.contains(bigint_id)) { + return ModulusId::BN254_FR; + } + if (this->m_secp256k1_fq.contains(bigint_id)) { + return ModulusId::SECP256K1_FQ; + } + if (this->m_secp256k1_fr.contains(bigint_id)) { + return ModulusId::SECP256K1_FR; + } + if (this->m_secp256r1_fq.contains(bigint_id)) { + return ModulusId::SECP256R1_FQ; + } + if (this->m_secp256r1_fr.contains(bigint_id)) { + return ModulusId::SECP256R1_FR; + } + + return ModulusId::UNKNOWN; + } + + big_bn254_fr bn254_fr(uint32_t bigint_id) + { + if (this->m_bn254_fr.contains(bigint_id)) { + return this->m_bn254_fr[bigint_id]; + } + return { 0 }; + } + + void set_bn254_fr(const big_bn254_fr& bigint, uint32_t bigint_id) { this->m_bn254_fr[bigint_id] = bigint; } + + big_bn254_fq bn254_fq(uint32_t bigint_id) + { + if (this->m_bn254_fq.contains(bigint_id)) { + return this->m_bn254_fq[bigint_id]; + } + return { 0 }; + } + + void set_bn254_fq(const big_bn254_fq& bigint, uint32_t bigint_id) { this->m_bn254_fq[bigint_id] = bigint; } + + big_secp256r1_fq secp256r1_fq(uint32_t bigint_id) + { + if (this->m_secp256r1_fq.contains(bigint_id)) { + return this->m_secp256r1_fq[bigint_id]; + } + return { 0 }; + } + + void set_secp256r1_fq(const big_secp256r1_fq& bigint, uint32_t bigint_id) + { + this->m_secp256r1_fq[bigint_id] = bigint; + } + + big_secp256r1_fr secp256r1_fr(uint32_t bigint_id) + { + if (this->m_secp256r1_fr.contains(bigint_id)) { + return this->m_secp256r1_fr[bigint_id]; + } + return { 0 }; + } + + void set_secp256r1_fr(const big_secp256r1_fr& bigint, uint32_t bigint_id) + { + this->m_secp256r1_fr[bigint_id] = bigint; + } + + big_secp256k1_fq secp256k1_fq(uint32_t bigint_id) + { + if (this->m_secp256k1_fq.contains(bigint_id)) { + return this->m_secp256k1_fq[bigint_id]; + } + return { 0 }; + } + + void set_secp256k1_fq(const big_secp256k1_fq& bigint, uint32_t bigint_id) + { + this->m_secp256k1_fq[bigint_id] = bigint; + } + + big_secp256k1_fr secp256k1_fr(uint32_t bigint_id) + { + if (this->m_secp256k1_fr.contains(bigint_id)) { + return this->m_secp256k1_fr[bigint_id]; + } + return { 0 }; + } + + void set_secp256k1_fr(const big_secp256k1_fr& bigint, uint32_t bigint_id) + { + this->m_secp256k1_fr[bigint_id] = bigint; + } +}; + +template +void create_bigint_from_le_bytes_constraint(Builder& builder, + const BigIntFromLeBytes& input, + DSLBigInts dsl_bigints); +template void create_bigint_to_le_bytes_constraint(Builder& builder, const BigIntToLeBytes& input); + +template +void create_bigint_operations_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); template -void create_bigint_from_le_bytes_constraint(Builder& builder, const BigIntFromLeBytes& input); +void create_bigint_addition_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); +template +void create_bigint_neg_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); +template +void create_bigint_mul_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); +template +void create_bigint_div_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); + } // namespace acir_format \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp index e8c4b22b4bf..a2ea78c919b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -18,34 +18,56 @@ TEST_F(BigIntTests, TestBigIntConstraintDummy) // Dummy Test: to be updated when big ints opcodes are implemented BigIntOperation add_constraint{ .lhs = 1, - .rhs = 2, - .result = 3, + .rhs = 1, + .result = 2, .opcode = BigIntOperationType::Add, }; - BigIntOperation neg_constraint{ - .lhs = 1, - .rhs = 2, - .result = 3, - .opcode = BigIntOperationType::Neg, - }; - BigIntOperation mul_constraint{ - .lhs = 1, - .rhs = 2, - .result = 3, - .opcode = BigIntOperationType::Mul, - }; - BigIntOperation div_constraint{ - .lhs = 1, - .rhs = 2, - .result = 3, - .opcode = BigIntOperationType::Div, - }; - BigIntFromLeBytes from_le_bytes_constraint{ + // BigIntOperation neg_constraint{ + // .lhs = 1, + // .rhs = 2, + // .result = 3, + // .opcode = BigIntOperationType::Neg, + // }; + // BigIntOperation mul_constraint{ + // .lhs = 1, + // .rhs = 2, + // .result = 3, + // .opcode = BigIntOperationType::Mul, + // }; + // BigIntOperation div_constraint{ + // .lhs = 1, + // .rhs = 2, + // .result = 3, + // .opcode = BigIntOperationType::Div, + // }; + BigIntFromLeBytes from_le_bytes_constraint_bigint1{ .inputs = { 0 }, - .modulus = { 23 }, + .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x86, 0x91, 0x6a, 0x81, 0x97, + 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, + .result = 1, + }; + BigIntFromLeBytes from_le_bytes_constraint_bigint2{ + .inputs = { 1 }, + .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x86, 0x91, 0x6a, 0x81, 0x97, + 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, .result = 1, }; + BigIntToLeBytes result_to_le_bytes{ + .input = 2, + .result = { 1 }, + }; + // poly_triple constrain_1_is_7{ + // .a = 5, + // .b = 7, + // .c = 0, + // .q_m = 0, + // .q_l = 1, + // .q_r = -1, + // .q_o = 0, + // .q_c = 0, + // }; + AcirFormat constraint_system{ .varnum = 4, .public_inputs = {}, @@ -65,14 +87,18 @@ TEST_F(BigIntTests, TestBigIntConstraintDummy) .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, - .bigint_from_le_bytes_constraints = { from_le_bytes_constraint }, - .bigint_operations = { add_constraint, neg_constraint, mul_constraint, div_constraint }, + .bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1, from_le_bytes_constraint_bigint2 }, + .bigint_to_le_bytes_constraints = { result_to_le_bytes }, + .bigint_operations = { add_constraint }, //, neg_constraint, mul_constraint, div_constraint }, .constraints = {}, .block_constraints = {}, }; - WitnessVector witness{ 0, 0, 1 }; + WitnessVector witness{ + 3, + 6, + }; // 3+3 =6 auto builder = create_circuit(constraint_system, /*size_hint*/ 0, witness); auto composer = Composer(); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp index 11ea6a77b9d..c2ea1c0546b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp @@ -67,6 +67,7 @@ TEST_F(EcOperations, TestECOperations) .ec_add_constraints = { ec_add_constraint }, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp index fb3e405e2f1..ee506c7f567 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp @@ -107,6 +107,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {}, @@ -152,6 +153,7 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {}, @@ -192,6 +194,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp index fe64491c90c..b72b473987b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp @@ -142,6 +142,7 @@ TEST(ECDSASecp256r1, test_hardcoded) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {}, @@ -188,6 +189,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintSucceed) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {}, @@ -232,6 +234,7 @@ TEST(ECDSASecp256r1, TestECDSACompilesForVerifier) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {}, @@ -271,6 +274,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintFail) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index f281f965eea..7f2693f4171 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -100,6 +100,7 @@ Builder create_inner_circuit() .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = { expr_a, expr_b, expr_c, expr_d }, .block_constraints = {} }; @@ -253,6 +254,7 @@ Builder create_outer_circuit(std::vector& inner_circuits) .ec_add_constraints = {}, .recursion_constraints = recursion_constraints, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {} }; From 160a564440b1851f661d25e47e151389fe3c3663 Mon Sep 17 00:00:00 2001 From: ludamad Date: Tue, 30 Jan 2024 16:42:59 +0000 Subject: [PATCH 02/10] fix: build --- .../src/barretenberg/dsl/acir_format/bigint_constraint.cpp | 6 ------ .../src/barretenberg/dsl/acir_format/bigint_constraint.hpp | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp index d1dc660d464..0171a1ffdf7 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp @@ -46,9 +46,6 @@ ModulusId modulus_param_to_id(ModulusParam param) return ModulusId::UNKNOWN; } -template class DSLBigInts; -template class DSLBigInts; - template void create_bigint_operations_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint); template void create_bigint_operations_constraint( @@ -255,9 +252,6 @@ void create_bigint_operations_constraint(const BigIntOperation& input, DSLBigInt } } } -// DSLBigInts; - -// template DSLBigInts& DSLBigInts::get(); template void create_bigint_from_le_bytes_constraint(Builder& builder, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp index f4981ee90a4..cd7e5e794fa 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp @@ -72,7 +72,7 @@ template class DSLBigInts { std::map m_secp256r1_fr; public: - DSLBigInts(); + DSLBigInts() = default; ModulusId get_modulus_id(uint32_t bigint_id) { @@ -174,7 +174,7 @@ template class DSLBigInts { template void create_bigint_from_le_bytes_constraint(Builder& builder, const BigIntFromLeBytes& input, - DSLBigInts dsl_bigints); + DSLBigInts& dsl_bigints); template void create_bigint_to_le_bytes_constraint(Builder& builder, const BigIntToLeBytes& input); template From a1d1d0aadbb1a5637da90d96c0d1964c55c9676d Mon Sep 17 00:00:00 2001 From: guipublic Date: Wed, 31 Jan 2024 09:07:00 +0000 Subject: [PATCH 03/10] prevent fall through --- .../dsl/acir_format/bigint_constraint.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp index 0171a1ffdf7..61c050846a1 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp @@ -75,31 +75,37 @@ void create_bigint_addition_constraint(const BigIntOperation& input, DSLBigInts< auto lhs = dsl_bigint.bn254_fr(input.lhs); auto rhs = dsl_bigint.bn254_fr(input.rhs); dsl_bigint.set_bn254_fr(lhs + rhs, input.result); + break; } case ModulusId::BN254_FQ: { auto lhs = dsl_bigint.bn254_fq(input.lhs); auto rhs = dsl_bigint.bn254_fq(input.rhs); dsl_bigint.set_bn254_fq(lhs + rhs, input.result); + break; } case ModulusId::SECP256K1_FQ: { auto lhs = dsl_bigint.secp256k1_fq(input.lhs); auto rhs = dsl_bigint.secp256k1_fq(input.rhs); dsl_bigint.set_secp256k1_fq(lhs + rhs, input.result); + break; } case ModulusId::SECP256K1_FR: { auto lhs = dsl_bigint.secp256k1_fr(input.lhs); auto rhs = dsl_bigint.secp256k1_fr(input.rhs); dsl_bigint.set_secp256k1_fr(lhs + rhs, input.result); + break; } case ModulusId::SECP256R1_FQ: { auto lhs = dsl_bigint.secp256r1_fq(input.lhs); auto rhs = dsl_bigint.secp256r1_fq(input.rhs); dsl_bigint.set_secp256r1_fq(lhs + rhs, input.result); + break; } case ModulusId::SECP256R1_FR: { auto lhs = dsl_bigint.secp256r1_fr(input.lhs); auto rhs = dsl_bigint.secp256r1_fr(input.rhs); dsl_bigint.set_secp256r1_fr(lhs + rhs, input.result); + break; } default: { ASSERT(false); @@ -115,31 +121,37 @@ void create_bigint_neg_constraint(const BigIntOperation& input, DSLBigInts Date: Wed, 31 Jan 2024 09:14:45 +0000 Subject: [PATCH 04/10] fix build --- .../src/barretenberg/dsl/acir_format/block_constraint.test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp index 384520e7f80..cae41ac1aac 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp @@ -128,6 +128,7 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = { block }, From 55121ac8e39780059bf8bca33305ae3767a6286a Mon Sep 17 00:00:00 2001 From: guipublic Date: Wed, 31 Jan 2024 09:15:28 +0000 Subject: [PATCH 05/10] fix build --- .../cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index b4b3a6f7af9..34479163676 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -474,6 +474,7 @@ TEST_F(AcirFormatTests, TestKeccakPermutation) .ec_add_constraints = {}, .recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, .constraints = {}, .block_constraints = {} }; From dbc19107a0d1d1b9185346e69a55c4a706b1c0e4 Mon Sep 17 00:00:00 2001 From: guipublic Date: Wed, 31 Jan 2024 14:24:05 +0000 Subject: [PATCH 06/10] test case for bigint opcodes (wip) --- .../dsl/acir_format/acir_format.cpp | 3 + .../dsl/acir_format/bigint_constraint.cpp | 31 ++- .../dsl/acir_format/bigint_constraint.hpp | 10 +- .../acir_format/bigint_constraint.test.cpp | 178 +++++++++++++++--- 4 files changed, 185 insertions(+), 37 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 09cccb57dac..216caeb9579 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -101,6 +101,9 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo for (const auto& constraint : constraint_system.bigint_operations) { create_bigint_operations_constraint(constraint, dsl_bigints); } + for (const auto& constraint : constraint_system.bigint_to_le_bytes_constraints) { + create_bigint_to_le_bytes_constraint(builder, constraint, dsl_bigints); + } // TODO(https://github.com/AztecProtocol/barretenberg/issues/817): disable these for UGH for now since we're not yet // dealing with proper recursion diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp index 61c050846a1..5c5302c6b0a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp @@ -299,21 +299,26 @@ void create_bigint_from_le_bytes_constraint(Builder& builder, if (i < input.modulus.size()) { modulus_64 += input.modulus[i] * base; base = base * 256; - } - if (i % 8 == 0) { - modulus_limbs.push_back(modulus_64); - modulus_64 = 0; + if ((i + 1) % 8 == 0) { + modulus_limbs.push_back(modulus_64); + modulus_64 = 0; + base = 1; + } } } auto modulus = ModulusParam{ .modulus_0 = modulus_limbs[0], .modulus_1 = modulus_limbs[1], .modulus_2 = modulus_limbs[2], .modulus_3 = modulus_limbs[3] }; - bb::stdlib::byte_array bytes; - for (auto input : input.inputs) { - field_ct element = field_ct::from_witness_index(&builder, input); - byte_array_ct element_bytes(element, 1); - bytes.write(element_bytes); + bb::stdlib::byte_array bytes = bb::stdlib::byte_array(&builder, 32); + for (size_t i = 0; i < 32; ++i) { + if (i < input.inputs.size()) { + field_ct element = field_ct::from_witness_index(&builder, input.inputs[i]); + byte_array_ct element_bytes(element, 1); + bytes.write_at(element_bytes, i); + } else { + bytes[i] = 0; + } } auto modulus_id = modulus_param_to_id(modulus); @@ -322,6 +327,7 @@ void create_bigint_from_le_bytes_constraint(Builder& builder, case BN254_FQ: { auto big = big_bn254_fq(bytes); dsl_bigints.set_bn254_fq(big, input.result); + break; } case BN254_FR: { @@ -367,6 +373,7 @@ void create_bigint_to_le_bytes_constraint(Builder& builder, using big_secp256k1_fr = bb::stdlib::bigfield; using big_secp256r1_fq = bb::stdlib::bigfield; using big_secp256r1_fr = bb::stdlib::bigfield; + using field_ct = bb::stdlib::field_t; auto modulus_id = dsl_bigints.get_modulus_id(input.input); bb::stdlib::byte_array byte_array; @@ -407,7 +414,13 @@ void create_bigint_to_le_bytes_constraint(Builder& builder, ASSERT(false); break; } + // TODO: check both sizes are equal for (size_t i = 0; i < input.result.size(); ++i) { + info(byte_array[i].normalize().witness_index); + info(byte_array[i].normalize().get_value()); + info(input.result[i]); + field_ct result = field_ct::from_witness_index(&builder, input.result[i]); + info(result.get_value()); builder.assert_equal(byte_array[i].normalize().witness_index, input.result[i]); } } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp index cd7e5e794fa..97e7fa4b2be 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp @@ -103,6 +103,7 @@ template class DSLBigInts { if (this->m_bn254_fr.contains(bigint_id)) { return this->m_bn254_fr[bigint_id]; } + ASSERT(false); return { 0 }; } @@ -113,6 +114,7 @@ template class DSLBigInts { if (this->m_bn254_fq.contains(bigint_id)) { return this->m_bn254_fq[bigint_id]; } + ASSERT(false); return { 0 }; } @@ -123,6 +125,7 @@ template class DSLBigInts { if (this->m_secp256r1_fq.contains(bigint_id)) { return this->m_secp256r1_fq[bigint_id]; } + ASSERT(false); return { 0 }; } @@ -136,6 +139,7 @@ template class DSLBigInts { if (this->m_secp256r1_fr.contains(bigint_id)) { return this->m_secp256r1_fr[bigint_id]; } + ASSERT(false); return { 0 }; } @@ -149,6 +153,7 @@ template class DSLBigInts { if (this->m_secp256k1_fq.contains(bigint_id)) { return this->m_secp256k1_fq[bigint_id]; } + ASSERT(false); return { 0 }; } @@ -175,7 +180,10 @@ template void create_bigint_from_le_bytes_constraint(Builder& builder, const BigIntFromLeBytes& input, DSLBigInts& dsl_bigints); -template void create_bigint_to_le_bytes_constraint(Builder& builder, const BigIntToLeBytes& input); +template +void create_bigint_to_le_bytes_constraint(Builder& builder, + const BigIntToLeBytes& input, + DSLBigInts& dsl_bigints); template void create_bigint_operations_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp index a2ea78c919b..674a85c2a1b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -1,8 +1,10 @@ #include "bigint_constraint.hpp" #include "acir_format.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/plonk/proof_system/types/proof.hpp" #include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" +#include #include #include @@ -13,25 +15,135 @@ class BigIntTests : public ::testing::Test { static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } }; +std::pair generate_big_int_op_constraint(BigIntOperationType op, + uint8_t lhs, + uint8_t rhs, + WitnessVector& witness_values) +{ + uint32_t result = static_cast(witness_values.size()); + BigIntOperation constraint{ + .lhs = lhs, + .rhs = rhs, + .result = result, + .opcode = op, + }; + BigIntToLeBytes to_bytes{ + .input = result, + .result = { static_cast(witness_values.size()) }, + }; + // overflow is NOT supported, you have to make sure there is no overflow. + switch (op) { + case Add: + witness_values.push_back(witness_values[lhs] + witness_values[rhs]); + break; + case Neg: + witness_values.push_back(witness_values[lhs] - witness_values[rhs]); + break; + case Mul: + witness_values.push_back(witness_values[lhs] * witness_values[rhs]); + break; + case Div: + default: + ASSERT(false); + break; + } + + return std::pair(constraint, to_bytes); +} + +TEST_F(BigIntTests, TestBigIntConstraintSimple) +{ + // 3 + 3 = 6 + // 3 = bigint(1) = from_bytes(w(1)) + // 6 = bigint(2) = to_bytes(w(2)) + BigIntOperation add_constraint{ + .lhs = 1, + .rhs = 1, + .result = 2, + .opcode = BigIntOperationType::Add, + }; + + BigIntFromLeBytes from_le_bytes_constraint_bigint1{ + .inputs = { 1 }, + .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, + 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, + .result = 1, + }; + + BigIntToLeBytes result2_to_le_bytes{ + .input = 2, .result = { 2 }, // 3+3=6 + }; + + AcirFormat constraint_system{ + .varnum = 5, + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1 }, + .bigint_to_le_bytes_constraints = { result2_to_le_bytes }, + .bigint_operations = { add_constraint }, + .constraints = {}, + .block_constraints = {}, + + }; + + WitnessVector witness{ + 0, 3, 4, 3, 0, + }; + auto builder = create_circuit(constraint_system, /*size_hint*/ 0, witness); + // ASSERT(false); + auto composer = Composer(); + auto prover = composer.create_ultra_with_keccak_prover(builder); + auto proof = prover.construct_proof(); + EXPECT_TRUE(builder.check_circuit()); + auto verifier = composer.create_ultra_with_keccak_verifier(builder); + EXPECT_EQ(verifier.verify_proof(proof), true); +} + TEST_F(BigIntTests, TestBigIntConstraintDummy) { - // Dummy Test: to be updated when big ints opcodes are implemented + // 3 + 3 = 6 + // 3 = bigint(1) = from_bytes(w(1)) + // 6 = bigint(2) = to_bytes(w(2)) BigIntOperation add_constraint{ .lhs = 1, .rhs = 1, .result = 2, .opcode = BigIntOperationType::Add, }; + // 3 + 0 = 3 = bigint(4) = to_bytes(w(1)) + // 3 = bigint(1) + // 0 = bigint(3) = from_bytes(w(4)) + BigIntOperation add_constraint2{ + .lhs = 1, + .rhs = 3, + .result = 4, + .opcode = BigIntOperationType::Add, + }; // BigIntOperation neg_constraint{ - // .lhs = 1, - // .rhs = 2, + // .lhs = 2, + // .rhs = 1, // .result = 3, // .opcode = BigIntOperationType::Neg, // }; // BigIntOperation mul_constraint{ // .lhs = 1, - // .rhs = 2, - // .result = 3, + // .rhs = 4, + // .result = 5, // .opcode = BigIntOperationType::Mul, // }; // BigIntOperation div_constraint{ @@ -41,25 +153,35 @@ TEST_F(BigIntTests, TestBigIntConstraintDummy) // .opcode = BigIntOperationType::Div, // }; BigIntFromLeBytes from_le_bytes_constraint_bigint1{ - .inputs = { 0 }, - .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x86, 0x91, 0x6a, 0x81, 0x97, - 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, - .result = 1, - }; - BigIntFromLeBytes from_le_bytes_constraint_bigint2{ .inputs = { 1 }, - .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x86, 0x91, 0x6a, 0x81, 0x97, + .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, .result = 1, }; - - BigIntToLeBytes result_to_le_bytes{ - .input = 2, + // BigIntFromLeBytes from_le_bytes_constraint_bigint2{ + // .inputs = { 2 }, + // .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, + // 0x97, + // 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, + // .result = 2, + // }; + BigIntFromLeBytes from_le_bytes_constraint_bigint3{ + .inputs = { 4 }, + .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, + 0x97, + 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, + .result = 3, + }; + BigIntToLeBytes result2_to_le_bytes{ + .input = 2, .result = { 2 }, // 3+3=6 + }; + BigIntToLeBytes result4_to_le_bytes{ + .input = 3, .result = { 1 }, }; - // poly_triple constrain_1_is_7{ - // .a = 5, - // .b = 7, + // poly_triple constrain_3_is_1{ + // .a = 1, + // .b = 3, // .c = 0, // .q_m = 0, // .q_l = 1, @@ -69,7 +191,7 @@ TEST_F(BigIntTests, TestBigIntConstraintDummy) // }; AcirFormat constraint_system{ - .varnum = 4, + .varnum = 5, .public_inputs = {}, .logic_constraints = {}, .range_constraints = {}, @@ -87,24 +209,26 @@ TEST_F(BigIntTests, TestBigIntConstraintDummy) .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, - .bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1, from_le_bytes_constraint_bigint2 }, - .bigint_to_le_bytes_constraints = { result_to_le_bytes }, - .bigint_operations = { add_constraint }, //, neg_constraint, mul_constraint, div_constraint }, + .bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1, + from_le_bytes_constraint_bigint3 }, // from_le_bytes_constraint_bigint2 }, + .bigint_to_le_bytes_constraints = { result2_to_le_bytes, result4_to_le_bytes }, // result_to_le_bytes_3 }, + .bigint_operations = { add_constraint, add_constraint2 }, // neg_constraint }, //, neg_constraint, + // mul_constraint, div_constraint + // }, .constraints = {}, .block_constraints = {}, }; WitnessVector witness{ - 3, - 6, - }; // 3+3 =6 + 0, 3, 6, 3, 0, + }; auto builder = create_circuit(constraint_system, /*size_hint*/ 0, witness); - + // ASSERT(false); auto composer = Composer(); auto prover = composer.create_ultra_with_keccak_prover(builder); auto proof = prover.construct_proof(); - + EXPECT_TRUE(builder.check_circuit()); auto verifier = composer.create_ultra_with_keccak_verifier(builder); EXPECT_EQ(verifier.verify_proof(proof), true); From 297299e1c4959880e82608a736d24106b5d026f4 Mon Sep 17 00:00:00 2001 From: guipublic Date: Fri, 2 Feb 2024 09:42:47 +0000 Subject: [PATCH 07/10] big endian bytes for big field and reduce --- .../dsl/acir_format/bigint_constraint.cpp | 47 ++- .../acir_format/bigint_constraint.test.cpp | 345 +++++++++++++----- 2 files changed, 279 insertions(+), 113 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp index 5c5302c6b0a..f7ea01f8a66 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp @@ -310,20 +310,21 @@ void create_bigint_from_le_bytes_constraint(Builder& builder, .modulus_1 = modulus_limbs[1], .modulus_2 = modulus_limbs[2], .modulus_3 = modulus_limbs[3] }; - bb::stdlib::byte_array bytes = bb::stdlib::byte_array(&builder, 32); + bb::stdlib::byte_array rev_bytes = bb::stdlib::byte_array(&builder, 32); for (size_t i = 0; i < 32; ++i) { if (i < input.inputs.size()) { field_ct element = field_ct::from_witness_index(&builder, input.inputs[i]); byte_array_ct element_bytes(element, 1); - bytes.write_at(element_bytes, i); + rev_bytes.write_at(element_bytes, i); } else { - bytes[i] = 0; + rev_bytes[i] = 0; } } + bb::stdlib::byte_array bytes = rev_bytes.reverse(); auto modulus_id = modulus_param_to_id(modulus); - switch (modulus_id) { + switch (modulus_id) { case BN254_FQ: { auto big = big_bn254_fq(bytes); dsl_bigints.set_bn254_fq(big, input.result); @@ -373,39 +374,44 @@ void create_bigint_to_le_bytes_constraint(Builder& builder, using big_secp256k1_fr = bb::stdlib::bigfield; using big_secp256r1_fq = bb::stdlib::bigfield; using big_secp256r1_fr = bb::stdlib::bigfield; - using field_ct = bb::stdlib::field_t; auto modulus_id = dsl_bigints.get_modulus_id(input.input); bb::stdlib::byte_array byte_array; switch (modulus_id) { case BN254_FQ: { big_bn254_fq big = dsl_bigints.bn254_fq(input.input); + big.self_reduce(); byte_array = big.to_byte_array(); break; } case BN254_FR: { big_bn254_fr big = dsl_bigints.bn254_fr(input.input); + big.self_reduce(); byte_array = big.to_byte_array(); break; } case SECP256K1_FQ: { big_secp256k1_fq big = dsl_bigints.secp256k1_fq(input.input); + big.self_reduce(); byte_array = big.to_byte_array(); break; } case SECP256K1_FR: { big_secp256k1_fr big = dsl_bigints.secp256k1_fr(input.input); + big.self_reduce(); byte_array = big.to_byte_array(); break; } case SECP256R1_FQ: { big_secp256r1_fq big = dsl_bigints.secp256r1_fq(input.input); + big.self_reduce(); byte_array = big.to_byte_array(); break; } case SECP256R1_FR: { big_secp256r1_fr big = dsl_bigints.secp256r1_fr(input.input); + big.self_reduce(); byte_array = big.to_byte_array(); break; } @@ -414,14 +420,29 @@ void create_bigint_to_le_bytes_constraint(Builder& builder, ASSERT(false); break; } - // TODO: check both sizes are equal - for (size_t i = 0; i < input.result.size(); ++i) { - info(byte_array[i].normalize().witness_index); - info(byte_array[i].normalize().get_value()); - info(input.result[i]); - field_ct result = field_ct::from_witness_index(&builder, input.result[i]); - info(result.get_value()); - builder.assert_equal(byte_array[i].normalize().witness_index, input.result[i]); + byte_array = byte_array.reverse(); + ASSERT(input.result.size() <= byte_array.size()); + for (size_t i = 0; i < byte_array.size(); ++i) { + if (i < input.result.size()) { + + // This should instead use assert_equal: builder.assert_equal(byte_array[i].normalize().witness_index, + // input.result[i]); but unit tests require this because they do not constraint the witness, and then if we + // use assert_equal in that case, we can generate a proof for non matching values (cf test_assert_equal in + // field.test.cpp). We should check that Noir always constraint the results of to_bytes + poly_triple assert_equal{ + .a = byte_array[i].normalize().witness_index, + .b = input.result[i], + .c = 0, + .q_m = 0, + .q_l = 1, + .q_r = -1, + .q_o = 0, + .q_c = 0, + }; + builder.create_poly_gate(assert_equal); + } else { + byte_array[i].normalize().is_zero(); + } } } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp index 674a85c2a1b..87d3e139167 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -14,41 +14,197 @@ class BigIntTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } }; +using fr = field; -std::pair generate_big_int_op_constraint(BigIntOperationType op, - uint8_t lhs, - uint8_t rhs, - WitnessVector& witness_values) +std::tuple +generate_big_int_op_constraint_with_modulus( + BigIntOperationType op, fr lhs, fr rhs, WitnessVector& witness_values, const std::vector& modulus) { - uint32_t result = static_cast(witness_values.size()); + // CAUTION We assume here the operands and the result fit into one byte! + // So trying to divide 7/2 won't work, but 8/2 will do. + auto lhs_id = static_cast(witness_values.size()); + witness_values.push_back(lhs); + auto rhs_id = static_cast(witness_values.size()); + witness_values.push_back(rhs); + BigIntFromLeBytes from_le_bytes_constraint_bigint_lhs{ + .inputs = { lhs_id }, + .modulus = modulus, + .result = lhs_id, + }; + BigIntFromLeBytes from_le_bytes_constraint_bigint_rhs{ + .inputs = { rhs_id }, + .modulus = modulus, + .result = rhs_id, + }; + + auto result = static_cast(witness_values.size()); + BigIntOperation constraint{ + .lhs = lhs_id, + .rhs = rhs_id, + .result = result, + .opcode = op, + }; + // Expecting the result to be just one byte long + BigIntToLeBytes to_bytes{ + .input = result, + .result = { static_cast(witness_values.size()) }, + }; + // overflow is NOT supported, you have to make sure there is no overflow/underflow. + fr value = 0; + switch (op) { + case Add: + value = witness_values[lhs_id] + witness_values[rhs_id]; + break; + case Neg: + value = witness_values[lhs_id] - witness_values[rhs_id]; + break; + case Mul: + value = witness_values[lhs_id] * witness_values[rhs_id]; + break; + case Div: + value = witness_values[lhs_id] / witness_values[rhs_id]; + break; + default: + ASSERT(false); + break; + } + + witness_values.push_back(value); + return { from_le_bytes_constraint_bigint_lhs, from_le_bytes_constraint_bigint_rhs, constraint, to_bytes }; +} + +std::tuple generate_big_int_op_constraint( + BigIntOperationType op, fr lhs, fr rhs, WitnessVector& witness_values) +{ + // modulus is bn254/fq + return generate_big_int_op_constraint_with_modulus( + op, + lhs, + rhs, + witness_values, + { + 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, + 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, + }); +} + +std::tuple +generate_big_int_op_constraint_secpk1_fr(BigIntOperationType op, fr lhs, fr rhs, WitnessVector& witness_values) +{ + return generate_big_int_op_constraint_with_modulus( + op, lhs, rhs, witness_values, { 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0x48, + 0xAF, 0xE6, 0xDC, 0xAE, 0xBA, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); +} + +std::tuple +generate_big_int_op_constraint_secpk1_fq(BigIntOperationType op, fr lhs, fr rhs, WitnessVector& witness_values) +{ + return generate_big_int_op_constraint_with_modulus( + op, lhs, rhs, witness_values, { 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); +} +void apply_constraints(AcirFormat& constraint_system, + std::tuple constraints) +{ + constraint_system.bigint_from_le_bytes_constraints.push_back(get<0>(constraints)); + constraint_system.bigint_from_le_bytes_constraints.push_back(get<1>(constraints)); + constraint_system.bigint_to_le_bytes_constraints.push_back(get<3>(constraints)); + constraint_system.bigint_operations.push_back(get<2>(constraints)); +} + +std::tuple generate_big_int_op_constraint_with_id(BigIntOperationType op, + uint32_t lhs_id, + uint32_t rhs_id, + WitnessVector& witness_values) +{ + // lhs_id, rhs_id are big int it, so we can generate the operation directly + auto result = static_cast(witness_values.size()); BigIntOperation constraint{ - .lhs = lhs, - .rhs = rhs, + .lhs = lhs_id, + .rhs = rhs_id, .result = result, .opcode = op, }; + // Expecting the result to be just one byte long BigIntToLeBytes to_bytes{ .input = result, .result = { static_cast(witness_values.size()) }, }; - // overflow is NOT supported, you have to make sure there is no overflow. + // overflow is NOT supported, you have to make sure there is no overflow/underflow. + fr value = 0; switch (op) { case Add: - witness_values.push_back(witness_values[lhs] + witness_values[rhs]); + value = witness_values[lhs_id] + witness_values[rhs_id]; break; case Neg: - witness_values.push_back(witness_values[lhs] - witness_values[rhs]); + value = witness_values[lhs_id] - witness_values[rhs_id]; break; case Mul: - witness_values.push_back(witness_values[lhs] * witness_values[rhs]); + value = witness_values[lhs_id] * witness_values[rhs_id]; break; case Div: + value = witness_values[lhs_id] / witness_values[rhs_id]; + break; default: ASSERT(false); break; } - return std::pair(constraint, to_bytes); + witness_values.push_back(value); + return { constraint, to_bytes }; +} + +// Based on TestBigIntConstraintSimple, we generate constraints for multiple operations at the same time. +TEST_F(BigIntTests, TestBigIntConstraintMultiple) +{ + WitnessVector witness; + auto contraints = generate_big_int_op_constraint(BigIntOperationType::Add, fr(3), fr(1), witness); + auto contraints2 = generate_big_int_op_constraint(BigIntOperationType::Add, fr(3), fr(1), witness); + auto contraints3 = generate_big_int_op_constraint(BigIntOperationType::Neg, fr(5), fr(2), witness); + auto contraints4 = generate_big_int_op_constraint(BigIntOperationType::Mul, fr(5), fr(3), witness); + auto contraints5 = generate_big_int_op_constraint(BigIntOperationType::Div, fr(8), fr(2), witness); + AcirFormat constraint_system{ + .varnum = static_cast(witness.size() + 1), + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = {}, + .block_constraints = {}, + }; + apply_constraints(constraint_system, contraints); + apply_constraints(constraint_system, contraints2); + apply_constraints(constraint_system, contraints3); + apply_constraints(constraint_system, contraints4); + apply_constraints(constraint_system, contraints5); + constraint_system.varnum = static_cast(witness.size() + 1); + + auto builder = create_circuit(constraint_system, /*size_hint*/ 0, witness); + + auto composer = Composer(); + auto prover = composer.create_ultra_with_keccak_prover(builder); + auto proof = prover.construct_proof(); + EXPECT_TRUE(builder.check_circuit()); + auto verifier = composer.create_ultra_with_keccak_verifier(builder); + EXPECT_EQ(verifier.verify_proof(proof), true); } TEST_F(BigIntTests, TestBigIntConstraintSimple) @@ -102,10 +258,9 @@ TEST_F(BigIntTests, TestBigIntConstraintSimple) }; WitnessVector witness{ - 0, 3, 4, 3, 0, + 0, 3, 6, 3, 0, }; auto builder = create_circuit(constraint_system, /*size_hint*/ 0, witness); - // ASSERT(false); auto composer = Composer(); auto prover = composer.create_ultra_with_keccak_prover(builder); auto proof = prover.construct_proof(); @@ -114,84 +269,19 @@ TEST_F(BigIntTests, TestBigIntConstraintSimple) EXPECT_EQ(verifier.verify_proof(proof), true); } -TEST_F(BigIntTests, TestBigIntConstraintDummy) +// Based on TestBigIntConstraintMultiple, we generate constraints re-using the bigfields created by the first two +// operations +TEST_F(BigIntTests, TestBigIntConstraintReuse) { - // 3 + 3 = 6 - // 3 = bigint(1) = from_bytes(w(1)) - // 6 = bigint(2) = to_bytes(w(2)) - BigIntOperation add_constraint{ - .lhs = 1, - .rhs = 1, - .result = 2, - .opcode = BigIntOperationType::Add, - }; - // 3 + 0 = 3 = bigint(4) = to_bytes(w(1)) - // 3 = bigint(1) - // 0 = bigint(3) = from_bytes(w(4)) - BigIntOperation add_constraint2{ - .lhs = 1, - .rhs = 3, - .result = 4, - .opcode = BigIntOperationType::Add, - }; - // BigIntOperation neg_constraint{ - // .lhs = 2, - // .rhs = 1, - // .result = 3, - // .opcode = BigIntOperationType::Neg, - // }; - // BigIntOperation mul_constraint{ - // .lhs = 1, - // .rhs = 4, - // .result = 5, - // .opcode = BigIntOperationType::Mul, - // }; - // BigIntOperation div_constraint{ - // .lhs = 1, - // .rhs = 2, - // .result = 3, - // .opcode = BigIntOperationType::Div, - // }; - BigIntFromLeBytes from_le_bytes_constraint_bigint1{ - .inputs = { 1 }, - .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, - 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, - .result = 1, - }; - // BigIntFromLeBytes from_le_bytes_constraint_bigint2{ - // .inputs = { 2 }, - // .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, - // 0x97, - // 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, - // .result = 2, - // }; - BigIntFromLeBytes from_le_bytes_constraint_bigint3{ - .inputs = { 4 }, - .modulus = { 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, - 0x97, - 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, }, - .result = 3, - }; - BigIntToLeBytes result2_to_le_bytes{ - .input = 2, .result = { 2 }, // 3+3=6 - }; - BigIntToLeBytes result4_to_le_bytes{ - .input = 3, - .result = { 1 }, - }; - // poly_triple constrain_3_is_1{ - // .a = 1, - // .b = 3, - // .c = 0, - // .q_m = 0, - // .q_l = 1, - // .q_r = -1, - // .q_o = 0, - // .q_c = 0, - // }; + WitnessVector witness; + auto contraints = generate_big_int_op_constraint_secpk1_fr(BigIntOperationType::Add, fr(3), fr(1), witness); + auto contraints2 = generate_big_int_op_constraint_secpk1_fr(BigIntOperationType::Neg, fr(5), fr(2), witness); + auto contraints3 = generate_big_int_op_constraint_with_id(BigIntOperationType::Mul, 0, 5, witness); + auto contraints4 = generate_big_int_op_constraint_with_id(BigIntOperationType::Div, 0, 1, witness); + auto contraints5 = generate_big_int_op_constraint_with_id(BigIntOperationType::Neg, 7, 1, witness); AcirFormat constraint_system{ - .varnum = 5, + .varnum = static_cast(witness.size() + 1), .public_inputs = {}, .logic_constraints = {}, .range_constraints = {}, @@ -209,28 +299,83 @@ TEST_F(BigIntTests, TestBigIntConstraintDummy) .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, - .bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1, - from_le_bytes_constraint_bigint3 }, // from_le_bytes_constraint_bigint2 }, - .bigint_to_le_bytes_constraints = { result2_to_le_bytes, result4_to_le_bytes }, // result_to_le_bytes_3 }, - .bigint_operations = { add_constraint, add_constraint2 }, // neg_constraint }, //, neg_constraint, - // mul_constraint, div_constraint - // }, + .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {}, - }; + apply_constraints(constraint_system, contraints); + apply_constraints(constraint_system, contraints2); + constraint_system.bigint_to_le_bytes_constraints.push_back(get<1>(contraints3)); + constraint_system.bigint_operations.push_back(get<0>(contraints3)); + constraint_system.bigint_to_le_bytes_constraints.push_back(get<1>(contraints4)); + constraint_system.bigint_operations.push_back(get<0>(contraints4)); + constraint_system.bigint_to_le_bytes_constraints.push_back(get<1>(contraints5)); + constraint_system.bigint_operations.push_back(get<0>(contraints5)); + constraint_system.varnum = static_cast(witness.size() + 1); - WitnessVector witness{ - 0, 3, 6, 3, 0, - }; auto builder = create_circuit(constraint_system, /*size_hint*/ 0, witness); - // ASSERT(false); + auto composer = Composer(); auto prover = composer.create_ultra_with_keccak_prover(builder); auto proof = prover.construct_proof(); EXPECT_TRUE(builder.check_circuit()); auto verifier = composer.create_ultra_with_keccak_verifier(builder); + EXPECT_EQ(verifier.verify_proof(proof), true); +} +TEST_F(BigIntTests, TestBigIntConstraintReuse2) +{ + WitnessVector witness; + auto contraints = generate_big_int_op_constraint_secpk1_fq(BigIntOperationType::Add, fr(3), fr(1), witness); + auto contraints2 = generate_big_int_op_constraint_secpk1_fq(BigIntOperationType::Neg, fr(5), fr(2), witness); + auto contraints3 = generate_big_int_op_constraint_with_id(BigIntOperationType::Add, 0, 5, witness); + auto contraints4 = generate_big_int_op_constraint_with_id(BigIntOperationType::Neg, 0, 1, witness); + auto contraints5 = generate_big_int_op_constraint_with_id(BigIntOperationType::Neg, 7, 1, witness); + + AcirFormat constraint_system{ + .varnum = static_cast(witness.size() + 1), + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = {}, + .block_constraints = {}, + }; + apply_constraints(constraint_system, contraints); + apply_constraints(constraint_system, contraints2); + constraint_system.bigint_to_le_bytes_constraints.push_back(get<1>(contraints3)); + constraint_system.bigint_operations.push_back(get<0>(contraints3)); + constraint_system.bigint_to_le_bytes_constraints.push_back(get<1>(contraints4)); + constraint_system.bigint_operations.push_back(get<0>(contraints4)); + constraint_system.bigint_to_le_bytes_constraints.push_back(get<1>(contraints5)); + constraint_system.bigint_operations.push_back(get<0>(contraints5)); + constraint_system.varnum = static_cast(witness.size() + 1); + + auto builder = create_circuit(constraint_system, /*size_hint*/ 0, witness); + + auto composer = Composer(); + auto prover = composer.create_ultra_with_keccak_prover(builder); + auto proof = prover.construct_proof(); + EXPECT_TRUE(builder.check_circuit()); + auto verifier = composer.create_ultra_with_keccak_verifier(builder); EXPECT_EQ(verifier.verify_proof(proof), true); } From abcd9380b5f850be55e260c1bcd7fbf2a83514fe Mon Sep 17 00:00:00 2001 From: kevaundray Date: Fri, 2 Feb 2024 13:31:03 +0000 Subject: [PATCH 08/10] Update barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp --- .../cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp index f7ea01f8a66..06d0caac810 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp @@ -328,7 +328,6 @@ void create_bigint_from_le_bytes_constraint(Builder& builder, case BN254_FQ: { auto big = big_bn254_fq(bytes); dsl_bigints.set_bn254_fq(big, input.result); - break; } case BN254_FR: { From dc59ab4a71e219c847bc916a6f0e63d31e1212a0 Mon Sep 17 00:00:00 2001 From: guipublic Date: Fri, 2 Feb 2024 14:49:56 +0000 Subject: [PATCH 09/10] code review: add doc comments --- .../src/barretenberg/dsl/acir_format/bigint_constraint.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp index 97e7fa4b2be..f6614f5ce87 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp @@ -38,6 +38,8 @@ struct BigIntToLeBytes { friend bool operator==(BigIntToLeBytes const& lhs, BigIntToLeBytes const& rhs) = default; }; +/// Enumerates the supported modulus types for big integer operations. +/// Specifies whether a bigint refers to a BN254/SECP256K1/SECP256R1 Fq or Fr modulus. enum ModulusId { BN254_FQ = 0, BN254_FR, @@ -48,6 +50,9 @@ enum ModulusId { UNKNOWN, }; +/// 256-bit modulus value for a field element +/// The modulus is represented by 4 64-bits limbs +/// Used to define the modulus for big integer operations. class ModulusParam { public: uint64_t modulus_0; @@ -55,6 +60,7 @@ class ModulusParam { uint64_t modulus_2; uint64_t modulus_3; }; + template class DSLBigInts { using big_bn254_fq = bb::stdlib::bigfield; using big_bn254_fr = bb::stdlib::bigfield; From 3ac9255706d2adc0b307a8cdfa8fddf36db978a8 Mon Sep 17 00:00:00 2001 From: guipublic Date: Fri, 2 Feb 2024 15:25:59 +0000 Subject: [PATCH 10/10] rename bigint-op neg into sub --- .../dsl/acir_format/acir_to_constraint_buf.hpp | 2 +- .../dsl/acir_format/bigint_constraint.cpp | 10 +++++----- .../dsl/acir_format/bigint_constraint.hpp | 4 ++-- .../dsl/acir_format/bigint_constraint.test.cpp | 16 ++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index a741cb9539b..a967b01b647 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -273,7 +273,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .lhs = arg.lhs, .rhs = arg.rhs, .result = arg.output, - .opcode = BigIntOperationType::Neg, + .opcode = BigIntOperationType::Sub, }); } else if constexpr (std::is_same_v) { af.bigint_operations.push_back(BigIntOperation{ diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp index 06d0caac810..f4d5ea9def0 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp @@ -54,9 +54,9 @@ template void create_bigint_addition_constraint(const BigIn DSLBigInts& dsl_bigint); template void create_bigint_addition_constraint( const BigIntOperation& input, DSLBigInts& dsl_bigint); -template void create_bigint_neg_constraint(const BigIntOperation& input, +template void create_bigint_sub_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint); -template void create_bigint_neg_constraint( +template void create_bigint_sub_constraint( const BigIntOperation& input, DSLBigInts& dsl_bigint); template void create_bigint_mul_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint); @@ -114,7 +114,7 @@ void create_bigint_addition_constraint(const BigIntOperation& input, DSLBigInts< } template -void create_bigint_neg_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint) +void create_bigint_sub_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigint) { switch (dsl_bigint.get_modulus_id(input.lhs)) { case ModulusId::BN254_FR: { @@ -259,8 +259,8 @@ void create_bigint_operations_constraint(const BigIntOperation& input, DSLBigInt create_bigint_addition_constraint(input, dsl_bigint); break; } - case BigIntOperationType::Neg: { - create_bigint_neg_constraint(input, dsl_bigint); + case BigIntOperationType::Sub: { + create_bigint_sub_constraint(input, dsl_bigint); break; } case BigIntOperationType::Mul: { diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp index f6614f5ce87..1feb0fffce1 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp @@ -16,7 +16,7 @@ struct BigIntFromLeBytes { friend bool operator==(BigIntFromLeBytes const& lhs, BigIntFromLeBytes const& rhs) = default; }; -enum BigIntOperationType { Add, Neg, Mul, Div }; +enum BigIntOperationType { Add, Sub, Mul, Div }; struct BigIntOperation { uint32_t lhs; @@ -196,7 +196,7 @@ void create_bigint_operations_constraint(const BigIntOperation& input, DSLBigInt template void create_bigint_addition_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); template -void create_bigint_neg_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); +void create_bigint_sub_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); template void create_bigint_mul_constraint(const BigIntOperation& input, DSLBigInts& dsl_bigints); template diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp index dbe57fad9fc..161c6076692 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -55,7 +55,7 @@ generate_big_int_op_constraint_with_modulus( case Add: value = witness_values[lhs_id] + witness_values[rhs_id]; break; - case Neg: + case Sub: value = witness_values[lhs_id] - witness_values[rhs_id]; break; case Mul: @@ -138,7 +138,7 @@ std::tuple generate_big_int_op_constraint_with case Add: value = witness_values[lhs_id] + witness_values[rhs_id]; break; - case Neg: + case Sub: value = witness_values[lhs_id] - witness_values[rhs_id]; break; case Mul: @@ -162,7 +162,7 @@ TEST_F(BigIntTests, TestBigIntConstraintMultiple) WitnessVector witness; auto contraints = generate_big_int_op_constraint(BigIntOperationType::Add, fr(3), fr(1), witness); auto contraints2 = generate_big_int_op_constraint(BigIntOperationType::Add, fr(3), fr(1), witness); - auto contraints3 = generate_big_int_op_constraint(BigIntOperationType::Neg, fr(5), fr(2), witness); + auto contraints3 = generate_big_int_op_constraint(BigIntOperationType::Sub, fr(5), fr(2), witness); auto contraints4 = generate_big_int_op_constraint(BigIntOperationType::Mul, fr(5), fr(3), witness); auto contraints5 = generate_big_int_op_constraint(BigIntOperationType::Div, fr(8), fr(2), witness); AcirFormat constraint_system{ @@ -277,10 +277,10 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse) { WitnessVector witness; auto contraints = generate_big_int_op_constraint_secpk1_fr(BigIntOperationType::Add, fr(3), fr(1), witness); - auto contraints2 = generate_big_int_op_constraint_secpk1_fr(BigIntOperationType::Neg, fr(5), fr(2), witness); + auto contraints2 = generate_big_int_op_constraint_secpk1_fr(BigIntOperationType::Sub, fr(5), fr(2), witness); auto contraints3 = generate_big_int_op_constraint_with_id(BigIntOperationType::Mul, 0, 5, witness); auto contraints4 = generate_big_int_op_constraint_with_id(BigIntOperationType::Div, 0, 1, witness); - auto contraints5 = generate_big_int_op_constraint_with_id(BigIntOperationType::Neg, 7, 1, witness); + auto contraints5 = generate_big_int_op_constraint_with_id(BigIntOperationType::Sub, 7, 1, witness); AcirFormat constraint_system{ .varnum = static_cast(witness.size() + 1), @@ -332,10 +332,10 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse2) { WitnessVector witness; auto contraints = generate_big_int_op_constraint_secpk1_fq(BigIntOperationType::Add, fr(3), fr(1), witness); - auto contraints2 = generate_big_int_op_constraint_secpk1_fq(BigIntOperationType::Neg, fr(5), fr(2), witness); + auto contraints2 = generate_big_int_op_constraint_secpk1_fq(BigIntOperationType::Sub, fr(5), fr(2), witness); auto contraints3 = generate_big_int_op_constraint_with_id(BigIntOperationType::Add, 0, 5, witness); - auto contraints4 = generate_big_int_op_constraint_with_id(BigIntOperationType::Neg, 0, 1, witness); - auto contraints5 = generate_big_int_op_constraint_with_id(BigIntOperationType::Neg, 7, 1, witness); + auto contraints4 = generate_big_int_op_constraint_with_id(BigIntOperationType::Sub, 0, 1, witness); + auto contraints5 = generate_big_int_op_constraint_with_id(BigIntOperationType::Sub, 7, 1, witness); AcirFormat constraint_system{ .varnum = static_cast(witness.size() + 1),