8#include "../bool/bool.hpp"
9#include "../byte_array/byte_array.hpp"
10#include "../field/field.hpp"
24#include <gtest/gtest.h>
48template <
template <
typename,
typename>
class BigField,
typename Builder,
typename Params>
53template <
template <
typename,
typename>
class BigField,
typename Builder,
typename Params>
89 uint512_t(fq_ct::get_maximum_unreduced_value()) - 1,
90 uint512_t(fq_ct::get_maximum_unreduced_value()),
91 uint512_t(fq_ct::get_maximum_unreduced_value()) + 1,
92 (
uint512_t(1) << (stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION * 4)) - 1,
102 EXPECT_EQ(val.get_value() >= fq_ct::modulus,
true);
105 EXPECT_EQ(result_check,
true);
127 fq_ct combined_a = fq_ct::unsafe_construct_from_limbs(limb_0, limb_1, limb_2, limb_3,
true);
128 combined_a.set_limb_max(3, other_mask);
131 const bool limbs_less_than_max = (limb_0_native <= fq_ct::get_maximum_unreduced_limb_value()) &&
132 (limb_1_native <= fq_ct::get_maximum_unreduced_limb_value()) &&
133 (limb_2_native <= fq_ct::get_maximum_unreduced_limb_value()) &&
134 (limb_3_native <= fq_ct::get_maximum_unreduced_limb_value());
135 EXPECT_EQ(limbs_less_than_max,
true);
138 EXPECT_GT(combined_a.get_maximum_value(),
139 fq_ct::get_maximum_unreduced_value()
143 EXPECT_EQ(combined_a.get_value() > fq_ct::modulus,
true);
148 EXPECT_EQ(combined_a.get_maximum_value() <= fq_ct::get_maximum_unreduced_value(),
true);
173 fq_ct combined_a = fq_ct::unsafe_construct_from_limbs(limb_0, limb_1, limb_2, limb_3);
176 combined_a.set_limb_max(0, (
uint256_t(1) << fq_ct::MAX_UNREDUCED_LIMB_BITS) + 1000);
179 EXPECT_EQ(combined_a.get_maximum_value() <= fq_ct::get_maximum_unreduced_value(),
true);
186 EXPECT_EQ(combined_a.get_maximum_value() <= fq_ct::get_maximum_unreduced_value(),
true);
215 fq_ct combined_a = fq_ct::unsafe_construct_from_limbs(limb_0, limb_1, limb_2, limb_3);
216 combined_a.set_limb_max(3, other_mask);
220 for (
size_t i = 0; i < 11; ++i) {
221 const uint64_t msb_index_before = combined_a.get_limb(0).maximum_value.get_msb();
222 combined_a = combined_a + combined_a;
223 const uint64_t msb_index_after = combined_a.get_limb(0).maximum_value.get_msb();
226 EXPECT_EQ(msb_index_after, msb_index_before + 1ULL);
228 EXPECT_EQ(combined_a.get_limb(0).maximum_value.get_msb(), fq_ct::MAX_UNREDUCED_LIMB_BITS);
229 EXPECT_EQ(combined_a.get_limb(0).maximum_value > fq_ct::get_maximum_unreduced_limb_value(),
true);
232 combined_a = combined_a + combined_a;
233 EXPECT_EQ(combined_a.get_limb(0).maximum_value.get_msb(), fq_ct::NUM_LIMB_BITS);
248 fr elt_native_hi =
fr(
uint256_t(elt_native).
slice(fq_ct::NUM_LIMB_BITS * 2, fq_ct::NUM_LIMB_BITS * 4));
256 for (
size_t i = 0; i < 4; ++i) {
258 uint256_t max_value = field_element.get_limb(i).maximum_value;
260 EXPECT_GE(max_value, witness_value)
261 <<
"invariant violation in " << operation_name <<
":\n limb[" << i <<
"] max_value:\n " << max_value
262 <<
" < \n witness_value\n " << witness_value;
266 uint256_t computed_prime = field_element.get_limb(0).element.get_value();
267 computed_prime += field_element.get_limb(1).element.get_value() * fq_ct::shift_1;
268 computed_prime += field_element.get_limb(2).element.get_value() * fq_ct::shift_2;
269 computed_prime += field_element.get_limb(3).element.get_value() * fq_ct::shift_3;
270 uint256_t actual_prime = field_element.get_prime_basis_limb().get_value();
272 EXPECT_EQ(
fr(computed_prime),
fr(actual_prime))
273 <<
"invariant violation in " << operation_name <<
":\n computed prime:\n " <<
fr(computed_prime)
274 <<
" != \n actual prime:\n " <<
fr(actual_prime);
277 for (
size_t i = 0; i < 4; ++i) {
278 uint64_t max_bits = field_element.get_limb(i).maximum_value.get_msb() + 1;
280 EXPECT_LT(max_bits, fq_ct::PROHIBITED_LIMB_BITS)
281 <<
"invariant violation in " << operation_name <<
":\n limb[" << i <<
"] has " << max_bits
282 <<
" bits, which exceeds PROHIBITED_LIMB_BITS (" << fq_ct::PROHIBITED_LIMB_BITS <<
")";
287 template <
typename BinaryOp,
typename NativeOp>
290 const std::string& operation_name,
291 const bool skip_zero =
false)
299 fq_ct c_ct = binary_op(a_ct, b_ct);
300 fq_native c_native = native_op(a_native, b_native);
308 if (skip_zero && (is_fq_value_zero || is_fr_value_zero)) {
314 fq_ct edge_case = fq_ct::create_from_u512_as_witness(&
builder, edge_value,
true);
317 fq_ct result_ct = binary_op(c_ct, edge_case);
318 fq_native result_native = native_op(c_native, edge_native);
322 c_native = result_native;
329 if (skip_zero && (is_fq_value_zero || is_fr_value_zero)) {
335 fq_ct large_case = fq_ct::create_from_u512_as_witness(&
builder, large_value,
true);
338 fq_ct result_ct = binary_op(c_ct, large_case);
339 fq_native result_native = native_op(c_native, large_native);
343 c_native = result_native;
351 EXPECT_EQ(c_ct.get_value(),
uint512_t(c_native)) <<
"native check failed for " << operation_name <<
" (final)";
358#define INVARIANT_BINARY_OP_TEST(op_name, op_symbol, skip_zero) \
359 static void test_invariants_during_##op_name() \
361 test_invariants_during_binary_operation([](const fq_ct& a, const fq_ct& b) { return a op_symbol b; }, \
362 [](const fq_native& a, const fq_native& b) { return a op_symbol b; }, \
396 edge_case.assert_is_in_field();
410 fq_ct large_case = fq_ct::create_from_u512_as_witness(&
builder, large_value,
true);
411 large_case.assert_is_in_field();
419 EXPECT_EQ(
builder.err(),
"bigfield::unsafe_assert_less_than: r2 or r3 too large: hi limb.");
423 EXPECT_EQ(
builder.err(),
"bigfield::assert_less_than: limb 2 or 3 too large: hi limb.");
455 larger_value.assert_less_than(smaller_value);
459 EXPECT_EQ(
builder.err(),
"bigfield::unsafe_assert_less_than: r2 or r3 too large: hi limb.");
472 edge_case.reduce_mod_target_modulus();
475 EXPECT_EQ(edge_case.get_value() < fq_ct::modulus,
true);
476 EXPECT_EQ(edge_case.get_value(),
uint512_t(edge_case_native));
480 fq_ct large_case = fq_ct::create_from_u512_as_witness(&
builder, large_value,
true);
483 large_case.reduce_mod_target_modulus();
486 EXPECT_EQ(large_case.get_value() < fq_ct::modulus,
true);
487 EXPECT_EQ(large_case.get_value(),
uint512_t(large_case_native));
503 value_p_plus_n.assert_equal(value_n);
507 fq_ct random_plus_p =
509 random_plus_p.assert_equal(random_ct);
526 fq_ct output = a_ct / zero;
527 fq_ct output_modulus = a_ct / zero_modulus;
530 EXPECT_EQ(output.get_value(), 0);
531 EXPECT_EQ(output_modulus.get_value(), 0);
535 EXPECT_EQ(
builder.err(),
"bigfield: prime limb diff is zero, but expected non-zero");
546 fq_ct output = a_ct / zero;
549 EXPECT_EQ(output.get_value(), 0);
553 EXPECT_EQ(
builder.err(),
"bigfield: prime limb diff is zero, but expected non-zero");
562 fq_ct output = fq_ct::div_check_denominator_nonzero({}, zero);
565 EXPECT_EQ(output.get_value(), 0);
569 EXPECT_EQ(
builder.err(),
"bigfield: prime limb diff is zero, but expected non-zero");
602 "bigfield: prime limb diff is zero, but expected non-zero");
609using CircuitTypes = testing::Types<typename bb::stdlib::bn254<UltraCircuitBuilder>::BaseField,
620 TestFixture::test_larger_than_bigfield_allowed();
624 TestFixture::test_reduction_check_works();
628 TestFixture::test_reduction_works_on_limb_overflow();
632 TestFixture::test_maximum_value_tracking_during_addition();
638 TestFixture::test_invariants_during_addition();
642 TestFixture::test_invariants_during_subtraction();
646 TestFixture::test_invariants_during_multiplication();
650 TestFixture::test_invariants_during_division();
654 TestFixture::test_invariants_during_squaring();
658 TestFixture::test_invariants_during_negation();
664 TestFixture::test_assert_is_in_field();
668 TestFixture::test_assert_is_in_field_fails();
672 TestFixture::test_assert_less_than();
676 TestFixture::test_assert_less_than_fails();
680 TestFixture::test_reduce_mod_target_modulus();
684 TestFixture::test_assert_equal_edge_case();
689 TestFixture::test_divide_by_zero_fails();
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
typename extract_builder< BigField >::type builder_t
typename extract_fq_params< BigField >::type params_t
typename extract_builder< BigField >::type builder_t
constexpr InputType operator!(InputType type)
#define INVARIANT_BINARY_OP_TEST(op_name, op_symbol, skip_zero)
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
Implements boolean logic in-circuit.
Represents a dynamic array of bytes in-circuit.
static void test_larger_than_bigfield_allowed()
stdlib::witness_t< Builder > witness_ct
static void test_invariants_during_negation()
static std::pair< fq_native, fq_ct > get_random_witness(Builder *builder, bool reduce_input=false)
static void test_assert_less_than_fails()
builder_t< BigField > Builder
static void test_invariants_during_binary_operation(BinaryOp binary_op, NativeOp native_op, const std::string &operation_name, const bool skip_zero=false)
static void test_assert_is_in_field_fails()
typename bb::stdlib::bn254< Builder >::ScalarField fr_ct
static void test_assert_less_than()
static void test_maximum_value_tracking_during_addition()
static const std::array< uint512_t, 10 > values_larger_than_bigfield
static void test_assert_equal_edge_case()
static void test_reduction_check_works()
static void test_reduce_mod_target_modulus()
static void test_reduction_works_on_limb_overflow()
static void test_assert_is_in_field()
static constexpr std::array< uint512_t, 5 > edge_case_values
static constexpr uint512_t reduction_upper_bound
static void test_invariants_during_squaring()
static void check_invariants(const fq_ct &field_element, const std::string &operation_name)
static void test_divide_by_zero_fails()
bb::field< params_t< BigField > > fq_native
ECCVMCircuitBuilder Builder
crypto::Poseidon2Bn254ScalarFieldParams Params
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)
field< Bn254FrParams > fr
C slice(C const &container, size_t start)
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
#define STANDARD_TESTING_TAGS
testing::Types< bb::MegaCircuitBuilder, bb::UltraCircuitBuilder > CircuitTypes
General class for prime fields see Prime field documentation["field documentation"] for general imple...
static constexpr uint256_t modulus
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field sqr() const noexcept
BB_INLINE constexpr field reduce_once() const noexcept