4#include <gmock/gmock.h>
5#include <gtest/gtest.h>
35using namespace simulation;
36using ::testing::Return;
37using ::testing::ReturnRef;
38using ::testing::StrictMock;
39using tracegen::DataCopyTraceBuilder;
40using tracegen::ExecutionTraceBuilder;
41using tracegen::TestTraceContainer;
47class DataCopyConstrainingBuilderTest :
public ::testing::Test {
49 DataCopyConstrainingBuilderTest() { EXPECT_CALL(context, get_memory()).WillRepeatedly(ReturnRef(mem)); }
53 RangeCheck
range_check = RangeCheck(range_check_event_emitter);
56 GreaterThan
gt = GreaterThan(mock_field_gt, range_check, gt_event_emitter);
58 DataCopy
copy_data = DataCopy(execution_id_manager, gt, event_emitter);
63 TestTraceContainer
trace = TestTraceContainer({
65 { C::precomputed_first_row, 1 },
71 MemoryValue::from<FF>(1), MemoryValue::from<FF>(2), MemoryValue::from<FF>(3), MemoryValue::from<FF>(4),
72 MemoryValue::from<FF>(5), MemoryValue::from<FF>(6), MemoryValue::from<FF>(7), MemoryValue::from<FF>(8),
76class NestedCdConstrainingBuilderTest :
public DataCopyConstrainingBuilderTest {
78 NestedCdConstrainingBuilderTest()
81 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
true));
82 EXPECT_CALL(context, get_parent_id).WillRepeatedly(Return(1));
83 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(2));
84 EXPECT_CALL(context, get_parent_cd_size).WillRepeatedly(Return(
data.size()));
85 EXPECT_CALL(context, get_parent_cd_addr).WillRepeatedly(Return(0));
89TEST_F(NestedCdConstrainingBuilderTest, CdZeroCopy)
91 uint32_t copy_size = 0;
96 tracegen::DataCopyTraceBuilder
builder;
102 check_relation<data_copy>(trace);
110TEST_F(NestedCdConstrainingBuilderTest, SimpleNestedCdCopy)
112 uint32_t copy_size =
static_cast<uint32_t
>(
data.size());
115 EXPECT_CALL(context, get_calldata(
cd_offset, copy_size)).WillOnce(Return(
data));
125 check_relation<data_copy>(trace);
136TEST_F(NestedCdConstrainingBuilderTest, SimpleNestedCdCopySizeOneNoPadding)
138 uint32_t copy_size = 1;
143 EXPECT_CALL(context, get_calldata(
cd_offset, copy_size)).WillOnce(Return(result_cd));
153 check_relation<data_copy>(trace);
161TEST_F(NestedCdConstrainingBuilderTest, SimpleNestedCdCopySizeOneWithPadding)
163 uint32_t copy_size = 1;
174 check_relation<data_copy>(trace);
182TEST_F(NestedCdConstrainingBuilderTest, NestedCdCopyPadded)
185 uint32_t copy_size = 10;
188 uint32_t effective_reads =
static_cast<uint32_t
>(
data.size());
190 EXPECT_CALL(context, get_calldata(
cd_offset, effective_reads)).WillOnce(Return(
data));
200 check_relation<data_copy>(trace);
208TEST_F(NestedCdConstrainingBuilderTest, NestedCdCopyPartial)
216 EXPECT_CALL(context, get_calldata(
offset, size)).WillOnce(Return(result_cd));
226 check_relation<data_copy>(trace);
234TEST_F(NestedCdConstrainingBuilderTest, ZeroCopySizeOffsetOOB)
236 uint32_t
offset =
static_cast<uint32_t
>(
data.size()) + 1;
250 check_relation<data_copy>(trace);
258TEST_F(NestedCdConstrainingBuilderTest, NonZeroCopySizeOffsetOOB)
260 uint32_t
offset =
static_cast<uint32_t
>(
data.size()) + 1;
274 check_relation<data_copy>(trace);
282TEST_F(NestedCdConstrainingBuilderTest, OutofRangeError)
289 "Attempting to write out of bounds memory");
297 check_relation<data_copy>(trace);
305TEST_F(NestedCdConstrainingBuilderTest, HighestMemoryAddressesWithPadding)
307 uint32_t
offset =
static_cast<uint32_t
>(
data.size() - 1);
313 uint32_t effective_reads =
static_cast<uint32_t
>(
data.size()) -
offset;
316 EXPECT_CALL(context, get_calldata(
offset, effective_reads)).WillOnce(Return(result_cd));
326 check_relation<data_copy>(trace);
334TEST_F(NestedCdConstrainingBuilderTest, HighestMemoryAddressesNoPadding)
337 uint32_t size =
static_cast<uint32_t
>(
data.size()) - 2;
342 EXPECT_CALL(context, get_calldata(
offset, size)).WillOnce(Return(result_cd));
352 check_relation<data_copy>(trace);
360class HighCdAddressConstrainingBuilderTest :
public DataCopyConstrainingBuilderTest {
362 HighCdAddressConstrainingBuilderTest()
365 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
true));
366 EXPECT_CALL(context, get_parent_id).WillRepeatedly(Return(1));
367 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(2));
368 EXPECT_CALL(context, get_parent_cd_size).WillRepeatedly(Return(
data.size()));
373TEST_F(HighCdAddressConstrainingBuilderTest, HighestMemoryAddressesWithPadding)
375 uint32_t
offset =
static_cast<uint32_t
>(
data.size() - 1);
381 uint32_t effective_reads =
static_cast<uint32_t
>(
data.size()) -
offset;
384 EXPECT_CALL(context, get_calldata(
offset, effective_reads)).WillOnce(Return(result_cd));
394 check_relation<data_copy>(trace);
402TEST_F(HighCdAddressConstrainingBuilderTest, HighestMemoryAddressesNoPadding)
405 uint32_t size =
static_cast<uint32_t
>(
data.size()) - 2;
410 EXPECT_CALL(context, get_calldata(
offset, size)).WillOnce(Return(result_cd));
420 check_relation<data_copy>(trace);
429class SrcExceedsMemConstrainingBuilderTest :
public DataCopyConstrainingBuilderTest {
431 SrcExceedsMemConstrainingBuilderTest()
435 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
true));
436 EXPECT_CALL(context, get_parent_id).WillRepeatedly(Return(1));
437 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(2));
438 EXPECT_CALL(context, get_parent_cd_size).WillRepeatedly(Return(src_data_size));
439 EXPECT_CALL(context, get_parent_cd_addr).WillRepeatedly(Return(src_addr));
447TEST_F(SrcExceedsMemConstrainingBuilderTest, SrcOutOfRangeClampedNotAnError)
456 uint32_t effective_reads = 3;
459 EXPECT_CALL(
context, get_calldata(
offset, effective_reads)).WillOnce(Return(result_cd));
470 check_relation<data_copy>(
trace);
479TEST_F(SrcExceedsMemConstrainingBuilderTest, SrcOutOfRangeWithOffset)
488 uint32_t effective_reads = 2;
491 EXPECT_CALL(context, get_calldata(
offset, effective_reads)).WillOnce(Return(result_cd));
501 check_relation<data_copy>(trace);
510TEST_F(SrcExceedsMemConstrainingBuilderTest, SrcOutOfRangeClampedBelowOffset)
529 check_relation<data_copy>(trace);
538TEST_F(SrcExceedsMemConstrainingBuilderTest, SrcAndDstBothOutOfRange)
548 "Attempting to write out of bounds memory");
556 check_relation<data_copy>(trace);
564class EnqueuedCdConstrainingBuilderTest :
public DataCopyConstrainingBuilderTest {
566 EnqueuedCdConstrainingBuilderTest()
569 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
false));
570 EXPECT_CALL(context, get_parent_id).WillRepeatedly(Return(0));
571 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(1));
572 EXPECT_CALL(context, get_parent_cd_size).WillRepeatedly(Return(
data.size()));
573 EXPECT_CALL(context, get_parent_cd_addr).WillRepeatedly(Return(0));
576 tracegen::CalldataTraceBuilder calldata_builder;
577 std::vector<FF> calldata_ff(
data.size());
578 std::ranges::transform(
581 CalldataEvent cd_event = {
583 .calldata = calldata_ff,
585 calldata_builder.process_retrieval({ cd_event },
trace);
589TEST_F(EnqueuedCdConstrainingBuilderTest, CdZeroCopy)
591 uint32_t copy_size = 0;
596 tracegen::DataCopyTraceBuilder
builder;
602 check_relation<data_copy>(trace);
603 check_all_interactions<DataCopyTraceBuilder>(trace);
606TEST_F(EnqueuedCdConstrainingBuilderTest, SimpleEnqueuedCdCopy)
608 auto copy_size =
static_cast<uint32_t
>(
data.size());
611 EXPECT_CALL(context, get_calldata(
cd_offset, copy_size)).WillOnce(Return(
data));
621 check_relation<data_copy>(trace);
622 check_all_interactions<DataCopyTraceBuilder>(trace);
625TEST_F(EnqueuedCdConstrainingBuilderTest, EnqueuedCallCdCopyPadding)
628 uint32_t copy_size = 10;
630 uint32_t effective_reads =
static_cast<uint32_t
>(
data.size());
632 EXPECT_CALL(context, get_calldata(
cd_offset, effective_reads)).WillOnce(Return(
data));
642 check_relation<data_copy>(trace);
643 check_all_interactions<DataCopyTraceBuilder>(trace);
646TEST_F(EnqueuedCdConstrainingBuilderTest, EnqueuedCallCdCopyPartial)
654 EXPECT_CALL(context, get_calldata(
offset, size)).WillOnce(Return(result_cd));
664 check_relation<data_copy>(trace);
665 check_all_interactions<DataCopyTraceBuilder>(trace);
668class EnqueuedEmptyCdConstrainingBuilderTest :
public DataCopyConstrainingBuilderTest {
670 EnqueuedEmptyCdConstrainingBuilderTest()
673 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
false));
674 EXPECT_CALL(context, get_parent_id).WillRepeatedly(Return(0));
675 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(1));
676 EXPECT_CALL(context, get_parent_cd_size).WillRepeatedly(Return(0));
677 EXPECT_CALL(context, get_parent_cd_addr).WillRepeatedly(Return(0));
680 tracegen::CalldataTraceBuilder calldata_builder;
681 CalldataEvent cd_event = {
685 calldata_builder.process_retrieval({ cd_event },
trace);
689TEST_F(EnqueuedEmptyCdConstrainingBuilderTest, CdZeroCopy)
691 uint32_t copy_size = 0;
696 tracegen::DataCopyTraceBuilder
builder;
702 check_relation<data_copy>(trace);
703 check_all_interactions<DataCopyTraceBuilder>(trace);
706TEST_F(EnqueuedEmptyCdConstrainingBuilderTest, SimpleEnqueuedCdCopy)
708 uint32_t copy_size = 4;
719 check_relation<data_copy>(trace);
720 check_all_interactions<DataCopyTraceBuilder>(trace);
723TEST_F(EnqueuedEmptyCdConstrainingBuilderTest, EnqueuedCallCdCopyPadding)
726 std::vector<FF> result_cd = {};
727 result_cd.resize(10, 0);
728 auto copy_size =
static_cast<uint32_t
>(result_cd.size());
738 check_relation<data_copy>(trace);
739 check_all_interactions<DataCopyTraceBuilder>(trace);
746TEST(DataCopyWithExecutionPerm, CdCopy)
751 uint32_t copy_size = 4;
754 uint32_t parent_context_id = 99;
757 MemoryValue::from<FF>(8), MemoryValue::from<FF>(7), MemoryValue::from<FF>(6), MemoryValue::from<FF>(5),
758 MemoryValue::from<FF>(4), MemoryValue::from<FF>(3), MemoryValue::from<FF>(2), MemoryValue::from<FF>(1),
769 StrictMock<MockContext>
context;
770 EXPECT_CALL(context, get_memory()).WillRepeatedly(ReturnRef(
mem));
771 EXPECT_CALL(context, get_parent_cd_size).WillRepeatedly(Return(
data.size()));
772 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
true));
773 EXPECT_CALL(context, get_parent_cd_addr).WillRepeatedly(Return(
parent_cd_addr));
774 EXPECT_CALL(context, get_calldata(
cd_offset, copy_size))
775 .WillRepeatedly(::testing::Invoke([&
data,
cd_offset, copy_size]() {
779 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(
context_id));
780 EXPECT_CALL(context, get_parent_id).WillRepeatedly(Return(parent_context_id));
787 TestTraceContainer
trace({
789 { C::precomputed_first_row, 1 },
790 { C::execution_sel, 1 },
792 { C::execution_parent_id, parent_context_id },
793 { C::execution_sel_exec_dispatch_calldata_copy, 1 },
794 { C::execution_register_0_, copy_size },
797 { C::execution_sel_opcode_error, 0 },
799 { C::execution_parent_calldata_size,
static_cast<uint32_t
>(
data.size()) },
808 check_relation<data_copy>(trace);
814class NestedRdConstrainingBuilderTest :
public DataCopyConstrainingBuilderTest {
816 NestedRdConstrainingBuilderTest()
819 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
true));
820 EXPECT_CALL(context, get_last_child_id).WillRepeatedly(Return(2));
821 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(2));
822 EXPECT_CALL(context, get_last_rd_size).WillRepeatedly(Return(
data.size()));
823 EXPECT_CALL(context, get_last_rd_addr).WillRepeatedly(Return(0));
827TEST_F(NestedRdConstrainingBuilderTest, RdZeroCopy)
829 uint32_t copy_size = 0;
830 uint32_t rd_offset = 0;
834 tracegen::DataCopyTraceBuilder
builder;
840 check_relation<data_copy>(trace);
841 check_all_interactions<DataCopyTraceBuilder>(trace);
845class SrcExceedsMemRdConstrainingBuilderTest :
public DataCopyConstrainingBuilderTest {
847 SrcExceedsMemRdConstrainingBuilderTest()
849 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
true));
850 EXPECT_CALL(context, get_last_child_id).WillRepeatedly(Return(2));
851 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(2));
852 EXPECT_CALL(context, get_last_rd_size).WillRepeatedly(Return(rd_data_size));
853 EXPECT_CALL(context, get_last_rd_addr).WillRepeatedly(Return(rd_addr));
861TEST_F(SrcExceedsMemRdConstrainingBuilderTest, SrcOutOfRangeClampedNotAnError)
870 uint32_t effective_reads = 2;
873 EXPECT_CALL(
context, get_returndata(
offset, effective_reads)).WillOnce(Return(result_rd));
883 check_relation<data_copy>(
trace);
884 check_all_interactions<DataCopyTraceBuilder>(
trace);
887TEST(DataCopyWithExecutionPerm, RdCopy)
891 uint32_t rd_offset = 3;
892 uint32_t copy_size = 4;
898 MemoryValue::from<FF>(1), MemoryValue::from<FF>(2), MemoryValue::from<FF>(3), MemoryValue::from<FF>(4),
899 MemoryValue::from<FF>(5), MemoryValue::from<FF>(6), MemoryValue::from<FF>(7), MemoryValue::from<FF>(8),
907 StrictMock<MockContext>
context;
908 EXPECT_CALL(context, get_memory()).WillRepeatedly(ReturnRef(
mem));
909 EXPECT_CALL(context, get_last_rd_size).WillRepeatedly(Return(
data.size()));
910 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
true));
911 EXPECT_CALL(context, get_last_rd_addr).WillRepeatedly(Return(
child_rd_addr));
912 EXPECT_CALL(context, get_returndata(rd_offset, copy_size))
913 .WillRepeatedly(::testing::Invoke([&
data, rd_offset, copy_size]() {
917 EXPECT_CALL(context, get_last_child_id).WillRepeatedly(Return(
child_context_id));
918 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(
context_id));
925 TestTraceContainer
trace({
927 { C::precomputed_first_row, 1 },
928 { C::execution_sel, 1 },
931 { C::execution_sel_exec_dispatch_returndata_copy, 1 },
932 { C::execution_register_0_, copy_size },
933 { C::execution_register_1_, rd_offset },
935 { C::execution_sel_opcode_error, 0 },
937 { C::execution_last_child_returndata_size,
static_cast<uint32_t
>(
data.size()) },
946 check_relation<data_copy>(trace);
952TEST(DataCopyWithExecutionPerm, ErrorPropagation)
956 uint32_t rd_offset = 10;
957 uint32_t copy_size = 4;
963 uint32_t child_data_size = 10;
966 StrictMock<MockContext>
context;
967 EXPECT_CALL(context, get_memory()).WillRepeatedly(ReturnRef(
mem));
968 EXPECT_CALL(context, get_last_rd_size).WillRepeatedly(Return(child_data_size));
969 EXPECT_CALL(context, has_parent).WillRepeatedly(Return(
true));
970 EXPECT_CALL(context, get_last_rd_addr).WillRepeatedly(Return(
child_rd_addr));
971 EXPECT_CALL(context, get_context_id).WillRepeatedly(Return(
context_id));
972 EXPECT_CALL(context, get_last_child_id).WillRepeatedly(Return(
child_context_id));
982 TestTraceContainer
trace({
984 { C::precomputed_first_row, 1 },
985 { C::execution_sel, 1 },
988 { C::execution_sel_exec_dispatch_returndata_copy, 1 },
989 { C::execution_register_0_, copy_size },
990 { C::execution_register_1_, rd_offset },
991 { C::execution_rop_2_, big_dst_addr },
992 { C::execution_sel_opcode_error, 1 },
994 { C::execution_last_child_returndata_size, child_data_size },
999 "Attempting to write out of bounds memory");
1004 check_relation<data_copy>(trace);
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
#define AVM_HIGHEST_MEM_ADDRESS
void rd_copy(ContextInterface &context, uint32_t copy_size, uint32_t offset, MemoryAddress dst_addr) override
Copies returndata from the last executed context to the dst_addr.
void cd_copy(ContextInterface &context, uint32_t copy_size, uint32_t offset, MemoryAddress dst_addr) override
Writes calldata into dst_addr. There is slight difference in how enqueued and nested contexts are han...
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)
Process the greater-than events and populate the relevant columns in the trace.
GreaterThanTraceBuilder gt_builder
EventEmitter< GreaterThanEvent > gt_event_emitter
ExecutionIdManager execution_id_manager
EventEmitter< RangeCheckEvent > range_check_event_emitter
StrictMock< MockFieldGreaterThan > mock_field_gt
EventEmitter< DataCopyEvent > event_emitter
const std::vector< MemoryValue > data
StrictMock< MockContext > context
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
TEST_F(AvmRecursiveTests, TwoLayerAvmRecursionFailsWithWrongPIs)
lookup_settings< lookup_data_copy_check_dst_addr_in_range_settings_ > lookup_data_copy_check_dst_addr_in_range_settings
permutation_settings< perm_execution_dispatch_to_cd_copy_settings_ > perm_execution_dispatch_to_cd_copy_settings
lookup_settings< lookup_data_copy_offset_plus_size_is_gt_data_size_settings_ > lookup_data_copy_offset_plus_size_is_gt_data_size_settings
lookup_settings< lookup_data_copy_sel_has_reads_settings_ > lookup_data_copy_sel_has_reads_settings
lookup_settings< lookup_data_copy_check_src_addr_in_range_settings_ > lookup_data_copy_check_src_addr_in_range_settings
permutation_settings< perm_execution_dispatch_to_rd_copy_settings_ > perm_execution_dispatch_to_rd_copy_settings
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
uint32_t child_context_id