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 constexpr F
a{ 0x01, 0x02, 0x03, 0x04 };
125 constexpr F
b{ 0x05, 0x06, 0x07, 0x08 };
128 constexpr F
sum =
a +
b;
129 constexpr F diff =
a -
b;
130 constexpr F prod =
a *
b;
131 constexpr F sq =
a.
sqr();
134 EXPECT_EQ(
sum,
a +
b);
135 EXPECT_EQ(diff,
a -
b);
136 EXPECT_EQ(prod,
a *
b);
137 EXPECT_EQ(sq,
a.
sqr());
144 constexpr uint256_t a{ 0x1111, 0x2222, 0x3333, 0x4444 };
147 static_assert(
a == c ||
a == c - F::modulus);
158 uint256_t a_raw = TestFixture::get_random_element_raw();
159 uint256_t b_raw = TestFixture::get_random_element_raw();
175 uint256_t a_raw = TestFixture::get_random_element_raw();
176 uint256_t b_raw = TestFixture::get_random_element_raw();
192 uint256_t a_raw = TestFixture::get_random_element_raw();
193 uint256_t b_raw = TestFixture::get_random_element_raw();
209 uint256_t a_raw = TestFixture::get_random_element_raw();
224 uint256_t original = TestFixture::get_random_element_raw();
225 F field_element(original);
228 EXPECT_EQ(original, recovered);
239 F
a = F::random_element();
253 auto [is_sqr, root] = one.sqrt();
256 EXPECT_EQ(root.sqr(), one);
263 F
a = F::random_element();
265 auto [is_sqr, root] = a_sqr.
sqrt();
268 EXPECT_EQ(root.sqr(), a_sqr);
269 EXPECT_TRUE((root ==
a) || (root == -
a));
281 F x = F::random_element();
282 F lambda = F::cube_root_of_unity();
283 F lambda_x = x * lambda;
285 F x_cubed = x * x * x;
286 F lambda_x_cubed = lambda_x * lambda_x * lambda_x;
288 EXPECT_EQ(x_cubed, lambda_x_cubed);
300 F
a = F::random_element();
308 F
a = F::random_element();
316 F
a = F::random_element();
324 F
a = F::random_element();
335 constexpr size_t batch_size = 10;
340 for (
size_t i = 0; i < batch_size; ++i) {
341 elements[i] = F::random_element();
342 inverses[i] = elements[i];
345 F::batch_invert(&inverses[0], batch_size);
347 for (
size_t i = 0; i < batch_size; ++i) {
348 F product = elements[i] * inverses[i];
349 product = product.reduce_once().reduce_once();
350 EXPECT_EQ(product, F::one());
362 F
a = F::random_element();
366 F expected = a_copy + F(2);
367 EXPECT_EQ(
a, expected);
370 expected = a_copy + F(5);
371 EXPECT_EQ(
a, expected);
378 F
a = F::random_element();
384 EXPECT_EQ(
a, a_before + F(1));
391 F
a = F::random_element();
397 EXPECT_EQ(
a, a_old + F(1));
410 auto small_number = 10;
411 F small_field_elt = F(small_number).from_montgomery_form();
413 small_field_elt.data[0], small_field_elt.data[1], small_field_elt.data[2], small_field_elt.data[3]);
415 F big_field_elt = F(big_number).from_montgomery_form();
417 big_field_elt.data[0], big_field_elt.data[1], big_field_elt.data[2], big_field_elt.data[3]);
421 EXPECT_EQ(small_number_from_limbs, small_number);
422 EXPECT_EQ(big_number, big_number_from_limbs);
424 F result = small_field_elt + big_field_elt;
427 uint256_t result_from_limbs(result.data[0], result.data[1], result.data[2], result.data[3]);
430 bool is_gte_modulus = result_from_limbs >= F::modulus;
431 EXPECT_EQ(is_gte_modulus,
true);
448 0xDEADBEEFCAFEBABEULL, 0xFEDCBA9876543210ULL, 0x123456789ABCDEF0ULL, F::modulus.data[3] / 2
451 for (
size_t limb_idx = 0; limb_idx < 4; ++limb_idx) {
453 limbs[limb_idx] = limb_values[limb_idx];
455 F
a = create_element_with_limbs<F>(limbs[0], limbs[1], limbs[2], limbs[3]);
456 F
b = F::random_element();
463 EXPECT_EQ(
uint256_t(
sum), expected_sum.
lo) <<
"Add failed for limb " << limb_idx;
468 EXPECT_EQ(
uint256_t(diff), expected_diff.
lo) <<
"Sub failed for limb " << limb_idx;
473 EXPECT_EQ(
uint256_t(prod), expected_prod.
lo) <<
"Mul failed for limb " << limb_idx;
478 EXPECT_EQ(
uint256_t(sq), expected_sq.
lo) <<
"Sqr failed for limb " << limb_idx;
490 { { 0, 0x9876543210FEDCBAULL, 0, 0 } },
491 { { 0, 0, 0x1111222233334444ULL, 0 } },
492 { { 0, 0, 0, F::modulus.data[3] / 2 } } } };
497 for (
size_t i = 0; i < 4; ++i) {
498 elems[i] = create_element_with_limbs<F>(
499 limb_patterns[i][0], limb_patterns[i][1], limb_patterns[i][2], limb_patterns[i][3]);
504 for (
size_t i = 0; i < 4; ++i) {
505 for (
size_t j = 0; j < 4; ++j) {
506 F prod = elems[i] * elems[j];
508 EXPECT_EQ(
uint256_t(prod), expected_prod.
lo) <<
"Failed for limb " << i <<
" * limb " << j;
530 EXPECT_EQ(
uint256_t(sq), expected_sq.
lo) <<
"Sqr failed for (p - " <<
offset <<
")^2";
533 F a_plus_one =
a + F(1);
535 F prod =
a * a_plus_one;
538 <<
"Mul failed for (p - " <<
offset <<
") * (p - " <<
offset <<
" + 1)";
554 for (uint64_t
offset : offsets) {
556 if constexpr (F::modulus.data[3] >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) {
560 F two_256_minus_p_elt(two_256_minus_p);
561 two_256_minus_p_elt.self_from_montgomery_form_reduced();
562 F p_minus_offset(F::modulus -
offset);
563 p_minus_offset.self_from_montgomery_form_reduced();
564 a = p_minus_offset + two_256_minus_p_elt;
568 for (
size_t i = 0; i < 4; ++i) {
569 EXPECT_EQ(
a.
data[i], 0xFFFFFFFFFFFFFFFFULL);
575 F p_minus_one(F::modulus - 1);
576 p_minus_one.self_from_montgomery_form_reduced();
577 F p_minus_offset(F::modulus -
offset);
578 p_minus_offset.self_from_montgomery_form_reduced();
579 a = p_minus_one + p_minus_offset;
583 F
b = F::random_element();
593 EXPECT_EQ(
uint256_t(diff), expected_diff.
lo) <<
"Sub failed for offset " <<
offset;
597 EXPECT_EQ(
uint256_t(prod), expected_prod.
lo) <<
"Mul failed for offset " <<
offset;
613 F
a = F::random_element();
615 EXPECT_EQ(actual, expected);
628 constexpr uint256_t two_p = F::modulus + F::modulus;
631 for (
size_t i = 0; i < 100; i++) {
632 F
a = F::random_element();
638 ASSERT_LT(a_internal, two_p) <<
"Input not in coarse form";
643 uint256_t result_internal(result.data[0], result.data[1], result.data[2], result.data[3]);
644 EXPECT_LT(result_internal, two_p) <<
"Result of from_montgomery_form exceeds [0, 2p) range";
652 F p_minus_one(F::modulus - 1);
653 p_minus_one.self_from_montgomery_form();
654 F p_minus_offset_plus_one(F::modulus -
offset + 1);
655 p_minus_offset_plus_one.self_from_montgomery_form();
656 F
a = p_minus_one + p_minus_offset_plus_one;
660 ASSERT_LT(a_internal, two_p) <<
"Test setup: element not in valid range";
664 uint256_t result_internal(result.data[0], result.data[1], result.data[2], result.data[3]);
665 EXPECT_LT(result_internal, two_p)
666 <<
"Edge case: Result of from_montgomery_form exceeds [0, 2p) for offset " <<
offset;
676 constexpr uint256_t two_p = F::modulus + F::modulus;
679 for (
size_t i = 0; i < 100; i++) {
680 F
a = F::random_element();
686 ASSERT_LT(a_internal, two_p) <<
"Input not in coarse form";
691 uint256_t result_internal(result.data[0], result.data[1], result.data[2], result.data[3]);
692 EXPECT_LT(result_internal, two_p) <<
"Result of to_montgomery_form exceeds [0, 2p) range";
700 F p_minus_one(F::modulus - 1);
701 p_minus_one.self_from_montgomery_form();
702 F p_minus_offset_plus_one(F::modulus -
offset + 1);
703 p_minus_offset_plus_one.self_from_montgomery_form();
704 F
a = p_minus_one + p_minus_offset_plus_one;
708 ASSERT_LT(a_internal, two_p) <<
"Test setup: element not in valid range";
712 uint256_t result_internal(result.data[0], result.data[1], result.data[2], result.data[3]);
713 EXPECT_LT(result_internal, two_p)
714 <<
"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
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)