Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bitwise.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cstdint>
5
17
18namespace bb::avm2::constraining {
19namespace {
20
21using tracegen::BitwiseTraceBuilder;
22using tracegen::TestTraceContainer;
24using C = Column;
26
27using tracegen::PrecomputedTraceBuilder;
28
29TEST(BitwiseConstrainingTest, EmptyRow)
30{
31 check_relation<bitwise>(testing::empty_trace());
32}
33
34// Testing a positive AND operation for each integral type (U1, U8, ... U128)
35TEST(BitwiseConstrainingTest, AndWithTracegen)
36{
37 TestTraceContainer trace;
38 BitwiseTraceBuilder builder;
40 { .operation = BitwiseOperation::AND,
41 .a = MemoryValue::from(uint1_t(1)),
42 .b = MemoryValue::from(uint1_t(1)),
43 .res = 1 },
44 { .operation = BitwiseOperation::AND,
45 .a = MemoryValue::from<uint8_t>(85),
46 .b = MemoryValue::from<uint8_t>(175),
47 .res = 5 },
48 { .operation = BitwiseOperation::AND,
49 .a = MemoryValue::from<uint16_t>(5323),
50 .b = MemoryValue::from<uint16_t>(321),
51 .res = 65 },
52 { .operation = BitwiseOperation::AND,
53 .a = MemoryValue::from<uint32_t>(13793),
54 .b = MemoryValue::from<uint32_t>(10590617),
55 .res = 4481 },
56 { .operation = BitwiseOperation::AND,
57 .a = MemoryValue::from<uint64_t>(0x7bff744e3cdf79LLU),
58 .b = MemoryValue::from<uint64_t>(0x14ccccccccb6LLU),
59 .res = 0x14444c0ccc30LLU },
60 { .operation = BitwiseOperation::AND,
61 .a = MemoryValue::from<uint128_t>((uint128_t{ 0xb900000000000001 } << 64)),
62 .b = MemoryValue::from<uint128_t>((uint128_t{ 0x1006021301080000 } << 64) +
63 uint128_t{ 0x000000000000001080876844827 }),
64 .res = uint128_t{ 0x1000000000000000 } << 64 }
65 };
66
67 builder.process(events, trace);
68
69 EXPECT_EQ(trace.get_num_rows(), 33); // 33 = 1 + 1 + 1 + 2 + 4 + 8 + 16 (extra_shift_row U1 U8 U16 U32 U64 U128)
70 check_relation<bitwise>(trace);
71}
72
73// Testing a positive OR operation for each integral type (U1, U8, ... U128)
74TEST(BitwiseConstrainingTest, OrWithTracegen)
75{
76 TestTraceContainer trace;
77 BitwiseTraceBuilder builder;
79 { .operation = BitwiseOperation::OR,
80 .a = MemoryValue::from(uint1_t(1)),
81 .b = MemoryValue::from(uint1_t(0)),
82 .res = 1 },
83 { .operation = BitwiseOperation::OR,
84 .a = MemoryValue::from<uint8_t>(128),
85 .b = MemoryValue::from<uint8_t>(127),
86 .res = 255 },
87 { .operation = BitwiseOperation::OR,
88 .a = MemoryValue::from<uint16_t>(5323),
89 .b = MemoryValue::from<uint16_t>(321),
90 .res = 5579 },
91 { .operation = BitwiseOperation::OR,
92 .a = MemoryValue::from<uint32_t>(13793),
93 .b = MemoryValue::from<uint32_t>(10590617),
94 .res = 10599929 },
95 { .operation = BitwiseOperation::OR,
96 .a = MemoryValue::from<uint64_t>(0x7bff744e3cdf79LLU),
97 .b = MemoryValue::from<uint64_t>(0x14ccccccccb6LLU),
98 .res = 0x7bfffccefcdfffLLU },
99 { .operation = BitwiseOperation::OR,
100 .a = MemoryValue::from<uint128_t>((uint128_t{ 0xb900000000000000 } << 64)),
101 .b = MemoryValue::from<uint128_t>((uint128_t{ 0x1006021301080000 } << 64) +
102 uint128_t{ 0x000000000000001080876844827 }),
103 .res = (uint128_t{ 0xb906021301080000 } << 64) + uint128_t{ 0x0001080876844827 } },
104 };
105
106 builder.process(events, trace);
107
108 EXPECT_EQ(trace.get_num_rows(), 33); // 33 = 1 + 1 + 1 + 2 + 4 + 8 + 16 (extra_shift_row U1 U8 U16 U32 U64 U128)
109 check_relation<bitwise>(trace);
110}
111
112// Testing a positive XOR operation for each integral type (U1, U8, ... U128)
113TEST(BitwiseConstrainingTest, XorWithTracegen)
114{
115 TestTraceContainer trace;
116 BitwiseTraceBuilder builder;
117
119 { .operation = BitwiseOperation::XOR,
120 .a = MemoryValue::from(uint1_t(1)),
121 .b = MemoryValue::from(uint1_t(1)),
122 .res = 0 },
123 { .operation = BitwiseOperation::XOR,
124 .a = MemoryValue::from<uint8_t>(85),
125 .b = MemoryValue::from<uint8_t>(175),
126 .res = 250 },
127 { .operation = BitwiseOperation::XOR,
128 .a = MemoryValue::from<uint16_t>(5323),
129 .b = MemoryValue::from<uint16_t>(321),
130 .res = 5514 },
131 { .operation = BitwiseOperation::XOR,
132 .a = MemoryValue::from<uint32_t>(13793),
133 .b = MemoryValue::from<uint32_t>(10590617),
134 .res = 10595448 },
135 { .operation = BitwiseOperation::XOR,
136 .a = MemoryValue::from<uint64_t>(0x7bff744e3cdf79LLU),
137 .b = MemoryValue::from<uint64_t>(0x14ccccccccb6LLU),
138 .res = 0x7bebb882f013cfLLU },
139 { .operation = BitwiseOperation::XOR,
140 .a = MemoryValue::from<uint128_t>((uint128_t{ 0xb900000000000001 } << 64)),
141 .b = MemoryValue::from<uint128_t>((uint128_t{ 0x1006021301080000 } << 64) +
142 uint128_t{ 0x000000000000001080876844827 }),
143 .res = (uint128_t{ 0xa906021301080001 } << 64) + uint128_t{ 0x0001080876844827 } },
144 };
145
146 builder.process(events, trace);
147
148 EXPECT_EQ(trace.get_num_rows(), 33); // 33 = 1 + 1 + 1 + 2 + 4 + 8 + 16 (extra_shift_row U1 U8 U16 U32 U64 U128)
149 check_relation<bitwise>(trace);
150}
151
152TEST(BitwiseConstrainingTest, MixedOperationsWithTracegen)
153{
154 TestTraceContainer trace;
155 BitwiseTraceBuilder builder;
157 { .operation = BitwiseOperation::OR,
158 .a = MemoryValue::from(uint1_t(1)),
159 .b = MemoryValue::from(uint1_t(0)),
160 .res = 1 },
161 { .operation = BitwiseOperation::AND,
162 .a = MemoryValue::from<uint32_t>(13793),
163 .b = MemoryValue::from<uint32_t>(10590617),
164 .res = 4481 },
165 { .operation = BitwiseOperation::XOR,
166 .a = MemoryValue::from<uint16_t>(5323),
167 .b = MemoryValue::from<uint16_t>(321),
168 .res = 5514 },
169 { .operation = BitwiseOperation::XOR,
170 .a = MemoryValue::from<uint32_t>(13793),
171 .b = MemoryValue::from<uint32_t>(10590617),
172 .res = 10595448 },
173 { .operation = BitwiseOperation::AND,
174 .a = MemoryValue::from<uint8_t>(85),
175 .b = MemoryValue::from<uint8_t>(175),
176 .res = 5 },
177 { .operation = BitwiseOperation::AND,
178 .a = MemoryValue::from<uint8_t>(85),
179 .b = MemoryValue::from<uint8_t>(175),
180 .res = 5 },
181 };
182
183 builder.process(events, trace);
184
185 EXPECT_EQ(trace.get_num_rows(), 14); // 14 = 1 + 3 * 1 + 1 * 2 + 2 * 4 (extra_shift_row + 2U1 + 1U8 + 1U16 + 2U32)
186 check_relation<bitwise>(trace);
187}
188
189TEST(BitwiseConstrainingTest, NegativeWrongInit)
190{
191 TestTraceContainer trace = TestTraceContainer::from_rows({
192 {
193 .bitwise_acc_ia = 25,
194 .bitwise_acc_ib = 25,
195 .bitwise_acc_ic = 25,
196 .bitwise_ia_byte = 25,
197 .bitwise_ib_byte = 25,
198 .bitwise_ic_byte = 25,
199 .bitwise_last = 1,
200 },
201 });
202
204
205 trace.set(C::bitwise_ia_byte, 0, 24); // Mutate to wrong value violating BITW_INIT_A
206 trace.set(C::bitwise_ib_byte, 0, 27); // Mutate to wrong value violating BITW_INIT_B
207 trace.set(C::bitwise_ic_byte, 0, 28); // Mutate to wrong value violating BITW_INIT_C
208
209 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_INIT_A), "BITW_INIT_A");
210 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_INIT_B), "BITW_INIT_B");
211 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_INIT_C), "BITW_INIT_C");
212}
213
214TEST(BitwiseConstrainingTest, NegativeTruncateCtr)
215{
216 TestTraceContainer trace = TestTraceContainer::from_rows({
217 {
218 .bitwise_ctr = 4,
219 .bitwise_sel = 1,
220 },
221 {
222 .bitwise_ctr = 3,
223 .bitwise_sel = 1,
224 },
225 {
226 .bitwise_ctr = 2,
227 .bitwise_sel = 1,
228 },
229 {
230 .bitwise_ctr = 1,
231 .bitwise_last = 1,
232 .bitwise_sel = 1,
233 },
234 });
235
236 check_relation<bitwise>(trace, bitwise::SR_BITW_CTR_DECREMENT);
237
238 trace.set(C::bitwise_ctr, 3, 0);
239 trace.set(C::bitwise_last, 3, 0);
240 trace.set(C::bitwise_sel, 3, 0);
241
242 // Trace nows ends with bitwise_ctr == 2 without bitwise_last being set.
243 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_CTR_DECREMENT), "BITW_CTR_DECREMENT");
244}
245
246TEST(BitwiseConstrainingTest, NegativeGapCtr)
247{
248 TestTraceContainer trace = TestTraceContainer::from_rows({
249 {
250 .bitwise_ctr = 4,
251 .bitwise_sel = 1,
252 },
253 {
254 .bitwise_ctr = 3,
255 .bitwise_last = 1,
256 .bitwise_sel = 1,
257 },
258 });
259
260 check_relation<bitwise>(trace, bitwise::SR_BITW_CTR_DECREMENT);
261 trace.set(C::bitwise_ctr, 1, 2); // Mutate to wrong value (ctr decreases from 4 to 2)
262 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_CTR_DECREMENT), "BITW_CTR_DECREMENT");
263}
264
265TEST(BitwiseConstrainingTest, NegativeLastSetBeforeEnd)
266{
267 TestTraceContainer trace = TestTraceContainer::from_rows({
268 {
269 .bitwise_ctr = 8,
270 .bitwise_ctr_min_one_inv = FF(7).invert(),
271 .bitwise_sel = 1,
272 },
273 {
274 .bitwise_ctr = 7,
275 .bitwise_ctr_min_one_inv = FF(6).invert(),
276 .bitwise_sel = 1,
277
278 },
279 {
280 .bitwise_ctr = 6,
281 .bitwise_ctr_min_one_inv = FF(5).invert(),
282 .bitwise_sel = 1,
283 },
284 });
285
286 check_relation<bitwise>(trace, bitwise::SR_BITW_LAST_FOR_CTR_ONE);
287 trace.set(C::bitwise_last, 2, 1); // Mutate to wrong value (wrongly activate bitwise_last on last row)
289 "BITW_LAST_FOR_CTR_ONE");
290}
291
292TEST(BitwiseConstrainingTest, NegativeDeactivateRow)
293{
294 TestTraceContainer trace = TestTraceContainer::from_rows({
295 {
296 .bitwise_ctr = 8,
297 .bitwise_ctr_inv = FF(8).invert(),
298 .bitwise_sel = 1,
299 },
300 {
301 .bitwise_ctr = 7,
302 .bitwise_ctr_inv = FF(7).invert(),
303 .bitwise_sel = 1,
304 },
305 {
306 .bitwise_ctr = 6,
307 .bitwise_ctr_inv = FF(6).invert(),
308 .bitwise_sel = 1,
309 },
310 });
311
312 check_relation<bitwise>(trace, bitwise::SR_BITW_SEL_CTR_NON_ZERO);
313 trace.set(C::bitwise_sel, 1, 0); // Mutate to wrong value
315 "BITW_SEL_CTR_NON_ZERO");
316}
317
318TEST(BitwiseConstrainingTest, NegativeChangeOpIDBeforeEnd)
319{
320 TestTraceContainer trace = TestTraceContainer::from_rows({
321 {
322 .bitwise_op_id = static_cast<uint8_t>(BitwiseOperation::XOR),
323 },
324 {
325 .bitwise_op_id = static_cast<uint8_t>(BitwiseOperation::XOR),
326 },
327 {
328 .bitwise_last = 1,
329 .bitwise_op_id = static_cast<uint8_t>(BitwiseOperation::XOR),
330 },
331 });
332
333 check_relation<bitwise>(trace, bitwise::SR_BITW_OP_ID_REL);
334 trace.set(C::bitwise_op_id, 1, static_cast<uint8_t>(BitwiseOperation::AND)); // Mutate to wrong value
335 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_OP_ID_REL), "BITW_OP_ID_REL");
336}
337
338TEST(BitwiseConstrainingTest, NegativeWrongAccumulation)
339{
340 TestTraceContainer trace = TestTraceContainer::from_rows({
341 {
342 .bitwise_acc_ia = 0xaa11,
343 .bitwise_acc_ib = 0xbb22,
344 .bitwise_acc_ic = 0xcc33,
345 .bitwise_ia_byte = 0x11,
346 .bitwise_ib_byte = 0x22,
347 .bitwise_ic_byte = 0x33,
348 },
349 {
350 .bitwise_acc_ia = 0xaa,
351 .bitwise_acc_ib = 0xbb,
352 .bitwise_acc_ic = 0xcc,
353 .bitwise_last = 1,
354 },
355 });
356
358
359 trace.set(C::bitwise_acc_ia, 0, 0xaa1f); // Mutate to wrong value violating BITW_ACC_REL_A
360 trace.set(C::bitwise_acc_ib, 0, 0xbb2f); // Mutate to wrong value violating BITW_ACC_REL_B
361 trace.set(C::bitwise_acc_ic, 0, 0xcc3f); // Mutate to wrong value violating BITW_ACC_REL_C
362
363 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_ACC_REL_A), "BITW_ACC_REL_A");
364 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_ACC_REL_B), "BITW_ACC_REL_B");
365 EXPECT_THROW_WITH_MESSAGE(check_relation<bitwise>(trace, bitwise::SR_BITW_ACC_REL_C), "BITW_ACC_REL_C");
366}
367
368TEST(BitwiseConstrainingTest, MixedOperationsInteractions)
369{
370 TestTraceContainer trace;
371 BitwiseTraceBuilder builder;
372 PrecomputedTraceBuilder precomputed_builder;
374 { .operation = BitwiseOperation::OR,
375 .a = MemoryValue::from(uint1_t(1)),
376 .b = MemoryValue::from(uint1_t(0)),
377 .res = 1 },
378 { .operation = BitwiseOperation::AND,
379 .a = MemoryValue::from<uint32_t>(13793),
380 .b = MemoryValue::from<uint32_t>(10590617),
381 .res = 4481 },
382 { .operation = BitwiseOperation::XOR,
383 .a = MemoryValue::from<uint16_t>(5323),
384 .b = MemoryValue::from<uint16_t>(321),
385 .res = 5514 },
386 { .operation = BitwiseOperation::XOR,
387 .a = MemoryValue::from<uint32_t>(13793),
388 .b = MemoryValue::from<uint32_t>(10590617),
389 .res = 10595448 },
390 { .operation = BitwiseOperation::AND,
391 .a = MemoryValue::from<uint8_t>(85),
392 .b = MemoryValue::from<uint8_t>(175),
393 .res = 5 },
394 { .operation = BitwiseOperation::AND,
395 .a = MemoryValue::from<uint8_t>(85),
396 .b = MemoryValue::from<uint8_t>(175),
397 .res = 5 },
398 };
399
400 builder.process(events, trace);
401
402 precomputed_builder.process_misc(trace, 256 * 256 * 3);
403 precomputed_builder.process_bitwise(trace);
404 precomputed_builder.process_tag_parameters(trace);
405
406 check_all_interactions<BitwiseTraceBuilder>(trace);
407 check_relation<bitwise>(trace);
408}
409
410TEST(BitwiseConstrainingTest, BitwiseExecInteraction)
411{
412 TestTraceContainer trace = TestTraceContainer::from_rows({ {
413 // Bitwise Entry
414 .bitwise_acc_ia = 0x01,
415 .bitwise_acc_ib = 0x01,
416 .bitwise_acc_ic = 0x00,
417 .bitwise_err = 1,
418 .bitwise_op_id = static_cast<uint8_t>(BitwiseOperation::AND),
419 .bitwise_sel = 1,
420 .bitwise_tag_a = static_cast<uint8_t>(ValueTag::FF),
421 .bitwise_tag_b = static_cast<uint8_t>(ValueTag::U8),
422 .bitwise_tag_c = static_cast<uint8_t>(ValueTag::U8),
423
424 // Execution Entry
425 .execution_mem_tag_reg_0_ = static_cast<uint8_t>(ValueTag::FF),
426 .execution_mem_tag_reg_1_ = static_cast<uint8_t>(ValueTag::U8),
427 .execution_mem_tag_reg_2_ = static_cast<uint8_t>(ValueTag::U8),
428 .execution_register_0_ = 0x01,
429 .execution_register_1_ = 0x01,
430 .execution_register_2_ = 0x00,
431 .execution_sel_execute_bitwise = 1,
432 .execution_sel_opcode_error = 1,
433 .execution_subtrace_operation_id = static_cast<uint8_t>(BitwiseOperation::AND),
434 } });
435
436 check_interaction<BitwiseTraceBuilder, lookup_bitwise_dispatch_exec_bitwise_settings>(trace);
437}
438
439TEST(BitwiseConstrainingTest, InvalidBitwiseExecInteraction)
440{
441 TestTraceContainer trace = TestTraceContainer::from_rows({ {
442 // Bitwise Entry
443 .bitwise_acc_ia = 0x01,
444 .bitwise_acc_ib = 0x01,
445 .bitwise_acc_ic = 0x00,
446 .bitwise_op_id = static_cast<uint8_t>(BitwiseOperation::AND),
447 .bitwise_sel = 1,
448 .bitwise_tag_a = static_cast<uint8_t>(ValueTag::U8),
449 .bitwise_tag_b = static_cast<uint8_t>(ValueTag::U8),
450 .bitwise_tag_c = static_cast<uint8_t>(ValueTag::U8),
451
452 // Execution Entry
453 .execution_mem_tag_reg_0_ = static_cast<uint8_t>(ValueTag::U8),
454 .execution_mem_tag_reg_1_ = static_cast<uint8_t>(ValueTag::U16), // Mismatch
455 .execution_mem_tag_reg_2_ = static_cast<uint8_t>(ValueTag::U8),
456 .execution_register_0_ = 0x01,
457 .execution_register_1_ = 0x01,
458 .execution_register_2_ = 0x00,
459 .execution_sel_execute_bitwise = 1,
460 .execution_subtrace_operation_id = static_cast<uint8_t>(BitwiseOperation::AND),
461 } });
462
464 (check_interaction<BitwiseTraceBuilder, lookup_bitwise_dispatch_exec_bitwise_settings>(trace)),
465 "Failed.*BITWISE_DISPATCH_EXEC_BITWISE. Could not find tuple in destination.");
466}
467
468TEST(BitwiseConstrainingTest, ErrorHandlingInputFF)
469{
470 TestTraceContainer trace;
471 BitwiseTraceBuilder builder;
472 PrecomputedTraceBuilder precomputed_builder;
473
475 { .operation = BitwiseOperation::XOR,
478 .res = 0 },
479 };
480 builder.process(events, trace);
481 precomputed_builder.process_bitwise(trace);
482 precomputed_builder.process_tag_parameters(trace);
483
484 check_relation<bitwise>(trace);
485}
486
487TEST(BitwiseConstrainingTest, ErrorHandlingInputTagMismatch)
488{
489 TestTraceContainer trace;
490 BitwiseTraceBuilder builder;
491
493 { .operation = BitwiseOperation::AND,
496 .res = 0 },
497 };
498 builder.process(events, trace);
499
500 check_relation<bitwise>(trace);
501 check_all_interactions<BitwiseTraceBuilder>(trace);
502}
503
504TEST(BitwiseConstrainingTest, ErrorHandlingMultiple)
505{
506 TestTraceContainer trace;
507 BitwiseTraceBuilder builder;
508
510 { .operation = BitwiseOperation::AND,
513 .res = 0 },
514 };
515 builder.process(events, trace);
516
517 check_relation<bitwise>(trace);
518}
519
520} // namespace
521} // namespace bb::avm2::constraining
static TaggedValue from(T value)
static TaggedValue from_tag(ValueTag tag, FF value)
static constexpr size_t SR_BITW_CTR_DECREMENT
Definition bitwise.hpp:79
static constexpr size_t SR_BITW_LAST_FOR_CTR_ONE
Definition bitwise.hpp:81
static constexpr size_t SR_BITW_OP_ID_REL
Definition bitwise.hpp:78
static constexpr size_t SR_BITW_ACC_REL_C
Definition bitwise.hpp:87
static constexpr size_t SR_BITW_ACC_REL_B
Definition bitwise.hpp:86
static constexpr size_t SR_BITW_ACC_REL_A
Definition bitwise.hpp:85
static constexpr size_t SR_BITW_INIT_C
Definition bitwise.hpp:84
static constexpr size_t SR_BITW_INIT_B
Definition bitwise.hpp:83
static constexpr size_t SR_BITW_INIT_A
Definition bitwise.hpp:82
static constexpr size_t SR_BITW_SEL_CTR_NON_ZERO
Definition bitwise.hpp:80
static TestTraceContainer from_rows(const std::vector< AvmFullRow > &rows)
void set(Column col, uint32_t row, const FF &value)
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:119
AluTraceBuilder builder
Definition alu.test.cpp:123
TestTraceContainer trace
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
Definition macros.hpp:7
AvmFlavorSettings::FF FF
TEST(TxExecutionConstrainingTest, WriteTreeValue)
Definition tx.test.cpp:508
TestTraceContainer empty_trace()
Definition fixtures.cpp:153
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
unsigned __int128 uint128_t
Definition serialize.hpp:44
Bitwise bitwise