24#include <gtest/gtest.h>
36template <
typename F> F create_element_with_limbs(uint64_t l0, uint64_t l1, uint64_t l2, uint64_t l3)
40 result.self_from_montgomery_form_reduced();
44#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
46 EXPECT_EQ(result.data[0], l0);
47 EXPECT_EQ(result.data[1], l1);
48 EXPECT_EQ(result.data[2], l2);
49 EXPECT_EQ(result.data[3], l3);
63 while (res >= F::modulus) {
71using PrimeFieldTypes = ::testing::Types<bb::fq, bb::fr, secp256k1::fq, secp256k1::fr, secp256r1::fq, secp256r1::fr>;
74using SqrtFieldTypes = ::testing::Types<bb::fq, bb::fr, secp256k1::fq, secp256r1::fq>;
106 constexpr F
a{ 0x01, 0x02, 0x03, 0x04 };
107 constexpr F
b{ 0x01, 0x02, 0x03, 0x04 };
109 constexpr F c{ 0x01, 0x02, 0x03, 0x05 };
110 constexpr F d{ 0x01, 0x02, 0x04, 0x04 };
111 constexpr F e{ 0x01, 0x03, 0x03, 0x04 };
112 constexpr F f{ 0x02, 0x02, 0x03, 0x04 };
113 static_assert(
a ==
b);
114 static_assert(!(
a == c));
115 static_assert(!(
a == d));
116 static_assert(!(
a == e));
117 static_assert(!(
a == f));
124 F modulus_form{ F::modulus.
data[0], F::modulus.data[1], F::modulus.data[2], F::modulus.data[3] };
125 EXPECT_TRUE(modulus_form.is_zero());
127 F prefix_match{ F::modulus.data[0], F::modulus.data[1], F::modulus.data[2], F::modulus.data[3] - 1 };
128 EXPECT_FALSE(prefix_match.is_zero());
130 F first_limb_only{ F::modulus.data[0], 0, 0, 0 };
131 EXPECT_FALSE(first_limb_only.is_zero());
138 constexpr F
a{ 0x01, 0x02, 0x03, 0x04 };
139 constexpr F
b{ 0x05, 0x06, 0x07, 0x08 };
142 constexpr F
sum =
a +
b;
143 constexpr F diff =
a -
b;
144 constexpr F prod =
a *
b;
145 constexpr F sq =
a.
sqr();
148 EXPECT_EQ(
sum,
a +
b);
149 EXPECT_EQ(diff,
a -
b);
150 EXPECT_EQ(prod,
a *
b);
151 EXPECT_EQ(sq,
a.
sqr());
158 constexpr uint256_t a{ 0x1111, 0x2222, 0x3333, 0x4444 };
161 static_assert(
a == c ||
a == c - F::modulus);
172 uint256_t a_raw = TestFixture::get_random_element_raw();
173 uint256_t b_raw = TestFixture::get_random_element_raw();
189 uint256_t a_raw = TestFixture::get_random_element_raw();
190 uint256_t b_raw = TestFixture::get_random_element_raw();
206 uint256_t a_raw = TestFixture::get_random_element_raw();
207 uint256_t b_raw = TestFixture::get_random_element_raw();
223 uint256_t a_raw = TestFixture::get_random_element_raw();
238 uint256_t original = TestFixture::get_random_element_raw();
239 F field_element(original);
242 EXPECT_EQ(original, recovered);
253 F
a = F::random_element();
267 auto [is_sqr, root] = one.sqrt();
270 EXPECT_EQ(root.sqr(), one);
277 F
a = F::random_element();
279 auto [is_sqr, root] = a_sqr.
sqrt();
282 EXPECT_EQ(root.sqr(), a_sqr);
283 EXPECT_TRUE((root ==
a) || (root == -
a));
295 F x = F::random_element();
296 F lambda = F::cube_root_of_unity();
297 F lambda_x = x * lambda;
299 F x_cubed = x * x * x;
300 F lambda_x_cubed = lambda_x * lambda_x * lambda_x;
302 EXPECT_EQ(x_cubed, lambda_x_cubed);
314 F
a = F::random_element();
322 F
a = F::random_element();
330 F
a = F::random_element();
338 F
a = F::random_element();
349 constexpr size_t batch_size = 10;
354 for (
size_t i = 0; i < batch_size; ++i) {
355 elements[i] = F::random_element();
356 inverses[i] = elements[i];
359 F::batch_invert(&inverses[0], batch_size);
361 for (
size_t i = 0; i < batch_size; ++i) {
362 F product = elements[i] * inverses[i];
363 product = product.reduce_once().reduce_once();
364 EXPECT_EQ(product, F::one());
376 F
a = F::random_element();
380 F expected = a_copy + F(2);
381 EXPECT_EQ(
a, expected);
384 expected = a_copy + F(5);
385 EXPECT_EQ(
a, expected);
392 F
a = F::random_element();
398 EXPECT_EQ(
a, a_before + F(1));
405 F
a = F::random_element();
411 EXPECT_EQ(
a, a_old + F(1));
424 auto small_number = 10;
425 F small_field_elt = F(small_number).from_montgomery_form();
427 small_field_elt.data[0], small_field_elt.data[1], small_field_elt.data[2], small_field_elt.data[3]);
429 F big_field_elt = F(big_number).from_montgomery_form();
431 big_field_elt.data[0], big_field_elt.data[1], big_field_elt.data[2], big_field_elt.data[3]);
435 EXPECT_EQ(small_number_from_limbs, small_number);
436 EXPECT_EQ(big_number, big_number_from_limbs);
438 F result = small_field_elt + big_field_elt;
441 uint256_t result_from_limbs(result.data[0], result.data[1], result.data[2], result.data[3]);
444 bool is_gte_modulus = result_from_limbs >= F::modulus;
445 EXPECT_EQ(is_gte_modulus,
true);
462 0xDEADBEEFCAFEBABEULL, 0xFEDCBA9876543210ULL, 0x123456789ABCDEF0ULL, F::modulus.data[3] / 2
465 for (
size_t limb_idx = 0; limb_idx < 4; ++limb_idx) {
467 limbs[limb_idx] = limb_values[limb_idx];
469 F
a = create_element_with_limbs<F>(limbs[0], limbs[1], limbs[2], limbs[3]);
470 F
b = F::random_element();
477 EXPECT_EQ(
uint256_t(
sum), expected_sum.
lo) <<
"Add failed for limb " << limb_idx;
482 EXPECT_EQ(
uint256_t(diff), expected_diff.
lo) <<
"Sub failed for limb " << limb_idx;
487 EXPECT_EQ(
uint256_t(prod), expected_prod.
lo) <<
"Mul failed for limb " << limb_idx;
492 EXPECT_EQ(
uint256_t(sq), expected_sq.
lo) <<
"Sqr failed for limb " << limb_idx;
504 { { 0, 0x9876543210FEDCBAULL, 0, 0 } },
505 { { 0, 0, 0x1111222233334444ULL, 0 } },
506 { { 0, 0, 0, F::modulus.data[3] / 2 } } } };
511 for (
size_t i = 0; i < 4; ++i) {
512 elems[i] = create_element_with_limbs<F>(
513 limb_patterns[i][0], limb_patterns[i][1], limb_patterns[i][2], limb_patterns[i][3]);
518 for (
size_t i = 0; i < 4; ++i) {
519 for (
size_t j = 0; j < 4; ++j) {
520 F prod = elems[i] * elems[j];
522 EXPECT_EQ(
uint256_t(prod), expected_prod.
lo) <<
"Failed for limb " << i <<
" * limb " << j;
544 EXPECT_EQ(
uint256_t(sq), expected_sq.
lo) <<
"Sqr failed for (p - " <<
offset <<
")^2";
547 F a_plus_one =
a + F(1);
549 F prod =
a * a_plus_one;
552 <<
"Mul failed for (p - " <<
offset <<
") * (p - " <<
offset <<
" + 1)";
568 for (uint64_t
offset : offsets) {
570 if constexpr (F::modulus.data[3] >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) {
574 F two_256_minus_p_elt(two_256_minus_p);
575 two_256_minus_p_elt.self_from_montgomery_form_reduced();
576 F p_minus_offset(F::modulus -
offset);
577 p_minus_offset.self_from_montgomery_form_reduced();
578 a = p_minus_offset + two_256_minus_p_elt;
582 for (
size_t i = 0; i < 4; ++i) {
583 EXPECT_EQ(
a.
data[i], 0xFFFFFFFFFFFFFFFFULL);
589 F p_minus_one(F::modulus - 1);
590 p_minus_one.self_from_montgomery_form_reduced();
591 F p_minus_offset(F::modulus -
offset);
592 p_minus_offset.self_from_montgomery_form_reduced();
593 a = p_minus_one + p_minus_offset;
597 F
b = F::random_element();
607 EXPECT_EQ(
uint256_t(diff), expected_diff.
lo) <<
"Sub failed for offset " <<
offset;
611 EXPECT_EQ(
uint256_t(prod), expected_prod.
lo) <<
"Mul failed for offset " <<
offset;
627 F
a = F::random_element();
629 EXPECT_EQ(actual, expected);
634#ifndef BB_NO_EXCEPTIONS
647 uint8_t* buf =
reinterpret_cast<uint8_t*
>(
buffer.data());
648 size_t buf_size =
buffer.size();
649 uint8_t* field_bytes =
nullptr;
650 for (
size_t i = 0; i + 33 <= buf_size; i++) {
651 if (buf[i] == 0xc4 && buf[i + 1] == 0x20) {
652 field_bytes = &buf[i + 2];
656 ASSERT_NE(field_bytes,
nullptr) <<
"Could not find 32-byte bin payload in msgpack buffer";
660 for (
int i = 31; i >= 0; i--) {
661 field_bytes[i] =
static_cast<uint8_t
>(non_canonical.
data[0] & 0xFF);
668 msgpack::object_handle oh = msgpack::unpack(
buffer.data(),
buffer.size());
670 oh.get().convert(result);
677 GTEST_SKIP() <<
"Skipping: throw_or_abort calls abort() when BB_NO_EXCEPTIONS is defined";
691 constexpr uint256_t two_p = F::modulus + F::modulus;
694 for (
size_t i = 0; i < 100; i++) {
695 F
a = F::random_element();
701 ASSERT_LT(a_internal, two_p) <<
"Input not in coarse form";
706 uint256_t result_internal(result.data[0], result.data[1], result.data[2], result.data[3]);
707 EXPECT_LT(result_internal, two_p) <<
"Result of from_montgomery_form exceeds [0, 2p) range";
715 F p_minus_one(F::modulus - 1);
716 p_minus_one.self_from_montgomery_form();
717 F p_minus_offset_plus_one(F::modulus -
offset + 1);
718 p_minus_offset_plus_one.self_from_montgomery_form();
719 F
a = p_minus_one + p_minus_offset_plus_one;
723 ASSERT_LT(a_internal, two_p) <<
"Test setup: element not in valid range";
727 uint256_t result_internal(result.data[0], result.data[1], result.data[2], result.data[3]);
728 EXPECT_LT(result_internal, two_p)
729 <<
"Edge case: Result of from_montgomery_form exceeds [0, 2p) for offset " <<
offset;
739 constexpr uint256_t two_p = F::modulus + F::modulus;
742 for (
size_t i = 0; i < 100; i++) {
743 F
a = F::random_element();
749 ASSERT_LT(a_internal, two_p) <<
"Input not in coarse form";
754 uint256_t result_internal(result.data[0], result.data[1], result.data[2], result.data[3]);
755 EXPECT_LT(result_internal, two_p) <<
"Result of to_montgomery_form exceeds [0, 2p) range";
763 F p_minus_one(F::modulus - 1);
764 p_minus_one.self_from_montgomery_form();
765 F p_minus_offset_plus_one(F::modulus -
offset + 1);
766 p_minus_offset_plus_one.self_from_montgomery_form();
767 F
a = p_minus_one + p_minus_offset_plus_one;
771 ASSERT_LT(a_internal, two_p) <<
"Test setup: element not in valid range";
775 uint256_t result_internal(result.data[0], result.data[1], result.data[2], result.data[3]);
776 EXPECT_LT(result_internal, two_p)
777 <<
"Edge case: Result of to_montgomery_form exceeds [0, 2p) for offset " <<
offset;
static uint256_t get_random_element_raw()
virtual uint256_t get_random_uint256()=0
std::unique_ptr< uint8_t[]> buffer
uintx< uint256_t > uint512_t
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Entry point for Barretenberg command-line interface.
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
Inner sum(Cont< Inner, Args... > const &in)
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
::testing::Types< bb::fq, bb::fr > TwoFiftyFourBitFieldTypes
::testing::Types< bb::fq, bb::fr, secp256k1::fq, secp256r1::fq > SqrtFieldTypes
::testing::Types< secp256k1::fq, secp256k1::fr > TwoFiftySixBitFieldTypes
::testing::Types< bb::fq, bb::fr, secp256k1::fq, secp256k1::fr, secp256r1::fq, secp256r1::fr > PrimeFieldTypes
::testing::Types< bb::fq, bb::fr, secp256k1::fq, secp256k1::fr > CubeRootFieldTypes
BB_INLINE constexpr field to_montgomery_form() const noexcept
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
BB_INLINE constexpr field sqr() const noexcept
constexpr std::pair< bool, field > sqrt() const noexcept
Compute square root of the field element.
BB_INLINE constexpr field from_montgomery_form() const noexcept
std::pair< T, T > msgpack_roundtrip(const T &object)