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);
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();
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{
227 (instr_event.error.has_value() && instr_event.error == InstrDeserializationEventError::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++) {
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();
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);
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 = InstrDeserializationEventError::INSTRUCTION_OUT_OF_RANGE,
387 .bytecode = bytecode_ptr,
398TEST(InstrFetchingConstrainingTest, SingleInstructionOutOfRangeSplitOperand)
403 .operands = { Operand::from<uint16_t>(0x1279),
408 std::vector<uint8_t>
bytecode = set_ff_instruction.serialize();
416 .bytecode = bytecode_ptr,
417 .error = InstrDeserializationEventError::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),
455 .error = InstrDeserializationEventError::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 = InstrDeserializationEventError::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 = InstrDeserializationEventError::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);
645 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytes_from_bc_dec_settings>(
647 "Failed.*BYTES_FROM_BC_DEC. Could not find tuple in destination.");
654TEST(InstrFetchingConstrainingTest, NegativeWrongBytecodeSizeBcDecompositionInteractions)
656 TestTraceContainer
trace;
657 BytecodeTraceBuilder bytecode_builder;
660 const uint32_t pc = 15;
661 std::vector<uint8_t>
bytecode(pc, 0x23);
667 for (
const auto& opcode : opcodes) {
668 TestTraceContainer
trace;
671 const auto instr_bytecode = instr.serialize();
677 bytecode_builder.process_instruction_fetching({ {
680 .instruction = instr,
681 .bytecode = bytecode_ptr,
684 bytecode_builder.process_decomposition({ {
686 .bytecode = bytecode_ptr,
691 auto valid_trace =
trace;
692 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytecode_size_from_bc_dec_settings>(valid_trace);
694 auto mutated_trace =
trace;
695 const FF mutated_value =
trace.
get(C::instr_fetching_bytecode_size, 1) + 1;
696 mutated_trace.set(C::instr_fetching_bytecode_size, 1, mutated_value);
699 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_bytecode_size_from_bc_dec_settings>(
701 "Failed.*BYTECODE_SIZE_FROM_BC_DEC. Could not find tuple in destination.");
705TEST(InstrFetchingConstrainingTest, NegativeWrongTagValidationInteractions)
707 TestTraceContainer
trace;
708 BytecodeTraceBuilder bytecode_builder;
715 for (
const auto& opcode : opcodes) {
716 TestTraceContainer
trace;
718 bytecode_builder.process_instruction_fetching(
719 { { .bytecode_id = 1,
721 .instruction = instr,
728 check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_tag_value_validation_settings>(trace);
730 auto valid_trace =
trace;
733 auto mutated_trace =
trace;
734 ASSERT_EQ(
trace.
get(C::instr_fetching_tag_out_of_range, 1), 0);
735 mutated_trace.set(C::instr_fetching_tag_out_of_range, 1, 1);
738 (check_interaction<BytecodeTraceBuilder, lookup_instr_fetching_tag_value_validation_settings>(
740 "Failed.*LOOKUP_INSTR_FETCHING_TAG_VALUE_VALIDATION.*Could not find tuple in destination.");
745TEST(InstrFetchingConstrainingTest, NegativeNotTogglingInstrOutOfRange)
747 TestTraceContainer
trace({
748 { { C::precomputed_first_row, 1 } },
750 { C::instr_fetching_bytes_to_read, 11 },
751 { C::instr_fetching_instr_abs_diff, 0 },
752 { C::instr_fetching_instr_out_of_range, 1 },
753 { C::instr_fetching_instr_size, 12 },
754 { C::instr_fetching_sel, 1 },
760 trace.
set(C::instr_fetching_instr_out_of_range, 1, 0);
763 "INSTR_OUT_OF_RANGE_TOGGLE");
767TEST(InstrFetchingConstrainingTest, NegativeTogglingInstrInRange)
769 TestTraceContainer
trace({
770 { { C::precomputed_first_row, 1 } },
772 { C::instr_fetching_bytes_to_read, 12 },
773 { C::instr_fetching_instr_abs_diff, 0 },
774 { C::instr_fetching_instr_out_of_range, 0 },
775 { C::instr_fetching_instr_size, 12 },
776 { C::instr_fetching_sel, 1 },
782 trace.
set(C::instr_fetching_instr_out_of_range, 1, 1);
785 "INSTR_OUT_OF_RANGE_TOGGLE");
789TEST(InstrFetchingConstrainingTest, NegativeNotTogglingPcOutOfRange)
791 TestTraceContainer
trace({
792 { { C::precomputed_first_row, 1 } },
794 { C::instr_fetching_bytecode_size, 12 },
795 { C::instr_fetching_pc, 12 },
796 { C::instr_fetching_pc_abs_diff, 0 },
797 { C::instr_fetching_pc_out_of_range, 1 },
798 { C::instr_fetching_sel, 1 },
804 trace.
set(C::instr_fetching_pc_out_of_range, 1, 0);
807 "PC_OUT_OF_RANGE_TOGGLE");
811TEST(InstrFetchingConstrainingTest, NegativeTogglingPcInRange)
813 TestTraceContainer
trace({
814 { { C::precomputed_first_row, 1 } },
816 { C::instr_fetching_bytecode_size, 12 },
817 { C::instr_fetching_pc, 11 },
818 { C::instr_fetching_pc_abs_diff, 0 },
819 { C::instr_fetching_pc_out_of_range, 0 },
820 { C::instr_fetching_sel, 1 },
826 trace.
set(C::instr_fetching_pc_out_of_range, 1, 1);
829 "PC_OUT_OF_RANGE_TOGGLE");
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
#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)
InstrDeserializationEventError
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
static constexpr uint256_t modulus_minus_two