1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
25using tracegen::BytecodeTraceBuilder;
26using tracegen::PrecomputedTraceBuilder;
27using tracegen::RangeCheckTraceBuilder;
28using tracegen::TestTraceContainer;
33using instr_fetching = instr_fetching<FF>;
35using simulation::BytecodeDecompositionEvent;
37using simulation::Instruction;
38using simulation::InstructionFetchingEvent;
40using simulation::RangeCheckEvent;
42TEST(InstrFetchingConstrainingTest, EmptyRow)
48TEST(InstrFetchingConstrainingTest, Add8WithTraceGen)
50 TestTraceContainer
trace;
57 .operands = { Operand::from<uint8_t>(0x34), Operand::from<uint8_t>(0x35), Operand::from<uint8_t>(0x36) },
60 std::vector<uint8_t> bytecode = add_8_instruction.serialize();
62 builder.process_instruction_fetching({ { .bytecode_id = 1,
64 .instruction = add_8_instruction,
70 check_relation<instr_fetching>(
trace);
75TEST(InstrFetchingConstrainingTest, EcaddWithTraceGen)
77 TestTraceContainer
trace;
84 .operands = { Operand::from<uint16_t>(0x1279),
85 Operand::from<uint16_t>(0x127a),
86 Operand::from<uint16_t>(0x127b),
87 Operand::from<uint16_t>(0x127c),
88 Operand::from<uint16_t>(0x127d),
89 Operand::from<uint16_t>(0x127e),
90 Operand::from<uint16_t>(0x127f) },
93 std::vector<uint8_t> bytecode = ecadd_instruction.serialize();
94 builder.process_instruction_fetching({ { .bytecode_id = 1,
96 .instruction = ecadd_instruction,
102 check_relation<instr_fetching>(
trace);
109 std::vector<uint8_t> bytecode;
112 instructions.reserve(num_opcodes);
115 for (
size_t i = 0; i < num_opcodes; i++) {
116 pc_positions.at(i) =
static_cast<uint32_t
>(bytecode.size());
118 instructions.emplace_back(instr);
119 const auto instruction_bytes = instr.serialize();
120 bytecode.insert(bytecode.end(),
129 instr_events.reserve(num_opcodes);
130 for (
size_t i = 0; i < num_opcodes; i++) {
131 instr_events.emplace_back(InstructionFetchingEvent{
132 .bytecode_id = 1, .pc = pc_positions.at(i), .instruction = instructions.at(i), .bytecode = bytecode_ptr });
139TEST(InstrFetchingConstrainingTest, EachOpcodeWithTraceGen)
141 TestTraceContainer
trace;
145 builder.process_instruction_fetching(gen_instr_events_each_opcode(),
trace);
150 check_relation<instr_fetching>(
trace);
156TEST(InstrFetchingConstrainingTest, NegativeWrongOperand)
162 std::vector<size_t> sub_relations = {
170 C::instr_fetching_indirect, C::instr_fetching_op1, C::instr_fetching_op2, C::instr_fetching_op3,
171 C::instr_fetching_op4, C::instr_fetching_op5, C::instr_fetching_op6, C::instr_fetching_op7,
174 for (
const auto& opcode : opcodes) {
175 TestTraceContainer
trace;
177 builder.process_instruction_fetching(
178 { { .bytecode_id = 1,
180 .instruction = instr,
185 check_relation<instr_fetching>(
trace);
189 for (
size_t i = 0; i < operand_cols.size(); i++) {
190 auto mutated_trace =
trace;
191 const FF mutated_operand =
trace.
get(operand_cols.at(i), 0) + 1;
192 mutated_trace.set(operand_cols.at(i), 0, mutated_operand);
202TEST(InstrFetchingConstrainingTest, WireInstructionSpecInteractions)
204 TestTraceContainer
trace;
205 BytecodeTraceBuilder bytecode_builder;
210 bytecode_builder.process_instruction_fetching(gen_instr_events_each_opcode(),
trace);
215 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_wire_instruction_info_settings>(
trace);
216 check_relation<instr_fetching>(
trace);
222 range_check_events.reserve(instr_events.size());
224 for (
const auto& instr_event : instr_events) {
225 range_check_events.emplace_back(RangeCheckEvent{
226 .value = instr_event.error == InstrDeserializationError::PC_OUT_OF_RANGE
227 ? instr_event.pc - instr_event.bytecode->size()
228 : instr_event.bytecode->size() - instr_event.pc - 1,
232 return range_check_events;
237TEST(InstrFetchingConstrainingTest, BcDecompositionInteractions)
239 TestTraceContainer
trace;
240 BytecodeTraceBuilder bytecode_builder;
243 const auto instr_fetch_events = gen_instr_events_each_opcode();
244 bytecode_builder.process_instruction_fetching(instr_fetch_events,
trace);
245 bytecode_builder.process_decomposition({ {
246 .bytecode_id = instr_fetch_events.at(0).bytecode_id,
247 .bytecode = instr_fetch_events.at(0).bytecode,
259 check_relation<instr_fetching>(
trace);
266 TestTraceContainer
trace;
267 BytecodeTraceBuilder bytecode_builder;
275 bytecode_builder.process_instruction_fetching(instr_events,
trace);
290 check_relation<instr_fetching>(
trace);
296 TestTraceContainer
trace;
297 BytecodeTraceBuilder bytecode_builder;
303 bytecode_builder.process_instruction_fetching(instr_events,
trace);
316 check_relation<instr_fetching>(
trace);
322TEST(InstrFetchingConstrainingTest, MultipleBytecodes)
324 const auto instr_fetch_events = gen_instr_events_each_opcode();
325 constexpr size_t num_of_bytecodes = 5;
329 for (
size_t i = 0; i < num_of_bytecodes; i++) {
330 std::vector<uint8_t> bytecode;
331 const auto num_of_instr = i * 6;
333 for (
size_t j = 0; j < num_of_instr; j++) {
334 const auto& instr = instr_fetch_events.at(j).instruction;
335 const auto instruction_bytes = instr.serialize();
336 bytecode.insert(bytecode.end(),
343 for (
size_t j = 0; j < num_of_instr; j++) {
344 auto instr_event = instr_fetch_events.at(j);
345 instr_event.bytecode_id =
static_cast<BytecodeId>(i);
346 instr_event.bytecode = bytecode_ptr;
347 instr_events.emplace_back(instr_event);
352 .bytecode = bytecode_ptr,
362TEST(InstrFetchingConstrainingTest, SingleInstructionOutOfRange)
367 .operands = { Operand::from<uint8_t>(0x34), Operand::from<uint8_t>(0x35), Operand::from<uint8_t>(0x36) },
370 std::vector<uint8_t> bytecode = add_8_instruction.serialize();
378 .bytecode = bytecode_ptr,
379 .error = InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE,
386 .bytecode = bytecode_ptr,
397TEST(InstrFetchingConstrainingTest, SingleInstructionOutOfRangeSplitOperand)
402 .operands = { Operand::from<uint16_t>(0x1279),
404 Operand::from<FF>(FF::modulus_minus_two) },
407 std::vector<uint8_t> bytecode = set_ff_instruction.serialize();
408 bytecode.resize(bytecode.size() - 2);
415 .bytecode = bytecode_ptr,
416 .error = InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE,
423 .bytecode = bytecode_ptr,
431TEST(InstrFetchingConstrainingTest, SingleInstructionPcOutOfRange)
436 .operands = { Operand::from<uint8_t>(0x34), Operand::from<uint8_t>(0x35), Operand::from<uint8_t>(0x36) },
439 std::vector<uint8_t> bytecode = add_8_instruction.serialize();
447 .instruction = add_8_instruction,
448 .bytecode = bytecode_ptr,
452 .pc =
static_cast<uint32_t
>(bytecode_ptr->size() + 1),
453 .bytecode = bytecode_ptr,
454 .error = InstrDeserializationError::PC_OUT_OF_RANGE,
461 .bytecode = bytecode_ptr,
471TEST(InstrFetchingConstrainingTest, SingleInstructionOpcodeOutOfRange)
476 .operands = { Operand::from<uint16_t>(0x1234),
478 Operand::from<uint128_t>(
static_cast<uint128_t>(0xFF) << 120) },
481 std::vector<uint8_t> bytecode = set_128_instruction.serialize();
488 .instruction = set_128_instruction,
489 .bytecode = bytecode_ptr,
494 .bytecode = bytecode_ptr,
495 .error = InstrDeserializationError::OPCODE_OUT_OF_RANGE,
502 .bytecode = bytecode_ptr,
512TEST(InstrFetchingConstrainingTest, SingleInstructionTagOutOfRange)
517 .operands = { Operand::from<uint16_t>(0x1234), Operand::from<uint8_t>(12), Operand::from<uint16_t>(0x5678) },
520 std::vector<uint8_t> bytecode = set_16_instruction.serialize();
527 .instruction = set_16_instruction,
528 .bytecode = bytecode_ptr,
529 .error = InstrDeserializationError::TAG_OUT_OF_RANGE,
536 .bytecode = bytecode_ptr,
544TEST(InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions)
546 BytecodeTraceBuilder bytecode_builder;
553 for (
const auto& opcode : opcodes) {
554 TestTraceContainer
trace;
556 bytecode_builder.process_instruction_fetching(
557 { { .bytecode_id = 1,
559 .instruction = instr,
566 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_wire_instruction_info_settings>(
trace);
568 ASSERT_EQ(
trace.
get(C::lookup_instr_fetching_wire_instruction_info_counts,
static_cast<uint32_t
>(opcode)), 1);
571 C::instr_fetching_exec_opcode, C::instr_fetching_instr_size, C::instr_fetching_sel_has_tag,
572 C::instr_fetching_sel_tag_is_op2, C::instr_fetching_sel_op_dc_0, C::instr_fetching_sel_op_dc_1,
573 C::instr_fetching_sel_op_dc_2, C::instr_fetching_sel_op_dc_3, C::instr_fetching_sel_op_dc_4,
574 C::instr_fetching_sel_op_dc_5, C::instr_fetching_sel_op_dc_6, C::instr_fetching_sel_op_dc_7,
575 C::instr_fetching_sel_op_dc_8, C::instr_fetching_sel_op_dc_9, C::instr_fetching_sel_op_dc_10,
576 C::instr_fetching_sel_op_dc_11, C::instr_fetching_sel_op_dc_12, C::instr_fetching_sel_op_dc_13,
577 C::instr_fetching_sel_op_dc_14, C::instr_fetching_sel_op_dc_15, C::instr_fetching_sel_op_dc_16,
581 for (
const auto& col : mutated_cols) {
582 auto mutated_trace =
trace;
583 const FF mutated_value =
trace.
get(col, 1) + 1;
584 mutated_trace.set(col, 1, mutated_value);
587 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_wire_instruction_info_settings>(
589 "Failed.*LOOKUP_INSTR_FETCHING_WIRE_INSTRUCTION_INFO.*Could not find tuple in destination.");
595TEST(InstrFetchingConstrainingTest, NegativeWrongBcDecompositionInteractions)
597 TestTraceContainer
trace;
598 BytecodeTraceBuilder bytecode_builder;
604 for (
const auto& opcode : opcodes) {
605 TestTraceContainer
trace;
608 bytecode_builder.process_instruction_fetching({ {
611 .instruction = instr,
612 .bytecode = bytecode_ptr,
615 bytecode_builder.process_decomposition({ {
617 .bytecode = bytecode_ptr,
621 auto valid_trace =
trace;
622 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytes_from_bc_dec_settings>(valid_trace);
625 C::instr_fetching_pc, C::instr_fetching_bytecode_id, C::instr_fetching_bd0, C::instr_fetching_bd1,
626 C::instr_fetching_bd2, C::instr_fetching_bd3, C::instr_fetching_bd4, C::instr_fetching_bd5,
627 C::instr_fetching_bd6, C::instr_fetching_bd7, C::instr_fetching_bd8, C::instr_fetching_bd9,
628 C::instr_fetching_bd10, C::instr_fetching_bd11, C::instr_fetching_bd12, C::instr_fetching_bd13,
629 C::instr_fetching_bd14, C::instr_fetching_bd15, C::instr_fetching_bd16, C::instr_fetching_bd17,
630 C::instr_fetching_bd18, C::instr_fetching_bd19, C::instr_fetching_bd20, C::instr_fetching_bd21,
631 C::instr_fetching_bd22, C::instr_fetching_bd23, C::instr_fetching_bd24, C::instr_fetching_bd25,
632 C::instr_fetching_bd26, C::instr_fetching_bd27, C::instr_fetching_bd28, C::instr_fetching_bd29,
633 C::instr_fetching_bd30, C::instr_fetching_bd31, C::instr_fetching_bd32, C::instr_fetching_bd33,
634 C::instr_fetching_bd34, C::instr_fetching_bd35, C::instr_fetching_bd36,
638 for (
const auto& col : mutated_cols) {
639 auto mutated_trace =
trace;
640 const FF mutated_value =
trace.
get(col, 1) + 1;
641 mutated_trace.set(col, 1, mutated_value);
644 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytes_from_bc_dec_settings>(
646 "Failed.*BYTES_FROM_BC_DEC. Could not find tuple in destination.");
653TEST(InstrFetchingConstrainingTest, NegativeWrongBytecodeSizeBcDecompositionInteractions)
655 TestTraceContainer
trace;
656 BytecodeTraceBuilder bytecode_builder;
659 const uint32_t pc = 15;
660 std::vector<uint8_t> bytecode(pc, 0x23);
666 for (
const auto& opcode : opcodes) {
667 TestTraceContainer
trace;
670 const auto instr_bytecode = instr.serialize();
671 bytecode.insert(bytecode.end(),
676 bytecode_builder.process_instruction_fetching({ {
679 .instruction = instr,
680 .bytecode = bytecode_ptr,
683 bytecode_builder.process_decomposition({ {
685 .bytecode = bytecode_ptr,
690 auto valid_trace =
trace;
691 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytecode_size_from_bc_dec_settings>(valid_trace);
693 auto mutated_trace =
trace;
694 const FF mutated_value =
trace.
get(C::instr_fetching_bytecode_size, 1) + 1;
695 mutated_trace.set(C::instr_fetching_bytecode_size, 1, mutated_value);
698 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytecode_size_from_bc_dec_settings>(
700 "Failed.*BYTECODE_SIZE_FROM_BC_DEC. Could not find tuple in destination.");
704TEST(InstrFetchingConstrainingTest, NegativeWrongTagValidationInteractions)
706 TestTraceContainer
trace;
707 BytecodeTraceBuilder bytecode_builder;
714 for (
const auto& opcode : opcodes) {
715 TestTraceContainer
trace;
717 bytecode_builder.process_instruction_fetching(
718 { { .bytecode_id = 1,
720 .instruction = instr,
727 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_tag_value_validation_settings>(
trace);
729 auto valid_trace =
trace;
732 auto mutated_trace =
trace;
733 ASSERT_EQ(
trace.
get(C::instr_fetching_tag_out_of_range, 1), 0);
734 mutated_trace.set(C::instr_fetching_tag_out_of_range, 1, 1);
737 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_tag_value_validation_settings>(
739 "Failed.*LOOKUP_INSTR_FETCHING_TAG_VALUE_VALIDATION.*Could not find tuple in destination.");
744TEST(InstrFetchingConstrainingTest, NegativeNotTogglingInstrOutOfRange)
746 TestTraceContainer
trace({
747 { { C::precomputed_first_row, 1 } },
749 { C::instr_fetching_bytes_to_read, 11 },
750 { C::instr_fetching_instr_abs_diff, 0 },
751 { C::instr_fetching_instr_out_of_range, 1 },
752 { C::instr_fetching_instr_size, 12 },
753 { C::instr_fetching_sel, 1 },
759 trace.
set(C::instr_fetching_instr_out_of_range, 1, 0);
762 "INSTR_OUT_OF_RANGE_TOGGLE");
766TEST(InstrFetchingConstrainingTest, NegativeTogglingInstrInRange)
768 TestTraceContainer
trace({
769 { { C::precomputed_first_row, 1 } },
771 { C::instr_fetching_bytes_to_read, 12 },
772 { C::instr_fetching_instr_abs_diff, 0 },
773 { C::instr_fetching_instr_out_of_range, 0 },
774 { C::instr_fetching_instr_size, 12 },
775 { C::instr_fetching_sel, 1 },
781 trace.
set(C::instr_fetching_instr_out_of_range, 1, 1);
784 "INSTR_OUT_OF_RANGE_TOGGLE");
788TEST(InstrFetchingConstrainingTest, NegativeNotTogglingPcOutOfRange)
790 TestTraceContainer
trace({
791 { { C::precomputed_first_row, 1 } },
793 { C::instr_fetching_bytecode_size, 12 },
794 { C::instr_fetching_pc, 12 },
795 { C::instr_fetching_pc_abs_diff, 0 },
796 { C::instr_fetching_pc_out_of_range, 1 },
797 { C::instr_fetching_sel, 1 },
803 trace.
set(C::instr_fetching_pc_out_of_range, 1, 0);
806 "PC_OUT_OF_RANGE_TOGGLE");
810TEST(InstrFetchingConstrainingTest, NegativeTogglingPcInRange)
812 TestTraceContainer
trace({
813 { { C::precomputed_first_row, 1 } },
815 { C::instr_fetching_bytecode_size, 12 },
816 { C::instr_fetching_pc, 11 },
817 { C::instr_fetching_pc_abs_diff, 0 },
818 { C::instr_fetching_pc_out_of_range, 0 },
819 { C::instr_fetching_sel, 1 },
825 trace.
set(C::instr_fetching_pc_out_of_range, 1, 1);
828 "PC_OUT_OF_RANGE_TOGGLE");
#define AVM_PC_SIZE_IN_BITS
EventEmitter< BytecodeDecompositionEvent > decomposition_events
static constexpr size_t SR_OP1_BYTES_DECOMPOSITION
static constexpr size_t SR_OP3_BYTES_DECOMPOSITION
static constexpr size_t SR_INDIRECT_BYTES_DECOMPOSITION
static constexpr size_t SR_OP6_BYTES_DECOMPOSITION
static constexpr size_t SR_OP4_BYTES_DECOMPOSITION
static constexpr size_t SR_INSTR_OUT_OF_RANGE_TOGGLE
static std::string get_subrelation_label(size_t index)
static constexpr size_t SR_OP7_BYTES_DECOMPOSITION
static constexpr size_t SR_OP5_BYTES_DECOMPOSITION
static constexpr size_t SR_PC_OUT_OF_RANGE_TOGGLE
static constexpr size_t SR_OP2_BYTES_DECOMPOSITION
void process_wire_instruction_spec(TraceContainer &trace)
void process_memory_tag_range(TraceContainer &trace)
void process_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
void process_sel_range_16(TraceContainer &trace)
void process_sel_range_8(TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::RangeCheckEvent >::Container &events, 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)
RangeCheckTraceBuilder range_check_builder
PrecomputedTraceBuilder precomputed_builder
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(TxExecutionConstrainingTest, WriteTreeValue)
InstrDeserializationError
Instruction random_instruction(WireOpCode w_opcode)
TestTraceContainer empty_trace()
lookup_settings< lookup_instr_fetching_wire_instruction_info_settings_ > lookup_instr_fetching_wire_instruction_info_settings
lookup_settings< lookup_instr_fetching_bytecode_size_from_bc_dec_settings_ > lookup_instr_fetching_bytecode_size_from_bc_dec_settings
lookup_settings< lookup_instr_fetching_bytes_from_bc_dec_settings_ > lookup_instr_fetching_bytes_from_bc_dec_settings
lookup_settings< lookup_instr_fetching_instr_abs_diff_positive_settings_ > lookup_instr_fetching_instr_abs_diff_positive_settings
lookup_settings< lookup_instr_fetching_pc_abs_diff_positive_settings_ > lookup_instr_fetching_pc_abs_diff_positive_settings
lookup_settings< lookup_instr_fetching_tag_value_validation_settings_ > lookup_instr_fetching_tag_value_validation_settings
Instruction
Enumeration of VM instructions that can be executed.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
unsigned __int128 uint128_t