6#include <gtest/gtest.h>
11#pragma GCC diagnostic ignored "-Wunused-const-variable"
17template <
class Builder_>
class BoolTest :
public ::testing::Test {
34 for (
bool is_const : {
false,
true }) {
35 for (
bool value : {
false,
true }) {
36 for (
bool is_inverted : {
false,
true }) {
52 const std::function<
bool(
bool,
bool)>& expected_op)
61 size_t num_gates_start =
builder.get_num_finalized_gates_inefficient();
63 if (!
a.is_constant() && !
b.is_constant()) {
64 a.set_origin_tag(submitted_value_origin_tag);
65 b.set_origin_tag(challenge_origin_tag);
69 bool expected = expected_op(lhs.value ^ lhs.is_inverted, rhs.value ^ rhs.is_inverted);
72 <<
"Failed on " << op_name <<
" with inputs: lhs = {const=" << lhs.is_const <<
", val=" << lhs.value
73 <<
", inv=" << lhs.is_inverted <<
"}, rhs = {const=" << rhs.is_const <<
", val=" << rhs.value
74 <<
", inv=" << rhs.is_inverted <<
"}";
76 if (
a.is_constant() &&
b.is_constant()) {
80 if (!
a.is_constant() && !
b.is_constant()) {
87 size_t diff =
builder.get_num_finalized_gates_inefficient() - num_gates_start;
89 EXPECT_EQ(diff,
static_cast<size_t>(!
a.is_constant() && !
b.is_constant()));
99 size_t num_gates_start =
builder.get_num_finalized_gates_inefficient();
107 EXPECT_TRUE(num_gates_start ==
builder.get_num_finalized_gates_inefficient());
113 size_t num_gates_start =
builder.get_num_finalized_gates_inefficient();
114 const size_t witness_idx_zero =
builder.add_variable(
bb::fr(0));
115 const size_t witness_idx_one =
builder.add_variable(
bb::fr(1));
116 const size_t non_bool_witness_idx =
builder.add_variable(
bb::fr(15));
119 EXPECT_EQ(bool_witness.
get_value(),
false);
122 EXPECT_EQ(bool_witness.
get_value(),
true);
124 EXPECT_EQ(
builder.get_num_finalized_gates_inefficient() - num_gates_start, 0);
128 "bool_t: creating a witness bool from a non-boolean value");
133 size_t num_gates_start =
builder.get_num_finalized_gates_inefficient();
142 EXPECT_TRUE(
builder.get_num_finalized_gates_inefficient() - num_gates_start == 2);
149 if (random_value * random_value - random_value != 0) {
151 "bool_t: witness value is not 0 or 1");
157 const bool use_range_constraint =
true;
159 for (
size_t num_inputs = 1; num_inputs < 50; num_inputs++) {
161 size_t num_gates_start =
builder.get_num_finalized_gates_inefficient();
163 std::vector<uint32_t> indices;
164 for (
size_t idx = 0; idx < num_inputs; idx++) {
169 size_t sorted_list_size = num_inputs + 2;
171 sorted_list_size =
std::max(sorted_list_size, 8UL);
173 size_t fixed_additional_gates = 4;
175 size_t expected =
numeric::ceil_div(sorted_list_size, 4UL) + fixed_additional_gates;
177 size_t actual =
builder.get_num_finalized_gates_inefficient() - num_gates_start;
179 EXPECT_EQ(actual, expected);
181 builder.create_unconstrained_gates(indices);
190 "bool_t: witness value is not 0 or 1");
227 [](
bool a,
bool b) {
return !
a ||
b; });
235 [](
bool a,
bool b) {
return !(
a ^
b); });
252 if (
a.is_constant() &&
b.is_constant() && !(!
a.get_value() ||
b.get_value())) {
255 bool result_is_constant = (!
a ||
b).is_constant();
257 size_t num_gates_start =
builder.get_num_finalized_gates_inefficient();
259 if (!
a.is_constant() && !
b.is_constant()) {
260 a.set_origin_tag(submitted_value_origin_tag);
261 b.set_origin_tag(challenge_origin_tag);
266 bool expected = !(lhs.value ^ lhs.is_inverted) || rhs.value ^ rhs.is_inverted;
268 size_t diff =
builder.get_num_finalized_gates_inefficient() - num_gates_start;
270 if (!
a.is_constant() && !
b.is_constant()) {
275 if (result_is_constant) {
280 if (!result_is_constant &&
a.is_constant() && !
b.is_constant()) {
284 if (!result_is_constant && !
a.is_constant() &&
b.is_constant()) {
305 if (
a.is_constant() &&
b.is_constant() &&
a.get_value() ==
b.get_value()) {
308 return (
a.is_inverted()) ? 1 : 0;
315 if (!
a.is_constant() && !
b.is_constant()) {
319 }
else if (!
a.is_constant()) {
328 return b.get_value() ? 2 : 1;
329 }
else if (!
b.is_constant()) {
338 return a.get_value() ? 2 : 1;
342 if (lhs.
value == rhs.value) {
345 }
else if (lhs.
value) {
370 size_t num_gates_start =
builder.get_num_finalized_gates_inefficient();
371 if (!
a.is_constant() && !
b.is_constant()) {
373 a.set_origin_tag(challenge_origin_tag);
374 b.set_origin_tag(next_challenge_tag);
378 size_t diff =
builder.get_num_finalized_gates_inefficient() - num_gates_start;
379 if (!
a.is_constant() && !
b.is_constant()) {
380 EXPECT_EQ(result.
get_origin_tag(), first_second_third_merged_tag);
384 bool expected = (condition.
get_value()) ?
a.get_value() :
b.get_value();
392 (
a.is_constant() &&
b.is_constant() &&
a.get_value() ==
b.get_value())) {
395 EXPECT_EQ(diff, expected_gates);
396 }
else if (!
a.is_constant() && !
b.is_constant()) {
398 EXPECT_EQ(diff, 3UL);
416 size_t num_gates_start =
builder.get_num_finalized_gates_inefficient();
417 if (!
a.is_constant()) {
418 a.set_origin_tag(submitted_value_origin_tag);
422 if (!
a.is_constant()) {
426 size_t diff =
builder.get_num_finalized_gates_inefficient() - num_gates_start;
429 EXPECT_EQ(diff,
static_cast<size_t>(!
a.is_constant() && a_raw.is_inverted));
445 bool failed =
a.get_value() !=
b.get_value();
447 if (!
a.is_constant() && !
b.is_constant()) {
450 EXPECT_EQ(
builder.failed(), failed);
451 }
else if (!
a.is_constant() || !
b.is_constant()) {
467 auto gates_before =
builder.get_num_finalized_gates_inefficient();
472 a.set_origin_tag(submitted_value_origin_tag);
473 b.set_origin_tag(challenge_origin_tag);
476 EXPECT_EQ(
a.get_value(), 1);
479 EXPECT_EQ(
a.get_origin_tag(), first_two_merged_tag);
482 EXPECT_EQ(
b.get_value(), 1);
485 EXPECT_EQ(
b.get_origin_tag(), challenge_origin_tag);
487 a.set_origin_tag(submitted_value_origin_tag);
516 EXPECT_EQ(result,
true);
518 auto gates_after =
builder.get_num_finalized_gates_inefficient();
519 EXPECT_EQ(gates_after - gates_before, 6UL);
541 bool_ct rhs = ((
a &&
b) || (
a && c)) ^ (!d || f);
547 info(
"a: ",
a.get_value(),
" b: ",
b.get_value(),
" c: ", c.
get_value());
566 TestFixture::test_construct_from_const_bool();
571 TestFixture::test_construct_from_witness();
575 TestFixture::test_construct_from_witness_range_constraint();
580 TestFixture::test_normalize();
584 TestFixture::test_xor();
589 TestFixture::test_AND();
594 TestFixture::test_OR();
599 TestFixture::test_EQ();
604 TestFixture::test_NEQ();
609 TestFixture::test_implies();
614 TestFixture::test_implies_both_ways();
619 TestFixture::test_must_imply();
624 TestFixture::test_conditional_assign();
629 TestFixture::test_basic_operations_tags();
634 TestFixture::test_simple_proof();
638 TestFixture::test_assert_equal();
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
void test_construct_from_witness_index()
void test_implies_both_ways()
void test_conditional_assign()
void test_binary_op(std::string const &op_name, const std::function< bool_ct(const bool_ct &, const bool_ct &)> &op, const std::function< bool(bool, bool)> &expected_op)
void test_basic_operations_tags()
void test_construct_from_const_bool()
static size_t compute_conditional_assign_gates(const bool_ct &condition, const bool_ct &a, const bool_ct &b, const BoolInput &lhs, const BoolInput &rhs)
std::array< BoolInput, 8 > all_inputs
void test_construct_from_witness_range_constraint()
stdlib::witness_t< Builder > witness_ct
void test_construct_from_witness()
static bool_ct create_bool_ct(const BoolInput &in, Builder *builder)
stdlib::bool_t< Builder > bool_ct
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
virtual uint256_t get_random_uint256()=0
Implements boolean logic in-circuit.
void set_origin_tag(const OriginTag &new_tag) const
bool_t implies(const bool_t &other) const
Implements implication operator in circuit.
static bool_t conditional_assign(const bool_t< Builder > &predicate, const bool_t &lhs, const bool_t &rhs)
Conditionally assign lhs or rhs based on predicate, always returns normalized result.
static bool_t from_witness_index_unsafe(Builder *ctx, uint32_t witness_index)
Create a bool_t from a witness index that is known to contain a constrained bool value.
bool_t implies_both_ways(const bool_t &other) const
Implements a "double-implication" (<=>), a.k.a "iff", a.k.a. "biconditional".
OriginTag get_origin_tag() const
constexpr T ceil_div(const T &numerator, const T &denominator)
Computes the ceiling of the division of two integral types.
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Entry point for Barretenberg command-line interface.
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
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
static constexpr field one()
static constexpr field zero()