@@ -22,6 +22,7 @@ namespace bb::avm2::constraining {
22
22
namespace {
23
23
24
24
using tracegen::BytecodeTraceBuilder;
25
+ using tracegen::PrecomputedTraceBuilder;
25
26
using tracegen::TestTraceContainer;
26
27
using FF = AvmFlavorSettings::FF;
27
28
using C = Column;
@@ -138,7 +139,6 @@ TEST(InstrFetchingConstrainingTest, EachOpcodeWithTraceGen)
138
139
// We perform this for a random instruction for opcodes: REVERT_16, CAST_8, TORADIXBE
139
140
TEST (InstrFetchingConstrainingTest, NegativeWrongOperand)
140
141
{
141
- TestTraceContainer trace;
142
142
BytecodeTraceBuilder builder;
143
143
144
144
std::vector<WireOpCode> opcodes = { WireOpCode::REVERT_16, WireOpCode::CAST_8, WireOpCode::TORADIXBE };
@@ -155,6 +155,7 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongOperand)
155
155
};
156
156
157
157
for (const auto & opcode : opcodes) {
158
+ TestTraceContainer trace;
158
159
const auto instr = testing::random_instruction (opcode);
159
160
builder.process_instruction_fetching ({ simulation::InstructionFetchingEvent{
160
161
.bytecode_id = 1 ,
@@ -186,7 +187,7 @@ TEST(InstrFetchingConstrainingTest, WireInstructionSpecInteractions)
186
187
TestTraceContainer trace;
187
188
BytecodeTraceBuilder bytecode_builder;
188
189
189
- tracegen:: PrecomputedTraceBuilder precomputed_builder;
190
+ PrecomputedTraceBuilder precomputed_builder;
190
191
precomputed_builder.process_wire_instruction_spec (trace);
191
192
bytecode_builder.process_instruction_fetching (gen_instr_events_each_opcode (), trace);
192
193
precomputed_builder.process_misc (trace, trace.get_num_rows ()); // Limit to the number of rows we need.
@@ -221,5 +222,110 @@ TEST(InstrFetchingConstrainingTest, BcDecompositionInteractions)
221
222
check_interaction<bc_decomposition_lookup>(trace);
222
223
}
223
224
225
+ // Negative interaction test with some values not matching the instruction spec table.
226
+ TEST (InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions)
227
+ {
228
+ using wire_instr_spec_lookup = lookup_instr_fetching_wire_instruction_info_relation<FF>;
229
+
230
+ BytecodeTraceBuilder bytecode_builder;
231
+ PrecomputedTraceBuilder precomputed_builder;
232
+
233
+ // Some arbitrary chosen opcodes. We limit to one as this unit test is costly.
234
+ // Test works if the following vector is extended to other opcodes though.
235
+ std::vector<WireOpCode> opcodes = { WireOpCode::CALLDATACOPY };
236
+
237
+ for (const auto & opcode : opcodes) {
238
+ TestTraceContainer trace;
239
+ const auto instr = testing::random_instruction (opcode);
240
+ bytecode_builder.process_instruction_fetching (
241
+ { simulation::InstructionFetchingEvent{ .bytecode_id = 1 ,
242
+ .pc = 0 ,
243
+ .instruction = instr,
244
+ .bytecode =
245
+ std::make_shared<std::vector<uint8_t >>(instr.encode ()) } },
246
+ trace);
247
+ precomputed_builder.process_wire_instruction_spec (trace);
248
+ precomputed_builder.process_misc (trace, trace.get_num_rows ()); // Limit to the number of rows we need.
249
+
250
+ tracegen::LookupIntoIndexedByClk<wire_instr_spec_lookup::Settings>().process (trace);
251
+ check_interaction<wire_instr_spec_lookup>(trace);
252
+
253
+ const std::vector<C> mutated_cols = {
254
+ C::instr_fetching_exec_opcode, C::instr_fetching_instr_size_in_bytes, C::instr_fetching_sel_op_dc_0,
255
+ C::instr_fetching_sel_op_dc_1, C::instr_fetching_sel_op_dc_2, C::instr_fetching_sel_op_dc_3,
256
+ C::instr_fetching_sel_op_dc_4, C::instr_fetching_sel_op_dc_5, C::instr_fetching_sel_op_dc_6,
257
+ C::instr_fetching_sel_op_dc_7, C::instr_fetching_sel_op_dc_8, C::instr_fetching_sel_op_dc_9,
258
+ C::instr_fetching_sel_op_dc_10, C::instr_fetching_sel_op_dc_11, C::instr_fetching_sel_op_dc_12,
259
+ C::instr_fetching_sel_op_dc_13, C::instr_fetching_sel_op_dc_14, C::instr_fetching_sel_op_dc_15,
260
+ C::instr_fetching_sel_op_dc_16, C::instr_fetching_sel_op_dc_17,
261
+ };
262
+
263
+ // Mutate execution opcode
264
+ for (const auto & col : mutated_cols) {
265
+ auto mutated_trace = trace;
266
+ const FF mutated_value = trace.get (col, 0 ) + 1 ; // Mutate to value + 1
267
+ mutated_trace.set (col, 0 , mutated_value);
268
+ EXPECT_THROW_WITH_MESSAGE (check_interaction<wire_instr_spec_lookup>(mutated_trace),
269
+ " Relation.*WIRE_INSTRUCTION_INFO.* ACCUMULATION.* is non-zero" );
270
+ }
271
+ }
272
+ }
273
+
274
+ // Negative interaction test with some values not matching the bytecode decomposition table.
275
+ TEST (InstrFetchingConstrainingTest, NegativeWrongBcDecompositionInteractions)
276
+ {
277
+ using bc_decomposition_lookup = lookup_instr_fetching_bytes_from_bc_dec_relation<FF>;
278
+
279
+ TestTraceContainer trace;
280
+ BytecodeTraceBuilder bytecode_builder;
281
+
282
+ // Some arbitrary chosen opcodes. We limit to one as this unit test is costly.
283
+ // Test works if the following vector is extended to other opcodes though.
284
+ std::vector<WireOpCode> opcodes = { WireOpCode::STATICCALL };
285
+
286
+ for (const auto & opcode : opcodes) {
287
+ TestTraceContainer trace;
288
+ const auto instr = testing::random_instruction (opcode);
289
+ auto bytecode_ptr = std::make_shared<std::vector<uint8_t >>(instr.encode ());
290
+ bytecode_builder.process_instruction_fetching ({ simulation::InstructionFetchingEvent{
291
+ .bytecode_id = 1 ,
292
+ .pc = 0 ,
293
+ .instruction = instr,
294
+ .bytecode = bytecode_ptr,
295
+ } },
296
+ trace);
297
+ bytecode_builder.process_decomposition ({ simulation::BytecodeDecompositionEvent{
298
+ .bytecode_id = 1 ,
299
+ .bytecode = bytecode_ptr,
300
+ } },
301
+ trace);
302
+
303
+ tracegen::LookupIntoDynamicTableSequential<bc_decomposition_lookup::Settings>().process (trace);
304
+ check_interaction<bc_decomposition_lookup>(trace);
305
+
306
+ const std::vector<C> mutated_cols = {
307
+ C::instr_fetching_pc, C::instr_fetching_bytecode_id, C::instr_fetching_bd0, C::instr_fetching_bd1,
308
+ C::instr_fetching_bd2, C::instr_fetching_bd3, C::instr_fetching_bd4, C::instr_fetching_bd5,
309
+ C::instr_fetching_bd6, C::instr_fetching_bd7, C::instr_fetching_bd8, C::instr_fetching_bd9,
310
+ C::instr_fetching_bd10, C::instr_fetching_bd11, C::instr_fetching_bd12, C::instr_fetching_bd13,
311
+ C::instr_fetching_bd14, C::instr_fetching_bd15, C::instr_fetching_bd16, C::instr_fetching_bd17,
312
+ C::instr_fetching_bd18, C::instr_fetching_bd19, C::instr_fetching_bd20, C::instr_fetching_bd21,
313
+ C::instr_fetching_bd22, C::instr_fetching_bd23, C::instr_fetching_bd24, C::instr_fetching_bd25,
314
+ C::instr_fetching_bd26, C::instr_fetching_bd27, C::instr_fetching_bd28, C::instr_fetching_bd29,
315
+ C::instr_fetching_bd30, C::instr_fetching_bd31, C::instr_fetching_bd32, C::instr_fetching_bd33,
316
+ C::instr_fetching_bd34, C::instr_fetching_bd35, C::instr_fetching_bd36,
317
+ };
318
+
319
+ // Mutate execution opcode
320
+ for (const auto & col : mutated_cols) {
321
+ auto mutated_trace = trace;
322
+ const FF mutated_value = trace.get (col, 0 ) + 1 ; // Mutate to value + 1
323
+ mutated_trace.set (col, 0 , mutated_value);
324
+ EXPECT_THROW_WITH_MESSAGE (check_interaction<bc_decomposition_lookup>(mutated_trace),
325
+ " Relation.*BYTES_FROM_BC_DEC.* ACCUMULATION.* is non-zero" );
326
+ }
327
+ }
328
+ }
329
+
224
330
} // namespace
225
331
} // namespace bb::avm2::constraining
0 commit comments