Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ void create_logic_gate(Builder& builder,
field_ct right = to_field_ct(b, builder);

field_ct computed_result = bb::stdlib::logic<Builder>::create_logic_constraint(left, right, num_bits, is_xor_gate);

// In write-VK mode the result witness holds a dummy zero. When both inputs are constant the computed result is a
// compile-time constant, so assert_equal would spuriously fail. Patch the witness value so the downstream
// assertion sees the correct value.
if (builder.is_write_vk_mode() && computed_result.is_constant()) {
builder.set_variable(result, computed_result.get_value());
}

field_ct acir_result = field_ct::from_witness_index(&builder, result);
computed_result.assert_equal(acir_result);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ class LogicConstraintTestingFunctions {
return WitnessOrConstant<FF>::from_index(input_index);
};

bb::fr lhs = FF(static_cast<uint256_t>(1) << num_bits - 1); // All bits from 0 to num_bits-1 are set
bb::fr rhs = FF(static_cast<uint256_t>(1) << num_bits - 1); // All bits from 0 to num_bits-1 are set
bb::fr lhs = FF((static_cast<uint256_t>(1) << num_bits) - 1); // All bits from 0 to num_bits-1 are set
bb::fr rhs = FF((static_cast<uint256_t>(1) << num_bits) - 1); // All bits from 0 to num_bits-1 are set
bb::fr result = is_xor_gate ? (static_cast<uint256_t>(lhs) ^ static_cast<uint256_t>(rhs))
: (static_cast<uint256_t>(lhs) & static_cast<uint256_t>(rhs));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,19 @@ field_t<Builder> logic<Builder>::create_logic_constraint(
Builder* ctx = b.get_context();
uint256_t a_native(a.get_value());
field_pt a_witness = field_pt::from_witness_index(ctx, ctx->put_constant_variable(a_native));
a_witness.set_origin_tag(a.get_origin_tag());
return create_logic_constraint(a_witness, b, num_bits, is_xor_gate, get_chunk);
}

if (!a.is_constant() && b.is_constant()) {
Builder* ctx = a.get_context();
uint256_t b_native(b.get_value());
field_pt b_witness = field_pt::from_witness_index(ctx, ctx->put_constant_variable(b_native));
b_witness.set_origin_tag(b.get_origin_tag());
return create_logic_constraint(a, b_witness, num_bits, is_xor_gate, get_chunk);
}

Builder* ctx = a.get_context();
Builder* ctx = validate_context<Builder>(a.get_context(), b.get_context());

// We slice the input values into 32-bit chunks, and then use a multi-table lookup to compute the AND or XOR
// of each chunk. Since we perform the lookup from 32-bit multi-tables, the lookup operation implicitly enforces a
Expand Down Expand Up @@ -111,6 +113,7 @@ field_t<Builder> logic<Builder>::create_logic_constraint(
a.assert_equal(a_accumulator, "stdlib logic: failed to reconstruct left operand");
b.assert_equal(b_accumulator, "stdlib logic: failed to reconstruct right operand");

res.set_origin_tag(OriginTag(a.get_origin_tag(), b.get_origin_tag()));
return res;
}
template class logic<bb::UltraCircuitBuilder>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,64 @@ TYPED_TEST(LogicTest, DifferentWitnessSameResult)
bool result = CircuitChecker::check(builder);
EXPECT_EQ(result, false);
}

// Regression test: OriginTag must propagate through all logic constraint paths.
TYPED_TEST(LogicTest, OriginTagPropagation)
{
STDLIB_TYPE_ALIASES
STANDARD_TESTING_TAGS

auto builder = Builder();
uint256_t a_val = 0xAB;
uint256_t b_val = 0xCD;

// Both witnesses
{
field_ct x = witness_ct(&builder, a_val);
field_ct y = witness_ct(&builder, b_val);
x.set_origin_tag(submitted_value_origin_tag);
y.set_origin_tag(challenge_origin_tag);

field_ct and_result = stdlib::logic<Builder>::create_logic_constraint(x, y, 8, false);
field_ct xor_result = stdlib::logic<Builder>::create_logic_constraint(x, y, 8, true);

EXPECT_EQ(and_result.get_origin_tag(), first_two_merged_tag);
EXPECT_EQ(xor_result.get_origin_tag(), first_two_merged_tag);
}

// Left constant, right witness
{
field_ct x_const(&builder, a_val);
field_ct y = witness_ct(&builder, b_val);
x_const.set_origin_tag(submitted_value_origin_tag);
y.set_origin_tag(challenge_origin_tag);

field_ct result = stdlib::logic<Builder>::create_logic_constraint(x_const, y, 8, false);
EXPECT_EQ(result.get_origin_tag(), first_two_merged_tag);
}

// Right constant, left witness
{
field_ct x = witness_ct(&builder, a_val);
field_ct y_const(&builder, b_val);
x.set_origin_tag(submitted_value_origin_tag);
y_const.set_origin_tag(challenge_origin_tag);

field_ct result = stdlib::logic<Builder>::create_logic_constraint(x, y_const, 8, false);
EXPECT_EQ(result.get_origin_tag(), first_two_merged_tag);
}

// Both constants
{
field_ct x_const(&builder, a_val);
field_ct y_const(&builder, b_val);
x_const.set_origin_tag(submitted_value_origin_tag);
y_const.set_origin_tag(challenge_origin_tag);

field_ct result = stdlib::logic<Builder>::create_logic_constraint(x_const, y_const, 8, false);
EXPECT_EQ(result.get_origin_tag(), first_two_merged_tag);
}

bool result = CircuitChecker::check(builder);
EXPECT_EQ(result, true);
}
Loading