Skip to content

Commit 617671b

Browse files
committed
add from_witness_index_unsafe, turn members private
1 parent ac71126 commit 617671b

File tree

11 files changed

+75
-38
lines changed

11 files changed

+75
-38
lines changed

barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void create_ec_add_constraint(Builder& builder, const EcAdd& input, bool has_val
4444
if (infinite.is_constant()) {
4545
builder.fix_witness(input.result_infinite, infinite.get_value());
4646
} else {
47-
builder.assert_equal(infinite.witness_index, input.result_infinite);
47+
builder.assert_equal(infinite.get_normalized_witness_index(), input.result_infinite);
4848
}
4949
}
5050

barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ void create_multi_scalar_mul_constraint(Builder& builder,
4949
if (output_point.is_point_at_infinity().is_constant()) {
5050
builder.fix_witness(input.out_point_is_infinite, output_point.is_point_at_infinity().get_value());
5151
} else {
52-
builder.assert_equal(output_point.is_point_at_infinity().witness_index, input.out_point_is_infinite);
52+
builder.assert_equal(output_point.is_point_at_infinity().get_normalized_witness_index(),
53+
input.out_point_is_infinite);
5354
}
5455
if (output_point.x.is_constant()) {
5556
builder.fix_witness(input.out_point_x, output_point.x.get_value());

barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ TEST(stdlib_schnorr, schnorr_signature_verification_result)
123123
stdlib::schnorr_signature_bits sig = stdlib::schnorr_convert_signature(&builder, signature);
124124
byte_array_ct message(&builder, longer_string);
125125
bool_ct signature_result = schnorr_signature_verification_result(message, pub_key, sig);
126-
EXPECT_EQ(signature_result.witness_bool, true);
126+
EXPECT_EQ(signature_result.get_normalized_witness_index(), true);
127127

128128
info("num gates = ", builder.get_estimated_num_finalized_gates());
129129

@@ -166,7 +166,7 @@ TEST(stdlib_schnorr, signature_verification_result_failure)
166166
stdlib::schnorr_signature_bits sig = stdlib::schnorr_convert_signature(&builder, signature);
167167
byte_array_ct message(&builder, message_string);
168168
bool_ct signature_result = schnorr_signature_verification_result(message, pub_key2_ct, sig);
169-
EXPECT_EQ(signature_result.witness_bool, false);
169+
EXPECT_EQ(signature_result.get_value(), false);
170170

171171
info("num gates = ", builder.get_estimated_num_finalized_gates());
172172

barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,9 +1111,9 @@ template <typename TestType> class stdlib_biggroup : public testing::Test {
11111111
// scalar = -naf[254] + \sum_{i=0}^{253}(1-2*naf[i]) 2^{253-i}
11121112
fr reconstructed_val(0);
11131113
for (size_t i = 0; i < length; i++) {
1114-
reconstructed_val += (fr(1) - fr(2) * fr(naf[i].witness_bool)) * fr(uint256_t(1) << (length - 1 - i));
1114+
reconstructed_val += (fr(1) - fr(2) * fr(naf[i].get_value())) * fr(uint256_t(1) << (length - 1 - i));
11151115
};
1116-
reconstructed_val -= fr(naf[length].witness_bool);
1116+
reconstructed_val -= fr(naf[length].get_value());
11171117
EXPECT_EQ(scalar_val, reconstructed_val);
11181118
}
11191119

barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,11 @@ element<C, Fq, Fr, G> element<C, Fq, Fr, G>::operator+(const element& other) con
124124
// n.b. can likely optimize this
125125
bool_ct result_is_infinity = infinity_predicate && (!lhs_infinity && !rhs_infinity);
126126
if constexpr (IsUltraBuilder<C>) {
127-
result_is_infinity.get_context()->update_used_witnesses(result_is_infinity.witness_index);
127+
result_is_infinity.get_context()->update_used_witnesses(result_is_infinity.get_normalized_witness_index());
128128
}
129129
result_is_infinity = result_is_infinity || (lhs_infinity && rhs_infinity);
130130
if constexpr (IsUltraBuilder<C>) {
131-
result_is_infinity.get_context()->update_used_witnesses(result_is_infinity.witness_index);
131+
result_is_infinity.get_context()->update_used_witnesses(result_is_infinity.get_normalized_witness_index());
132132
}
133133
result.set_point_at_infinity(result_is_infinity);
134134

@@ -202,11 +202,11 @@ element<C, Fq, Fr, G> element<C, Fq, Fr, G>::operator-(const element& other) con
202202
// n.b. can likely optimize this
203203
bool_ct result_is_infinity = infinity_predicate && (!lhs_infinity && !rhs_infinity);
204204
if constexpr (IsUltraBuilder<C>) {
205-
result_is_infinity.get_context()->update_used_witnesses(result_is_infinity.witness_index);
205+
result_is_infinity.get_context()->update_used_witnesses(result_is_infinity.get_normalized_witness_index());
206206
}
207207
result_is_infinity = result_is_infinity || (lhs_infinity && rhs_infinity);
208208
if constexpr (IsUltraBuilder<C>) {
209-
result_is_infinity.get_context()->update_used_witnesses(result_is_infinity.witness_index);
209+
result_is_infinity.get_context()->update_used_witnesses(result_is_infinity.get_normalized_witness_index());
210210
}
211211
result.set_point_at_infinity(result_is_infinity);
212212
result.set_origin_tag(OriginTag(get_origin_tag(), other.get_origin_tag()));

barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_nafs.hpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -510,24 +510,10 @@ std::vector<bool_t<C>> element<C, Fq, Fr, G>::compute_naf(const Fr& scalar, cons
510510
// if the next entry is false, we need to flip the sign of the current entry. i.e. make negative
511511
// This is a VERY hacky workaround to ensure that UltraBuilder will apply a basic
512512
// range constraint per bool, and not a full 1-bit range gate
513-
if (next_entry == false) {
514-
bool_ct bit(ctx, true);
515-
bit.context = ctx;
516-
bit.witness_index = witness_t<C>(ctx, true).witness_index; // flip sign
517-
bit.witness_bool = true;
518-
ctx->create_new_range_constraint(
519-
bit.witness_index, 1, "biggroup_nafs: compute_naf extracted too many bits in non-next_entry case");
520-
521-
naf_entries[num_rounds - i - 1] = bit;
522-
} else {
523-
bool_ct bit(ctx, false);
524-
bit.witness_index = witness_t<C>(ctx, false).witness_index; // don't flip sign
525-
bit.witness_bool = false;
526-
ctx->create_new_range_constraint(
527-
bit.witness_index, 1, "biggroup_nafs: compute_naf extracted too many bits in next_entry case");
513+
bool_ct bit(witness_t<C>(ctx, !next_entry));
514+
515+
naf_entries[num_rounds - i - 1] = bit;
528516

529-
naf_entries[num_rounds - i - 1] = bit;
530-
}
531517
// We need to manually propagate the origin tag
532518
naf_entries[num_rounds - i - 1].set_origin_tag(scalar.get_origin_tag());
533519
}

barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,24 @@ bool_t<Builder>::bool_t(bool_t<Builder>&& other)
7979
, tag(other.tag)
8080
{}
8181

82+
/**
83+
* @brief Create a `bool_t` from a witness index that is **known** to contain a constrained bool value.
84+
* @warning The witness value **is not** constrained to be boolean. We simply perform an out-of-circuit sanity check.
85+
*/
86+
template <typename Builder>
87+
bool_t<Builder> bool_t<Builder>::from_witness_index_unsafe(Builder* ctx, const uint32_t witness_index)
88+
{
89+
ASSERT(witness_index != IS_CONSTANT);
90+
bool_t<Builder> result(ctx);
91+
result.witness_index = witness_index;
92+
bb::fr value = ctx->get_variable(witness_index);
93+
// It does not create a constraint.
94+
BB_ASSERT_EQ(value * value - value, 0, "bool_t: creating a witness bool from a non-boolean value");
95+
result.witness_bool = (ctx->get_variable(witness_index) == 1);
96+
result.witness_inverted = false;
97+
return result;
98+
}
99+
82100
/**
83101
* @brief Assigns a native `bool` to `bool_t` object.
84102
*/

barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ template <typename Builder> class bool_t {
7070
bool_t& operator=(const bool_t& other);
7171
bool_t& operator=(bool_t&& other);
7272

73+
static bool_t from_witness_index_unsafe(Builder* ctx, uint32_t witness_index);
74+
7375
// bitwise operations
7476
bool_t operator&(const bool_t& other) const;
7577
bool_t operator|(const bool_t& other) const;
@@ -109,6 +111,13 @@ template <typename Builder> class bool_t {
109111
bool get_value() const { return witness_bool ^ witness_inverted; }
110112

111113
bool is_constant() const { return witness_index == IS_CONSTANT; }
114+
bool is_inverted() const
115+
{
116+
if (is_constant()) {
117+
ASSERT(!witness_inverted);
118+
}
119+
return witness_inverted;
120+
}
112121

113122
bool_t normalize() const;
114123

@@ -127,11 +136,16 @@ template <typename Builder> class bool_t {
127136
context->fix_witness(witness_index, get_value());
128137
unset_free_witness_tag();
129138
}
139+
140+
private:
130141
mutable Builder* context = nullptr;
131142
mutable bool witness_bool = false;
132143
mutable bool witness_inverted = false;
133144
mutable uint32_t witness_index = IS_CONSTANT;
134145
mutable OriginTag tag{};
146+
147+
template <typename, typename> friend class bigfield;
148+
template <typename> friend class field_t;
135149
};
136150

137151
template <typename T> inline std::ostream& operator<<(std::ostream& os, bool_t<T> const& v)

barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,31 @@ template <class Builder_> class BoolTest : public ::testing::Test {
102102
EXPECT_TRUE(a_true.get_value());
103103
EXPECT_FALSE(a_false.get_value());
104104
EXPECT_TRUE(a_true.is_constant() && a_false.is_constant());
105-
EXPECT_TRUE(!a_true.witness_inverted && !a_false.witness_inverted);
105+
EXPECT_TRUE(!a_true.is_inverted() && !a_false.is_inverted());
106106
// No gates have been added
107107
EXPECT_TRUE(num_gates_start == builder.get_estimated_num_finalized_gates());
108108
}
109109

110+
void test_construct_from_witness_index()
111+
{
112+
Builder builder = Builder();
113+
size_t num_gates_start = builder.get_estimated_num_finalized_gates();
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));
117+
118+
bool_ct bool_witness = bool_ct::from_witness_index_unsafe(&builder, witness_idx_zero);
119+
EXPECT_EQ(bool_witness.get_value(), false);
120+
121+
bool_witness = bool_ct::from_witness_index_unsafe(&builder, witness_idx_one);
122+
EXPECT_EQ(bool_witness.get_value(), true);
123+
// No gates are added.
124+
EXPECT_EQ(builder.get_estimated_num_finalized_gates() - num_gates_start, 0);
125+
126+
// Out-of-circuit failure when witness points to a non-bool value.
127+
EXPECT_THROW_OR_ABORT(bool_witness = bool_ct::from_witness_index_unsafe(&builder, non_bool_witness_idx),
128+
"bool_t: creating a witness bool from a non-boolean value");
129+
}
110130
void test_construct_from_witness()
111131
{
112132
Builder builder = Builder();
@@ -117,7 +137,7 @@ template <class Builder_> class BoolTest : public ::testing::Test {
117137
EXPECT_TRUE(a_true.get_value());
118138
EXPECT_FALSE(a_false.get_value());
119139
EXPECT_TRUE(!a_true.is_constant() && !a_false.is_constant());
120-
EXPECT_TRUE(!a_true.witness_inverted && !a_false.witness_inverted);
140+
EXPECT_TRUE(!a_true.is_inverted() && !a_false.is_inverted());
121141
// Each witness bool must be constrained => expect 2 gates being added
122142
EXPECT_TRUE(builder.get_estimated_num_finalized_gates() - num_gates_start == 2);
123143
EXPECT_TRUE(CircuitChecker::check(builder));
@@ -217,13 +237,13 @@ template <class Builder_> class BoolTest : public ::testing::Test {
217237
if (!result_is_constant && a.is_constant() && !b.is_constant()) {
218238
// we only add gates if the value `true` is not flipped to `false` and we need to add a new
219239
// constant == 1, which happens iff `b` is not inverted.
220-
EXPECT_EQ(diff, static_cast<size_t>(!b.witness_inverted));
240+
EXPECT_EQ(diff, static_cast<size_t>(!b.is_inverted()));
221241
}
222242

223243
if (!result_is_constant && !a.is_constant() && b.is_constant()) {
224244
// we only add gates if the value `true` is not flipped to `false` and we need to add a new
225245
// constant == 1, which happens iff `a` is inverted.
226-
EXPECT_EQ(diff, static_cast<size_t>(a.witness_inverted));
246+
EXPECT_EQ(diff, static_cast<size_t>(a.is_inverted()));
227247
}
228248
EXPECT_EQ(CircuitChecker::check(builder), expected);
229249
}
@@ -283,9 +303,9 @@ template <class Builder_> class BoolTest : public ::testing::Test {
283303
if (!a.is_constant()) {
284304
EXPECT_EQ(c.get_origin_tag(), submitted_value_origin_tag);
285305
}
286-
EXPECT_EQ(c.witness_inverted, false);
306+
EXPECT_EQ(c.is_inverted(), false);
287307
size_t diff = builder.get_estimated_num_finalized_gates() - num_gates_start;
288-
// Note that although `normalize()` returns value, it flips the `witness_inverted` flag of `a` if it was
308+
// Note that although `normalize()` returns value, it flips the `is_inverted()` flag of `a` if it was
289309
// `true`.
290310
EXPECT_EQ(diff, static_cast<size_t>(!a.is_constant() && a_raw.is_inverted));
291311
EXPECT_TRUE(CircuitChecker::check(builder));

barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ template <typename Builder> class stdlib_field : public testing::Test {
164164

165165
if (!expected_to_be_constant) {
166166
EXPECT_TRUE(CircuitChecker::check(builder));
167-
EXPECT_TRUE(converted.witness_index == field_elt.witness_index);
167+
EXPECT_TRUE(converted.get_normalized_witness_index() == field_elt.witness_index);
168168
}
169169
}
170170
// Check that the conversion aborts in the case of random field elements.

0 commit comments

Comments
 (0)