From d46389e45f304bfd8b5acfeceaa9e561689dcce3 Mon Sep 17 00:00:00 2001 From: Rumata888 Date: Thu, 8 Jun 2023 18:31:24 +0000 Subject: [PATCH] Less than fix --- .../stdlib/encryption/ecdsa/ecdsa_impl.hpp | 4 ++-- .../stdlib/primitives/bigfield/bigfield.test.cpp | 11 +++++++++++ .../stdlib/primitives/bigfield/bigfield_impl.hpp | 13 ++++++++----- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp index b81bf8b90c..44a3ee1100 100644 --- a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp +++ b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp @@ -75,7 +75,7 @@ bool_t verify_signature(const stdlib::byte_array& message, // s should be less than |Fr| / 2 // Read more about this at: https://www.derpturkey.com/inherent-malleability-of-ecdsa-signatures/amp/ - s.assert_less_than(Fr::modulus / 2); + s.assert_less_than((Fr::modulus + 1) / 2); Fr u1 = z / s; Fr u2 = r / s; @@ -148,7 +148,7 @@ bool_t verify_signature_prehashed_message_noassert(const stdlib::byte_ // s should be less than |Fr| / 2 // Read more about this at: https://www.derpturkey.com/inherent-malleability-of-ecdsa-signatures/amp/ - s.assert_less_than(Fr::modulus / 2); + s.assert_less_than((Fr::modulus + 1) / 2); Fr u1 = z / s; Fr u2 = r / s; diff --git a/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.test.cpp b/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.test.cpp index b4a1b360ef..bf390bc40e 100644 --- a/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.test.cpp +++ b/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.test.cpp @@ -746,6 +746,17 @@ template class stdlib_bigfield : public testing::Test { } bool result = composer.check_circuit(); EXPECT_EQ(result, true); + // Checking edge conditions + fq random_input = fq::random_element(); + fq_ct a(witness_ct(&composer, fr(uint256_t(random_input).slice(0, fq_ct::NUM_LIMB_BITS * 2))), + witness_ct(&composer, + fr(uint256_t(random_input).slice(fq_ct::NUM_LIMB_BITS * 2, fq_ct::NUM_LIMB_BITS * 4)))); + + a.assert_less_than(random_input + 1); + EXPECT_EQ(composer.check_circuit(), true); + + a.assert_less_than(random_input); + EXPECT_EQ(composer.check_circuit(), false); } static void test_byte_array_constructors() diff --git a/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp b/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp index 5c89292987..b4f4c2a0a6 100644 --- a/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp +++ b/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp @@ -1671,14 +1671,17 @@ template void bigfield::assert_less_than(const ui if (is_constant()) { return; } - + ASSERT(upper_limit != 0); + // The circuit checks that limit - this >= 0, so if we are doing a less_than comparison, we need to subtract 1 from + // the limit + uint256_t strict_upper_limit = upper_limit - uint256_t(1); self_reduce(); // this method in particular enforces limb vals are <2^b - needed for logic described above uint256_t value = get_value().lo; - const uint256_t upper_limit_value_0 = upper_limit.slice(0, NUM_LIMB_BITS); - const uint256_t upper_limit_value_1 = upper_limit.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2); - const uint256_t upper_limit_value_2 = upper_limit.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3); - const uint256_t upper_limit_value_3 = upper_limit.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4); + const uint256_t upper_limit_value_0 = strict_upper_limit.slice(0, NUM_LIMB_BITS); + const uint256_t upper_limit_value_1 = strict_upper_limit.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2); + const uint256_t upper_limit_value_2 = strict_upper_limit.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3); + const uint256_t upper_limit_value_3 = strict_upper_limit.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4); bool borrow_0_value = value.slice(0, NUM_LIMB_BITS) > upper_limit_value_0; bool borrow_1_value =