2#include <gmock/gmock.h>
3#include <gtest/gtest.h>
32using ::testing::Return;
33using ::testing::StrictMock;
35using tracegen::ExecutionTraceBuilder;
36using tracegen::GreaterThanTraceBuilder;
37using tracegen::MemoryTraceBuilder;
38using tracegen::PrecomputedTraceBuilder;
39using tracegen::TestTraceContainer;
40using tracegen::ToRadixTraceBuilder;
46using ToRadixSimulator = simulation::ToRadix;
48using simulation::EventEmitter;
49using simulation::GreaterThan;
50using simulation::GreaterThanEvent;
51using simulation::MockExecutionIdManager;
52using simulation::MockFieldGreaterThan;
53using simulation::NoopEventEmitter;
54using simulation::PureGreaterThan;
55using simulation::RangeCheck;
56using simulation::RangeCheckEvent;
57using simulation::ToRadixEvent;
58using simulation::ToRadixMemoryEvent;
62TEST(ToRadixConstrainingTest, EmptyRow)
67TEST(ToRadixConstrainingTest, ToLeBitsBasicTest)
69 EventEmitter<ToRadixEvent> to_radix_event_emitter;
70 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
74 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
76 auto [bits, truncated] = to_radix_simulator.to_le_bits(
FF::one(), 254);
78 EXPECT_EQ(bits.size(), 254);
79 EXPECT_FALSE(truncated);
81 TestTraceContainer
trace({
82 { { C::precomputed_first_row, 1 } },
88 check_relation<to_radix>(trace);
91TEST(ToRadixConstrainingTest, ToLeBitsPMinusOne)
93 EventEmitter<ToRadixEvent> to_radix_event_emitter;
94 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
98 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
100 auto [bits, truncated] = to_radix_simulator.to_le_bits(
FF::neg_one(), 254);
102 EXPECT_EQ(bits.size(), 254);
103 EXPECT_FALSE(truncated);
105 TestTraceContainer
trace({
106 { { C::precomputed_first_row, 1 } },
112 check_relation<to_radix>(trace);
115TEST(ToRadixConstrainingTest, ToLeBitsShortest)
117 EventEmitter<ToRadixEvent> to_radix_event_emitter;
118 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
122 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
124 auto [bits, truncated] = to_radix_simulator.to_le_bits(
FF::one(), 1);
126 EXPECT_EQ(bits.size(), 1);
127 EXPECT_FALSE(truncated);
129 TestTraceContainer
trace({
130 { { C::precomputed_first_row, 1 } },
136 check_relation<to_radix>(trace);
139TEST(ToRadixConstrainingTest, ToLeBitsPadded)
141 EventEmitter<ToRadixEvent> to_radix_event_emitter;
142 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
146 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
148 auto [bits, truncated] = to_radix_simulator.to_le_bits(
FF::one(), 500);
150 EXPECT_EQ(bits.size(), 500);
151 EXPECT_FALSE(truncated);
153 TestTraceContainer
trace({
154 { { C::precomputed_first_row, 1 } },
160 check_relation<to_radix>(trace);
163TEST(ToRadixConstrainingTest, ToLeRadixBasic)
165 EventEmitter<ToRadixEvent> to_radix_event_emitter;
166 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
170 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
173 auto [bytes, truncated] = to_radix_simulator.to_le_radix(
value, 32, 256);
177 std::reverse(expected_bytes.begin(), expected_bytes.end());
178 EXPECT_EQ(bytes, expected_bytes);
179 EXPECT_FALSE(truncated);
181 TestTraceContainer
trace({
182 { { C::precomputed_first_row, 1 } },
188 check_relation<to_radix>(trace);
191TEST(ToRadixConstrainingTest, ToLeRadixPMinusOne)
193 EventEmitter<ToRadixEvent> to_radix_event_emitter;
194 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
198 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
201 auto [bytes, truncated] = to_radix_simulator.to_le_radix(
value, 32, 256);
205 std::reverse(expected_bytes.begin(), expected_bytes.end());
206 EXPECT_EQ(bytes, expected_bytes);
207 EXPECT_FALSE(truncated);
209 TestTraceContainer
trace({
210 { { C::precomputed_first_row, 1 } },
216 check_relation<to_radix>(trace);
219TEST(ToRadixConstrainingTest, ToLeRadixOneByte)
221 EventEmitter<ToRadixEvent> to_radix_event_emitter;
222 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
226 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
228 auto [bytes, truncated] = to_radix_simulator.to_le_radix(
FF::one(), 1, 256);
230 std::vector<uint8_t> expected_bytes = { 1 };
231 EXPECT_EQ(bytes, expected_bytes);
232 EXPECT_FALSE(truncated);
234 TestTraceContainer
trace({
235 { { C::precomputed_first_row, 1 } },
241 check_relation<to_radix>(trace);
244TEST(ToRadixConstrainingTest, ToLeRadixPadded)
246 EventEmitter<ToRadixEvent> to_radix_event_emitter;
247 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
251 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
254 auto [bytes, truncated] = to_radix_simulator.to_le_radix(
value, 64, 256);
258 std::reverse(expected_bytes.begin(), expected_bytes.end());
259 expected_bytes.resize(64);
260 EXPECT_EQ(bytes, expected_bytes);
261 EXPECT_FALSE(truncated);
263 TestTraceContainer
trace({
264 { { C::precomputed_first_row, 1 } },
270 check_relation<to_radix>(trace);
273TEST(ToRadixConstrainingTest, ToLeBitsInteractions)
275 EventEmitter<ToRadixEvent> to_radix_event_emitter;
276 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
280 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
284 TestTraceContainer
trace({
285 { { C::precomputed_first_row, 1 } },
288 ToRadixTraceBuilder to_radix_builder;
289 to_radix_builder.process(to_radix_event_emitter.dump_events(), trace);
303 check_relation<to_radix>(trace);
306TEST(ToRadixConstrainingTest, ToLeRadixInteractions)
308 EventEmitter<ToRadixEvent> to_radix_event_emitter;
309 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
313 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
315 to_radix_simulator.to_le_radix(
FF::neg_one(), 32, 256);
317 TestTraceContainer
trace({
318 { { C::precomputed_first_row, 1 } },
321 ToRadixTraceBuilder to_radix_builder;
322 to_radix_builder.process(to_radix_event_emitter.dump_events(), trace);
337 check_relation<to_radix>(trace);
340TEST(ToRadixConstrainingTest, NegativeOverflowCheck)
342 TestTraceContainer
trace({
343 { { C::precomputed_first_row, 1 } },
346 std::vector<uint8_t> modulus_le_bits(256, 0);
347 for (
size_t i = 0; i < 256; i++) {
351 ToRadixEvent
event = { .value =
FF::zero(), .radix = 2, .limbs = modulus_le_bits };
360TEST(ToRadixConstrainingTest, NegativeConsistency)
362 EventEmitter<ToRadixEvent> to_radix_event_emitter;
363 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
367 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
369 to_radix_simulator.to_le_radix(
FF(256), 32, 256);
371 TestTraceContainer
trace({
372 { { C::precomputed_first_row, 1 } },
379 trace.
set(Column::to_radix_sel, 6, 0);
382 "SELECTOR_CONSISTENCY");
385 trace.
set(Column::to_radix_radix, 5, 200);
388 "CONSTANT_CONSISTENCY_RADIX");
391 trace.
set(Column::to_radix_value, 4, 27);
394 "CONSTANT_CONSISTENCY_VALUE");
397 trace.
set(Column::to_radix_safe_limbs, 3, 200);
400 "CONSTANT_CONSISTENCY_SAFE_LIMBS");
407TEST(ToRadixMemoryConstrainingTest, EmptyRow)
412TEST(ToRadixMemoryConstrainingTest, BasicTest)
417 uint32_t num_limbs = 4;
420 TestTraceContainer
trace = TestTraceContainer({
423 { C::precomputed_first_row, 1 },
426 { C::gt_input_a,
dst_addr + num_limbs },
427 { C::gt_input_b, MAX_MEM },
430 { C::execution_sel, 1 },
431 { C::execution_sel_exec_dispatch_to_radix, 1 },
432 { C::execution_register_0_,
value },
433 { C::execution_register_1_, radix },
434 { C::execution_register_2_, num_limbs },
435 { C::execution_register_3_, 0 },
442 { C::to_radix_mem_sel, 1 },
443 { C::to_radix_mem_max_mem_size, MAX_MEM },
444 { C::to_radix_mem_two, 2 },
445 { C::to_radix_mem_two_five_six, 256 },
447 { C::to_radix_mem_execution_clk, 0 },
448 { C::to_radix_mem_space_id, 0 },
449 { C::to_radix_mem_dst_addr,
dst_addr },
450 { C::to_radix_mem_write_addr_upper_bound,
dst_addr + num_limbs },
452 { C::to_radix_mem_value_to_decompose,
value },
453 { C::to_radix_mem_radix, radix },
454 { C::to_radix_mem_num_limbs, num_limbs },
455 { C::to_radix_mem_is_output_bits, 0 },
457 { C::to_radix_mem_start, 1 },
458 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).
invert() },
460 { C::to_radix_mem_sel_num_limbs_is_zero, 0 },
461 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).
invert() },
462 { C::to_radix_mem_sel_value_is_zero, 0 },
465 { C::to_radix_mem_limb_value, 1 },
466 { C::to_radix_mem_sel_should_decompose, 1 },
467 { C::to_radix_mem_sel_should_write_mem, 1 },
468 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 1 },
469 { C::to_radix_mem_value_found, 1 },
470 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(
MemoryTag::U8) },
474 { C::gt_input_a, 2 },
475 { C::gt_input_b, radix },
480 { C::to_radix_mem_sel, 1 },
482 { C::to_radix_mem_execution_clk, 0 },
483 { C::to_radix_mem_space_id, 0 },
484 { C::to_radix_mem_dst_addr,
dst_addr + 1 },
486 { C::to_radix_mem_value_to_decompose,
value },
487 { C::to_radix_mem_radix, radix },
488 { C::to_radix_mem_num_limbs, num_limbs - 1 },
489 { C::to_radix_mem_is_output_bits, 0 },
492 { C::to_radix_mem_num_limbs_minus_one_inv,
FF(num_limbs - 2).
invert() },
494 { C::to_radix_mem_limb_value, 3 },
495 { C::to_radix_mem_sel_should_decompose, 1 },
496 { C::to_radix_mem_sel_should_write_mem, 1 },
497 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 2 },
498 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(
MemoryTag::U8) },
501 { C::gt_input_a, radix },
502 { C::gt_input_b, 256 },
507 { C::to_radix_mem_sel, 1 },
509 { C::to_radix_mem_execution_clk, 0 },
510 { C::to_radix_mem_space_id, 0 },
511 { C::to_radix_mem_dst_addr,
dst_addr + 2 },
513 { C::to_radix_mem_value_to_decompose,
value },
514 { C::to_radix_mem_radix, radix },
515 { C::to_radix_mem_num_limbs, num_limbs - 2 },
516 { C::to_radix_mem_is_output_bits, 0 },
519 { C::to_radix_mem_num_limbs_minus_one_inv,
FF(num_limbs - 3).
invert() },
521 { C::to_radix_mem_limb_value, 3 },
522 { C::to_radix_mem_sel_should_decompose, 1 },
523 { C::to_radix_mem_sel_should_write_mem, 1 },
524 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 3 },
525 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(
MemoryTag::U8) },
529 { C::to_radix_mem_sel, 1 },
531 { C::to_radix_mem_execution_clk, 0 },
532 { C::to_radix_mem_space_id, 0 },
533 { C::to_radix_mem_dst_addr, 13 },
535 { C::to_radix_mem_value_to_decompose,
value },
536 { C::to_radix_mem_radix, radix },
537 { C::to_radix_mem_num_limbs, num_limbs - 3 },
538 { C::to_radix_mem_is_output_bits, 0 },
540 { C::to_radix_mem_last, 1 },
542 { C::to_radix_mem_limb_value, 7 },
543 { C::to_radix_mem_sel_should_decompose, 1 },
544 { C::to_radix_mem_sel_should_write_mem, 1 },
545 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 4 },
546 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(
MemoryTag::U8) },
557 { value_addr, MemoryValue::from<FF>(
value) },
558 { radix_addr, MemoryValue::from<uint32_t>(radix) },
559 { num_limbs_addr, MemoryValue::from<uint32_t>(num_limbs) },
560 { is_output_bits_addr, MemoryValue::from<uint1_t>(
false) },
561 {
dst_addr, MemoryValue::from<uint8_t>(1) },
562 {
dst_addr + 1, MemoryValue::from<uint8_t>(3) },
563 {
dst_addr + 2, MemoryValue::from<uint8_t>(3) },
564 {
dst_addr + 3, MemoryValue::from<uint8_t>(7) },
567 for (uint32_t i = 0; i < memory_values.size(); ++i) {
568 const auto& [addr,
value] = memory_values[i];
571 { { C::memory_sel, 1 },
572 { C::memory_space_id, 0 },
573 { C::memory_address, addr },
574 { C::memory_value,
value.as_ff() },
575 { C::memory_tag,
static_cast<uint8_t
>(
value.get_tag()) },
576 { C::memory_rw, i > 3 ? 1 : 0 } },
580 EventEmitter<ToRadixEvent> to_radix_event_emitter;
581 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
585 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
588 to_radix_simulator.to_le_radix(
value, num_limbs, radix);
591 auto events = to_radix_event_emitter.get_events();
599 check_relation<to_radix_mem>(trace);
600 check_all_interactions<ToRadixTraceBuilder>(trace);
603 trace.
set(Column::to_radix_mem_sel_should_write_mem, 2, 0);
605 "SEL_SHOULD_WRITE_MEM_CONTINUITY");
608 trace.
set(Column::to_radix_mem_sel_should_decompose, 2, 0);
610 "SEL_SHOULD_DECOMPOSE_CONTINUITY");
613TEST(ToRadixMemoryConstrainingTest, DstOutOfRange)
618 uint32_t num_limbs = 2;
619 auto dst_addr =
static_cast<uint64_t
>(MAX_MEM - 1);
621 TestTraceContainer
trace = TestTraceContainer({
624 { C::precomputed_first_row, 1 },
627 { C::gt_input_a,
dst_addr + num_limbs },
628 { C::gt_input_b, MAX_MEM },
634 { C::execution_sel, 1 },
635 { C::execution_sel_exec_dispatch_to_radix, 1 },
636 { C::execution_register_0_,
value },
637 { C::execution_register_1_, radix },
638 { C::execution_register_2_, num_limbs },
639 { C::execution_register_3_, 0 },
641 { C::execution_sel_opcode_error, 1 },
644 { C::to_radix_mem_sel, 1 },
645 { C::to_radix_mem_max_mem_size, MAX_MEM },
646 { C::to_radix_mem_two, 2 },
647 { C::to_radix_mem_two_five_six, 256 },
649 { C::to_radix_mem_execution_clk, 0 },
650 { C::to_radix_mem_space_id, 0 },
651 { C::to_radix_mem_dst_addr,
dst_addr },
652 { C::to_radix_mem_write_addr_upper_bound,
dst_addr + num_limbs },
654 { C::to_radix_mem_value_to_decompose,
value },
655 { C::to_radix_mem_radix, radix },
656 { C::to_radix_mem_num_limbs, num_limbs },
657 { C::to_radix_mem_is_output_bits, 0 },
659 { C::to_radix_mem_sel_dst_out_of_range_err, 1 },
660 { C::to_radix_mem_input_validation_error, 1 },
661 { C::to_radix_mem_err, 1 },
663 { C::to_radix_mem_start, 1 },
664 { C::to_radix_mem_last, 1 },
665 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).
invert() },
667 { C::to_radix_mem_sel_num_limbs_is_zero, 0 },
668 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).
invert() },
669 { C::to_radix_mem_sel_value_is_zero, 0 },
674 check_relation<to_radix_mem>(trace);
675 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_dst_addr_in_range_settings>(trace);
676 check_interaction<ExecutionTraceBuilder, perm_execution_dispatch_to_to_radix_settings>(trace);
679TEST(ToRadixMemoryConstrainingTest, InvalidRadix)
684 uint32_t num_limbs = 2;
687 TestTraceContainer
trace = TestTraceContainer({
690 { C::precomputed_first_row, 1 },
693 { C::gt_input_a, 2 },
694 { C::gt_input_b, radix },
699 { C::to_radix_mem_sel, 1 },
700 { C::to_radix_mem_max_mem_size, MAX_MEM },
701 { C::to_radix_mem_two, 2 },
702 { C::to_radix_mem_two_five_six, 256 },
704 { C::to_radix_mem_execution_clk, 0 },
705 { C::to_radix_mem_space_id, 0 },
706 { C::to_radix_mem_dst_addr,
dst_addr },
707 { C::to_radix_mem_write_addr_upper_bound,
dst_addr + num_limbs },
709 { C::to_radix_mem_value_to_decompose,
value },
710 { C::to_radix_mem_radix, radix },
711 { C::to_radix_mem_num_limbs, num_limbs },
712 { C::to_radix_mem_is_output_bits, 0 },
714 { C::to_radix_mem_sel_radix_lt_2_err, 1 },
715 { C::to_radix_mem_input_validation_error, 1 },
716 { C::to_radix_mem_err, 1 },
718 { C::to_radix_mem_start, 1 },
719 { C::to_radix_mem_last, 1 },
720 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).
invert() },
722 { C::to_radix_mem_sel_num_limbs_is_zero, 0 },
723 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).
invert() },
724 { C::to_radix_mem_sel_value_is_zero, 0 },
728 check_relation<to_radix_mem>(trace);
729 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(trace);
732TEST(ToRadixMemoryConstrainingTest, InvalidBitwiseRadix)
737 uint32_t num_limbs = 2;
741 TestTraceContainer
trace = TestTraceContainer({
744 { C::precomputed_first_row, 1 },
747 { C::gt_input_a, 2 },
748 { C::gt_input_b, radix },
753 { C::to_radix_mem_sel, 1 },
754 { C::to_radix_mem_max_mem_size, MAX_MEM },
755 { C::to_radix_mem_two, 2 },
756 { C::to_radix_mem_two_five_six, 256 },
758 { C::to_radix_mem_execution_clk, 0 },
759 { C::to_radix_mem_space_id, 0 },
760 { C::to_radix_mem_dst_addr,
dst_addr },
761 { C::to_radix_mem_write_addr_upper_bound,
dst_addr + num_limbs },
763 { C::to_radix_mem_value_to_decompose,
value },
764 { C::to_radix_mem_radix, radix },
765 { C::to_radix_mem_num_limbs, num_limbs },
768 { C::to_radix_mem_sel_invalid_bitwise_radix, 1 },
769 { C::to_radix_mem_input_validation_error, 1 },
770 { C::to_radix_mem_err, 1 },
772 { C::to_radix_mem_start, 1 },
773 { C::to_radix_mem_last, 1 },
774 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).
invert() },
776 { C::to_radix_mem_sel_num_limbs_is_zero, 0 },
777 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).
invert() },
778 { C::to_radix_mem_sel_value_is_zero, 0 },
782 check_relation<to_radix_mem>(trace);
783 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(trace);
786TEST(ToRadixMemoryConstrainingTest, InvalidNumLimbsForValue)
791 uint32_t num_limbs = 0;
795 TestTraceContainer
trace = TestTraceContainer({
798 { C::precomputed_first_row, 1 },
801 { C::gt_input_a, 2 },
802 { C::gt_input_b, radix },
807 { C::to_radix_mem_sel, 1 },
808 { C::to_radix_mem_max_mem_size, MAX_MEM },
809 { C::to_radix_mem_two, 2 },
810 { C::to_radix_mem_two_five_six, 256 },
812 { C::to_radix_mem_execution_clk, 0 },
813 { C::to_radix_mem_space_id, 0 },
814 { C::to_radix_mem_dst_addr,
dst_addr },
815 { C::to_radix_mem_write_addr_upper_bound,
dst_addr + num_limbs },
817 { C::to_radix_mem_value_to_decompose,
value },
818 { C::to_radix_mem_radix, radix },
819 { C::to_radix_mem_num_limbs, num_limbs },
822 { C::to_radix_mem_sel_invalid_num_limbs_err, 1 },
823 { C::to_radix_mem_input_validation_error, 1 },
824 { C::to_radix_mem_err, 1 },
826 { C::to_radix_mem_start, 1 },
827 { C::to_radix_mem_last, 1 },
828 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).
invert() },
830 { C::to_radix_mem_sel_num_limbs_is_zero, 1 },
831 { C::to_radix_mem_num_limbs_inv, 0 },
832 { C::to_radix_mem_sel_value_is_zero, 0 },
836 check_relation<to_radix_mem>(trace);
837 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(trace);
840TEST(ToRadixMemoryConstrainingTest, TruncationError)
845 uint32_t num_limbs = 3;
849 TestTraceContainer
trace = TestTraceContainer({
852 { C::precomputed_first_row, 1 },
855 { C::gt_input_a, 2 },
856 { C::gt_input_b, radix },
861 { C::to_radix_mem_sel, 1 },
862 { C::to_radix_mem_max_mem_size, MAX_MEM },
863 { C::to_radix_mem_two, 2 },
864 { C::to_radix_mem_two_five_six, 256 },
866 { C::to_radix_mem_execution_clk, 0 },
867 { C::to_radix_mem_space_id, 0 },
868 { C::to_radix_mem_dst_addr,
dst_addr },
869 { C::to_radix_mem_write_addr_upper_bound,
dst_addr + num_limbs },
871 { C::to_radix_mem_value_to_decompose,
value },
872 { C::to_radix_mem_radix, radix },
873 { C::to_radix_mem_num_limbs, num_limbs },
876 { C::to_radix_mem_sel_truncation_error, 1 },
877 { C::to_radix_mem_err, 1 },
879 { C::to_radix_mem_start, 1 },
880 { C::to_radix_mem_last, 1 },
881 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).
invert() },
883 { C::to_radix_mem_sel_should_decompose, 1 },
884 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 1 },
885 { C::to_radix_mem_limb_value, 3 },
886 { C::to_radix_mem_value_found, 0 },
888 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).
invert() },
889 { C::to_radix_mem_sel_value_is_zero, 0 },
893 check_relation<to_radix_mem>(trace);
894 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(trace);
897 trace.
set(C::to_radix_mem_sel_truncation_error, 1, 0);
900 trace.
set(C::to_radix_mem_sel_truncation_error, 1, 1);
903 trace.
set(C::to_radix_mem_value_found, 1, 1);
908TEST(ToRadixMemoryConstrainingTest, ZeroNumLimbsAndZeroValueIsNoop)
913 uint32_t num_limbs = 0;
917 TestTraceContainer
trace = TestTraceContainer({
920 { C::precomputed_first_row, 1 },
923 { C::gt_input_a, 2 },
924 { C::gt_input_b, radix },
929 { C::to_radix_mem_sel, 1 },
930 { C::to_radix_mem_max_mem_size, MAX_MEM },
931 { C::to_radix_mem_two, 2 },
932 { C::to_radix_mem_two_five_six, 256 },
934 { C::to_radix_mem_execution_clk, 0 },
935 { C::to_radix_mem_space_id, 0 },
936 { C::to_radix_mem_dst_addr,
dst_addr },
937 { C::to_radix_mem_write_addr_upper_bound,
dst_addr + num_limbs },
939 { C::to_radix_mem_value_to_decompose,
value },
940 { C::to_radix_mem_radix, radix },
941 { C::to_radix_mem_num_limbs, num_limbs },
944 { C::to_radix_mem_start, 1 },
945 { C::to_radix_mem_last, 1 },
946 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).
invert() },
948 { C::to_radix_mem_sel_num_limbs_is_zero, 1 },
949 { C::to_radix_mem_num_limbs_inv, 0 },
950 { C::to_radix_mem_sel_value_is_zero, 1 },
951 { C::to_radix_mem_value_inv, 0 },
954 check_relation<to_radix_mem>(trace);
955 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(trace);
958TEST(ToRadixMemoryConstrainingTest, ComplexTest)
960 EventEmitter<ToRadixEvent> to_radix_event_emitter;
961 EventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
965 simulation::MemoryStore
memory;
967 StrictMock<MockFieldGreaterThan>
field_gt;
971 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
975 uint32_t num_limbs = 256;
980 to_radix_simulator.to_be_radix(
981 memory,
FF(1337), 10, 6,
false, 0xdeadbeef);
983 TestTraceContainer
trace;
986 builder.process_with_memory(to_radix_mem_event_emitter.dump_events(), trace);
996 check_relation<to_radix>(trace);
997 check_relation<to_radix_mem>(trace);
1020TEST(ToRadixMemoryConstrainingTest, NegativeGhostRowMemoryWrite_RelationsOnly)
1024 TestTraceContainer
trace({
1026 { C::precomputed_first_row, 1 },
1029 { C::to_radix_mem_sel, 0 },
1030 { C::to_radix_mem_sel_should_write_mem, 1 },
1031 { C::to_radix_mem_execution_clk, 1 },
1032 { C::to_radix_mem_space_id, 1 },
1033 { C::to_radix_mem_dst_addr, 100 },
1034 { C::to_radix_mem_limb_value, 999 },
1035 { C::to_radix_mem_output_tag, 2 },
1042 "SEL_SHOULD_WRITE_MEM_REQUIRES_SEL");
1051TEST(ToRadixMemoryConstrainingTest, NegativeGhostRowInjectionBlocked)
1053 TestTraceContainer
trace;
1054 MemoryTraceBuilder memory_trace_builder;
1055 PrecomputedTraceBuilder precomputed_trace_builder;
1058 uint32_t malicious_clk = 42;
1059 uint16_t malicious_space_id = 1;
1061 uint8_t malicious_limb_value = 0x99;
1067 .execution_clk = malicious_clk,
1069 .addr = malicious_addr,
1071 .space_id = malicious_space_id,
1076 precomputed_trace_builder.process_sel_range_8(trace);
1077 precomputed_trace_builder.process_sel_range_16(trace);
1078 precomputed_trace_builder.process_misc(trace, 1 << 16);
1079 precomputed_trace_builder.process_tag_parameters(trace);
1080 memory_trace_builder.process(mem_events, trace);
1083 uint32_t memory_row = 0;
1085 if (
trace.
get(C::memory_sel, row) == 1) {
1093 uint32_t ghost_row = 0;
1096 { C::precomputed_first_row, 1 },
1097 { C::precomputed_clk, ghost_row },
1098 { C::to_radix_mem_sel, 0 },
1099 { C::to_radix_mem_sel_should_write_mem, 1 },
1100 { C::to_radix_mem_execution_clk, malicious_clk },
1101 { C::to_radix_mem_space_id, malicious_space_id },
1102 { C::to_radix_mem_dst_addr, malicious_addr },
1103 { C::to_radix_mem_limb_value, malicious_limb_value },
1104 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(malicious_tag) },
1107 trace.
set(C::memory_sel_to_radix_write, memory_row, 1);
DeduplicatingEventEmitter< GreaterThanEvent > gt_emitter
FieldGreaterThan field_gt
DeduplicatingEventEmitter< RangeCheckEvent > range_check_emitter
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
static TaggedValue from_tag(ValueTag tag, FF value)
static constexpr size_t SR_SEL_SHOULD_WRITE_MEM_CONTINUITY
static constexpr size_t SR_SEL_SHOULD_DECOMPOSE_CONTINUITY
static constexpr size_t SR_TRUNCATION_ERROR
static constexpr size_t SR_SEL_SHOULD_WRITE_MEM_REQUIRES_SEL
static constexpr size_t SR_SELECTOR_CONSISTENCY
static constexpr size_t SR_OVERFLOW_CHECK
static constexpr size_t SR_CONSTANT_CONSISTENCY_SAFE_LIMBS
static constexpr size_t SR_CONSTANT_CONSISTENCY_RADIX
static constexpr size_t SR_CONSTANT_CONSISTENCY_VALUE
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
Process the ALU events and populate the ALU relevant columns in the trace.
void process(const simulation::EventEmitterInterface< simulation::GreaterThanEvent >::Container &events, TraceContainer &trace)
void process_to_radix_p_decompositions(TraceContainer &trace)
void process_to_radix_safe_limbs(TraceContainer &trace)
void process_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
void process_sel_range_8(TraceContainer &trace)
const FF & get(Column col, uint32_t row) const
uint32_t get_num_rows() const
void set(Column col, uint32_t row, const FF &value)
constexpr bool get_bit(uint64_t bit_index) const
PrecomputedTraceBuilder precomputed_builder
GreaterThanTraceBuilder gt_builder
ExecutionIdManager execution_id_manager
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
TestTraceContainer empty_trace()
lookup_settings< lookup_to_radix_limb_less_than_radix_range_settings_ > lookup_to_radix_limb_less_than_radix_range_settings
lookup_settings< lookup_to_radix_limb_p_diff_range_settings_ > lookup_to_radix_limb_p_diff_range_settings
lookup_settings< lookup_to_radix_mem_check_dst_addr_in_range_settings_ > lookup_to_radix_mem_check_dst_addr_in_range_settings
lookup_settings< lookup_to_radix_mem_check_radix_lt_2_settings_ > lookup_to_radix_mem_check_radix_lt_2_settings
lookup_settings< lookup_to_radix_limb_range_settings_ > lookup_to_radix_limb_range_settings
lookup_settings< lookup_to_radix_mem_check_radix_gt_256_settings_ > lookup_to_radix_mem_check_radix_gt_256_settings
lookup_settings< lookup_to_radix_fetch_safe_limbs_settings_ > lookup_to_radix_fetch_safe_limbs_settings
lookup_settings< lookup_to_radix_mem_input_output_to_radix_settings_ > lookup_to_radix_mem_input_output_to_radix_settings
lookup_settings< lookup_to_radix_fetch_p_limb_settings_ > lookup_to_radix_fetch_p_limb_settings
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static constexpr field neg_one()
static constexpr field one()
static constexpr uint256_t modulus
constexpr field invert() const noexcept
BB_INLINE std::vector< uint8_t > to_buffer() const
static constexpr field zero()