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;
38using simulation::Instruction;
39using simulation::InstructionFetchingEvent;
41using simulation::RangeCheckEvent;
43TEST(InstrFetchingConstrainingTest, EmptyRow)
49TEST(InstrFetchingConstrainingTest, Add8WithTraceGen)
51 TestTraceContainer
trace;
58 .operands = { Operand::from<uint8_t>(0x34), Operand::from<uint8_t>(0x35), Operand::from<uint8_t>(0x36) },
61 std::vector<uint8_t> bytecode = add_8_instruction.serialize();
63 builder.process_instruction_fetching({ { .bytecode_id = 1,
65 .instruction = add_8_instruction,
71 check_relation<instr_fetching>(
trace);
76TEST(InstrFetchingConstrainingTest, EcaddWithTraceGen)
78 TestTraceContainer
trace;
85 .operands = { Operand::from<uint16_t>(0x1279),
86 Operand::from<uint16_t>(0x127a),
87 Operand::from<uint16_t>(0x127b),
88 Operand::from<uint16_t>(0x127c),
89 Operand::from<uint16_t>(0x127d),
90 Operand::from<uint16_t>(0x127e),
91 Operand::from<uint16_t>(0x127f) },
94 std::vector<uint8_t> bytecode = ecadd_instruction.serialize();
95 builder.process_instruction_fetching({ { .bytecode_id = 1,
97 .instruction = ecadd_instruction,
103 check_relation<instr_fetching>(
trace);
110 std::vector<uint8_t> bytecode;
113 instructions.reserve(num_opcodes);
116 for (
size_t i = 0; i < num_opcodes; i++) {
117 pc_positions.at(i) =
static_cast<uint32_t
>(bytecode.size());
119 instructions.emplace_back(instr);
120 const auto instruction_bytes = instr.serialize();
121 bytecode.insert(bytecode.end(),
130 instr_events.reserve(num_opcodes);
131 for (
size_t i = 0; i < num_opcodes; i++) {
132 instr_events.emplace_back(InstructionFetchingEvent{
133 .bytecode_id = 1, .pc = pc_positions.at(i), .instruction = instructions.at(i), .bytecode = bytecode_ptr });
140TEST(InstrFetchingConstrainingTest, EachOpcodeWithTraceGen)
142 TestTraceContainer
trace;
146 builder.process_instruction_fetching(gen_instr_events_each_opcode(),
trace);
151 check_relation<instr_fetching>(
trace);
157TEST(InstrFetchingConstrainingTest, NegativeWrongOperand)
163 std::vector<size_t> sub_relations = {
171 C::instr_fetching_indirect, C::instr_fetching_op1, C::instr_fetching_op2, C::instr_fetching_op3,
172 C::instr_fetching_op4, C::instr_fetching_op5, C::instr_fetching_op6, C::instr_fetching_op7,
175 for (
const auto& opcode : opcodes) {
176 TestTraceContainer
trace;
178 builder.process_instruction_fetching(
179 { { .bytecode_id = 1,
181 .instruction = instr,
186 check_relation<instr_fetching>(
trace);
190 for (
size_t i = 0; i < operand_cols.size(); i++) {
191 auto mutated_trace =
trace;
192 const FF mutated_operand =
trace.
get(operand_cols.at(i), 0) + 1;
193 mutated_trace.set(operand_cols.at(i), 0, mutated_operand);
203TEST(InstrFetchingConstrainingTest, WireInstructionSpecInteractions)
205 TestTraceContainer
trace;
206 BytecodeTraceBuilder bytecode_builder;
211 bytecode_builder.process_instruction_fetching(gen_instr_events_each_opcode(),
trace);
216 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_wire_instruction_info_settings>(
trace);
217 check_relation<instr_fetching>(
trace);
223 range_check_events.reserve(instr_events.size());
225 for (
const auto& instr_event : instr_events) {
226 range_check_events.emplace_back(RangeCheckEvent{
227 .value = instr_event.error == InstrDeserializationError::PC_OUT_OF_RANGE
228 ? instr_event.pc - instr_event.bytecode->size()
229 : instr_event.bytecode->size() - instr_event.pc - 1,
233 return range_check_events;
238TEST(InstrFetchingConstrainingTest, BcDecompositionInteractions)
240 TestTraceContainer
trace;
241 BytecodeTraceBuilder bytecode_builder;
244 const auto instr_fetch_events = gen_instr_events_each_opcode();
245 bytecode_builder.process_instruction_fetching(instr_fetch_events,
trace);
246 bytecode_builder.process_decomposition({ {
247 .bytecode_id = instr_fetch_events.at(0).bytecode_id,
248 .bytecode = instr_fetch_events.at(0).bytecode,
260 check_relation<instr_fetching>(
trace);
267 TestTraceContainer
trace;
268 BytecodeTraceBuilder bytecode_builder;
276 bytecode_builder.process_instruction_fetching(instr_events,
trace);
291 check_relation<instr_fetching>(
trace);
297 TestTraceContainer
trace;
298 BytecodeTraceBuilder bytecode_builder;
304 bytecode_builder.process_instruction_fetching(instr_events,
trace);
317 check_relation<instr_fetching>(
trace);
323TEST(InstrFetchingConstrainingTest, MultipleBytecodes)
325 const auto instr_fetch_events = gen_instr_events_each_opcode();
326 constexpr size_t num_of_bytecodes = 5;
330 for (
size_t i = 0; i < num_of_bytecodes; i++) {
331 std::vector<uint8_t> bytecode;
332 const auto num_of_instr = i * 6;
334 for (
size_t j = 0; j < num_of_instr; j++) {
335 const auto& instr = instr_fetch_events.at(j).instruction;
336 const auto instruction_bytes = instr.serialize();
337 bytecode.insert(bytecode.end(),
344 for (
size_t j = 0; j < num_of_instr; j++) {
345 auto instr_event = instr_fetch_events.at(j);
346 instr_event.bytecode_id =
static_cast<BytecodeId>(i);
347 instr_event.bytecode = bytecode_ptr;
348 instr_events.emplace_back(instr_event);
353 .bytecode = bytecode_ptr,
363TEST(InstrFetchingConstrainingTest, SingleInstructionOutOfRange)
368 .operands = { Operand::from<uint8_t>(0x34), Operand::from<uint8_t>(0x35), Operand::from<uint8_t>(0x36) },
371 std::vector<uint8_t> bytecode = add_8_instruction.serialize();
379 .bytecode = bytecode_ptr,
380 .error = InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE,
387 .bytecode = bytecode_ptr,
398TEST(InstrFetchingConstrainingTest, SingleInstructionOutOfRangeSplitOperand)
403 .operands = { Operand::from<uint16_t>(0x1279),
405 Operand::from<FF>(FF::modulus_minus_two) },
408 std::vector<uint8_t> bytecode = set_ff_instruction.serialize();
409 bytecode.resize(bytecode.size() - 2);
416 .bytecode = bytecode_ptr,
417 .error = InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE,
424 .bytecode = bytecode_ptr,
432TEST(InstrFetchingConstrainingTest, SingleInstructionPcOutOfRange)
437 .operands = { Operand::from<uint8_t>(0x34), Operand::from<uint8_t>(0x35), Operand::from<uint8_t>(0x36) },
440 std::vector<uint8_t> bytecode = add_8_instruction.serialize();
448 .instruction = add_8_instruction,
449 .bytecode = bytecode_ptr,
453 .pc =
static_cast<uint32_t
>(bytecode_ptr->size() + 1),
454 .bytecode = bytecode_ptr,
455 .error = InstrDeserializationError::PC_OUT_OF_RANGE,
462 .bytecode = bytecode_ptr,
472TEST(InstrFetchingConstrainingTest, SingleInstructionOpcodeOutOfRange)
477 .operands = { Operand::from<uint16_t>(0x1234),
479 Operand::from<uint128_t>(
static_cast<uint128_t>(0xFF) << 120) },
482 std::vector<uint8_t> bytecode = set_128_instruction.serialize();
489 .instruction = set_128_instruction,
490 .bytecode = bytecode_ptr,
495 .bytecode = bytecode_ptr,
496 .error = InstrDeserializationError::OPCODE_OUT_OF_RANGE,
503 .bytecode = bytecode_ptr,
513TEST(InstrFetchingConstrainingTest, SingleInstructionTagOutOfRange)
518 .operands = { Operand::from<uint16_t>(0x1234), Operand::from<uint8_t>(12), Operand::from<uint16_t>(0x5678) },
521 std::vector<uint8_t> bytecode = set_16_instruction.serialize();
528 .instruction = set_16_instruction,
529 .bytecode = bytecode_ptr,
530 .error = InstrDeserializationError::TAG_OUT_OF_RANGE,
537 .bytecode = bytecode_ptr,
545TEST(InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions)
547 BytecodeTraceBuilder bytecode_builder;
554 for (
const auto& opcode : opcodes) {
555 TestTraceContainer
trace;
557 bytecode_builder.process_instruction_fetching(
558 { { .bytecode_id = 1,
560 .instruction = instr,
567 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_wire_instruction_info_settings>(
trace);
569 ASSERT_EQ(
trace.
get(C::lookup_instr_fetching_wire_instruction_info_counts,
static_cast<uint32_t
>(opcode)), 1);
572 C::instr_fetching_exec_opcode, C::instr_fetching_instr_size, C::instr_fetching_sel_has_tag,
573 C::instr_fetching_sel_tag_is_op2, C::instr_fetching_sel_op_dc_0, C::instr_fetching_sel_op_dc_1,
574 C::instr_fetching_sel_op_dc_2, C::instr_fetching_sel_op_dc_3, C::instr_fetching_sel_op_dc_4,
575 C::instr_fetching_sel_op_dc_5, C::instr_fetching_sel_op_dc_6, C::instr_fetching_sel_op_dc_7,
576 C::instr_fetching_sel_op_dc_8, C::instr_fetching_sel_op_dc_9, C::instr_fetching_sel_op_dc_10,
577 C::instr_fetching_sel_op_dc_11, C::instr_fetching_sel_op_dc_12, C::instr_fetching_sel_op_dc_13,
578 C::instr_fetching_sel_op_dc_14, C::instr_fetching_sel_op_dc_15, C::instr_fetching_sel_op_dc_16,
582 for (
const auto& col : mutated_cols) {
583 auto mutated_trace =
trace;
584 const FF mutated_value =
trace.
get(col, 1) + 1;
585 mutated_trace.set(col, 1, mutated_value);
588 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_wire_instruction_info_settings>(
590 "Failed.*LOOKUP_INSTR_FETCHING_WIRE_INSTRUCTION_INFO.*Could not find tuple in destination.");
596TEST(InstrFetchingConstrainingTest, NegativeWrongBcDecompositionInteractions)
598 TestTraceContainer
trace;
599 BytecodeTraceBuilder bytecode_builder;
605 for (
const auto& opcode : opcodes) {
606 TestTraceContainer
trace;
609 bytecode_builder.process_instruction_fetching({ {
612 .instruction = instr,
613 .bytecode = bytecode_ptr,
616 bytecode_builder.process_decomposition({ {
618 .bytecode = bytecode_ptr,
622 auto valid_trace =
trace;
623 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytes_from_bc_dec_settings>(valid_trace);
626 C::instr_fetching_pc, C::instr_fetching_bytecode_id, C::instr_fetching_bd0, C::instr_fetching_bd1,
627 C::instr_fetching_bd2, C::instr_fetching_bd3, C::instr_fetching_bd4, C::instr_fetching_bd5,
628 C::instr_fetching_bd6, C::instr_fetching_bd7, C::instr_fetching_bd8, C::instr_fetching_bd9,
629 C::instr_fetching_bd10, C::instr_fetching_bd11, C::instr_fetching_bd12, C::instr_fetching_bd13,
630 C::instr_fetching_bd14, C::instr_fetching_bd15, C::instr_fetching_bd16, C::instr_fetching_bd17,
631 C::instr_fetching_bd18, C::instr_fetching_bd19, C::instr_fetching_bd20, C::instr_fetching_bd21,
632 C::instr_fetching_bd22, C::instr_fetching_bd23, C::instr_fetching_bd24, C::instr_fetching_bd25,
633 C::instr_fetching_bd26, C::instr_fetching_bd27, C::instr_fetching_bd28, C::instr_fetching_bd29,
634 C::instr_fetching_bd30, C::instr_fetching_bd31, C::instr_fetching_bd32, C::instr_fetching_bd33,
635 C::instr_fetching_bd34, C::instr_fetching_bd35, C::instr_fetching_bd36,
639 for (
const auto& col : mutated_cols) {
640 auto mutated_trace =
trace;
641 const FF mutated_value =
trace.
get(col, 1) + 1;
642 mutated_trace.set(col, 1, mutated_value);
647 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytes_from_bc_dec_settings>(
649 "Failed.*BYTES_FROM_BC_DEC. Could not find tuple in destination.");
656TEST(InstrFetchingConstrainingTest, NegativeWrongBytecodeSizeBcDecompositionInteractions)
658 TestTraceContainer
trace;
659 BytecodeTraceBuilder bytecode_builder;
662 const uint32_t pc = 15;
663 std::vector<uint8_t> bytecode(pc, 0x23);
669 for (
const auto& opcode : opcodes) {
670 TestTraceContainer
trace;
673 const auto instr_bytecode = instr.serialize();
674 bytecode.insert(bytecode.end(),
679 bytecode_builder.process_instruction_fetching({ {
682 .instruction = instr,
683 .bytecode = bytecode_ptr,
686 bytecode_builder.process_decomposition({ {
688 .bytecode = bytecode_ptr,
693 auto valid_trace =
trace;
694 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytecode_size_from_bc_dec_settings>(valid_trace);
696 auto mutated_trace =
trace;
697 const FF mutated_value =
trace.
get(C::instr_fetching_bytecode_size, 1) + 1;
698 mutated_trace.set(C::instr_fetching_bytecode_size, 1, mutated_value);
703 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytecode_size_from_bc_dec_settings>(
705 "Failed.*BYTECODE_SIZE_FROM_BC_DEC. Could not find tuple in destination.");
709TEST(InstrFetchingConstrainingTest, NegativeWrongTagValidationInteractions)
711 TestTraceContainer
trace;
712 BytecodeTraceBuilder bytecode_builder;
719 for (
const auto& opcode : opcodes) {
720 TestTraceContainer
trace;
722 bytecode_builder.process_instruction_fetching(
723 { { .bytecode_id = 1,
725 .instruction = instr,
732 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_tag_value_validation_settings>(
trace);
734 auto valid_trace =
trace;
737 auto mutated_trace =
trace;
738 ASSERT_EQ(
trace.
get(C::instr_fetching_tag_out_of_range, 1), 0);
739 mutated_trace.set(C::instr_fetching_tag_out_of_range, 1, 1);
742 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_tag_value_validation_settings>(
744 "Failed.*LOOKUP_INSTR_FETCHING_TAG_VALUE_VALIDATION.*Could not find tuple in destination.");
749TEST(InstrFetchingConstrainingTest, NegativeNotTogglingInstrOutOfRange)
752 { .precomputed_first_row = 1 },
754 .instr_fetching_bytes_to_read = 11,
755 .instr_fetching_instr_abs_diff = 0,
756 .instr_fetching_instr_out_of_range = 1,
757 .instr_fetching_instr_size = 12,
758 .instr_fetching_sel = 1,
764 trace.
set(C::instr_fetching_instr_out_of_range, 1, 0);
767 "INSTR_OUT_OF_RANGE_TOGGLE");
771TEST(InstrFetchingConstrainingTest, NegativeTogglingInstrInRange)
774 { .precomputed_first_row = 1 },
776 .instr_fetching_bytes_to_read = 12,
777 .instr_fetching_instr_abs_diff = 0,
778 .instr_fetching_instr_out_of_range = 0,
779 .instr_fetching_instr_size = 12,
780 .instr_fetching_sel = 1,
786 trace.
set(C::instr_fetching_instr_out_of_range, 1, 1);
789 "INSTR_OUT_OF_RANGE_TOGGLE");
793TEST(InstrFetchingConstrainingTest, NegativeNotTogglingPcOutOfRange)
796 { .precomputed_first_row = 1 },
798 .instr_fetching_bytecode_size = 12,
799 .instr_fetching_pc = 12,
800 .instr_fetching_pc_abs_diff = 0,
801 .instr_fetching_pc_out_of_range = 1,
802 .instr_fetching_sel = 1,
808 trace.
set(C::instr_fetching_pc_out_of_range, 1, 0);
811 "PC_OUT_OF_RANGE_TOGGLE");
815TEST(InstrFetchingConstrainingTest, NegativeTogglingPcInRange)
818 { .precomputed_first_row = 1 },
820 .instr_fetching_bytecode_size = 12,
821 .instr_fetching_pc = 11,
822 .instr_fetching_pc_abs_diff = 0,
823 .instr_fetching_pc_out_of_range = 0,
824 .instr_fetching_sel = 1,
830 trace.
set(C::instr_fetching_pc_out_of_range, 1, 1);
833 "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
static TestTraceContainer from_rows(const std::vector< AvmFullRow > &rows)
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