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