Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
alu_integration.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
23
24namespace bb::avm2::constraining {
25
26namespace {
27
28using simulation::Alu;
29using simulation::AluEvent;
30using simulation::AluException;
31using simulation::DeduplicatingEventEmitter;
32using simulation::EventEmitter;
33using simulation::FieldGreaterThan;
34using simulation::FieldGreaterThanEvent;
35using simulation::GreaterThan;
36using simulation::GreaterThanEvent;
37using simulation::RangeCheck;
38using simulation::RangeCheckEvent;
39
40using tracegen::AluTraceBuilder;
41using tracegen::FieldGreaterThanTraceBuilder;
42using tracegen::GreaterThanTraceBuilder;
43using tracegen::PrecomputedTraceBuilder;
44using tracegen::RangeCheckTraceBuilder;
45
46using tracegen::TestTraceContainer;
48using alu = bb::avm2::alu<FF>;
49
50// Test suite focussing on ALU operations and their interactions with other gadgets.
51// In particular, ensuring that interactions are satisfiied under the different type of exceptions.
52
53// Base fixture that wires up concrete gadgets and their event emitters.
54class AluIntegrationTest : public ::testing::Test {
55 protected:
56 // Event emitters
57 DeduplicatingEventEmitter<RangeCheckEvent> range_check_emitter;
58 DeduplicatingEventEmitter<FieldGreaterThanEvent> field_gt_emitter;
59 DeduplicatingEventEmitter<GreaterThanEvent> gt_emitter;
60 EventEmitter<AluEvent> alu_emitter;
61
62 // Gadgets
63 RangeCheck range_check;
64 FieldGreaterThan field_gt;
65 GreaterThan greater_than;
67
68 // Trace Builder
69 AluTraceBuilder alu_trace_builder;
70 PrecomputedTraceBuilder precomputed_builder;
71 RangeCheckTraceBuilder range_check_builder;
72 FieldGreaterThanTraceBuilder field_gt_builder;
73 GreaterThanTraceBuilder gt_builder;
74
75 AluIntegrationTest()
80 {}
81
82 void process_events(TestTraceContainer& trace)
83 {
84 alu_trace_builder.process(alu_emitter.dump_events(), trace);
85 range_check_builder.process(range_check_emitter.dump_events(), trace);
86 field_gt_builder.process(field_gt_emitter.dump_events(), trace);
87 gt_builder.process(gt_emitter.dump_events(), trace);
88 precomputed_builder.process_misc(trace, 256);
89 precomputed_builder.process_power_of_2(trace);
90 precomputed_builder.process_tag_parameters(trace);
91 }
92};
93
94// ADD operations
95
96TEST_F(AluIntegrationTest, addBasicCase)
97{
98 auto a = MemoryValue::from_tag(MemoryTag::U32, UINT32_MAX - 3);
100 auto c = alu_simulator.add(a, b);
101 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U32, UINT32_MAX));
102
103 TestTraceContainer trace;
104 process_events(trace);
105 check_relation<alu>(trace);
106 check_all_interactions<AluTraceBuilder>(trace);
107}
108
109TEST_F(AluIntegrationTest, addWithTagMismatch)
110{
113
114 EXPECT_THROW(alu_simulator.add(a, b), AluException);
115
116 TestTraceContainer trace;
117 process_events(trace);
118 check_relation<alu>(trace);
119 check_all_interactions<AluTraceBuilder>(trace);
120}
121
122// SUB operations
123
124TEST_F(AluIntegrationTest, subBasicCase)
125{
128 auto c = alu_simulator.sub(a, b);
129 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U32, UINT32_MAX));
130
131 TestTraceContainer trace;
132 process_events(trace);
133 check_relation<alu>(trace);
134 check_all_interactions<AluTraceBuilder>(trace);
135}
136
137TEST_F(AluIntegrationTest, subWithTagMismatch)
138{
141
142 EXPECT_THROW(alu_simulator.sub(a, b), AluException);
143
144 TestTraceContainer trace;
145 process_events(trace);
146 check_relation<alu>(trace);
147 check_all_interactions<AluTraceBuilder>(trace);
148}
149
150// MUL operations
151
152TEST_F(AluIntegrationTest, mulBasicCase)
153{
154 auto a = MemoryValue::from_tag(MemoryTag::U32, 1 << 16);
155 auto b = MemoryValue::from_tag(MemoryTag::U32, 1 << 17);
156 auto c = alu_simulator.mul(a, b);
157 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U32, 0));
158
159 TestTraceContainer trace;
160 process_events(trace);
161 check_relation<alu>(trace);
162 check_all_interactions<AluTraceBuilder>(trace);
163}
164
165TEST_F(AluIntegrationTest, mulWithTagU128Mismatch)
166{
169
170 EXPECT_THROW(alu_simulator.mul(a, b), AluException);
171
172 TestTraceContainer trace;
173 process_events(trace);
174 check_relation<alu>(trace);
175 check_all_interactions<AluTraceBuilder>(trace);
176}
177
178// Test values from fuzzer which triggered a bug related to cf computation.
179TEST_F(AluIntegrationTest, mulU128FuzzBug1Cf0)
180{
181 // We need a * b_lo + a_lo * b_hi * 2^64 < 2^192 for cf = 0
182 uint256_t a_ff = uint256_t("0x000000000000000000000000000000003c18fbdb47886300e90ed3f8e4b4b4b1");
183 uint256_t b_ff = uint256_t("0x000000000000000000000000000000008eb2fbdb4724e898de03c8ed45033bb1");
184
185 uint256_t product = a_ff * (b_ff & MASK_64) + (((a_ff & MASK_64) * (b_ff >> 64)) >> 64);
186 ASSERT_LT(product, uint256_t(1) << 192);
187
191
192 TestTraceContainer trace;
193 process_events(trace);
194
195 EXPECT_EQ(trace.get(Column::alu_cf, 0), 0);
196
197 check_relation<alu>(trace);
198 check_all_interactions<AluTraceBuilder>(trace);
199}
200
201TEST_F(AluIntegrationTest, mulU128Cf1)
202{
203 // We need a * b_lo + a_lo * b_hi * 2^64 >= 2^192 for cf = 1
204 uint256_t a_ff = uint256_t("0x00000000000000000000000000000000ff18fbdb47886300fffed3f8e4b4b4b1");
205 uint256_t b_ff = uint256_t("0x00000000000000000000000000000000ffb2fbdb4724e898fff3c8ed45033bb1");
206
207 uint256_t product = a_ff * (b_ff & MASK_64) + (((a_ff & MASK_64) * (b_ff >> 64)) << 64);
208 ASSERT_GT(product, uint256_t(1) << 192);
209
213
214 TestTraceContainer trace;
215 process_events(trace);
216
217 EXPECT_EQ(trace.get(Column::alu_cf, 0), 1);
218
219 check_relation<alu>(trace);
220 check_all_interactions<AluTraceBuilder>(trace);
221}
222
223// DIV operations
224
225TEST_F(AluIntegrationTest, divBasicCase)
226{
227 auto a = MemoryValue::from_tag(MemoryTag::U32, 1 << 18);
228 auto b = MemoryValue::from_tag(MemoryTag::U32, 1 << 17);
229 auto c = alu_simulator.div(a, b);
230 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U32, 2));
231
232 TestTraceContainer trace;
233 process_events(trace);
234 check_relation<alu>(trace);
235 check_all_interactions<AluTraceBuilder>(trace);
236}
237
238TEST_F(AluIntegrationTest, divWithTagU128Mismatch)
239{
242
243 EXPECT_THROW(alu_simulator.div(a, b), AluException);
244
245 TestTraceContainer trace;
246 process_events(trace);
247 check_relation<alu>(trace);
248 check_all_interactions<AluTraceBuilder>(trace);
249}
250
251TEST_F(AluIntegrationTest, divWithTagU128MismatchDivByZero)
252{
255
256 EXPECT_THROW(alu_simulator.div(a, b), AluException);
257
258 TestTraceContainer trace;
259 process_events(trace);
260 check_relation<alu>(trace);
261 check_all_interactions<AluTraceBuilder>(trace);
262}
263
264TEST_F(AluIntegrationTest, divWithTagFFDivByZero)
265{
268
269 EXPECT_THROW(alu_simulator.div(a, b), AluException);
270
271 TestTraceContainer trace;
272 process_events(trace);
273 check_relation<alu>(trace);
274 check_all_interactions<AluTraceBuilder>(trace);
275}
276
277TEST_F(AluIntegrationTest, divWithTagU128DivByZero)
278{
281
282 EXPECT_THROW(alu_simulator.div(a, b), AluException);
283
284 TestTraceContainer trace;
285 process_events(trace);
286 check_relation<alu>(trace);
287 check_all_interactions<AluTraceBuilder>(trace);
288}
289
290// FDIV operations
291
292TEST_F(AluIntegrationTest, fdivBasicCase)
293{
294 auto a = MemoryValue::from_tag(MemoryTag::FF, 1 << 25);
295 auto b = MemoryValue::from_tag(MemoryTag::FF, 1 << 17);
296 auto c = alu_simulator.fdiv(a, b);
297 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::FF, 1 << 8));
298
299 TestTraceContainer trace;
300 process_events(trace);
301 check_relation<alu>(trace);
302 check_all_interactions<AluTraceBuilder>(trace);
303}
304
305TEST_F(AluIntegrationTest, fdivWithTagNotFF)
306{
309
310 EXPECT_THROW(alu_simulator.fdiv(a, b), AluException);
311
312 TestTraceContainer trace;
313 process_events(trace);
314 check_relation<alu>(trace);
315 check_all_interactions<AluTraceBuilder>(trace);
316}
317
318TEST_F(AluIntegrationTest, fdivWithTagNotFFDivByZero)
319{
322
323 EXPECT_THROW(alu_simulator.fdiv(a, b), AluException);
324
325 TestTraceContainer trace;
326 process_events(trace);
327 check_relation<alu>(trace);
328 check_all_interactions<AluTraceBuilder>(trace);
329}
330
331TEST_F(AluIntegrationTest, fdivDivByZero)
332{
335
336 EXPECT_THROW(alu_simulator.fdiv(a, b), AluException);
337
338 TestTraceContainer trace;
339 process_events(trace);
340 check_relation<alu>(trace);
341 check_all_interactions<AluTraceBuilder>(trace);
342}
343
344// EQ operations
345
346TEST_F(AluIntegrationTest, eqBasicCase)
347{
350 auto c = alu_simulator.eq(a, b);
351 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U1, 0));
352
353 TestTraceContainer trace;
354 process_events(trace);
355 check_relation<alu>(trace);
356 check_all_interactions<AluTraceBuilder>(trace);
357}
358
359TEST_F(AluIntegrationTest, eqWithTagFFMismatch)
360{
363
364 EXPECT_THROW(alu_simulator.eq(a, b), AluException);
365
366 TestTraceContainer trace;
367 process_events(trace);
368 check_relation<alu>(trace);
369 check_all_interactions<AluTraceBuilder>(trace);
370}
371
372TEST_F(AluIntegrationTest, eqWithTagU128Mismatch)
373{
376
377 EXPECT_THROW(alu_simulator.eq(a, b), AluException);
378
379 TestTraceContainer trace;
380 process_events(trace);
381 check_relation<alu>(trace);
382 check_all_interactions<AluTraceBuilder>(trace);
383}
384
385// LT operations
386TEST_F(AluIntegrationTest, ltBasicCase)
387{
390 auto c = alu_simulator.lt(a, b);
391 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U1, 0));
392
393 TestTraceContainer trace;
394 process_events(trace);
395 check_relation<alu>(trace);
396 check_all_interactions<AluTraceBuilder>(trace);
397}
398
399TEST_F(AluIntegrationTest, ltWithTagU64Mismatch)
400{
403
404 EXPECT_THROW(alu_simulator.lt(a, b), AluException);
405
406 TestTraceContainer trace;
407 process_events(trace);
408 check_relation<alu>(trace);
409 check_all_interactions<AluTraceBuilder>(trace);
410}
411
412TEST_F(AluIntegrationTest, ltWithTagFFMismatch)
413{
416
417 EXPECT_THROW(alu_simulator.lt(a, b), AluException);
418
419 TestTraceContainer trace;
420 process_events(trace);
421 check_relation<alu>(trace);
422 check_all_interactions<AluTraceBuilder>(trace);
423}
424
425// LTE operations
426
427TEST_F(AluIntegrationTest, lteBasicCase)
428{
431 auto c = alu_simulator.lte(a, b);
432 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U1, 1));
433
434 TestTraceContainer trace;
435 process_events(trace);
436 check_relation<alu>(trace);
437 check_all_interactions<AluTraceBuilder>(trace);
438}
439
440TEST_F(AluIntegrationTest, lteWithTagU32Mismatch)
441{
444
445 EXPECT_THROW(alu_simulator.lte(a, b), AluException);
446
447 TestTraceContainer trace;
448 process_events(trace);
449 check_relation<alu>(trace);
450 check_all_interactions<AluTraceBuilder>(trace);
451}
452
453TEST_F(AluIntegrationTest, lteWithTagFFMismatch)
454{
457
458 EXPECT_THROW(alu_simulator.lte(a, b), AluException);
459
460 TestTraceContainer trace;
461 process_events(trace);
462 check_relation<alu>(trace);
463 check_all_interactions<AluTraceBuilder>(trace);
464}
465
466// NOT operations
467
468TEST_F(AluIntegrationTest, opNotBasicCase)
469{
471 auto c = alu_simulator.op_not(a);
472 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U16, UINT16_MAX - 15));
473
474 TestTraceContainer trace;
475 process_events(trace);
476 check_relation<alu>(trace);
477 check_all_interactions<AluTraceBuilder>(trace);
478}
479
480TEST_F(AluIntegrationTest, opNotWithTagFF)
481{
483
484 EXPECT_THROW(alu_simulator.op_not(a), AluException);
485
486 TestTraceContainer trace;
487 process_events(trace);
488 check_relation<alu>(trace);
489 check_all_interactions<AluTraceBuilder>(trace);
490}
491
492// SHL operations
493
494TEST_F(AluIntegrationTest, shlBasicCase)
495{
498 auto c = alu_simulator.shl(a, b);
499 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U16, 60));
500
501 TestTraceContainer trace;
502 process_events(trace);
503 check_relation<alu>(trace);
504 check_all_interactions<AluTraceBuilder>(trace);
505}
506
507TEST_F(AluIntegrationTest, shlWithOverflowEdgeCase)
508{
511 auto c = alu_simulator.shl(a, b);
512 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U128, 0));
513
514 TestTraceContainer trace;
515 process_events(trace);
516 check_relation<alu>(trace);
517 check_all_interactions<AluTraceBuilder>(trace);
518}
519
520TEST_F(AluIntegrationTest, shlWithOverflowLargeShift)
521{
523 auto b = MemoryValue::from_tag(MemoryTag::U128, (static_cast<uint128_t>(1) << 127) + 8172364);
524 auto c = alu_simulator.shl(a, b);
525 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U128, 0));
526
527 TestTraceContainer trace;
528 process_events(trace);
529 check_relation<alu>(trace);
530 check_all_interactions<AluTraceBuilder>(trace);
531}
532
533TEST_F(AluIntegrationTest, shlWithTagFF)
534{
537
538 EXPECT_THROW(alu_simulator.shl(a, b), AluException);
539
540 TestTraceContainer trace;
541 process_events(trace);
542 check_relation<alu>(trace);
543 check_all_interactions<AluTraceBuilder>(trace);
544}
545
546TEST_F(AluIntegrationTest, shlWithTagFFMismatch)
547{
550
551 EXPECT_THROW(alu_simulator.shl(a, b), AluException);
552
553 TestTraceContainer trace;
554 process_events(trace);
555 check_relation<alu>(trace);
556 check_all_interactions<AluTraceBuilder>(trace);
557}
558
559TEST_F(AluIntegrationTest, shlWithTagU16Mismatch)
560{
563
564 EXPECT_THROW(alu_simulator.shl(a, b), AluException);
565
566 TestTraceContainer trace;
567 process_events(trace);
568 check_relation<alu>(trace);
569 check_all_interactions<AluTraceBuilder>(trace);
570}
571
572// SHR operations
573
574TEST_F(AluIntegrationTest, shrBasicCase)
575{
578 auto c = alu_simulator.shr(a, b);
579
580 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U16, 3));
581
582 TestTraceContainer trace;
583 process_events(trace);
584 check_relation<alu>(trace);
585 check_all_interactions<AluTraceBuilder>(trace);
586}
587
588TEST_F(AluIntegrationTest, shrWithOverflowEdgeCase)
589{
592 auto c = alu_simulator.shr(a, b);
593
594 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U128, 0));
595
596 TestTraceContainer trace;
597 process_events(trace);
598 check_relation<alu>(trace);
599 check_all_interactions<AluTraceBuilder>(trace);
600}
601
602TEST_F(AluIntegrationTest, shrWithOverflowLargeShift)
603{
605 auto b = MemoryValue::from_tag(MemoryTag::U128, (static_cast<uint128_t>(1) << 127) + 8172364);
606 auto c = alu_simulator.shr(a, b);
607
608 EXPECT_EQ(c, MemoryValue::from_tag(MemoryTag::U128, 0));
609
610 TestTraceContainer trace;
611 process_events(trace);
612 check_relation<alu>(trace);
613 check_all_interactions<AluTraceBuilder>(trace);
614}
615
616TEST_F(AluIntegrationTest, shrWithTagFF)
617{
620
621 EXPECT_THROW(alu_simulator.shr(a, b), AluException);
622
623 TestTraceContainer trace;
624 process_events(trace);
625 check_relation<alu>(trace);
626 check_all_interactions<AluTraceBuilder>(trace);
627}
628
629TEST_F(AluIntegrationTest, shrWithTagFFMismatch)
630{
633
634 EXPECT_THROW(alu_simulator.shr(a, b), AluException);
635
636 TestTraceContainer trace;
637 process_events(trace);
638 check_relation<alu>(trace);
639 check_all_interactions<AluTraceBuilder>(trace);
640}
641
642TEST_F(AluIntegrationTest, shrWithTagU16Mismatch)
643{
646
647 EXPECT_THROW(alu_simulator.shr(a, b), AluException);
648
649 TestTraceContainer trace;
650 process_events(trace);
651 check_relation<alu>(trace);
652 check_all_interactions<AluTraceBuilder>(trace);
653}
654
655// Truncate operations
656TEST_F(AluIntegrationTest, truncateBasicCase)
657{
659
661
662 TestTraceContainer trace;
663 process_events(trace);
664 check_relation<alu>(trace);
665 check_all_interactions<AluTraceBuilder>(trace);
666}
667
668} // namespace
669
670} // namespace bb::avm2::constraining
DeduplicatingEventEmitter< GreaterThanEvent > gt_emitter
DeduplicatingEventEmitter< FieldGreaterThanEvent > field_gt_emitter
GreaterThan greater_than
FieldGreaterThan field_gt
AluTraceBuilder alu_trace_builder
DeduplicatingEventEmitter< RangeCheckEvent > range_check_emitter
Alu alu_simulator
EventEmitter< AluEvent > alu_emitter
static TaggedValue from_tag(ValueTag tag, FF value)
MemoryValue lte(const MemoryValue &a, const MemoryValue &b) override
Check if the first memory value is less than or equal to the second and emit an event of type AluEven...
Definition alu.cpp:233
MemoryValue fdiv(const MemoryValue &a, const MemoryValue &b) override
Perform field division on two memory values and emit an event of type AluEvent.
Definition alu.cpp:156
MemoryValue truncate(const FF &a, MemoryTag dst_tag) override
Truncate a field element to a specific memory tag and emit an event of type AluEvent.
Definition alu.cpp:359
MemoryValue eq(const MemoryValue &a, const MemoryValue &b) override
Check if two memory values are equal and emit an event of type AluEvent.
Definition alu.cpp:189
MemoryValue lt(const MemoryValue &a, const MemoryValue &b) override
Check if the first memory value is less than the second and emit an event of type AluEvent.
Definition alu.cpp:210
MemoryValue shl(const MemoryValue &a, const MemoryValue &b) override
Perform left shift operation on a memory value and emit an event of type AluEvent.
Definition alu.cpp:278
MemoryValue add(const MemoryValue &a, const MemoryValue &b) override
Add two memory values and emit an event of type AluEvent.
Definition alu.cpp:24
MemoryValue sub(const MemoryValue &a, const MemoryValue &b) override
Subtract two memory values and emit an event of type AluEvent.
Definition alu.cpp:44
MemoryValue mul(const MemoryValue &a, const MemoryValue &b) override
Multiply two memory values and emit an event of type AluEvent.
Definition alu.cpp:64
MemoryValue shr(const MemoryValue &a, const MemoryValue &b) override
Perform right shift operation on a memory value and emit an event of type AluEvent.
Definition alu.cpp:320
MemoryValue op_not(const MemoryValue &a) override
Perform bitwise NOT operation on a memory value and emit an event of type AluEvent.
Definition alu.cpp:256
MemoryValue div(const MemoryValue &a, const MemoryValue &b) override
Divide two memory values and emit an event of type AluEvent.
Definition alu.cpp:108
const FF & get(Column col, uint32_t row) const
RangeCheckTraceBuilder range_check_builder
Definition alu.test.cpp:121
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:120
FieldGreaterThanTraceBuilder field_gt_builder
Definition alu.test.cpp:122
GreaterThanTraceBuilder gt_builder
Definition alu.test.cpp:123
RangeCheck range_check
TestTraceContainer trace
FF a
FF b
TEST_F(AvmRecursiveTests, GoblinRecursion)
A test of the Goblinized AVM recursive verifier.
constexpr uint128_t MASK_64
Definition constants.hpp:23
unsigned __int128 uint128_t
Definition serialize.hpp:44