Skip to content

Commit af81bec

Browse files
authored
Merge 3b6a942 into d0ea6eb
2 parents d0ea6eb + 3b6a942 commit af81bec

15 files changed

+120
-23
lines changed

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

+32-20
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,14 @@ void build_constraints(Builder& builder,
212212
gate_counter.track_diff(constraint_system.gates_per_opcode,
213213
constraint_system.original_opcode_indices.bigint_to_le_bytes_constraints.at(i));
214214
}
215+
// assert equals
216+
for (size_t i = 0; i < constraint_system.assert_equalities.size(); ++i) {
217+
const auto& constraint = constraint_system.assert_equalities.at(i);
218+
219+
builder.assert_equal(constraint.a, constraint.b);
220+
gate_counter.track_diff(constraint_system.gates_per_opcode,
221+
constraint_system.original_opcode_indices.assert_equalities.at(i));
222+
}
215223

216224
// RecursionConstraints
217225
// TODO(https://github.com/AztecProtocol/barretenberg/issues/817): disable these for MegaHonk for now since we're
@@ -227,10 +235,11 @@ void build_constraints(Builder& builder,
227235
process_plonk_recursion_constraints(builder, constraint_system, has_valid_witness_assignments, gate_counter);
228236
process_honk_recursion_constraints(builder, constraint_system, has_valid_witness_assignments, gate_counter);
229237

230-
// If the circuit does not itself contain honk recursion constraints but is going to be proven with honk then
231-
// recursively verified, add a default aggregation object
238+
// If the circuit does not itself contain honk recursion constraints but is going to be
239+
// proven with honk then recursively verified, add a default aggregation object
232240
if (constraint_system.honk_recursion_constraints.empty() && honk_recursion &&
233-
builder.is_recursive_circuit) { // Set a default aggregation object if we don't have one.
241+
builder.is_recursive_circuit) { // Set a default aggregation object if we don't have
242+
// one.
234243
AggregationObjectIndices current_aggregation_object =
235244
stdlib::recursion::init_default_agg_obj_indices<Builder>(builder);
236245
// Make sure the verification key records the public input indices of the
@@ -265,31 +274,34 @@ void process_plonk_recursion_constraints(Builder& builder,
265274
for (size_t constraint_idx = 0; constraint_idx < constraint_system.recursion_constraints.size(); ++constraint_idx) {
266275
auto constraint = constraint_system.recursion_constraints[constraint_idx];
267276

268-
// A proof passed into the constraint should be stripped of its public inputs, except in the case where a
269-
// proof contains an aggregation object itself. We refer to this as the `nested_aggregation_object`. The
270-
// verifier circuit requires that the indices to a nested proof aggregation state are a circuit constant.
271-
// The user tells us they how they want these constants set by keeping the nested aggregation object
272-
// attached to the proof as public inputs. As this is the only object that can prepended to the proof if the
273-
// proof is above the expected size (with public inputs stripped)
277+
// A proof passed into the constraint should be stripped of its public inputs, except in
278+
// the case where a proof contains an aggregation object itself. We refer to this as the
279+
// `nested_aggregation_object`. The verifier circuit requires that the indices to a
280+
// nested proof aggregation state are a circuit constant. The user tells us they how
281+
// they want these constants set by keeping the nested aggregation object attached to
282+
// the proof as public inputs. As this is the only object that can prepended to the
283+
// proof if the proof is above the expected size (with public inputs stripped)
274284
AggregationObjectPubInputIndices nested_aggregation_object = {};
275-
// If the proof has public inputs attached to it, we should handle setting the nested aggregation object
285+
// If the proof has public inputs attached to it, we should handle setting the nested
286+
// aggregation object
276287
if (constraint.proof.size() > proof_size_no_pub_inputs) {
277288
// The public inputs attached to a proof should match the aggregation object in size
278289
if (constraint.proof.size() - proof_size_no_pub_inputs != bb::AGGREGATION_OBJECT_SIZE) {
279-
auto error_string = format(
280-
"Public inputs are always stripped from proofs unless we have a recursive proof.\n"
281-
"Thus, public inputs attached to a proof must match the recursive aggregation object in size "
282-
"which is ",
283-
bb::AGGREGATION_OBJECT_SIZE);
290+
auto error_string = format("Public inputs are always stripped from proofs "
291+
"unless we have a recursive proof.\n"
292+
"Thus, public inputs attached to a proof must match "
293+
"the recursive aggregation object in size "
294+
"which is ",
295+
bb::AGGREGATION_OBJECT_SIZE);
284296
throw_or_abort(error_string);
285297
}
286298
for (size_t i = 0; i < bb::AGGREGATION_OBJECT_SIZE; ++i) {
287-
// Set the nested aggregation object indices to the current size of the public inputs
288-
// This way we know that the nested aggregation object indices will always be the last
289-
// indices of the public inputs
299+
// Set the nested aggregation object indices to the current size of the public
300+
// inputs This way we know that the nested aggregation object indices will
301+
// always be the last indices of the public inputs
290302
nested_aggregation_object[i] = static_cast<uint32_t>(constraint.public_inputs.size());
291-
// Attach the nested aggregation object to the end of the public inputs to fill in
292-
// the slot where the nested aggregation object index will point into
303+
// Attach the nested aggregation object to the end of the public inputs to fill
304+
// in the slot where the nested aggregation object index will point into
293305
constraint.public_inputs.emplace_back(constraint.proof[i]);
294306
}
295307
// Remove the aggregation object so that they can be handled as normal public inputs

barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct AcirFormatOriginalOpcodeIndices {
5353
std::vector<size_t> bigint_from_le_bytes_constraints;
5454
std::vector<size_t> bigint_to_le_bytes_constraints;
5555
std::vector<size_t> bigint_operations;
56+
std::vector<size_t> assert_equalities;
5657
std::vector<size_t> poly_triple_constraints;
5758
std::vector<size_t> quad_constraints;
5859
// Multiple opcode indices per block:
@@ -98,6 +99,7 @@ struct AcirFormat {
9899
std::vector<BigIntFromLeBytes> bigint_from_le_bytes_constraints;
99100
std::vector<BigIntToLeBytes> bigint_to_le_bytes_constraints;
100101
std::vector<BigIntOperation> bigint_operations;
102+
std::vector<bb::poly_triple_<bb::curve::BN254::ScalarField>> assert_equalities;
101103

102104
// A standard plonk arithmetic constraint, as defined in the poly_triple struct, consists of selector values
103105
// for q_M,q_L,q_R,q_O,q_C and indices of three variables taking the role of left, right and output wire
@@ -110,6 +112,9 @@ struct AcirFormat {
110112
// Has length equal to num_acir_opcodes.
111113
std::vector<size_t> gates_per_opcode = {};
112114

115+
// Set of constrained witnesses
116+
std::set<uint32_t> constrained_witness = {};
117+
113118
// Indices of the original opcode that originated each constraint in AcirFormat.
114119
AcirFormatOriginalOpcodeIndices original_opcode_indices;
115120

@@ -139,7 +144,8 @@ struct AcirFormat {
139144
block_constraints,
140145
bigint_from_le_bytes_constraints,
141146
bigint_to_le_bytes_constraints,
142-
bigint_operations);
147+
bigint_operations,
148+
assert_equalities);
143149

144150
friend bool operator==(AcirFormat const& lhs, AcirFormat const& rhs) = default;
145151
};

barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs)
6464
.bigint_from_le_bytes_constraints = {},
6565
.bigint_to_le_bytes_constraints = {},
6666
.bigint_operations = {},
67+
.assert_equalities = {},
6768
.poly_triple_constraints = { constraint },
6869
.quad_constraints = {},
6970
.block_constraints = {},
@@ -185,6 +186,7 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit)
185186
.bigint_from_le_bytes_constraints = {},
186187
.bigint_to_le_bytes_constraints = {},
187188
.bigint_operations = {},
189+
.assert_equalities = {},
188190
.poly_triple_constraints = { expr_a, expr_b, expr_c, expr_d },
189191
.quad_constraints = {},
190192
.block_constraints = {},
@@ -264,6 +266,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass)
264266
.bigint_from_le_bytes_constraints = {},
265267
.bigint_to_le_bytes_constraints = {},
266268
.bigint_operations = {},
269+
.assert_equalities = {},
267270
.poly_triple_constraints = { poly_triple{
268271
.a = schnorr_constraint.result,
269272
.b = schnorr_constraint.result,
@@ -370,6 +373,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange)
370373
.bigint_from_le_bytes_constraints = {},
371374
.bigint_to_le_bytes_constraints = {},
372375
.bigint_operations = {},
376+
.assert_equalities = {},
373377
.poly_triple_constraints = { poly_triple{
374378
.a = schnorr_constraint.result,
375379
.b = schnorr_constraint.result,
@@ -489,6 +493,7 @@ TEST_F(AcirFormatTests, TestVarKeccak)
489493
.bigint_from_le_bytes_constraints = {},
490494
.bigint_to_le_bytes_constraints = {},
491495
.bigint_operations = {},
496+
.assert_equalities = {},
492497
.poly_triple_constraints = { dummy },
493498
.quad_constraints = {},
494499
.block_constraints = {},
@@ -510,7 +515,7 @@ TEST_F(AcirFormatTests, TestKeccakPermutation)
510515
{
511516
Keccakf1600
512517
keccak_permutation{
513-
.state = {
518+
.state = {
514519
WitnessOrConstant<bb::fr>::from_index(1),
515520
WitnessOrConstant<bb::fr>::from_index(2),
516521
WitnessOrConstant<bb::fr>::from_index(3),
@@ -568,6 +573,7 @@ TEST_F(AcirFormatTests, TestKeccakPermutation)
568573
.bigint_from_le_bytes_constraints = {},
569574
.bigint_to_le_bytes_constraints = {},
570575
.bigint_operations = {},
576+
.assert_equalities = {},
571577
.poly_triple_constraints = {},
572578
.quad_constraints = {},
573579
.block_constraints = {},
@@ -644,6 +650,7 @@ TEST_F(AcirFormatTests, TestCollectsGateCounts)
644650
.bigint_from_le_bytes_constraints = {},
645651
.bigint_to_le_bytes_constraints = {},
646652
.bigint_operations = {},
653+
.assert_equalities = {},
647654
.poly_triple_constraints = { first_gate, second_gate },
648655
.quad_constraints = {},
649656
.block_constraints = {},

barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format_mocks.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ acir_format::AcirFormatOriginalOpcodeIndices create_empty_original_opcode_indice
2525
.bigint_from_le_bytes_constraints = {},
2626
.bigint_to_le_bytes_constraints = {},
2727
.bigint_operations = {},
28+
.assert_equalities = {},
2829
.poly_triple_constraints = {},
2930
.quad_constraints = {},
3031
.block_constraints = {},
@@ -100,6 +101,9 @@ void mock_opcode_indices(acir_format::AcirFormat& constraint_system)
100101
for (size_t i = 0; i < constraint_system.bigint_operations.size(); i++) {
101102
constraint_system.original_opcode_indices.bigint_operations.push_back(current_opcode++);
102103
}
104+
for (size_t i = 0; i < constraint_system.assert_equalities.size(); i++) {
105+
constraint_system.original_opcode_indices.assert_equalities.push_back(current_opcode++);
106+
}
103107
for (size_t i = 0; i < constraint_system.poly_triple_constraints.size(); i++) {
104108
constraint_system.original_opcode_indices.poly_triple_constraints.push_back(current_opcode++);
105109
}

barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include "acir_to_constraint_buf.hpp"
22
#include "barretenberg/common/container.hpp"
3+
#include "barretenberg/numeric/uint256/uint256.hpp"
4+
#include "barretenberg/plonk_honk_shared/arithmetization/gate_data.hpp"
35
#include <cstddef>
6+
#include <cstdint>
47
#include <tuple>
58
#include <utility>
69
#ifndef __wasm__
@@ -167,10 +170,50 @@ mul_quad_<fr> serialize_mul_quad_gate(Program::Expression const& arg)
167170
return quad;
168171
}
169172

173+
void constrain_witnesses(Program::Opcode::AssertZero const& arg, AcirFormat& af)
174+
{
175+
for (const auto& linear_term : arg.value.linear_combinations) {
176+
uint32_t witness_idx = std::get<1>(linear_term).value;
177+
af.constrained_witness.insert(witness_idx);
178+
}
179+
for (const auto& linear_term : arg.value.mul_terms) {
180+
uint32_t witness_idx = std::get<1>(linear_term).value;
181+
af.constrained_witness.insert(witness_idx);
182+
witness_idx = std::get<2>(linear_term).value;
183+
af.constrained_witness.insert(witness_idx);
184+
}
185+
}
186+
187+
std::pair<uint32_t, uint32_t> is_assert_equal(Program::Opcode::AssertZero const& arg,
188+
poly_triple const& pt,
189+
AcirFormat const& af)
190+
{
191+
if (!arg.value.mul_terms.empty() || arg.value.linear_combinations.size() != 2) {
192+
return { 0, 0 };
193+
}
194+
if (pt.q_l == -pt.q_r && pt.q_l != bb::fr::zero() && pt.q_c == bb::fr::zero()) {
195+
if (af.constrained_witness.contains(pt.a) && af.constrained_witness.contains(pt.b)) {
196+
return { pt.a, pt.b };
197+
}
198+
}
199+
return { 0, 0 };
200+
}
201+
170202
void handle_arithmetic(Program::Opcode::AssertZero const& arg, AcirFormat& af, size_t opcode_index)
171203
{
172204
if (arg.value.linear_combinations.size() <= 3) {
173205
poly_triple pt = serialize_arithmetic_gate(arg.value);
206+
207+
auto assert_equal = is_assert_equal(arg, pt, af);
208+
uint32_t w1 = std::get<0>(assert_equal);
209+
uint32_t w2 = std::get<1>(assert_equal);
210+
if (w1 != 0) {
211+
if (w1 != w2) {
212+
af.assert_equalities.push_back(pt);
213+
af.original_opcode_indices.assert_equalities.push_back(opcode_index);
214+
}
215+
return;
216+
}
174217
// Even if the number of linear terms is less than 3, we might not be able to fit it into a width-3 arithmetic
175218
// gate. This is the case if the linear terms are all disctinct witness from the multiplication term. In that
176219
// case, the serialize_arithmetic_gate() function will return a poly_triple with all 0's, and we use a width-4
@@ -187,6 +230,7 @@ void handle_arithmetic(Program::Opcode::AssertZero const& arg, AcirFormat& af, s
187230
af.quad_constraints.push_back(serialize_mul_quad_gate(arg.value));
188231
af.original_opcode_indices.quad_constraints.push_back(opcode_index);
189232
}
233+
constrain_witnesses(arg, af);
190234
}
191235

192236
uint32_t get_witness_from_function_input(Program::FunctionInput input)

barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ TEST_F(BigIntTests, TestBigIntConstraintMultiple)
197197
.bigint_from_le_bytes_constraints = {},
198198
.bigint_to_le_bytes_constraints = {},
199199
.bigint_operations = {},
200+
.assert_equalities = {},
200201
.poly_triple_constraints = {},
201202
.quad_constraints = {},
202203
.block_constraints = {},
@@ -270,6 +271,7 @@ TEST_F(BigIntTests, TestBigIntConstraintSimple)
270271
.bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1 },
271272
.bigint_to_le_bytes_constraints = { result2_to_le_bytes },
272273
.bigint_operations = { add_constraint },
274+
.assert_equalities = {},
273275
.poly_triple_constraints = {},
274276
.quad_constraints = {},
275277
.block_constraints = {},
@@ -327,6 +329,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse)
327329
.bigint_from_le_bytes_constraints = {},
328330
.bigint_to_le_bytes_constraints = {},
329331
.bigint_operations = {},
332+
.assert_equalities = {},
330333
.poly_triple_constraints = {},
331334
.quad_constraints = {},
332335
.block_constraints = {},
@@ -389,6 +392,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse2)
389392
.bigint_from_le_bytes_constraints = {},
390393
.bigint_to_le_bytes_constraints = {},
391394
.bigint_operations = {},
395+
.assert_equalities = {},
392396
.poly_triple_constraints = {},
393397
.quad_constraints = {},
394398
.block_constraints = {},
@@ -472,6 +476,7 @@ TEST_F(BigIntTests, TestBigIntDIV)
472476
.bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1, from_le_bytes_constraint_bigint2 },
473477
.bigint_to_le_bytes_constraints = { result3_to_le_bytes },
474478
.bigint_operations = { div_constraint },
479+
.assert_equalities = {},
475480
.poly_triple_constraints = {},
476481
.quad_constraints = {},
477482
.block_constraints = {},

barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint)
165165
.bigint_from_le_bytes_constraints = {},
166166
.bigint_to_le_bytes_constraints = {},
167167
.bigint_operations = {},
168+
.assert_equalities = {},
168169
.poly_triple_constraints = {},
169170
.quad_constraints = {},
170171
.block_constraints = { block },
@@ -216,6 +217,7 @@ TEST_F(MegaHonk, Databus)
216217
.bigint_from_le_bytes_constraints = {},
217218
.bigint_to_le_bytes_constraints = {},
218219
.bigint_operations = {},
220+
.assert_equalities = {},
219221
.poly_triple_constraints = {},
220222
.quad_constraints = {},
221223
.block_constraints = { block },
@@ -322,6 +324,7 @@ TEST_F(MegaHonk, DatabusReturn)
322324
.bigint_from_le_bytes_constraints = {},
323325
.bigint_to_le_bytes_constraints = {},
324326
.bigint_operations = {},
327+
.assert_equalities = {},
325328
.poly_triple_constraints = { assert_equal },
326329
.quad_constraints = {},
327330
.block_constraints = { block },

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

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ TEST_F(EcOperations, TestECOperations)
8787
.bigint_from_le_bytes_constraints = {},
8888
.bigint_to_le_bytes_constraints = {},
8989
.bigint_operations = {},
90+
.assert_equalities = {},
9091
.poly_triple_constraints = {},
9192
.quad_constraints = {},
9293
.block_constraints = {},
@@ -223,6 +224,7 @@ TEST_F(EcOperations, TestECMultiScalarMul)
223224
.bigint_from_le_bytes_constraints = {},
224225
.bigint_to_le_bytes_constraints = {},
225226
.bigint_operations = {},
227+
.assert_equalities = {},
226228
.poly_triple_constraints = { assert_equal },
227229
.quad_constraints = {},
228230
.block_constraints = {},

barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed)
119119
.bigint_from_le_bytes_constraints = {},
120120
.bigint_to_le_bytes_constraints = {},
121121
.bigint_operations = {},
122+
.assert_equalities = {},
122123
.poly_triple_constraints = {},
123124
.quad_constraints = {},
124125
.block_constraints = {},
@@ -173,6 +174,7 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier)
173174
.bigint_from_le_bytes_constraints = {},
174175
.bigint_to_le_bytes_constraints = {},
175176
.bigint_operations = {},
177+
.assert_equalities = {},
176178
.poly_triple_constraints = {},
177179
.quad_constraints = {},
178180
.block_constraints = {},
@@ -222,6 +224,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail)
222224
.bigint_from_le_bytes_constraints = {},
223225
.bigint_to_le_bytes_constraints = {},
224226
.bigint_operations = {},
227+
.assert_equalities = {},
225228
.poly_triple_constraints = {},
226229
.quad_constraints = {},
227230
.block_constraints = {},

0 commit comments

Comments
 (0)