diff --git a/barretenberg/cpp/pil/vm2/instr_fetching.pil b/barretenberg/cpp/pil/vm2/instr_fetching.pil index 800de09031f8..0d019a90e44c 100644 --- a/barretenberg/cpp/pil/vm2/instr_fetching.pil +++ b/barretenberg/cpp/pil/vm2/instr_fetching.pil @@ -2,18 +2,63 @@ include "bc_decomposition.pil"; include "range_check.pil"; include "constants_gen.pil"; +// Explanations +// ***************************************************************************** +// The role of this subtrace is to fetch an instruction from the bytecode at a +// position specified by pc. This subtrace copies the relevant bytecode portion +// from subtrace specified in bc_decomposition.pil. +// Note that instruction fetching will only be performed for the instructions +// which are executed by the execution trace and only once, i.e., even if +// the AVM executes several times a given instruction, the current sub-trace +// will only produce one row per static instruction. +// The main work performed by the current sub-trace consists in transforming +// bytes into the operands of the corresponding instruction. This part is +// expressed by the relations #[INDIRECT_BYTES_DECOMPOSITION] and +// #[OPXXX_BYTES_DECOMPOSITION]. They encode each operand based on relevant bytes +// of the relative position to PC depending on each opcode. Each wire opcode has +// a static specification in precomputed.pil (see WIRE INSTRUCTION SPEC table) +// corresponding to the operand decomposition (sel_op_dc_XXX). +// All the other relations deal with error handling (except lookups/interactions). +// We handle 4 possible different errors and consolidate into a single one: parsing_err. +// Only parsing_err is propagated to the execution trace. +// List of errors: +// 1) pc_out_of_range: pc is out-of-range if pc >= bytecode_size. +// - bytecode_size is retrieved from bc_decomposition.pil at pc == 0. +// 2) opcode_out_of_range: +// - opcode is out-of-range if the byte at pc is not a valid wire opcode. +// - this information is retrieved from precomputed.pil. +// 3) instr_out_of_range: remaing bytes in bytecode are less than instruction size. +// - instruction size (in bytes) is retrieved from precomputed.pil. +// - bytes_to_read (remaining bytes in bytecode) is retrieved from bc_decomposition.pil. +// 4) tag_out_of_range: +// - tag is out-of-range if a tag operand is not a valid memory tag. +// - this information is retrieved from precomputed.pil. +// +// There is a hierarchy among these errors, in the sense that if any of them is encountered +// the next ones are irrelevant. If pc is out of range, there is no instruction to consider. +// If the opcode is invalid, we cannot consider any instruction. If the instruction is not +// complete then there is no point to validate tag operands. +// Thus, our witness generation will never toggle more than a single error. We will +// enforce this constraint as it will help reducing the degrees of some relations. +// Assuming disjoint erros, the consolidated error is simply the sum of the 4 errors. + namespace instr_fetching; pol commit sel; +sel * (1 - sel) = 0; // No relations will be checked if this identity is satisfied. #[skippable_if] sel = 0; -sel * (1 - sel) = 0; - +// This pair identifies uniquely a given instruction among the bytecodes. pol commit pc; pol commit bytecode_id; + +// **************************************************************************** +// List of errors +// **************************************************************************** + // pc out-of-range error boolean pol commit pc_out_of_range; pc_out_of_range * (1 - pc_out_of_range) = 0; @@ -25,31 +70,27 @@ instr_out_of_range * (1 - instr_out_of_range) = 0; // opcode is out-of-range error boolean pol commit opcode_out_of_range; // copied from precomputed.pil +// memory tag is out-of-range error boolean +pol commit tag_out_of_range; // copied from precomputed.pil + +pol PARSING_ERROR_EXCEPT_TAG_ERROR = pc_out_of_range + opcode_out_of_range + instr_out_of_range; + // If any error occurs, we toggle the following boolean: pol commit parsing_err; -parsing_err = 1 - (1 - pc_out_of_range) * (1 - instr_out_of_range) * (1 - opcode_out_of_range); -// parsing_err is a boolean by definition (followed from above formula) +parsing_err = PARSING_ERROR_EXCEPT_TAG_ERROR + tag_out_of_range; +parsing_err * (1 - parsing_err) = 0; // enforces disjoint errors -// Retrieved from bc_decomposition.pil -pol commit bytes_to_read; + +// **************************************************************************** +// Handling pc_out_of_range error +// **************************************************************************** // Retrieved from bc_decomposition.pil based on bytecode_id with pc == 0 pol commit bytecode_size; -// Absolute difference variant where we compute: -// bytes_to_read - instr_size if instr_size <= bytes_to_read -// instr_size - bytes_to_read - 1 if instr_size > bytes_to_read (instr_out_of_range == 1) -pol commit instr_abs_diff; - -// From the following relation, we have: instr_abs_diff >= 0 ==> [instr_size > bytes_to_read <==> instr_out_of_range == 1] -#[INSTR_OUT_OF_RANGE_TOGGLE] -instr_abs_diff = (2 * instr_out_of_range - 1) * (instr_size - bytes_to_read) - instr_out_of_range; - -#[INSTR_ABS_DIFF_POSITIVE] -sel { instr_abs_diff } in precomputed.sel_range_8 { precomputed.clk }; - // We have to enforce that: pc < bytecode_size <==> pc_out_of_range == 0 -// We use same trick as above by using an absolute difference value. +// We use a specific absolute difference value to distinguish pc < bytecode_size +// from pc >= bytecode_size. // pc - bytecode_size if bytecode_size <= pc // bytecode_size - pc - 1 if bytecode_size > pc @@ -67,6 +108,53 @@ sel * (pc_size_in_bits - constants.AVM_PC_SIZE_IN_BITS) = 0; #[PC_ABS_DIFF_POSITIVE] sel { pc_abs_diff, pc_size_in_bits } in range_check.sel { range_check.value, range_check.rng_chk_bits }; + +// **************************************************************************** +// Handling instr_out_of_range error +// **************************************************************************** + +// Number of bytes which were read at a given pc. Retrieved from bc_decomposition.pil +pol commit bytes_to_read; + +// Instruction size in bytes. Copied from precomputed.pil +pol commit instr_size; + +// Absolute difference variant where we compute: +// bytes_to_read - instr_size if instr_size <= bytes_to_read +// instr_size - bytes_to_read - 1 if instr_size > bytes_to_read (instr_out_of_range == 1) +pol commit instr_abs_diff; + +// From the following relation, we have: instr_abs_diff >= 0 ==> [instr_size > bytes_to_read <==> instr_out_of_range == 1] +#[INSTR_OUT_OF_RANGE_TOGGLE] +instr_abs_diff = (2 * instr_out_of_range - 1) * (instr_size - bytes_to_read) - instr_out_of_range; + +#[INSTR_ABS_DIFF_POSITIVE] +sel { instr_abs_diff } in precomputed.sel_range_8 { precomputed.clk }; + + +// **************************************************************************** +// Handling tag_out_of_range error +// **************************************************************************** + +// Retrieved from precomputed.pil (instruction specification) +pol commit sel_has_tag; // With current instruction specs, tag can appear at op2 (SET_XXX) or op3 (CAST_8, CAST_16) +pol commit sel_tag_is_op2; // (sel_tag_is_op2 == 0 && sel_has_tag == 1) ==> op3 is a tag + +// Value to validate as tag. According to our instruction specifications, there is a maximum of one tag per instruction +// and it appears only at op2 or op3. +pol commit tag_value; +#[TAG_VALUE] +tag_value = (sel_has_tag - sel_tag_is_op2) * op3 + sel_tag_is_op2 * op2; + +// TODO: Investigate whether enforcing the tag checking in execution trace or in CAST/SET gadgets might be a better option. +#[TAG_VALUE_VALIDATION] +sel_has_tag { tag_value, tag_out_of_range } in precomputed.sel_range_8 { precomputed.clk, precomputed.sel_mem_tag_out_of_range }; + + +// **************************************************************************** +// Retrieval of information from other traces +// **************************************************************************** + // The size of the bytecode is bytes_remaining at pc == 0. #[BYTECODE_SIZE_FROM_BC_DEC] sel { bytecode_id, precomputed.zero, bytecode_size } in @@ -83,13 +171,15 @@ pol commit bd0, bd1, bd2, bd3, bd4, bd36; // Source selector for lookups to bc_decomposition.pil and instruction specifications in precomputed.pil. -pol commit sel_opcode_defined; +// When the pc is in range, we can at least fetch the byte of the wire opcode which allows to proceed to +// the next errors checking. +pol commit sel_pc_in_range; // Toggled except when pc is out of range. -sel_opcode_defined = sel * (1 - pc_out_of_range); +sel_pc_in_range = sel * (1 - pc_out_of_range); // Bring in the bytes from the bytecode columns. #[BYTES_FROM_BC_DEC] -sel_opcode_defined { +sel_pc_in_range { bytecode_id, pc, bytes_to_read, @@ -119,9 +209,6 @@ bc_decomposition.sel { // Wire to execution opcodes translation. pol commit exec_opcode; -// Instruction size in bytes -pol commit instr_size; - // Selectors for operands decomposition into bytes (copied from precomputed.pil) // This table is populated by a map generated by a cpp test in op_decomposition.test.cpp. pol commit sel_op_dc_0; @@ -144,11 +231,13 @@ pol commit sel_op_dc_16; pol commit sel_op_dc_17; #[WIRE_INSTRUCTION_INFO] -sel_opcode_defined { +sel_pc_in_range { bd0, opcode_out_of_range, exec_opcode, instr_size, + sel_has_tag, + sel_tag_is_op2, sel_op_dc_0, sel_op_dc_1, sel_op_dc_2, sel_op_dc_3, sel_op_dc_4, sel_op_dc_5, sel_op_dc_6, sel_op_dc_7, sel_op_dc_8, sel_op_dc_9, sel_op_dc_10, sel_op_dc_11, @@ -160,6 +249,8 @@ precomputed.sel_range_8 { precomputed.opcode_out_of_range, precomputed.exec_opcode, precomputed.instr_size, + precomputed.sel_has_tag, + precomputed.sel_tag_is_op2, precomputed.sel_op_dc_0, precomputed.sel_op_dc_1, precomputed.sel_op_dc_2, precomputed.sel_op_dc_3, precomputed.sel_op_dc_4, precomputed.sel_op_dc_5, precomputed.sel_op_dc_6, precomputed.sel_op_dc_7, precomputed.sel_op_dc_8, precomputed.sel_op_dc_9, precomputed.sel_op_dc_10, precomputed.sel_op_dc_11, @@ -167,13 +258,18 @@ precomputed.sel_range_8 { precomputed.sel_op_dc_16, precomputed.sel_op_dc_17 }; + +// **************************************************************************** +// Decomposition of the operands +// **************************************************************************** + pol commit indirect; // Operands. pol commit op1, op2, op3, op4, op5, op6, op7; -// We derive the operands only when no parsing error occurs. One might remove this gating but -// at a cost of some ugliness in the code (witgen would need a partially parsed instruction when +// We derive the operands only when no parsing error (except possibly tag out-of-range) occurs. One might remove +// this gating but at a cost of some ugliness in the code (witgen would need a partially parsed instruction when // the error instr_out_of_range is toggled). // The following relations decomposing operands (indirect, op1, ...) into bytes were code-generated by // a cpp test in op_decomposition.test.cpp. @@ -181,18 +277,18 @@ pol commit op1, op2, op3, op4, op5, op6, op7; pol SEL_OP_DC_18 = sel_op_dc_2 + sel_op_dc_6; #[INDIRECT_BYTES_DECOMPOSITION] -indirect = (1 - parsing_err) * (sel_op_dc_0 * (bd1 * 2**8 + bd2 * 2**0) + SEL_OP_DC_18 * (bd1 * 2**0)); +indirect = (1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * (sel_op_dc_0 * (bd1 * 2**8 + bd2 * 2**0) + SEL_OP_DC_18 * (bd1 * 2**0)); #[OP1_BYTES_DECOMPOSITION] -op1 = (1 - parsing_err) * (sel_op_dc_0 * (bd3 * 2**8 + bd4 * 2**0) + sel_op_dc_2 * (bd2 * 2**8 + bd3 * 2**0) + sel_op_dc_6 * (bd2 * 2**0) + sel_op_dc_15 * (bd1 * 2**24 + bd2 * 2**16 + bd3 * 2**8 + bd4 * 2**0)); +op1 = (1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * (sel_op_dc_0 * (bd3 * 2**8 + bd4 * 2**0) + sel_op_dc_2 * (bd2 * 2**8 + bd3 * 2**0) + sel_op_dc_6 * (bd2 * 2**0) + sel_op_dc_15 * (bd1 * 2**24 + bd2 * 2**16 + bd3 * 2**8 + bd4 * 2**0)); #[OP2_BYTES_DECOMPOSITION] -op2 = (1 - parsing_err) * (sel_op_dc_0 * (bd5 * 2**8 + bd6 * 2**0) + sel_op_dc_3 * (bd4 * 2**8 + bd5 * 2**0) + sel_op_dc_6 * (bd3 * 2**0) + sel_op_dc_8 * (bd4 * 2**0) + sel_op_dc_16 * (bd4 * 2**24 + bd5 * 2**16 + bd6 * 2**8 + bd7 * 2**0)); +op2 = (1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * (sel_op_dc_0 * (bd5 * 2**8 + bd6 * 2**0) + sel_op_dc_3 * (bd4 * 2**8 + bd5 * 2**0) + sel_op_dc_6 * (bd3 * 2**0) + sel_op_dc_8 * (bd4 * 2**0) + sel_op_dc_16 * (bd4 * 2**24 + bd5 * 2**16 + bd6 * 2**8 + bd7 * 2**0)); #[OP3_BYTES_DECOMPOSITION] -op3 = (1 - parsing_err) * (sel_op_dc_0 * (bd7 * 2**8 + bd8 * 2**0) + sel_op_dc_4 * (bd6 * 2**8 + bd7 * 2**0) + sel_op_dc_9 * (bd5 * 2**248 + bd6 * 2**240 + bd7 * 2**232 + bd8 * 2**224 + bd9 * 2**216 + bd10 * 2**208 + bd11 * 2**200 + bd12 * 2**192 + bd13 * 2**184 + bd14 * 2**176 + bd15 * 2**168 + bd16 * 2**160 + bd17 * 2**152 + bd18 * 2**144 + bd19 * 2**136 + bd20 * 2**128 + bd21 * 2**120 + bd22 * 2**112 + bd23 * 2**104 + bd24 * 2**96 + bd25 * 2**88 + bd26 * 2**80 + bd27 * 2**72 + bd28 * 2**64 + bd29 * 2**56 + bd30 * 2**48 + bd31 * 2**40 + bd32 * 2**32 + bd33 * 2**24 + bd34 * 2**16 + bd35 * 2**8 + bd36 * 2**0) + sel_op_dc_10 * (bd5 * 2**120 + bd6 * 2**112 + bd7 * 2**104 + bd8 * 2**96 + bd9 * 2**88 + bd10 * 2**80 + bd11 * 2**72 + bd12 * 2**64 + bd13 * 2**56 + bd14 * 2**48 + bd15 * 2**40 + bd16 * 2**32 + bd17 * 2**24 + bd18 * 2**16 + bd19 * 2**8 + bd20 * 2**0) + sel_op_dc_11 * (bd5 * 2**56 + bd6 * 2**48 + bd7 * 2**40 + bd8 * 2**32 + bd9 * 2**24 + bd10 * 2**16 + bd11 * 2**8 + bd12 * 2**0) + sel_op_dc_12 * (bd5 * 2**24 + bd6 * 2**16 + bd7 * 2**8 + bd8 * 2**0) + sel_op_dc_13 * (bd5 * 2**8 + bd6 * 2**0) + sel_op_dc_14 * (bd4 * 2**0) + sel_op_dc_17 * (bd6 * 2**0)); +op3 = (1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * (sel_op_dc_0 * (bd7 * 2**8 + bd8 * 2**0) + sel_op_dc_4 * (bd6 * 2**8 + bd7 * 2**0) + sel_op_dc_9 * (bd5 * 2**248 + bd6 * 2**240 + bd7 * 2**232 + bd8 * 2**224 + bd9 * 2**216 + bd10 * 2**208 + bd11 * 2**200 + bd12 * 2**192 + bd13 * 2**184 + bd14 * 2**176 + bd15 * 2**168 + bd16 * 2**160 + bd17 * 2**152 + bd18 * 2**144 + bd19 * 2**136 + bd20 * 2**128 + bd21 * 2**120 + bd22 * 2**112 + bd23 * 2**104 + bd24 * 2**96 + bd25 * 2**88 + bd26 * 2**80 + bd27 * 2**72 + bd28 * 2**64 + bd29 * 2**56 + bd30 * 2**48 + bd31 * 2**40 + bd32 * 2**32 + bd33 * 2**24 + bd34 * 2**16 + bd35 * 2**8 + bd36 * 2**0) + sel_op_dc_10 * (bd5 * 2**120 + bd6 * 2**112 + bd7 * 2**104 + bd8 * 2**96 + bd9 * 2**88 + bd10 * 2**80 + bd11 * 2**72 + bd12 * 2**64 + bd13 * 2**56 + bd14 * 2**48 + bd15 * 2**40 + bd16 * 2**32 + bd17 * 2**24 + bd18 * 2**16 + bd19 * 2**8 + bd20 * 2**0) + sel_op_dc_11 * (bd5 * 2**56 + bd6 * 2**48 + bd7 * 2**40 + bd8 * 2**32 + bd9 * 2**24 + bd10 * 2**16 + bd11 * 2**8 + bd12 * 2**0) + sel_op_dc_12 * (bd5 * 2**24 + bd6 * 2**16 + bd7 * 2**8 + bd8 * 2**0) + sel_op_dc_13 * (bd5 * 2**8 + bd6 * 2**0) + sel_op_dc_14 * (bd4 * 2**0) + sel_op_dc_17 * (bd6 * 2**0)); #[OP4_BYTES_DECOMPOSITION] -op4 = (1 - parsing_err) * (sel_op_dc_0 * (bd9 * 2**8 + bd10 * 2**0) + sel_op_dc_5 * (bd8 * 2**8 + bd9 * 2**0) + sel_op_dc_7 * (bd8 * 2**0)); +op4 = (1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * (sel_op_dc_0 * (bd9 * 2**8 + bd10 * 2**0) + sel_op_dc_5 * (bd8 * 2**8 + bd9 * 2**0) + sel_op_dc_7 * (bd8 * 2**0)); #[OP5_BYTES_DECOMPOSITION] -op5 = (1 - parsing_err) * (sel_op_dc_0 * (bd11 * 2**8 + bd12 * 2**0)); +op5 = (1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * (sel_op_dc_0 * (bd11 * 2**8 + bd12 * 2**0)); #[OP6_BYTES_DECOMPOSITION] -op6 = (1 - parsing_err) * (sel_op_dc_1 * (bd13 * 2**8 + bd14 * 2**0)); +op6 = (1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * (sel_op_dc_1 * (bd13 * 2**8 + bd14 * 2**0)); #[OP7_BYTES_DECOMPOSITION] -op7 = (1 - parsing_err) * (sel_op_dc_1 * (bd15 * 2**8 + bd16 * 2**0)); +op7 = (1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * (sel_op_dc_1 * (bd15 * 2**8 + bd16 * 2**0)); diff --git a/barretenberg/cpp/pil/vm2/precomputed.pil b/barretenberg/cpp/pil/vm2/precomputed.pil index cb925d2a7818..f4db85e7e800 100644 --- a/barretenberg/cpp/pil/vm2/precomputed.pil +++ b/barretenberg/cpp/pil/vm2/precomputed.pil @@ -52,6 +52,16 @@ pol constant integral_tag_length; // Columns for the byte length 1,1,2,...,16; // However, it would extend this lookup table with pairs such as (0,0), (7,0), (8,0) which is // not without any danger. +// Toggled at every row where clk is a byte and outside of memory tag +pol constant sel_mem_tag_out_of_range; + +// WIRE INSTRUCTION SPEC table +// The WIRE_INSTRUCTION_SPEC maps a WireOpCode to different values related to the instruction format such as: +// - array of decomposition selectors: sel_op_dc_XX +// - corresponding execution opcode: exec_opcode +// - instruction size (in bytes): instr_size +// - Selector on whether the instruction has a tag: sel_has_tag +// - Selector on whether operand op2 is a tag: sel_tag_is_op2 // Selectors for operands decomposition into bytes (required by instr_fetching.pil) // This table is populated by a map generated by a cpp test defined in op_decomposition.test.cpp. @@ -76,6 +86,8 @@ pol constant sel_op_dc_17; pol constant exec_opcode; pol constant instr_size; // Instruction size in bytes +pol constant sel_has_tag; // With current instruction specs, tag can appear at op2 (SET_XXX) or op3 (CAST_8, CAST_16) +pol constant sel_tag_is_op2; // (sel_tag_is_op2 == 0 && sel_has_tag == 1) ==> op3 is a tag // Toggled at rows whose clk interpreted as a byte does not correspond to a valid wire opcode // Toggled only up to clk = 255. (within range specified by sel_range_8) diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.cpp b/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.cpp index 0105bf5e6640..0e8c233d36b5 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.cpp @@ -196,13 +196,19 @@ const std::unordered_map WIRE_INSTRUCTION_SPEC .size_in_bytes = 8, .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SHR_16) } }, { WireOpCode::CAST_8, - { .exec_opcode = ExecutionOpCode::CAST, - .size_in_bytes = 5, - .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::CAST_8) } }, + { + .exec_opcode = ExecutionOpCode::CAST, + .size_in_bytes = 5, + .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::CAST_8), + .tag_operand_idx = 3, // op3 + } }, { WireOpCode::CAST_16, - { .exec_opcode = ExecutionOpCode::CAST, - .size_in_bytes = 7, - .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::CAST_16) } }, + { + .exec_opcode = ExecutionOpCode::CAST, + .size_in_bytes = 7, + .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::CAST_16), + .tag_operand_idx = 3, // op3 + } }, { WireOpCode::GETENVVAR_16, { .exec_opcode = ExecutionOpCode::GETENVVAR, .size_in_bytes = 5, @@ -240,29 +246,47 @@ const std::unordered_map WIRE_INSTRUCTION_SPEC .size_in_bytes = 1, .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::INTERNALRETURN) } }, { WireOpCode::SET_8, - { .exec_opcode = ExecutionOpCode::SET, - .size_in_bytes = 5, - .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_8) } }, + { + .exec_opcode = ExecutionOpCode::SET, + .size_in_bytes = 5, + .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_8), + .tag_operand_idx = 2, // op2 + } }, { WireOpCode::SET_16, - { .exec_opcode = ExecutionOpCode::SET, - .size_in_bytes = 7, - .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_16) } }, + { + .exec_opcode = ExecutionOpCode::SET, + .size_in_bytes = 7, + .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_16), + .tag_operand_idx = 2, // op2 + } }, { WireOpCode::SET_32, - { .exec_opcode = ExecutionOpCode::SET, - .size_in_bytes = 9, - .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_32) } }, + { + .exec_opcode = ExecutionOpCode::SET, + .size_in_bytes = 9, + .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_32), + .tag_operand_idx = 2, // op2 + } }, { WireOpCode::SET_64, - { .exec_opcode = ExecutionOpCode::SET, - .size_in_bytes = 13, - .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_64) } }, + { + .exec_opcode = ExecutionOpCode::SET, + .size_in_bytes = 13, + .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_64), + .tag_operand_idx = 2, // op2 + } }, { WireOpCode::SET_128, - { .exec_opcode = ExecutionOpCode::SET, - .size_in_bytes = 21, - .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_128) } }, + { + .exec_opcode = ExecutionOpCode::SET, + .size_in_bytes = 21, + .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_128), + .tag_operand_idx = 2, // op2 + } }, { WireOpCode::SET_FF, - { .exec_opcode = ExecutionOpCode::SET, - .size_in_bytes = 37, - .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_FF) } }, + { + .exec_opcode = ExecutionOpCode::SET, + .size_in_bytes = 37, + .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_FF), + .tag_operand_idx = 2, // op2 + } }, { WireOpCode::MOV_8, { .exec_opcode = ExecutionOpCode::MOV, .size_in_bytes = 4, diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.hpp b/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.hpp index 1e44b3447202..8e69c28a690f 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "barretenberg/vm2/common/opcodes.hpp" @@ -30,6 +31,8 @@ struct WireInstructionSpec { ExecutionOpCode exec_opcode; uint32_t size_in_bytes; std::array op_dc_selectors; + std::optional + tag_operand_idx; // Index of relevant operand in vector of operands as defined in WireOpCode_WIRE_FORMAT bool operator==(const WireInstructionSpec& other) const = default; }; diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.test.cpp index 045c66ca4a88..62acd5d314f4 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.test.cpp @@ -35,5 +35,30 @@ TEST(InstructionSpecTest, CheckAllInstructionSizes) } } +// Test checking that the hardcoded tag related fields in WIRE_INSTRUCTION_SPEC +// are correct. This test would fail only when we change the wire format of an instruction. +TEST(InstructionSpecTest, CheckAllInstructionsTagInformation) +{ + const auto& wire_format = simulation::testonly::get_instruction_wire_formats(); + + for (int i = 0; i < static_cast(WireOpCode::LAST_OPCODE_SENTINEL); i++) { + const auto wire_opcode = static_cast(i); + const auto& operands = wire_format.at(wire_opcode); + const auto tag_counts = std::count(operands.begin(), operands.end(), simulation::OperandType::TAG); + const auto& wire_instruction_spec = WIRE_INSTRUCTION_SPEC.at(wire_opcode); + + if (wire_instruction_spec.tag_operand_idx.has_value()) { + EXPECT_EQ(tag_counts, 1); + if (wire_instruction_spec.tag_operand_idx.value() == 2) { + EXPECT_EQ(operands.at(2), simulation::OperandType::TAG); + } else { + EXPECT_EQ(operands.at(3), simulation::OperandType::TAG); + } + } else { + EXPECT_EQ(tag_counts, 0); + } + } +} + } // namespace } // namespace bb::avm2 diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/memory_types.hpp b/barretenberg/cpp/src/barretenberg/vm2/common/memory_types.hpp index 1e1cfe273225..fadbd178f28e 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/common/memory_types.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/common/memory_types.hpp @@ -6,7 +6,6 @@ namespace bb::avm2 { -// Adapt NUM_MEMORY_TAGS in fixtures.cpp if this enum is modified. enum class MemoryTag { FF, U1, @@ -15,6 +14,7 @@ enum class MemoryTag { U32, U64, U128, + MAX = U128, }; using MemoryAddress = uint32_t; diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/instr_fetching.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/instr_fetching.test.cpp index 9960e1b60a24..c7a003336099 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/instr_fetching.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/instr_fetching.test.cpp @@ -49,6 +49,7 @@ using pc_abs_diff_positive_lookup = lookup_instr_fetching_pc_abs_diff_positive_r using wire_instr_spec_lookup = lookup_instr_fetching_wire_instruction_info_relation; using bc_decomposition_lookup = lookup_instr_fetching_bytes_from_bc_dec_relation; using bytecode_size_bc_decomposition_lookup = lookup_instr_fetching_bytecode_size_from_bc_dec_relation; +using tag_validation_lookup = lookup_instr_fetching_tag_value_validation_relation; using testing::random_bytes; @@ -317,6 +318,7 @@ void check_all(const std::vector& instr_events, precomputed_builder.process_wire_instruction_spec(trace); precomputed_builder.process_sel_range_8(trace); precomputed_builder.process_sel_range_16(trace); + precomputed_builder.process_memory_tag_range(trace); bytecode_builder.process_instruction_fetching(instr_events, trace); bytecode_builder.process_decomposition(decomposition_events, trace); range_check_builder.process(range_check_events, trace); @@ -325,6 +327,7 @@ void check_all(const std::vector& instr_events, LookupIntoIndexedByClk().process(trace); LookupIntoDynamicTableGeneric().process(trace); LookupIntoIndexedByClk().process(trace); + LookupIntoIndexedByClk().process(trace); LookupIntoDynamicTableGeneric().process(trace); LookupIntoDynamicTableGeneric().process(trace); @@ -336,6 +339,7 @@ void check_all(const std::vector& instr_events, check_interaction(trace); check_interaction(trace); check_interaction(trace); + check_interaction(trace); } // Positive test with 5 five bytecodes and bytecode_id = 0,1,2,3,4 @@ -528,6 +532,40 @@ TEST(InstrFetchingConstrainingTest, SingleInstructionOpcodeOutOfRange) check_all(instr_events, gen_range_check_events(instr_events), decomposition_events); } +// Positive test with one single instruction (SET_16) with error TAG_OUT_OF_RANGE. +// The bytecode consists into a serialized single instruction with pc = 0. +// The operand at index 1 is wrongly set to value 12 +TEST(InstrFetchingConstrainingTest, SingleInstructionTagOutOfRange) +{ + Instruction set_16_instruction = { + .opcode = WireOpCode::SET_16, + .indirect = 0, + .operands = { Operand::u16(0x1234), Operand::u8(12), Operand::u16(0x5678) }, + }; + + std::vector bytecode = set_16_instruction.serialize(); + const auto bytecode_ptr = std::make_shared>(std::move(bytecode)); + + const std::vector instr_events = { + { + .bytecode_id = 1, + .pc = 0, + .instruction = set_16_instruction, + .bytecode = bytecode_ptr, + .error = InstrDeserializationError::TAG_OUT_OF_RANGE, + }, + }; + + const std::vector decomposition_events = { + { + .bytecode_id = 1, + .bytecode = bytecode_ptr, + }, + }; + + check_all(instr_events, gen_range_check_events(instr_events), decomposition_events); +} + // Negative interaction test with some values not matching the instruction spec table. TEST(InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions) { @@ -556,14 +594,15 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions ASSERT_EQ(trace.get(C::lookup_instr_fetching_wire_instruction_info_counts, static_cast(opcode)), 1); check_interaction(trace); - constexpr std::array mutated_cols = { - C::instr_fetching_exec_opcode, C::instr_fetching_instr_size, C::instr_fetching_sel_op_dc_0, - C::instr_fetching_sel_op_dc_1, C::instr_fetching_sel_op_dc_2, C::instr_fetching_sel_op_dc_3, - C::instr_fetching_sel_op_dc_4, C::instr_fetching_sel_op_dc_5, C::instr_fetching_sel_op_dc_6, - C::instr_fetching_sel_op_dc_7, C::instr_fetching_sel_op_dc_8, C::instr_fetching_sel_op_dc_9, - C::instr_fetching_sel_op_dc_10, C::instr_fetching_sel_op_dc_11, C::instr_fetching_sel_op_dc_12, - C::instr_fetching_sel_op_dc_13, C::instr_fetching_sel_op_dc_14, C::instr_fetching_sel_op_dc_15, - C::instr_fetching_sel_op_dc_16, C::instr_fetching_sel_op_dc_17, + constexpr std::array mutated_cols = { + C::instr_fetching_exec_opcode, C::instr_fetching_instr_size, C::instr_fetching_sel_has_tag, + C::instr_fetching_sel_tag_is_op2, C::instr_fetching_sel_op_dc_0, C::instr_fetching_sel_op_dc_1, + C::instr_fetching_sel_op_dc_2, C::instr_fetching_sel_op_dc_3, C::instr_fetching_sel_op_dc_4, + C::instr_fetching_sel_op_dc_5, C::instr_fetching_sel_op_dc_6, C::instr_fetching_sel_op_dc_7, + C::instr_fetching_sel_op_dc_8, C::instr_fetching_sel_op_dc_9, C::instr_fetching_sel_op_dc_10, + C::instr_fetching_sel_op_dc_11, C::instr_fetching_sel_op_dc_12, C::instr_fetching_sel_op_dc_13, + C::instr_fetching_sel_op_dc_14, C::instr_fetching_sel_op_dc_15, C::instr_fetching_sel_op_dc_16, + C::instr_fetching_sel_op_dc_17, }; // Mutate execution opcode @@ -702,6 +741,49 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongBytecodeSizeBcDecompositionInte } } +// Negative interaction test for #[TAG_VALUE_VALIDATION] where tag_out_of_range is wrongly mutated +TEST(InstrFetchingConstrainingTest, NegativeWrongTagValidationInteractions) +{ + TestTraceContainer trace; + BytecodeTraceBuilder bytecode_builder; + PrecomputedTraceBuilder precomputed_builder; + + // Some chosen opcode with a tag. We limit to one as this unit test is costly. + // Test works if the following vector is extended to other opcodes though. + std::vector opcodes = { WireOpCode::SET_8 }; + + for (const auto& opcode : opcodes) { + TestTraceContainer trace; + const auto instr = testing::random_instruction(opcode); + bytecode_builder.process_instruction_fetching( + { { .bytecode_id = 1, + .pc = 0, + .instruction = instr, + .bytecode = std::make_shared>(instr.serialize()) } }, + trace); + precomputed_builder.process_memory_tag_range(trace); + precomputed_builder.process_sel_range_8(trace); + precomputed_builder.process_misc(trace, trace.get_num_rows()); // Limit to the number of rows we need. + + LookupIntoIndexedByClk().process(trace); + + auto valid_trace = trace; // Keep original trace before lookup processing + check_interaction(valid_trace); + + // Mutate tag out-of-range error + auto mutated_trace = trace; + ASSERT_EQ(trace.get(C::instr_fetching_tag_out_of_range, 1), 0); + mutated_trace.set(C::instr_fetching_tag_out_of_range, 1, 1); // Mutate by toggling the error. + + // We do not need to re-run LookupIntoIndexedByClk().process(trace); + // because we never mutate the indexing column for this lookup (clk) and for this lookup + // find_in_dst only uses column C::instr_fetching_tag_value mapped to (clk). So, the counts are still valid. + + EXPECT_THROW_WITH_MESSAGE(check_interaction(mutated_trace), + "Relation.*TAG_VALUE_VALIDATION.* ACCUMULATION.* is non-zero"); + } +} + // Negative test on not toggling instr_out_of_range when instr_size > bytes_to_read TEST(InstrFetchingConstrainingTest, NegativeNotTogglingInstrOutOfRange) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/op_decomposition.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/op_decomposition.test.cpp index aa9c904304ea..503b7c4a4278 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/op_decomposition.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/op_decomposition.test.cpp @@ -177,7 +177,7 @@ std::string render_pil( : format("#[OP", static_cast(i), "_BYTES_DECOMPOSITION]\n"); pil_equations += (i == 0) ? "indirect = " : format(OPERAND_PREFIX, static_cast(i), " = "); - pil_equations += "(1 - parsing_err) * ("; // Error gating multiplicative term + pil_equations += "(1 - PARSING_ERROR_EXCEPT_TAG_ERROR) * ("; // Error gating multiplicative term std::vector additive_terms; for (const auto& sel_layout : sel_layout_breakdowns[i]) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp index ab992ef28af6..ce8cd2eb8a23 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp @@ -9,9 +9,9 @@ namespace bb::avm2 { // The entities that will be used in the flavor. // clang-format off -#define AVM2_PRECOMPUTED_ENTITIES precomputed_as_unary, precomputed_bitwise_input_a, precomputed_bitwise_input_b, precomputed_bitwise_op_id, precomputed_bitwise_output, precomputed_clk, precomputed_exec_opcode, precomputed_first_row, precomputed_instr_size, precomputed_integral_tag_length, precomputed_opcode_out_of_range, precomputed_p_decomposition_limb, precomputed_p_decomposition_limb_index, precomputed_p_decomposition_radix, precomputed_power_of_2, precomputed_sel_bitwise, precomputed_sel_integral_tag, precomputed_sel_op_dc_0, precomputed_sel_op_dc_1, precomputed_sel_op_dc_10, precomputed_sel_op_dc_11, precomputed_sel_op_dc_12, precomputed_sel_op_dc_13, precomputed_sel_op_dc_14, precomputed_sel_op_dc_15, precomputed_sel_op_dc_16, precomputed_sel_op_dc_17, precomputed_sel_op_dc_2, precomputed_sel_op_dc_3, precomputed_sel_op_dc_4, precomputed_sel_op_dc_5, precomputed_sel_op_dc_6, precomputed_sel_op_dc_7, precomputed_sel_op_dc_8, precomputed_sel_op_dc_9, precomputed_sel_p_decomposition, precomputed_sel_range_16, precomputed_sel_range_8, precomputed_sel_sha256_compression, precomputed_sel_to_radix_safe_limbs, precomputed_sel_unary, precomputed_sha256_compression_round_constant, precomputed_to_radix_safe_limbs, precomputed_zero -#define AVM2_WIRE_ENTITIES execution_input, address_derivation_address, address_derivation_address_y, address_derivation_class_id, address_derivation_deployer_addr, address_derivation_g1_x, address_derivation_g1_y, address_derivation_incoming_viewing_key_x, address_derivation_incoming_viewing_key_y, address_derivation_init_hash, address_derivation_nullifier_key_x, address_derivation_nullifier_key_y, address_derivation_outgoing_viewing_key_x, address_derivation_outgoing_viewing_key_y, address_derivation_partial_address, address_derivation_partial_address_domain_separator, address_derivation_preaddress, address_derivation_preaddress_domain_separator, address_derivation_preaddress_public_key_x, address_derivation_preaddress_public_key_y, address_derivation_public_keys_hash, address_derivation_public_keys_hash_domain_separator, address_derivation_salt, address_derivation_salted_init_hash, address_derivation_sel, address_derivation_tagging_key_x, address_derivation_tagging_key_y, alu_dst_addr, alu_ia, alu_ia_addr, alu_ib, alu_ib_addr, alu_ic, alu_op, alu_sel_op_add, bc_decomposition_abs_diff, bc_decomposition_bytes, bc_decomposition_bytes_pc_plus_1, bc_decomposition_bytes_pc_plus_10, bc_decomposition_bytes_pc_plus_11, bc_decomposition_bytes_pc_plus_12, bc_decomposition_bytes_pc_plus_13, bc_decomposition_bytes_pc_plus_14, bc_decomposition_bytes_pc_plus_15, bc_decomposition_bytes_pc_plus_16, bc_decomposition_bytes_pc_plus_17, bc_decomposition_bytes_pc_plus_18, bc_decomposition_bytes_pc_plus_19, bc_decomposition_bytes_pc_plus_2, bc_decomposition_bytes_pc_plus_20, bc_decomposition_bytes_pc_plus_21, bc_decomposition_bytes_pc_plus_22, bc_decomposition_bytes_pc_plus_23, bc_decomposition_bytes_pc_plus_24, bc_decomposition_bytes_pc_plus_25, bc_decomposition_bytes_pc_plus_26, bc_decomposition_bytes_pc_plus_27, bc_decomposition_bytes_pc_plus_28, bc_decomposition_bytes_pc_plus_29, bc_decomposition_bytes_pc_plus_3, bc_decomposition_bytes_pc_plus_30, bc_decomposition_bytes_pc_plus_31, bc_decomposition_bytes_pc_plus_32, bc_decomposition_bytes_pc_plus_33, bc_decomposition_bytes_pc_plus_34, bc_decomposition_bytes_pc_plus_35, bc_decomposition_bytes_pc_plus_36, bc_decomposition_bytes_pc_plus_4, bc_decomposition_bytes_pc_plus_5, bc_decomposition_bytes_pc_plus_6, bc_decomposition_bytes_pc_plus_7, bc_decomposition_bytes_pc_plus_8, bc_decomposition_bytes_pc_plus_9, bc_decomposition_bytes_rem_inv, bc_decomposition_bytes_rem_min_one_inv, bc_decomposition_bytes_remaining, bc_decomposition_bytes_to_read, bc_decomposition_bytes_to_read_unary, bc_decomposition_id, bc_decomposition_last_of_contract, bc_decomposition_packed_field, bc_decomposition_pc, bc_decomposition_sel, bc_decomposition_sel_overflow_correction_needed, bc_decomposition_sel_packed, bc_decomposition_sel_pc_plus_1, bc_decomposition_sel_pc_plus_10, bc_decomposition_sel_pc_plus_11, bc_decomposition_sel_pc_plus_12, bc_decomposition_sel_pc_plus_13, bc_decomposition_sel_pc_plus_14, bc_decomposition_sel_pc_plus_15, bc_decomposition_sel_pc_plus_16, bc_decomposition_sel_pc_plus_17, bc_decomposition_sel_pc_plus_18, bc_decomposition_sel_pc_plus_19, bc_decomposition_sel_pc_plus_2, bc_decomposition_sel_pc_plus_20, bc_decomposition_sel_pc_plus_21, bc_decomposition_sel_pc_plus_22, bc_decomposition_sel_pc_plus_23, bc_decomposition_sel_pc_plus_24, bc_decomposition_sel_pc_plus_25, bc_decomposition_sel_pc_plus_26, bc_decomposition_sel_pc_plus_27, bc_decomposition_sel_pc_plus_28, bc_decomposition_sel_pc_plus_29, bc_decomposition_sel_pc_plus_3, bc_decomposition_sel_pc_plus_30, bc_decomposition_sel_pc_plus_31, bc_decomposition_sel_pc_plus_32, bc_decomposition_sel_pc_plus_33, bc_decomposition_sel_pc_plus_34, bc_decomposition_sel_pc_plus_35, bc_decomposition_sel_pc_plus_36, bc_decomposition_sel_pc_plus_4, bc_decomposition_sel_pc_plus_5, bc_decomposition_sel_pc_plus_6, bc_decomposition_sel_pc_plus_7, bc_decomposition_sel_pc_plus_8, bc_decomposition_sel_pc_plus_9, bc_hashing_bytecode_id, bc_hashing_incremental_hash, bc_hashing_latch, bc_hashing_output_hash, bc_hashing_packed_field, bc_hashing_pc_index, bc_hashing_sel, bc_hashing_start, bc_retrieval_address, bc_retrieval_artifact_hash, bc_retrieval_bytecode_id, bc_retrieval_class_id, bc_retrieval_deployer_addr, bc_retrieval_err, bc_retrieval_incoming_viewing_key_x, bc_retrieval_incoming_viewing_key_y, bc_retrieval_init_hash, bc_retrieval_nullifier_key_x, bc_retrieval_nullifier_key_y, bc_retrieval_outgoing_viewing_key_x, bc_retrieval_outgoing_viewing_key_y, bc_retrieval_private_function_root, bc_retrieval_public_bytecode_commitment, bc_retrieval_salt, bc_retrieval_sel, bc_retrieval_siloed_address, bc_retrieval_tagging_key_x, bc_retrieval_tagging_key_y, bitwise_acc_ia, bitwise_acc_ib, bitwise_acc_ic, bitwise_ctr, bitwise_ctr_inv, bitwise_ctr_min_one_inv, bitwise_ia_byte, bitwise_ib_byte, bitwise_ic_byte, bitwise_last, bitwise_op_id, bitwise_sel, bitwise_start, bitwise_tag, class_id_derivation_artifact_hash, class_id_derivation_class_id, class_id_derivation_private_function_root, class_id_derivation_public_bytecode_commitment, class_id_derivation_sel, class_id_derivation_temp_constant_for_lookup, context_stack_context_id, context_stack_contract_address, context_stack_is_static, context_stack_msg_sender, context_stack_pc, ecc_add_op, ecc_double_op, ecc_inv_2_p_y, ecc_inv_x_diff, ecc_inv_y_diff, ecc_lambda, ecc_p_is_inf, ecc_p_x, ecc_p_y, ecc_q_is_inf, ecc_q_x, ecc_q_y, ecc_r_is_inf, ecc_r_x, ecc_r_y, ecc_result_infinity, ecc_sel, ecc_x_match, ecc_y_match, execution_addressing_error_idx, execution_addressing_error_kind, execution_base_address_tag, execution_base_address_val, execution_bytecode_id, execution_clk, execution_context_id, execution_contract_address, execution_ex_opcode, execution_indirect, execution_is_static, execution_last, execution_msg_sender, execution_op1, execution_op1_after_relative, execution_op2, execution_op2_after_relative, execution_op3, execution_op3_after_relative, execution_op4, execution_op4_after_relative, execution_pc, execution_rop1, execution_rop2, execution_rop3, execution_rop4, execution_sel, execution_sel_addressing_error, execution_sel_op1_is_address, execution_sel_op2_is_address, execution_sel_op3_is_address, execution_sel_op4_is_address, ff_gt_a, ff_gt_a_hi, ff_gt_a_lo, ff_gt_b, ff_gt_b_hi, ff_gt_b_lo, ff_gt_borrow, ff_gt_cmp_rng_ctr, ff_gt_cmp_rng_ctr_inv, ff_gt_constant_128, ff_gt_p_a_borrow, ff_gt_p_b_borrow, ff_gt_p_sub_a_hi, ff_gt_p_sub_a_lo, ff_gt_p_sub_b_hi, ff_gt_p_sub_b_lo, ff_gt_res_hi, ff_gt_res_lo, ff_gt_result, ff_gt_sel, ff_gt_sel_gt, ff_gt_sel_shift_rng, instr_fetching_bd0, instr_fetching_bd1, instr_fetching_bd10, instr_fetching_bd11, instr_fetching_bd12, instr_fetching_bd13, instr_fetching_bd14, instr_fetching_bd15, instr_fetching_bd16, instr_fetching_bd17, instr_fetching_bd18, instr_fetching_bd19, instr_fetching_bd2, instr_fetching_bd20, instr_fetching_bd21, instr_fetching_bd22, instr_fetching_bd23, instr_fetching_bd24, instr_fetching_bd25, instr_fetching_bd26, instr_fetching_bd27, instr_fetching_bd28, instr_fetching_bd29, instr_fetching_bd3, instr_fetching_bd30, instr_fetching_bd31, instr_fetching_bd32, instr_fetching_bd33, instr_fetching_bd34, instr_fetching_bd35, instr_fetching_bd36, instr_fetching_bd4, instr_fetching_bd5, instr_fetching_bd6, instr_fetching_bd7, instr_fetching_bd8, instr_fetching_bd9, instr_fetching_bytecode_id, instr_fetching_bytecode_size, instr_fetching_bytes_to_read, instr_fetching_exec_opcode, instr_fetching_indirect, instr_fetching_instr_abs_diff, instr_fetching_instr_out_of_range, instr_fetching_instr_size, instr_fetching_op1, instr_fetching_op2, instr_fetching_op3, instr_fetching_op4, instr_fetching_op5, instr_fetching_op6, instr_fetching_op7, instr_fetching_opcode_out_of_range, instr_fetching_parsing_err, instr_fetching_pc, instr_fetching_pc_abs_diff, instr_fetching_pc_out_of_range, instr_fetching_pc_size_in_bits, instr_fetching_sel, instr_fetching_sel_op_dc_0, instr_fetching_sel_op_dc_1, instr_fetching_sel_op_dc_10, instr_fetching_sel_op_dc_11, instr_fetching_sel_op_dc_12, instr_fetching_sel_op_dc_13, instr_fetching_sel_op_dc_14, instr_fetching_sel_op_dc_15, instr_fetching_sel_op_dc_16, instr_fetching_sel_op_dc_17, instr_fetching_sel_op_dc_2, instr_fetching_sel_op_dc_3, instr_fetching_sel_op_dc_4, instr_fetching_sel_op_dc_5, instr_fetching_sel_op_dc_6, instr_fetching_sel_op_dc_7, instr_fetching_sel_op_dc_8, instr_fetching_sel_op_dc_9, instr_fetching_sel_opcode_defined, merkle_check_constant_2, merkle_check_current_index_in_layer, merkle_check_current_node, merkle_check_end, merkle_check_index_is_even, merkle_check_leaf, merkle_check_leaf_index, merkle_check_left_node, merkle_check_output_hash, merkle_check_remaining_path_len, merkle_check_remaining_path_len_inv, merkle_check_right_node, merkle_check_sel, merkle_check_sibling, merkle_check_start, merkle_check_tree_height, poseidon2_hash_a_0, poseidon2_hash_a_1, poseidon2_hash_a_2, poseidon2_hash_a_3, poseidon2_hash_b_0, poseidon2_hash_b_1, poseidon2_hash_b_2, poseidon2_hash_b_3, poseidon2_hash_end, poseidon2_hash_input_0, poseidon2_hash_input_1, poseidon2_hash_input_2, poseidon2_hash_input_len, poseidon2_hash_num_perm_rounds_rem, poseidon2_hash_num_perm_rounds_rem_inv, poseidon2_hash_output, poseidon2_hash_padding, poseidon2_hash_sel, poseidon2_hash_start, poseidon2_perm_B_10_0, poseidon2_perm_B_10_1, poseidon2_perm_B_10_2, poseidon2_perm_B_10_3, poseidon2_perm_B_11_0, poseidon2_perm_B_11_1, poseidon2_perm_B_11_2, poseidon2_perm_B_11_3, poseidon2_perm_B_12_0, poseidon2_perm_B_12_1, poseidon2_perm_B_12_2, poseidon2_perm_B_12_3, poseidon2_perm_B_13_0, poseidon2_perm_B_13_1, poseidon2_perm_B_13_2, poseidon2_perm_B_13_3, poseidon2_perm_B_14_0, poseidon2_perm_B_14_1, poseidon2_perm_B_14_2, poseidon2_perm_B_14_3, poseidon2_perm_B_15_0, poseidon2_perm_B_15_1, poseidon2_perm_B_15_2, poseidon2_perm_B_15_3, poseidon2_perm_B_16_0, poseidon2_perm_B_16_1, poseidon2_perm_B_16_2, poseidon2_perm_B_16_3, poseidon2_perm_B_17_0, poseidon2_perm_B_17_1, poseidon2_perm_B_17_2, poseidon2_perm_B_17_3, poseidon2_perm_B_18_0, poseidon2_perm_B_18_1, poseidon2_perm_B_18_2, poseidon2_perm_B_18_3, poseidon2_perm_B_19_0, poseidon2_perm_B_19_1, poseidon2_perm_B_19_2, poseidon2_perm_B_19_3, poseidon2_perm_B_20_0, poseidon2_perm_B_20_1, poseidon2_perm_B_20_2, poseidon2_perm_B_20_3, poseidon2_perm_B_21_0, poseidon2_perm_B_21_1, poseidon2_perm_B_21_2, poseidon2_perm_B_21_3, poseidon2_perm_B_22_0, poseidon2_perm_B_22_1, poseidon2_perm_B_22_2, poseidon2_perm_B_22_3, poseidon2_perm_B_23_0, poseidon2_perm_B_23_1, poseidon2_perm_B_23_2, poseidon2_perm_B_23_3, poseidon2_perm_B_24_0, poseidon2_perm_B_24_1, poseidon2_perm_B_24_2, poseidon2_perm_B_24_3, poseidon2_perm_B_25_0, poseidon2_perm_B_25_1, poseidon2_perm_B_25_2, poseidon2_perm_B_25_3, poseidon2_perm_B_26_0, poseidon2_perm_B_26_1, poseidon2_perm_B_26_2, poseidon2_perm_B_26_3, poseidon2_perm_B_27_0, poseidon2_perm_B_27_1, poseidon2_perm_B_27_2, poseidon2_perm_B_27_3, poseidon2_perm_B_28_0, poseidon2_perm_B_28_1, poseidon2_perm_B_28_2, poseidon2_perm_B_28_3, poseidon2_perm_B_29_0, poseidon2_perm_B_29_1, poseidon2_perm_B_29_2, poseidon2_perm_B_29_3, poseidon2_perm_B_30_0, poseidon2_perm_B_30_1, poseidon2_perm_B_30_2, poseidon2_perm_B_30_3, poseidon2_perm_B_31_0, poseidon2_perm_B_31_1, poseidon2_perm_B_31_2, poseidon2_perm_B_31_3, poseidon2_perm_B_32_0, poseidon2_perm_B_32_1, poseidon2_perm_B_32_2, poseidon2_perm_B_32_3, poseidon2_perm_B_33_0, poseidon2_perm_B_33_1, poseidon2_perm_B_33_2, poseidon2_perm_B_33_3, poseidon2_perm_B_34_0, poseidon2_perm_B_34_1, poseidon2_perm_B_34_2, poseidon2_perm_B_34_3, poseidon2_perm_B_35_0, poseidon2_perm_B_35_1, poseidon2_perm_B_35_2, poseidon2_perm_B_35_3, poseidon2_perm_B_36_0, poseidon2_perm_B_36_1, poseidon2_perm_B_36_2, poseidon2_perm_B_36_3, poseidon2_perm_B_37_0, poseidon2_perm_B_37_1, poseidon2_perm_B_37_2, poseidon2_perm_B_37_3, poseidon2_perm_B_38_0, poseidon2_perm_B_38_1, poseidon2_perm_B_38_2, poseidon2_perm_B_38_3, poseidon2_perm_B_39_0, poseidon2_perm_B_39_1, poseidon2_perm_B_39_2, poseidon2_perm_B_39_3, poseidon2_perm_B_40_0, poseidon2_perm_B_40_1, poseidon2_perm_B_40_2, poseidon2_perm_B_40_3, poseidon2_perm_B_41_0, poseidon2_perm_B_41_1, poseidon2_perm_B_41_2, poseidon2_perm_B_41_3, poseidon2_perm_B_42_0, poseidon2_perm_B_42_1, poseidon2_perm_B_42_2, poseidon2_perm_B_42_3, poseidon2_perm_B_43_0, poseidon2_perm_B_43_1, poseidon2_perm_B_43_2, poseidon2_perm_B_43_3, poseidon2_perm_B_44_0, poseidon2_perm_B_44_1, poseidon2_perm_B_44_2, poseidon2_perm_B_44_3, poseidon2_perm_B_45_0, poseidon2_perm_B_45_1, poseidon2_perm_B_45_2, poseidon2_perm_B_45_3, poseidon2_perm_B_46_0, poseidon2_perm_B_46_1, poseidon2_perm_B_46_2, poseidon2_perm_B_46_3, poseidon2_perm_B_47_0, poseidon2_perm_B_47_1, poseidon2_perm_B_47_2, poseidon2_perm_B_47_3, poseidon2_perm_B_48_0, poseidon2_perm_B_48_1, poseidon2_perm_B_48_2, poseidon2_perm_B_48_3, poseidon2_perm_B_49_0, poseidon2_perm_B_49_1, poseidon2_perm_B_49_2, poseidon2_perm_B_49_3, poseidon2_perm_B_4_0, poseidon2_perm_B_4_1, poseidon2_perm_B_4_2, poseidon2_perm_B_4_3, poseidon2_perm_B_50_0, poseidon2_perm_B_50_1, poseidon2_perm_B_50_2, poseidon2_perm_B_50_3, poseidon2_perm_B_51_0, poseidon2_perm_B_51_1, poseidon2_perm_B_51_2, poseidon2_perm_B_51_3, poseidon2_perm_B_52_0, poseidon2_perm_B_52_1, poseidon2_perm_B_52_2, poseidon2_perm_B_52_3, poseidon2_perm_B_53_0, poseidon2_perm_B_53_1, poseidon2_perm_B_53_2, poseidon2_perm_B_53_3, poseidon2_perm_B_54_0, poseidon2_perm_B_54_1, poseidon2_perm_B_54_2, poseidon2_perm_B_54_3, poseidon2_perm_B_55_0, poseidon2_perm_B_55_1, poseidon2_perm_B_55_2, poseidon2_perm_B_55_3, poseidon2_perm_B_56_0, poseidon2_perm_B_56_1, poseidon2_perm_B_56_2, poseidon2_perm_B_56_3, poseidon2_perm_B_57_0, poseidon2_perm_B_57_1, poseidon2_perm_B_57_2, poseidon2_perm_B_57_3, poseidon2_perm_B_58_0, poseidon2_perm_B_58_1, poseidon2_perm_B_58_2, poseidon2_perm_B_58_3, poseidon2_perm_B_59_0, poseidon2_perm_B_59_1, poseidon2_perm_B_59_2, poseidon2_perm_B_59_3, poseidon2_perm_B_5_0, poseidon2_perm_B_5_1, poseidon2_perm_B_5_2, poseidon2_perm_B_5_3, poseidon2_perm_B_6_0, poseidon2_perm_B_6_1, poseidon2_perm_B_6_2, poseidon2_perm_B_6_3, poseidon2_perm_B_7_0, poseidon2_perm_B_7_1, poseidon2_perm_B_7_2, poseidon2_perm_B_7_3, poseidon2_perm_B_8_0, poseidon2_perm_B_8_1, poseidon2_perm_B_8_2, poseidon2_perm_B_8_3, poseidon2_perm_B_9_0, poseidon2_perm_B_9_1, poseidon2_perm_B_9_2, poseidon2_perm_B_9_3, poseidon2_perm_EXT_LAYER_4, poseidon2_perm_EXT_LAYER_5, poseidon2_perm_EXT_LAYER_6, poseidon2_perm_EXT_LAYER_7, poseidon2_perm_T_0_4, poseidon2_perm_T_0_5, poseidon2_perm_T_0_6, poseidon2_perm_T_0_7, poseidon2_perm_T_1_4, poseidon2_perm_T_1_5, poseidon2_perm_T_1_6, poseidon2_perm_T_1_7, poseidon2_perm_T_2_4, poseidon2_perm_T_2_5, poseidon2_perm_T_2_6, poseidon2_perm_T_2_7, poseidon2_perm_T_3_4, poseidon2_perm_T_3_5, poseidon2_perm_T_3_6, poseidon2_perm_T_3_7, poseidon2_perm_T_60_4, poseidon2_perm_T_60_5, poseidon2_perm_T_60_6, poseidon2_perm_T_60_7, poseidon2_perm_T_61_4, poseidon2_perm_T_61_5, poseidon2_perm_T_61_6, poseidon2_perm_T_61_7, poseidon2_perm_T_62_4, poseidon2_perm_T_62_5, poseidon2_perm_T_62_6, poseidon2_perm_T_62_7, poseidon2_perm_T_63_4, poseidon2_perm_T_63_5, poseidon2_perm_T_63_6, poseidon2_perm_T_63_7, poseidon2_perm_a_0, poseidon2_perm_a_1, poseidon2_perm_a_2, poseidon2_perm_a_3, poseidon2_perm_b_0, poseidon2_perm_b_1, poseidon2_perm_b_2, poseidon2_perm_b_3, poseidon2_perm_sel, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, range_check_is_lte_u112, range_check_is_lte_u128, range_check_is_lte_u16, range_check_is_lte_u32, range_check_is_lte_u48, range_check_is_lte_u64, range_check_is_lte_u80, range_check_is_lte_u96, range_check_rng_chk_bits, range_check_sel, range_check_sel_r0_16_bit_rng_lookup, range_check_sel_r1_16_bit_rng_lookup, range_check_sel_r2_16_bit_rng_lookup, range_check_sel_r3_16_bit_rng_lookup, range_check_sel_r4_16_bit_rng_lookup, range_check_sel_r5_16_bit_rng_lookup, range_check_sel_r6_16_bit_rng_lookup, range_check_u16_r0, range_check_u16_r1, range_check_u16_r2, range_check_u16_r3, range_check_u16_r4, range_check_u16_r5, range_check_u16_r6, range_check_u16_r7, range_check_value, scalar_mul_bit, scalar_mul_bit_idx, scalar_mul_bit_radix, scalar_mul_end, scalar_mul_not_end, scalar_mul_point_inf, scalar_mul_point_x, scalar_mul_point_y, scalar_mul_res_inf, scalar_mul_res_x, scalar_mul_res_y, scalar_mul_scalar, scalar_mul_sel, scalar_mul_should_add, scalar_mul_start, scalar_mul_temp_inf, scalar_mul_temp_x, scalar_mul_temp_y, sha256_a, sha256_a_and_b, sha256_a_and_b_xor_a_and_c, sha256_a_and_c, sha256_a_rotr_13, sha256_a_rotr_2, sha256_a_rotr_22, sha256_a_rotr_2_xor_a_rotr_13, sha256_and_sel, sha256_b, sha256_b_and_c, sha256_c, sha256_ch, sha256_clk, sha256_computed_w_lhs, sha256_computed_w_rhs, sha256_d, sha256_e, sha256_e_and_f, sha256_e_rotr_11, sha256_e_rotr_25, sha256_e_rotr_6, sha256_e_rotr_6_xor_e_rotr_11, sha256_f, sha256_g, sha256_h, sha256_helper_w0, sha256_helper_w1, sha256_helper_w10, sha256_helper_w11, sha256_helper_w12, sha256_helper_w13, sha256_helper_w14, sha256_helper_w15, sha256_helper_w2, sha256_helper_w3, sha256_helper_w4, sha256_helper_w5, sha256_helper_w6, sha256_helper_w7, sha256_helper_w8, sha256_helper_w9, sha256_init_a, sha256_init_b, sha256_init_c, sha256_init_d, sha256_init_e, sha256_init_f, sha256_init_g, sha256_init_h, sha256_input_offset, sha256_is_input_round, sha256_latch, sha256_lhs_a_13, sha256_lhs_a_2, sha256_lhs_a_22, sha256_lhs_e_11, sha256_lhs_e_25, sha256_lhs_e_6, sha256_lhs_w_10, sha256_lhs_w_17, sha256_lhs_w_18, sha256_lhs_w_19, sha256_lhs_w_3, sha256_lhs_w_7, sha256_maj, sha256_next_a_lhs, sha256_next_a_rhs, sha256_next_e_lhs, sha256_next_e_rhs, sha256_not_e, sha256_not_e_and_g, sha256_output_a_lhs, sha256_output_a_rhs, sha256_output_b_lhs, sha256_output_b_rhs, sha256_output_c_lhs, sha256_output_c_rhs, sha256_output_d_lhs, sha256_output_d_rhs, sha256_output_e_lhs, sha256_output_e_rhs, sha256_output_f_lhs, sha256_output_f_rhs, sha256_output_g_lhs, sha256_output_g_rhs, sha256_output_h_lhs, sha256_output_h_rhs, sha256_output_offset, sha256_perform_round, sha256_rhs_a_13, sha256_rhs_a_2, sha256_rhs_a_22, sha256_rhs_e_11, sha256_rhs_e_25, sha256_rhs_e_6, sha256_rhs_w_10, sha256_rhs_w_17, sha256_rhs_w_18, sha256_rhs_w_19, sha256_rhs_w_3, sha256_rhs_w_7, sha256_round_constant, sha256_round_count, sha256_rounds_remaining, sha256_rounds_remaining_inv, sha256_s_0, sha256_s_1, sha256_sel, sha256_start, sha256_state_offset, sha256_w, sha256_w_15_rotr_18, sha256_w_15_rotr_7, sha256_w_15_rotr_7_xor_w_15_rotr_18, sha256_w_15_rshift_3, sha256_w_2_rotr_17, sha256_w_2_rotr_17_xor_w_2_rotr_19, sha256_w_2_rotr_19, sha256_w_2_rshift_10, sha256_w_s_0, sha256_w_s_1, sha256_xor_sel, to_radix_acc, to_radix_acc_under_p, to_radix_end, to_radix_exponent, to_radix_found, to_radix_is_unsafe_limb, to_radix_limb, to_radix_limb_eq_p, to_radix_limb_index, to_radix_limb_lt_p, to_radix_limb_p_diff, to_radix_limb_radix_diff, to_radix_not_end, to_radix_not_padding_limb, to_radix_p_limb, to_radix_radix, to_radix_rem_inverse, to_radix_safe_limbs, to_radix_safety_diff_inverse, to_radix_sel, to_radix_start, to_radix_value, lookup_poseidon2_hash_poseidon2_perm_counts, lookup_range_check_dyn_rng_chk_pow_2_counts, lookup_range_check_dyn_diff_is_u16_counts, lookup_range_check_r0_is_u16_counts, lookup_range_check_r1_is_u16_counts, lookup_range_check_r2_is_u16_counts, lookup_range_check_r3_is_u16_counts, lookup_range_check_r4_is_u16_counts, lookup_range_check_r5_is_u16_counts, lookup_range_check_r6_is_u16_counts, lookup_range_check_r7_is_u16_counts, lookup_to_radix_limb_range_counts, lookup_to_radix_limb_less_than_radix_range_counts, lookup_to_radix_fetch_safe_limbs_counts, lookup_to_radix_fetch_p_limb_counts, lookup_to_radix_limb_p_diff_range_counts, lookup_scalar_mul_to_radix_counts, lookup_scalar_mul_double_counts, lookup_scalar_mul_add_counts, lookup_address_derivation_salted_initialization_hash_poseidon2_0_counts, lookup_address_derivation_salted_initialization_hash_poseidon2_1_counts, lookup_address_derivation_partial_address_poseidon2_counts, lookup_address_derivation_public_keys_hash_poseidon2_0_counts, lookup_address_derivation_public_keys_hash_poseidon2_1_counts, lookup_address_derivation_public_keys_hash_poseidon2_2_counts, lookup_address_derivation_public_keys_hash_poseidon2_3_counts, lookup_address_derivation_public_keys_hash_poseidon2_4_counts, lookup_address_derivation_preaddress_poseidon2_counts, lookup_address_derivation_preaddress_scalar_mul_counts, lookup_address_derivation_address_ecadd_counts, lookup_bc_decomposition_bytes_are_bytes_counts, lookup_bc_decomposition_abs_diff_is_u16_counts, lookup_bc_decomposition_bytes_to_read_as_unary_counts, lookup_bc_hashing_get_packed_field_counts, lookup_bc_hashing_iv_is_len_counts, lookup_bc_hashing_poseidon2_hash_counts, lookup_bc_retrieval_class_id_derivation_counts, lookup_bc_retrieval_bytecode_hash_is_correct_counts, lookup_instr_fetching_instr_abs_diff_positive_counts, lookup_instr_fetching_pc_abs_diff_positive_counts, lookup_instr_fetching_bytecode_size_from_bc_dec_counts, lookup_instr_fetching_bytes_from_bc_dec_counts, lookup_instr_fetching_wire_instruction_info_counts, lookup_class_id_derivation_class_id_poseidon2_0_counts, lookup_class_id_derivation_class_id_poseidon2_1_counts, lookup_bitwise_integral_tag_length_counts, lookup_bitwise_byte_operations_counts, lookup_merkle_check_merkle_poseidon2_counts, lookup_sha256_round_constant_counts, lookup_ff_gt_a_lo_range_counts, lookup_ff_gt_a_hi_range_counts -#define AVM2_DERIVED_WITNESS_ENTITIES lookup_poseidon2_hash_poseidon2_perm_inv, lookup_range_check_dyn_rng_chk_pow_2_inv, lookup_range_check_dyn_diff_is_u16_inv, lookup_range_check_r0_is_u16_inv, lookup_range_check_r1_is_u16_inv, lookup_range_check_r2_is_u16_inv, lookup_range_check_r3_is_u16_inv, lookup_range_check_r4_is_u16_inv, lookup_range_check_r5_is_u16_inv, lookup_range_check_r6_is_u16_inv, lookup_range_check_r7_is_u16_inv, lookup_to_radix_limb_range_inv, lookup_to_radix_limb_less_than_radix_range_inv, lookup_to_radix_fetch_safe_limbs_inv, lookup_to_radix_fetch_p_limb_inv, lookup_to_radix_limb_p_diff_range_inv, lookup_scalar_mul_to_radix_inv, lookup_scalar_mul_double_inv, lookup_scalar_mul_add_inv, lookup_address_derivation_salted_initialization_hash_poseidon2_0_inv, lookup_address_derivation_salted_initialization_hash_poseidon2_1_inv, lookup_address_derivation_partial_address_poseidon2_inv, lookup_address_derivation_public_keys_hash_poseidon2_0_inv, lookup_address_derivation_public_keys_hash_poseidon2_1_inv, lookup_address_derivation_public_keys_hash_poseidon2_2_inv, lookup_address_derivation_public_keys_hash_poseidon2_3_inv, lookup_address_derivation_public_keys_hash_poseidon2_4_inv, lookup_address_derivation_preaddress_poseidon2_inv, lookup_address_derivation_preaddress_scalar_mul_inv, lookup_address_derivation_address_ecadd_inv, lookup_bc_decomposition_bytes_are_bytes_inv, lookup_bc_decomposition_abs_diff_is_u16_inv, lookup_bc_decomposition_bytes_to_read_as_unary_inv, lookup_bc_hashing_get_packed_field_inv, lookup_bc_hashing_iv_is_len_inv, lookup_bc_hashing_poseidon2_hash_inv, lookup_bc_retrieval_class_id_derivation_inv, lookup_bc_retrieval_bytecode_hash_is_correct_inv, lookup_instr_fetching_instr_abs_diff_positive_inv, lookup_instr_fetching_pc_abs_diff_positive_inv, lookup_instr_fetching_bytecode_size_from_bc_dec_inv, lookup_instr_fetching_bytes_from_bc_dec_inv, lookup_instr_fetching_wire_instruction_info_inv, lookup_class_id_derivation_class_id_poseidon2_0_inv, lookup_class_id_derivation_class_id_poseidon2_1_inv, lookup_bitwise_integral_tag_length_inv, lookup_bitwise_byte_operations_inv, lookup_merkle_check_merkle_poseidon2_inv, lookup_sha256_round_constant_inv, lookup_ff_gt_a_lo_range_inv, lookup_ff_gt_a_hi_range_inv +#define AVM2_PRECOMPUTED_ENTITIES precomputed_as_unary, precomputed_bitwise_input_a, precomputed_bitwise_input_b, precomputed_bitwise_op_id, precomputed_bitwise_output, precomputed_clk, precomputed_exec_opcode, precomputed_first_row, precomputed_instr_size, precomputed_integral_tag_length, precomputed_opcode_out_of_range, precomputed_p_decomposition_limb, precomputed_p_decomposition_limb_index, precomputed_p_decomposition_radix, precomputed_power_of_2, precomputed_sel_bitwise, precomputed_sel_has_tag, precomputed_sel_integral_tag, precomputed_sel_mem_tag_out_of_range, precomputed_sel_op_dc_0, precomputed_sel_op_dc_1, precomputed_sel_op_dc_10, precomputed_sel_op_dc_11, precomputed_sel_op_dc_12, precomputed_sel_op_dc_13, precomputed_sel_op_dc_14, precomputed_sel_op_dc_15, precomputed_sel_op_dc_16, precomputed_sel_op_dc_17, precomputed_sel_op_dc_2, precomputed_sel_op_dc_3, precomputed_sel_op_dc_4, precomputed_sel_op_dc_5, precomputed_sel_op_dc_6, precomputed_sel_op_dc_7, precomputed_sel_op_dc_8, precomputed_sel_op_dc_9, precomputed_sel_p_decomposition, precomputed_sel_range_16, precomputed_sel_range_8, precomputed_sel_sha256_compression, precomputed_sel_tag_is_op2, precomputed_sel_to_radix_safe_limbs, precomputed_sel_unary, precomputed_sha256_compression_round_constant, precomputed_to_radix_safe_limbs, precomputed_zero +#define AVM2_WIRE_ENTITIES execution_input, address_derivation_address, address_derivation_address_y, address_derivation_class_id, address_derivation_deployer_addr, address_derivation_g1_x, address_derivation_g1_y, address_derivation_incoming_viewing_key_x, address_derivation_incoming_viewing_key_y, address_derivation_init_hash, address_derivation_nullifier_key_x, address_derivation_nullifier_key_y, address_derivation_outgoing_viewing_key_x, address_derivation_outgoing_viewing_key_y, address_derivation_partial_address, address_derivation_partial_address_domain_separator, address_derivation_preaddress, address_derivation_preaddress_domain_separator, address_derivation_preaddress_public_key_x, address_derivation_preaddress_public_key_y, address_derivation_public_keys_hash, address_derivation_public_keys_hash_domain_separator, address_derivation_salt, address_derivation_salted_init_hash, address_derivation_sel, address_derivation_tagging_key_x, address_derivation_tagging_key_y, alu_dst_addr, alu_ia, alu_ia_addr, alu_ib, alu_ib_addr, alu_ic, alu_op, alu_sel_op_add, bc_decomposition_abs_diff, bc_decomposition_bytes, bc_decomposition_bytes_pc_plus_1, bc_decomposition_bytes_pc_plus_10, bc_decomposition_bytes_pc_plus_11, bc_decomposition_bytes_pc_plus_12, bc_decomposition_bytes_pc_plus_13, bc_decomposition_bytes_pc_plus_14, bc_decomposition_bytes_pc_plus_15, bc_decomposition_bytes_pc_plus_16, bc_decomposition_bytes_pc_plus_17, bc_decomposition_bytes_pc_plus_18, bc_decomposition_bytes_pc_plus_19, bc_decomposition_bytes_pc_plus_2, bc_decomposition_bytes_pc_plus_20, bc_decomposition_bytes_pc_plus_21, bc_decomposition_bytes_pc_plus_22, bc_decomposition_bytes_pc_plus_23, bc_decomposition_bytes_pc_plus_24, bc_decomposition_bytes_pc_plus_25, bc_decomposition_bytes_pc_plus_26, bc_decomposition_bytes_pc_plus_27, bc_decomposition_bytes_pc_plus_28, bc_decomposition_bytes_pc_plus_29, bc_decomposition_bytes_pc_plus_3, bc_decomposition_bytes_pc_plus_30, bc_decomposition_bytes_pc_plus_31, bc_decomposition_bytes_pc_plus_32, bc_decomposition_bytes_pc_plus_33, bc_decomposition_bytes_pc_plus_34, bc_decomposition_bytes_pc_plus_35, bc_decomposition_bytes_pc_plus_36, bc_decomposition_bytes_pc_plus_4, bc_decomposition_bytes_pc_plus_5, bc_decomposition_bytes_pc_plus_6, bc_decomposition_bytes_pc_plus_7, bc_decomposition_bytes_pc_plus_8, bc_decomposition_bytes_pc_plus_9, bc_decomposition_bytes_rem_inv, bc_decomposition_bytes_rem_min_one_inv, bc_decomposition_bytes_remaining, bc_decomposition_bytes_to_read, bc_decomposition_bytes_to_read_unary, bc_decomposition_id, bc_decomposition_last_of_contract, bc_decomposition_packed_field, bc_decomposition_pc, bc_decomposition_sel, bc_decomposition_sel_overflow_correction_needed, bc_decomposition_sel_packed, bc_decomposition_sel_pc_plus_1, bc_decomposition_sel_pc_plus_10, bc_decomposition_sel_pc_plus_11, bc_decomposition_sel_pc_plus_12, bc_decomposition_sel_pc_plus_13, bc_decomposition_sel_pc_plus_14, bc_decomposition_sel_pc_plus_15, bc_decomposition_sel_pc_plus_16, bc_decomposition_sel_pc_plus_17, bc_decomposition_sel_pc_plus_18, bc_decomposition_sel_pc_plus_19, bc_decomposition_sel_pc_plus_2, bc_decomposition_sel_pc_plus_20, bc_decomposition_sel_pc_plus_21, bc_decomposition_sel_pc_plus_22, bc_decomposition_sel_pc_plus_23, bc_decomposition_sel_pc_plus_24, bc_decomposition_sel_pc_plus_25, bc_decomposition_sel_pc_plus_26, bc_decomposition_sel_pc_plus_27, bc_decomposition_sel_pc_plus_28, bc_decomposition_sel_pc_plus_29, bc_decomposition_sel_pc_plus_3, bc_decomposition_sel_pc_plus_30, bc_decomposition_sel_pc_plus_31, bc_decomposition_sel_pc_plus_32, bc_decomposition_sel_pc_plus_33, bc_decomposition_sel_pc_plus_34, bc_decomposition_sel_pc_plus_35, bc_decomposition_sel_pc_plus_36, bc_decomposition_sel_pc_plus_4, bc_decomposition_sel_pc_plus_5, bc_decomposition_sel_pc_plus_6, bc_decomposition_sel_pc_plus_7, bc_decomposition_sel_pc_plus_8, bc_decomposition_sel_pc_plus_9, bc_hashing_bytecode_id, bc_hashing_incremental_hash, bc_hashing_latch, bc_hashing_output_hash, bc_hashing_packed_field, bc_hashing_pc_index, bc_hashing_sel, bc_hashing_start, bc_retrieval_address, bc_retrieval_artifact_hash, bc_retrieval_bytecode_id, bc_retrieval_class_id, bc_retrieval_deployer_addr, bc_retrieval_err, bc_retrieval_incoming_viewing_key_x, bc_retrieval_incoming_viewing_key_y, bc_retrieval_init_hash, bc_retrieval_nullifier_key_x, bc_retrieval_nullifier_key_y, bc_retrieval_outgoing_viewing_key_x, bc_retrieval_outgoing_viewing_key_y, bc_retrieval_private_function_root, bc_retrieval_public_bytecode_commitment, bc_retrieval_salt, bc_retrieval_sel, bc_retrieval_siloed_address, bc_retrieval_tagging_key_x, bc_retrieval_tagging_key_y, bitwise_acc_ia, bitwise_acc_ib, bitwise_acc_ic, bitwise_ctr, bitwise_ctr_inv, bitwise_ctr_min_one_inv, bitwise_ia_byte, bitwise_ib_byte, bitwise_ic_byte, bitwise_last, bitwise_op_id, bitwise_sel, bitwise_start, bitwise_tag, class_id_derivation_artifact_hash, class_id_derivation_class_id, class_id_derivation_private_function_root, class_id_derivation_public_bytecode_commitment, class_id_derivation_sel, class_id_derivation_temp_constant_for_lookup, context_stack_context_id, context_stack_contract_address, context_stack_is_static, context_stack_msg_sender, context_stack_pc, ecc_add_op, ecc_double_op, ecc_inv_2_p_y, ecc_inv_x_diff, ecc_inv_y_diff, ecc_lambda, ecc_p_is_inf, ecc_p_x, ecc_p_y, ecc_q_is_inf, ecc_q_x, ecc_q_y, ecc_r_is_inf, ecc_r_x, ecc_r_y, ecc_result_infinity, ecc_sel, ecc_x_match, ecc_y_match, execution_addressing_error_idx, execution_addressing_error_kind, execution_base_address_tag, execution_base_address_val, execution_bytecode_id, execution_clk, execution_context_id, execution_contract_address, execution_ex_opcode, execution_indirect, execution_is_static, execution_last, execution_msg_sender, execution_op1, execution_op1_after_relative, execution_op2, execution_op2_after_relative, execution_op3, execution_op3_after_relative, execution_op4, execution_op4_after_relative, execution_pc, execution_rop1, execution_rop2, execution_rop3, execution_rop4, execution_sel, execution_sel_addressing_error, execution_sel_op1_is_address, execution_sel_op2_is_address, execution_sel_op3_is_address, execution_sel_op4_is_address, ff_gt_a, ff_gt_a_hi, ff_gt_a_lo, ff_gt_b, ff_gt_b_hi, ff_gt_b_lo, ff_gt_borrow, ff_gt_cmp_rng_ctr, ff_gt_cmp_rng_ctr_inv, ff_gt_constant_128, ff_gt_p_a_borrow, ff_gt_p_b_borrow, ff_gt_p_sub_a_hi, ff_gt_p_sub_a_lo, ff_gt_p_sub_b_hi, ff_gt_p_sub_b_lo, ff_gt_res_hi, ff_gt_res_lo, ff_gt_result, ff_gt_sel, ff_gt_sel_gt, ff_gt_sel_shift_rng, instr_fetching_bd0, instr_fetching_bd1, instr_fetching_bd10, instr_fetching_bd11, instr_fetching_bd12, instr_fetching_bd13, instr_fetching_bd14, instr_fetching_bd15, instr_fetching_bd16, instr_fetching_bd17, instr_fetching_bd18, instr_fetching_bd19, instr_fetching_bd2, instr_fetching_bd20, instr_fetching_bd21, instr_fetching_bd22, instr_fetching_bd23, instr_fetching_bd24, instr_fetching_bd25, instr_fetching_bd26, instr_fetching_bd27, instr_fetching_bd28, instr_fetching_bd29, instr_fetching_bd3, instr_fetching_bd30, instr_fetching_bd31, instr_fetching_bd32, instr_fetching_bd33, instr_fetching_bd34, instr_fetching_bd35, instr_fetching_bd36, instr_fetching_bd4, instr_fetching_bd5, instr_fetching_bd6, instr_fetching_bd7, instr_fetching_bd8, instr_fetching_bd9, instr_fetching_bytecode_id, instr_fetching_bytecode_size, instr_fetching_bytes_to_read, instr_fetching_exec_opcode, instr_fetching_indirect, instr_fetching_instr_abs_diff, instr_fetching_instr_out_of_range, instr_fetching_instr_size, instr_fetching_op1, instr_fetching_op2, instr_fetching_op3, instr_fetching_op4, instr_fetching_op5, instr_fetching_op6, instr_fetching_op7, instr_fetching_opcode_out_of_range, instr_fetching_parsing_err, instr_fetching_pc, instr_fetching_pc_abs_diff, instr_fetching_pc_out_of_range, instr_fetching_pc_size_in_bits, instr_fetching_sel, instr_fetching_sel_has_tag, instr_fetching_sel_op_dc_0, instr_fetching_sel_op_dc_1, instr_fetching_sel_op_dc_10, instr_fetching_sel_op_dc_11, instr_fetching_sel_op_dc_12, instr_fetching_sel_op_dc_13, instr_fetching_sel_op_dc_14, instr_fetching_sel_op_dc_15, instr_fetching_sel_op_dc_16, instr_fetching_sel_op_dc_17, instr_fetching_sel_op_dc_2, instr_fetching_sel_op_dc_3, instr_fetching_sel_op_dc_4, instr_fetching_sel_op_dc_5, instr_fetching_sel_op_dc_6, instr_fetching_sel_op_dc_7, instr_fetching_sel_op_dc_8, instr_fetching_sel_op_dc_9, instr_fetching_sel_pc_in_range, instr_fetching_sel_tag_is_op2, instr_fetching_tag_out_of_range, instr_fetching_tag_value, merkle_check_constant_2, merkle_check_current_index_in_layer, merkle_check_current_node, merkle_check_end, merkle_check_index_is_even, merkle_check_leaf, merkle_check_leaf_index, merkle_check_left_node, merkle_check_output_hash, merkle_check_remaining_path_len, merkle_check_remaining_path_len_inv, merkle_check_right_node, merkle_check_sel, merkle_check_sibling, merkle_check_start, merkle_check_tree_height, poseidon2_hash_a_0, poseidon2_hash_a_1, poseidon2_hash_a_2, poseidon2_hash_a_3, poseidon2_hash_b_0, poseidon2_hash_b_1, poseidon2_hash_b_2, poseidon2_hash_b_3, poseidon2_hash_end, poseidon2_hash_input_0, poseidon2_hash_input_1, poseidon2_hash_input_2, poseidon2_hash_input_len, poseidon2_hash_num_perm_rounds_rem, poseidon2_hash_num_perm_rounds_rem_inv, poseidon2_hash_output, poseidon2_hash_padding, poseidon2_hash_sel, poseidon2_hash_start, poseidon2_perm_B_10_0, poseidon2_perm_B_10_1, poseidon2_perm_B_10_2, poseidon2_perm_B_10_3, poseidon2_perm_B_11_0, poseidon2_perm_B_11_1, poseidon2_perm_B_11_2, poseidon2_perm_B_11_3, poseidon2_perm_B_12_0, poseidon2_perm_B_12_1, poseidon2_perm_B_12_2, poseidon2_perm_B_12_3, poseidon2_perm_B_13_0, poseidon2_perm_B_13_1, poseidon2_perm_B_13_2, poseidon2_perm_B_13_3, poseidon2_perm_B_14_0, poseidon2_perm_B_14_1, poseidon2_perm_B_14_2, poseidon2_perm_B_14_3, poseidon2_perm_B_15_0, poseidon2_perm_B_15_1, poseidon2_perm_B_15_2, poseidon2_perm_B_15_3, poseidon2_perm_B_16_0, poseidon2_perm_B_16_1, poseidon2_perm_B_16_2, poseidon2_perm_B_16_3, poseidon2_perm_B_17_0, poseidon2_perm_B_17_1, poseidon2_perm_B_17_2, poseidon2_perm_B_17_3, poseidon2_perm_B_18_0, poseidon2_perm_B_18_1, poseidon2_perm_B_18_2, poseidon2_perm_B_18_3, poseidon2_perm_B_19_0, poseidon2_perm_B_19_1, poseidon2_perm_B_19_2, poseidon2_perm_B_19_3, poseidon2_perm_B_20_0, poseidon2_perm_B_20_1, poseidon2_perm_B_20_2, poseidon2_perm_B_20_3, poseidon2_perm_B_21_0, poseidon2_perm_B_21_1, poseidon2_perm_B_21_2, poseidon2_perm_B_21_3, poseidon2_perm_B_22_0, poseidon2_perm_B_22_1, poseidon2_perm_B_22_2, poseidon2_perm_B_22_3, poseidon2_perm_B_23_0, poseidon2_perm_B_23_1, poseidon2_perm_B_23_2, poseidon2_perm_B_23_3, poseidon2_perm_B_24_0, poseidon2_perm_B_24_1, poseidon2_perm_B_24_2, poseidon2_perm_B_24_3, poseidon2_perm_B_25_0, poseidon2_perm_B_25_1, poseidon2_perm_B_25_2, poseidon2_perm_B_25_3, poseidon2_perm_B_26_0, poseidon2_perm_B_26_1, poseidon2_perm_B_26_2, poseidon2_perm_B_26_3, poseidon2_perm_B_27_0, poseidon2_perm_B_27_1, poseidon2_perm_B_27_2, poseidon2_perm_B_27_3, poseidon2_perm_B_28_0, poseidon2_perm_B_28_1, poseidon2_perm_B_28_2, poseidon2_perm_B_28_3, poseidon2_perm_B_29_0, poseidon2_perm_B_29_1, poseidon2_perm_B_29_2, poseidon2_perm_B_29_3, poseidon2_perm_B_30_0, poseidon2_perm_B_30_1, poseidon2_perm_B_30_2, poseidon2_perm_B_30_3, poseidon2_perm_B_31_0, poseidon2_perm_B_31_1, poseidon2_perm_B_31_2, poseidon2_perm_B_31_3, poseidon2_perm_B_32_0, poseidon2_perm_B_32_1, poseidon2_perm_B_32_2, poseidon2_perm_B_32_3, poseidon2_perm_B_33_0, poseidon2_perm_B_33_1, poseidon2_perm_B_33_2, poseidon2_perm_B_33_3, poseidon2_perm_B_34_0, poseidon2_perm_B_34_1, poseidon2_perm_B_34_2, poseidon2_perm_B_34_3, poseidon2_perm_B_35_0, poseidon2_perm_B_35_1, poseidon2_perm_B_35_2, poseidon2_perm_B_35_3, poseidon2_perm_B_36_0, poseidon2_perm_B_36_1, poseidon2_perm_B_36_2, poseidon2_perm_B_36_3, poseidon2_perm_B_37_0, poseidon2_perm_B_37_1, poseidon2_perm_B_37_2, poseidon2_perm_B_37_3, poseidon2_perm_B_38_0, poseidon2_perm_B_38_1, poseidon2_perm_B_38_2, poseidon2_perm_B_38_3, poseidon2_perm_B_39_0, poseidon2_perm_B_39_1, poseidon2_perm_B_39_2, poseidon2_perm_B_39_3, poseidon2_perm_B_40_0, poseidon2_perm_B_40_1, poseidon2_perm_B_40_2, poseidon2_perm_B_40_3, poseidon2_perm_B_41_0, poseidon2_perm_B_41_1, poseidon2_perm_B_41_2, poseidon2_perm_B_41_3, poseidon2_perm_B_42_0, poseidon2_perm_B_42_1, poseidon2_perm_B_42_2, poseidon2_perm_B_42_3, poseidon2_perm_B_43_0, poseidon2_perm_B_43_1, poseidon2_perm_B_43_2, poseidon2_perm_B_43_3, poseidon2_perm_B_44_0, poseidon2_perm_B_44_1, poseidon2_perm_B_44_2, poseidon2_perm_B_44_3, poseidon2_perm_B_45_0, poseidon2_perm_B_45_1, poseidon2_perm_B_45_2, poseidon2_perm_B_45_3, poseidon2_perm_B_46_0, poseidon2_perm_B_46_1, poseidon2_perm_B_46_2, poseidon2_perm_B_46_3, poseidon2_perm_B_47_0, poseidon2_perm_B_47_1, poseidon2_perm_B_47_2, poseidon2_perm_B_47_3, poseidon2_perm_B_48_0, poseidon2_perm_B_48_1, poseidon2_perm_B_48_2, poseidon2_perm_B_48_3, poseidon2_perm_B_49_0, poseidon2_perm_B_49_1, poseidon2_perm_B_49_2, poseidon2_perm_B_49_3, poseidon2_perm_B_4_0, poseidon2_perm_B_4_1, poseidon2_perm_B_4_2, poseidon2_perm_B_4_3, poseidon2_perm_B_50_0, poseidon2_perm_B_50_1, poseidon2_perm_B_50_2, poseidon2_perm_B_50_3, poseidon2_perm_B_51_0, poseidon2_perm_B_51_1, poseidon2_perm_B_51_2, poseidon2_perm_B_51_3, poseidon2_perm_B_52_0, poseidon2_perm_B_52_1, poseidon2_perm_B_52_2, poseidon2_perm_B_52_3, poseidon2_perm_B_53_0, poseidon2_perm_B_53_1, poseidon2_perm_B_53_2, poseidon2_perm_B_53_3, poseidon2_perm_B_54_0, poseidon2_perm_B_54_1, poseidon2_perm_B_54_2, poseidon2_perm_B_54_3, poseidon2_perm_B_55_0, poseidon2_perm_B_55_1, poseidon2_perm_B_55_2, poseidon2_perm_B_55_3, poseidon2_perm_B_56_0, poseidon2_perm_B_56_1, poseidon2_perm_B_56_2, poseidon2_perm_B_56_3, poseidon2_perm_B_57_0, poseidon2_perm_B_57_1, poseidon2_perm_B_57_2, poseidon2_perm_B_57_3, poseidon2_perm_B_58_0, poseidon2_perm_B_58_1, poseidon2_perm_B_58_2, poseidon2_perm_B_58_3, poseidon2_perm_B_59_0, poseidon2_perm_B_59_1, poseidon2_perm_B_59_2, poseidon2_perm_B_59_3, poseidon2_perm_B_5_0, poseidon2_perm_B_5_1, poseidon2_perm_B_5_2, poseidon2_perm_B_5_3, poseidon2_perm_B_6_0, poseidon2_perm_B_6_1, poseidon2_perm_B_6_2, poseidon2_perm_B_6_3, poseidon2_perm_B_7_0, poseidon2_perm_B_7_1, poseidon2_perm_B_7_2, poseidon2_perm_B_7_3, poseidon2_perm_B_8_0, poseidon2_perm_B_8_1, poseidon2_perm_B_8_2, poseidon2_perm_B_8_3, poseidon2_perm_B_9_0, poseidon2_perm_B_9_1, poseidon2_perm_B_9_2, poseidon2_perm_B_9_3, poseidon2_perm_EXT_LAYER_4, poseidon2_perm_EXT_LAYER_5, poseidon2_perm_EXT_LAYER_6, poseidon2_perm_EXT_LAYER_7, poseidon2_perm_T_0_4, poseidon2_perm_T_0_5, poseidon2_perm_T_0_6, poseidon2_perm_T_0_7, poseidon2_perm_T_1_4, poseidon2_perm_T_1_5, poseidon2_perm_T_1_6, poseidon2_perm_T_1_7, poseidon2_perm_T_2_4, poseidon2_perm_T_2_5, poseidon2_perm_T_2_6, poseidon2_perm_T_2_7, poseidon2_perm_T_3_4, poseidon2_perm_T_3_5, poseidon2_perm_T_3_6, poseidon2_perm_T_3_7, poseidon2_perm_T_60_4, poseidon2_perm_T_60_5, poseidon2_perm_T_60_6, poseidon2_perm_T_60_7, poseidon2_perm_T_61_4, poseidon2_perm_T_61_5, poseidon2_perm_T_61_6, poseidon2_perm_T_61_7, poseidon2_perm_T_62_4, poseidon2_perm_T_62_5, poseidon2_perm_T_62_6, poseidon2_perm_T_62_7, poseidon2_perm_T_63_4, poseidon2_perm_T_63_5, poseidon2_perm_T_63_6, poseidon2_perm_T_63_7, poseidon2_perm_a_0, poseidon2_perm_a_1, poseidon2_perm_a_2, poseidon2_perm_a_3, poseidon2_perm_b_0, poseidon2_perm_b_1, poseidon2_perm_b_2, poseidon2_perm_b_3, poseidon2_perm_sel, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, range_check_is_lte_u112, range_check_is_lte_u128, range_check_is_lte_u16, range_check_is_lte_u32, range_check_is_lte_u48, range_check_is_lte_u64, range_check_is_lte_u80, range_check_is_lte_u96, range_check_rng_chk_bits, range_check_sel, range_check_sel_r0_16_bit_rng_lookup, range_check_sel_r1_16_bit_rng_lookup, range_check_sel_r2_16_bit_rng_lookup, range_check_sel_r3_16_bit_rng_lookup, range_check_sel_r4_16_bit_rng_lookup, range_check_sel_r5_16_bit_rng_lookup, range_check_sel_r6_16_bit_rng_lookup, range_check_u16_r0, range_check_u16_r1, range_check_u16_r2, range_check_u16_r3, range_check_u16_r4, range_check_u16_r5, range_check_u16_r6, range_check_u16_r7, range_check_value, scalar_mul_bit, scalar_mul_bit_idx, scalar_mul_bit_radix, scalar_mul_end, scalar_mul_not_end, scalar_mul_point_inf, scalar_mul_point_x, scalar_mul_point_y, scalar_mul_res_inf, scalar_mul_res_x, scalar_mul_res_y, scalar_mul_scalar, scalar_mul_sel, scalar_mul_should_add, scalar_mul_start, scalar_mul_temp_inf, scalar_mul_temp_x, scalar_mul_temp_y, sha256_a, sha256_a_and_b, sha256_a_and_b_xor_a_and_c, sha256_a_and_c, sha256_a_rotr_13, sha256_a_rotr_2, sha256_a_rotr_22, sha256_a_rotr_2_xor_a_rotr_13, sha256_and_sel, sha256_b, sha256_b_and_c, sha256_c, sha256_ch, sha256_clk, sha256_computed_w_lhs, sha256_computed_w_rhs, sha256_d, sha256_e, sha256_e_and_f, sha256_e_rotr_11, sha256_e_rotr_25, sha256_e_rotr_6, sha256_e_rotr_6_xor_e_rotr_11, sha256_f, sha256_g, sha256_h, sha256_helper_w0, sha256_helper_w1, sha256_helper_w10, sha256_helper_w11, sha256_helper_w12, sha256_helper_w13, sha256_helper_w14, sha256_helper_w15, sha256_helper_w2, sha256_helper_w3, sha256_helper_w4, sha256_helper_w5, sha256_helper_w6, sha256_helper_w7, sha256_helper_w8, sha256_helper_w9, sha256_init_a, sha256_init_b, sha256_init_c, sha256_init_d, sha256_init_e, sha256_init_f, sha256_init_g, sha256_init_h, sha256_input_offset, sha256_is_input_round, sha256_latch, sha256_lhs_a_13, sha256_lhs_a_2, sha256_lhs_a_22, sha256_lhs_e_11, sha256_lhs_e_25, sha256_lhs_e_6, sha256_lhs_w_10, sha256_lhs_w_17, sha256_lhs_w_18, sha256_lhs_w_19, sha256_lhs_w_3, sha256_lhs_w_7, sha256_maj, sha256_next_a_lhs, sha256_next_a_rhs, sha256_next_e_lhs, sha256_next_e_rhs, sha256_not_e, sha256_not_e_and_g, sha256_output_a_lhs, sha256_output_a_rhs, sha256_output_b_lhs, sha256_output_b_rhs, sha256_output_c_lhs, sha256_output_c_rhs, sha256_output_d_lhs, sha256_output_d_rhs, sha256_output_e_lhs, sha256_output_e_rhs, sha256_output_f_lhs, sha256_output_f_rhs, sha256_output_g_lhs, sha256_output_g_rhs, sha256_output_h_lhs, sha256_output_h_rhs, sha256_output_offset, sha256_perform_round, sha256_rhs_a_13, sha256_rhs_a_2, sha256_rhs_a_22, sha256_rhs_e_11, sha256_rhs_e_25, sha256_rhs_e_6, sha256_rhs_w_10, sha256_rhs_w_17, sha256_rhs_w_18, sha256_rhs_w_19, sha256_rhs_w_3, sha256_rhs_w_7, sha256_round_constant, sha256_round_count, sha256_rounds_remaining, sha256_rounds_remaining_inv, sha256_s_0, sha256_s_1, sha256_sel, sha256_start, sha256_state_offset, sha256_w, sha256_w_15_rotr_18, sha256_w_15_rotr_7, sha256_w_15_rotr_7_xor_w_15_rotr_18, sha256_w_15_rshift_3, sha256_w_2_rotr_17, sha256_w_2_rotr_17_xor_w_2_rotr_19, sha256_w_2_rotr_19, sha256_w_2_rshift_10, sha256_w_s_0, sha256_w_s_1, sha256_xor_sel, to_radix_acc, to_radix_acc_under_p, to_radix_end, to_radix_exponent, to_radix_found, to_radix_is_unsafe_limb, to_radix_limb, to_radix_limb_eq_p, to_radix_limb_index, to_radix_limb_lt_p, to_radix_limb_p_diff, to_radix_limb_radix_diff, to_radix_not_end, to_radix_not_padding_limb, to_radix_p_limb, to_radix_radix, to_radix_rem_inverse, to_radix_safe_limbs, to_radix_safety_diff_inverse, to_radix_sel, to_radix_start, to_radix_value, lookup_poseidon2_hash_poseidon2_perm_counts, lookup_range_check_dyn_rng_chk_pow_2_counts, lookup_range_check_dyn_diff_is_u16_counts, lookup_range_check_r0_is_u16_counts, lookup_range_check_r1_is_u16_counts, lookup_range_check_r2_is_u16_counts, lookup_range_check_r3_is_u16_counts, lookup_range_check_r4_is_u16_counts, lookup_range_check_r5_is_u16_counts, lookup_range_check_r6_is_u16_counts, lookup_range_check_r7_is_u16_counts, lookup_to_radix_limb_range_counts, lookup_to_radix_limb_less_than_radix_range_counts, lookup_to_radix_fetch_safe_limbs_counts, lookup_to_radix_fetch_p_limb_counts, lookup_to_radix_limb_p_diff_range_counts, lookup_scalar_mul_to_radix_counts, lookup_scalar_mul_double_counts, lookup_scalar_mul_add_counts, lookup_address_derivation_salted_initialization_hash_poseidon2_0_counts, lookup_address_derivation_salted_initialization_hash_poseidon2_1_counts, lookup_address_derivation_partial_address_poseidon2_counts, lookup_address_derivation_public_keys_hash_poseidon2_0_counts, lookup_address_derivation_public_keys_hash_poseidon2_1_counts, lookup_address_derivation_public_keys_hash_poseidon2_2_counts, lookup_address_derivation_public_keys_hash_poseidon2_3_counts, lookup_address_derivation_public_keys_hash_poseidon2_4_counts, lookup_address_derivation_preaddress_poseidon2_counts, lookup_address_derivation_preaddress_scalar_mul_counts, lookup_address_derivation_address_ecadd_counts, lookup_bc_decomposition_bytes_are_bytes_counts, lookup_bc_decomposition_abs_diff_is_u16_counts, lookup_bc_decomposition_bytes_to_read_as_unary_counts, lookup_bc_hashing_get_packed_field_counts, lookup_bc_hashing_iv_is_len_counts, lookup_bc_hashing_poseidon2_hash_counts, lookup_bc_retrieval_class_id_derivation_counts, lookup_bc_retrieval_bytecode_hash_is_correct_counts, lookup_instr_fetching_pc_abs_diff_positive_counts, lookup_instr_fetching_instr_abs_diff_positive_counts, lookup_instr_fetching_tag_value_validation_counts, lookup_instr_fetching_bytecode_size_from_bc_dec_counts, lookup_instr_fetching_bytes_from_bc_dec_counts, lookup_instr_fetching_wire_instruction_info_counts, lookup_class_id_derivation_class_id_poseidon2_0_counts, lookup_class_id_derivation_class_id_poseidon2_1_counts, lookup_bitwise_integral_tag_length_counts, lookup_bitwise_byte_operations_counts, lookup_merkle_check_merkle_poseidon2_counts, lookup_sha256_round_constant_counts, lookup_ff_gt_a_lo_range_counts, lookup_ff_gt_a_hi_range_counts +#define AVM2_DERIVED_WITNESS_ENTITIES lookup_poseidon2_hash_poseidon2_perm_inv, lookup_range_check_dyn_rng_chk_pow_2_inv, lookup_range_check_dyn_diff_is_u16_inv, lookup_range_check_r0_is_u16_inv, lookup_range_check_r1_is_u16_inv, lookup_range_check_r2_is_u16_inv, lookup_range_check_r3_is_u16_inv, lookup_range_check_r4_is_u16_inv, lookup_range_check_r5_is_u16_inv, lookup_range_check_r6_is_u16_inv, lookup_range_check_r7_is_u16_inv, lookup_to_radix_limb_range_inv, lookup_to_radix_limb_less_than_radix_range_inv, lookup_to_radix_fetch_safe_limbs_inv, lookup_to_radix_fetch_p_limb_inv, lookup_to_radix_limb_p_diff_range_inv, lookup_scalar_mul_to_radix_inv, lookup_scalar_mul_double_inv, lookup_scalar_mul_add_inv, lookup_address_derivation_salted_initialization_hash_poseidon2_0_inv, lookup_address_derivation_salted_initialization_hash_poseidon2_1_inv, lookup_address_derivation_partial_address_poseidon2_inv, lookup_address_derivation_public_keys_hash_poseidon2_0_inv, lookup_address_derivation_public_keys_hash_poseidon2_1_inv, lookup_address_derivation_public_keys_hash_poseidon2_2_inv, lookup_address_derivation_public_keys_hash_poseidon2_3_inv, lookup_address_derivation_public_keys_hash_poseidon2_4_inv, lookup_address_derivation_preaddress_poseidon2_inv, lookup_address_derivation_preaddress_scalar_mul_inv, lookup_address_derivation_address_ecadd_inv, lookup_bc_decomposition_bytes_are_bytes_inv, lookup_bc_decomposition_abs_diff_is_u16_inv, lookup_bc_decomposition_bytes_to_read_as_unary_inv, lookup_bc_hashing_get_packed_field_inv, lookup_bc_hashing_iv_is_len_inv, lookup_bc_hashing_poseidon2_hash_inv, lookup_bc_retrieval_class_id_derivation_inv, lookup_bc_retrieval_bytecode_hash_is_correct_inv, lookup_instr_fetching_pc_abs_diff_positive_inv, lookup_instr_fetching_instr_abs_diff_positive_inv, lookup_instr_fetching_tag_value_validation_inv, lookup_instr_fetching_bytecode_size_from_bc_dec_inv, lookup_instr_fetching_bytes_from_bc_dec_inv, lookup_instr_fetching_wire_instruction_info_inv, lookup_class_id_derivation_class_id_poseidon2_0_inv, lookup_class_id_derivation_class_id_poseidon2_1_inv, lookup_bitwise_integral_tag_length_inv, lookup_bitwise_byte_operations_inv, lookup_merkle_check_merkle_poseidon2_inv, lookup_sha256_round_constant_inv, lookup_ff_gt_a_lo_range_inv, lookup_ff_gt_a_hi_range_inv #define AVM2_SHIFTED_ENTITIES bc_decomposition_bytes_shift, bc_decomposition_bytes_pc_plus_1_shift, bc_decomposition_bytes_pc_plus_10_shift, bc_decomposition_bytes_pc_plus_11_shift, bc_decomposition_bytes_pc_plus_12_shift, bc_decomposition_bytes_pc_plus_13_shift, bc_decomposition_bytes_pc_plus_14_shift, bc_decomposition_bytes_pc_plus_15_shift, bc_decomposition_bytes_pc_plus_16_shift, bc_decomposition_bytes_pc_plus_17_shift, bc_decomposition_bytes_pc_plus_18_shift, bc_decomposition_bytes_pc_plus_19_shift, bc_decomposition_bytes_pc_plus_2_shift, bc_decomposition_bytes_pc_plus_20_shift, bc_decomposition_bytes_pc_plus_21_shift, bc_decomposition_bytes_pc_plus_22_shift, bc_decomposition_bytes_pc_plus_23_shift, bc_decomposition_bytes_pc_plus_24_shift, bc_decomposition_bytes_pc_plus_25_shift, bc_decomposition_bytes_pc_plus_26_shift, bc_decomposition_bytes_pc_plus_27_shift, bc_decomposition_bytes_pc_plus_28_shift, bc_decomposition_bytes_pc_plus_29_shift, bc_decomposition_bytes_pc_plus_3_shift, bc_decomposition_bytes_pc_plus_30_shift, bc_decomposition_bytes_pc_plus_31_shift, bc_decomposition_bytes_pc_plus_32_shift, bc_decomposition_bytes_pc_plus_33_shift, bc_decomposition_bytes_pc_plus_34_shift, bc_decomposition_bytes_pc_plus_35_shift, bc_decomposition_bytes_pc_plus_4_shift, bc_decomposition_bytes_pc_plus_5_shift, bc_decomposition_bytes_pc_plus_6_shift, bc_decomposition_bytes_pc_plus_7_shift, bc_decomposition_bytes_pc_plus_8_shift, bc_decomposition_bytes_pc_plus_9_shift, bc_decomposition_bytes_remaining_shift, bc_decomposition_id_shift, bc_decomposition_pc_shift, bc_decomposition_sel_shift, bc_hashing_bytecode_id_shift, bc_hashing_incremental_hash_shift, bc_hashing_pc_index_shift, bc_hashing_sel_shift, bc_hashing_start_shift, bitwise_acc_ia_shift, bitwise_acc_ib_shift, bitwise_acc_ic_shift, bitwise_ctr_shift, bitwise_op_id_shift, execution_sel_shift, ff_gt_a_hi_shift, ff_gt_a_lo_shift, ff_gt_b_hi_shift, ff_gt_b_lo_shift, ff_gt_cmp_rng_ctr_shift, ff_gt_p_sub_a_hi_shift, ff_gt_p_sub_a_lo_shift, ff_gt_p_sub_b_hi_shift, ff_gt_p_sub_b_lo_shift, ff_gt_sel_shift, ff_gt_sel_gt_shift, merkle_check_current_index_in_layer_shift, merkle_check_current_node_shift, merkle_check_leaf_shift, merkle_check_leaf_index_shift, merkle_check_remaining_path_len_shift, merkle_check_sel_shift, merkle_check_start_shift, merkle_check_tree_height_shift, poseidon2_hash_a_0_shift, poseidon2_hash_a_1_shift, poseidon2_hash_a_2_shift, poseidon2_hash_a_3_shift, poseidon2_hash_input_0_shift, poseidon2_hash_input_1_shift, poseidon2_hash_input_2_shift, poseidon2_hash_num_perm_rounds_rem_shift, poseidon2_hash_output_shift, poseidon2_hash_sel_shift, poseidon2_hash_start_shift, scalar_mul_bit_idx_shift, scalar_mul_point_inf_shift, scalar_mul_point_x_shift, scalar_mul_point_y_shift, scalar_mul_res_inf_shift, scalar_mul_res_x_shift, scalar_mul_res_y_shift, scalar_mul_scalar_shift, scalar_mul_sel_shift, scalar_mul_start_shift, scalar_mul_temp_inf_shift, scalar_mul_temp_x_shift, scalar_mul_temp_y_shift, sha256_a_shift, sha256_b_shift, sha256_c_shift, sha256_d_shift, sha256_e_shift, sha256_f_shift, sha256_g_shift, sha256_h_shift, sha256_helper_w0_shift, sha256_helper_w1_shift, sha256_helper_w10_shift, sha256_helper_w11_shift, sha256_helper_w12_shift, sha256_helper_w13_shift, sha256_helper_w14_shift, sha256_helper_w15_shift, sha256_helper_w2_shift, sha256_helper_w3_shift, sha256_helper_w4_shift, sha256_helper_w5_shift, sha256_helper_w6_shift, sha256_helper_w7_shift, sha256_helper_w8_shift, sha256_helper_w9_shift, sha256_rounds_remaining_shift, sha256_sel_shift, sha256_start_shift, to_radix_acc_shift, to_radix_acc_under_p_shift, to_radix_exponent_shift, to_radix_limb_shift, to_radix_limb_eq_p_shift, to_radix_limb_index_shift, to_radix_limb_lt_p_shift, to_radix_not_padding_limb_shift, to_radix_radix_shift, to_radix_safe_limbs_shift, to_radix_sel_shift, to_radix_start_shift, to_radix_value_shift #define AVM2_TO_BE_SHIFTED(e) e.bc_decomposition_bytes, e.bc_decomposition_bytes_pc_plus_1, e.bc_decomposition_bytes_pc_plus_10, e.bc_decomposition_bytes_pc_plus_11, e.bc_decomposition_bytes_pc_plus_12, e.bc_decomposition_bytes_pc_plus_13, e.bc_decomposition_bytes_pc_plus_14, e.bc_decomposition_bytes_pc_plus_15, e.bc_decomposition_bytes_pc_plus_16, e.bc_decomposition_bytes_pc_plus_17, e.bc_decomposition_bytes_pc_plus_18, e.bc_decomposition_bytes_pc_plus_19, e.bc_decomposition_bytes_pc_plus_2, e.bc_decomposition_bytes_pc_plus_20, e.bc_decomposition_bytes_pc_plus_21, e.bc_decomposition_bytes_pc_plus_22, e.bc_decomposition_bytes_pc_plus_23, e.bc_decomposition_bytes_pc_plus_24, e.bc_decomposition_bytes_pc_plus_25, e.bc_decomposition_bytes_pc_plus_26, e.bc_decomposition_bytes_pc_plus_27, e.bc_decomposition_bytes_pc_plus_28, e.bc_decomposition_bytes_pc_plus_29, e.bc_decomposition_bytes_pc_plus_3, e.bc_decomposition_bytes_pc_plus_30, e.bc_decomposition_bytes_pc_plus_31, e.bc_decomposition_bytes_pc_plus_32, e.bc_decomposition_bytes_pc_plus_33, e.bc_decomposition_bytes_pc_plus_34, e.bc_decomposition_bytes_pc_plus_35, e.bc_decomposition_bytes_pc_plus_4, e.bc_decomposition_bytes_pc_plus_5, e.bc_decomposition_bytes_pc_plus_6, e.bc_decomposition_bytes_pc_plus_7, e.bc_decomposition_bytes_pc_plus_8, e.bc_decomposition_bytes_pc_plus_9, e.bc_decomposition_bytes_remaining, e.bc_decomposition_id, e.bc_decomposition_pc, e.bc_decomposition_sel, e.bc_hashing_bytecode_id, e.bc_hashing_incremental_hash, e.bc_hashing_pc_index, e.bc_hashing_sel, e.bc_hashing_start, e.bitwise_acc_ia, e.bitwise_acc_ib, e.bitwise_acc_ic, e.bitwise_ctr, e.bitwise_op_id, e.execution_sel, e.ff_gt_a_hi, e.ff_gt_a_lo, e.ff_gt_b_hi, e.ff_gt_b_lo, e.ff_gt_cmp_rng_ctr, e.ff_gt_p_sub_a_hi, e.ff_gt_p_sub_a_lo, e.ff_gt_p_sub_b_hi, e.ff_gt_p_sub_b_lo, e.ff_gt_sel, e.ff_gt_sel_gt, e.merkle_check_current_index_in_layer, e.merkle_check_current_node, e.merkle_check_leaf, e.merkle_check_leaf_index, e.merkle_check_remaining_path_len, e.merkle_check_sel, e.merkle_check_start, e.merkle_check_tree_height, e.poseidon2_hash_a_0, e.poseidon2_hash_a_1, e.poseidon2_hash_a_2, e.poseidon2_hash_a_3, e.poseidon2_hash_input_0, e.poseidon2_hash_input_1, e.poseidon2_hash_input_2, e.poseidon2_hash_num_perm_rounds_rem, e.poseidon2_hash_output, e.poseidon2_hash_sel, e.poseidon2_hash_start, e.scalar_mul_bit_idx, e.scalar_mul_point_inf, e.scalar_mul_point_x, e.scalar_mul_point_y, e.scalar_mul_res_inf, e.scalar_mul_res_x, e.scalar_mul_res_y, e.scalar_mul_scalar, e.scalar_mul_sel, e.scalar_mul_start, e.scalar_mul_temp_inf, e.scalar_mul_temp_x, e.scalar_mul_temp_y, e.sha256_a, e.sha256_b, e.sha256_c, e.sha256_d, e.sha256_e, e.sha256_f, e.sha256_g, e.sha256_h, e.sha256_helper_w0, e.sha256_helper_w1, e.sha256_helper_w10, e.sha256_helper_w11, e.sha256_helper_w12, e.sha256_helper_w13, e.sha256_helper_w14, e.sha256_helper_w15, e.sha256_helper_w2, e.sha256_helper_w3, e.sha256_helper_w4, e.sha256_helper_w5, e.sha256_helper_w6, e.sha256_helper_w7, e.sha256_helper_w8, e.sha256_helper_w9, e.sha256_rounds_remaining, e.sha256_sel, e.sha256_start, e.to_radix_acc, e.to_radix_acc_under_p, e.to_radix_exponent, e.to_radix_limb, e.to_radix_limb_eq_p, e.to_radix_limb_index, e.to_radix_limb_lt_p, e.to_radix_not_padding_limb, e.to_radix_radix, e.to_radix_safe_limbs, e.to_radix_sel, e.to_radix_start, e.to_radix_value #define AVM2_ALL_ENTITIES AVM2_PRECOMPUTED_ENTITIES, AVM2_WIRE_ENTITIES, AVM2_DERIVED_WITNESS_ENTITIES, AVM2_SHIFTED_ENTITIES @@ -31,8 +31,8 @@ enum class ColumnAndShifts { SENTINEL_DO_NOT_USE, }; -constexpr auto NUM_COLUMNS_WITH_SHIFTS = 1101; -constexpr auto NUM_COLUMNS_WITHOUT_SHIFTS = 967; +constexpr auto NUM_COLUMNS_WITH_SHIFTS = 1110; +constexpr auto NUM_COLUMNS_WITHOUT_SHIFTS = 976; constexpr auto TO_BE_SHIFTED_COLUMNS_ARRAY = []() { return std::array{ AVM2_TO_BE_SHIFTED_COLUMNS }; }(); constexpr auto SHIFTED_COLUMNS_ARRAY = []() { return std::array{ AVM2_SHIFTED_COLUMNS }; }(); static_assert(TO_BE_SHIFTED_COLUMNS_ARRAY.size() == SHIFTED_COLUMNS_ARRAY.size()); diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp index 483fc721013c..1cfa38c286fe 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp @@ -95,13 +95,13 @@ class AvmFlavor { // This flavor would not be used with ZK Sumcheck static constexpr bool HasZK = false; - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 44; - static constexpr size_t NUM_WITNESS_ENTITIES = 923; + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 47; + static constexpr size_t NUM_WITNESS_ENTITIES = 929; static constexpr size_t NUM_SHIFTED_ENTITIES = 134; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 1101; + static constexpr size_t NUM_ALL_ENTITIES = 1110; // In the sumcheck univariate computation, we divide the trace in chunks and each chunk is // evenly processed by all the threads. This constant defines the maximum number of rows @@ -173,6 +173,7 @@ class AvmFlavor { lookup_instr_fetching_bytes_from_bc_dec_relation, lookup_instr_fetching_instr_abs_diff_positive_relation, lookup_instr_fetching_pc_abs_diff_positive_relation, + lookup_instr_fetching_tag_value_validation_relation, lookup_instr_fetching_wire_instruction_info_relation, lookup_merkle_check_merkle_poseidon2_relation, lookup_poseidon2_hash_poseidon2_perm_relation, @@ -459,7 +460,9 @@ class AvmFlavor { this->precomputed_p_decomposition_radix = verification_key->precomputed_p_decomposition_radix; this->precomputed_power_of_2 = verification_key->precomputed_power_of_2; this->precomputed_sel_bitwise = verification_key->precomputed_sel_bitwise; + this->precomputed_sel_has_tag = verification_key->precomputed_sel_has_tag; this->precomputed_sel_integral_tag = verification_key->precomputed_sel_integral_tag; + this->precomputed_sel_mem_tag_out_of_range = verification_key->precomputed_sel_mem_tag_out_of_range; this->precomputed_sel_op_dc_0 = verification_key->precomputed_sel_op_dc_0; this->precomputed_sel_op_dc_1 = verification_key->precomputed_sel_op_dc_1; this->precomputed_sel_op_dc_10 = verification_key->precomputed_sel_op_dc_10; @@ -482,6 +485,7 @@ class AvmFlavor { this->precomputed_sel_range_16 = verification_key->precomputed_sel_range_16; this->precomputed_sel_range_8 = verification_key->precomputed_sel_range_8; this->precomputed_sel_sha256_compression = verification_key->precomputed_sel_sha256_compression; + this->precomputed_sel_tag_is_op2 = verification_key->precomputed_sel_tag_is_op2; this->precomputed_sel_to_radix_safe_limbs = verification_key->precomputed_sel_to_radix_safe_limbs; this->precomputed_sel_unary = verification_key->precomputed_sel_unary; this->precomputed_sha256_compression_round_constant = diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/instr_fetching.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/instr_fetching.hpp index 37ab6f559fbe..c4fff557c716 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/instr_fetching.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/instr_fetching.hpp @@ -12,8 +12,8 @@ template class instr_fetchingImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 4, 3, 4, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4 }; + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 2, 3, 4, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4 }; template inline static bool skip(const AllEntities& in) { @@ -28,6 +28,9 @@ template class instr_fetchingImpl { [[maybe_unused]] const FF& scaling_factor) { const auto constants_AVM_PC_SIZE_IN_BITS = FF(32); + const auto instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR = new_term.instr_fetching_pc_out_of_range + + new_term.instr_fetching_opcode_out_of_range + + new_term.instr_fetching_instr_out_of_range; const auto instr_fetching_SEL_OP_DC_18 = new_term.instr_fetching_sel_op_dc_2 + new_term.instr_fetching_sel_op_dc_6; @@ -53,18 +56,13 @@ template class instr_fetchingImpl { { using Accumulator = typename std::tuple_element_t<3, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_parsing_err - - (FF(1) - (FF(1) - new_term.instr_fetching_pc_out_of_range) * - (FF(1) - new_term.instr_fetching_instr_out_of_range) * - (FF(1) - new_term.instr_fetching_opcode_out_of_range))); + (instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR + new_term.instr_fetching_tag_out_of_range)); tmp *= scaling_factor; std::get<3>(evals) += typename Accumulator::View(tmp); } - { // INSTR_OUT_OF_RANGE_TOGGLE + { using Accumulator = typename std::tuple_element_t<4, ContainerOverSubrelations>; - auto tmp = (new_term.instr_fetching_instr_abs_diff - - ((FF(2) * new_term.instr_fetching_instr_out_of_range - FF(1)) * - (new_term.instr_fetching_instr_size - new_term.instr_fetching_bytes_to_read) - - new_term.instr_fetching_instr_out_of_range)); + auto tmp = new_term.instr_fetching_parsing_err * (FF(1) - new_term.instr_fetching_parsing_err); tmp *= scaling_factor; std::get<4>(evals) += typename Accumulator::View(tmp); } @@ -86,27 +84,45 @@ template class instr_fetchingImpl { tmp *= scaling_factor; std::get<6>(evals) += typename Accumulator::View(tmp); } - { + { // INSTR_OUT_OF_RANGE_TOGGLE using Accumulator = typename std::tuple_element_t<7, ContainerOverSubrelations>; - auto tmp = (new_term.instr_fetching_sel_opcode_defined - - new_term.instr_fetching_sel * (FF(1) - new_term.instr_fetching_pc_out_of_range)); + auto tmp = (new_term.instr_fetching_instr_abs_diff - + ((FF(2) * new_term.instr_fetching_instr_out_of_range - FF(1)) * + (new_term.instr_fetching_instr_size - new_term.instr_fetching_bytes_to_read) - + new_term.instr_fetching_instr_out_of_range)); tmp *= scaling_factor; std::get<7>(evals) += typename Accumulator::View(tmp); } - { // INDIRECT_BYTES_DECOMPOSITION + { // TAG_VALUE using Accumulator = typename std::tuple_element_t<8, ContainerOverSubrelations>; + auto tmp = (new_term.instr_fetching_tag_value - + ((new_term.instr_fetching_sel_has_tag - new_term.instr_fetching_sel_tag_is_op2) * + new_term.instr_fetching_op3 + + new_term.instr_fetching_sel_tag_is_op2 * new_term.instr_fetching_op2)); + tmp *= scaling_factor; + std::get<8>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<9, ContainerOverSubrelations>; + auto tmp = (new_term.instr_fetching_sel_pc_in_range - + new_term.instr_fetching_sel * (FF(1) - new_term.instr_fetching_pc_out_of_range)); + tmp *= scaling_factor; + std::get<9>(evals) += typename Accumulator::View(tmp); + } + { // INDIRECT_BYTES_DECOMPOSITION + using Accumulator = typename std::tuple_element_t<10, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_indirect - - (FF(1) - new_term.instr_fetching_parsing_err) * + (FF(1) - instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR) * (new_term.instr_fetching_sel_op_dc_0 * (new_term.instr_fetching_bd1 * FF(256) + new_term.instr_fetching_bd2 * FF(1)) + instr_fetching_SEL_OP_DC_18 * new_term.instr_fetching_bd1 * FF(1))); tmp *= scaling_factor; - std::get<8>(evals) += typename Accumulator::View(tmp); + std::get<10>(evals) += typename Accumulator::View(tmp); } { // OP1_BYTES_DECOMPOSITION - using Accumulator = typename std::tuple_element_t<9, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<11, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_op1 - - (FF(1) - new_term.instr_fetching_parsing_err) * + (FF(1) - instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR) * (new_term.instr_fetching_sel_op_dc_0 * (new_term.instr_fetching_bd3 * FF(256) + new_term.instr_fetching_bd4 * FF(1)) + new_term.instr_fetching_sel_op_dc_2 * @@ -116,12 +132,12 @@ template class instr_fetchingImpl { (new_term.instr_fetching_bd1 * FF(16777216) + new_term.instr_fetching_bd2 * FF(65536) + new_term.instr_fetching_bd3 * FF(256) + new_term.instr_fetching_bd4 * FF(1)))); tmp *= scaling_factor; - std::get<9>(evals) += typename Accumulator::View(tmp); + std::get<11>(evals) += typename Accumulator::View(tmp); } { // OP2_BYTES_DECOMPOSITION - using Accumulator = typename std::tuple_element_t<10, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<12, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_op2 - - (FF(1) - new_term.instr_fetching_parsing_err) * + (FF(1) - instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR) * (new_term.instr_fetching_sel_op_dc_0 * (new_term.instr_fetching_bd5 * FF(256) + new_term.instr_fetching_bd6 * FF(1)) + new_term.instr_fetching_sel_op_dc_3 * @@ -132,13 +148,13 @@ template class instr_fetchingImpl { (new_term.instr_fetching_bd4 * FF(16777216) + new_term.instr_fetching_bd5 * FF(65536) + new_term.instr_fetching_bd6 * FF(256) + new_term.instr_fetching_bd7 * FF(1)))); tmp *= scaling_factor; - std::get<10>(evals) += typename Accumulator::View(tmp); + std::get<12>(evals) += typename Accumulator::View(tmp); } { // OP3_BYTES_DECOMPOSITION - using Accumulator = typename std::tuple_element_t<11, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<13, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_op3 - - (FF(1) - new_term.instr_fetching_parsing_err) * + (FF(1) - instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR) * (new_term.instr_fetching_sel_op_dc_0 * (new_term.instr_fetching_bd7 * FF(256) + new_term.instr_fetching_bd8 * FF(1)) + new_term.instr_fetching_sel_op_dc_4 * @@ -204,43 +220,43 @@ template class instr_fetchingImpl { new_term.instr_fetching_sel_op_dc_14 * new_term.instr_fetching_bd4 * FF(1) + new_term.instr_fetching_sel_op_dc_17 * new_term.instr_fetching_bd6 * FF(1))); tmp *= scaling_factor; - std::get<11>(evals) += typename Accumulator::View(tmp); + std::get<13>(evals) += typename Accumulator::View(tmp); } { // OP4_BYTES_DECOMPOSITION - using Accumulator = typename std::tuple_element_t<12, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<14, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_op4 - - (FF(1) - new_term.instr_fetching_parsing_err) * + (FF(1) - instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR) * (new_term.instr_fetching_sel_op_dc_0 * (new_term.instr_fetching_bd9 * FF(256) + new_term.instr_fetching_bd10 * FF(1)) + new_term.instr_fetching_sel_op_dc_5 * (new_term.instr_fetching_bd8 * FF(256) + new_term.instr_fetching_bd9 * FF(1)) + new_term.instr_fetching_sel_op_dc_7 * new_term.instr_fetching_bd8 * FF(1))); tmp *= scaling_factor; - std::get<12>(evals) += typename Accumulator::View(tmp); + std::get<14>(evals) += typename Accumulator::View(tmp); } { // OP5_BYTES_DECOMPOSITION - using Accumulator = typename std::tuple_element_t<13, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<15, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_op5 - - (FF(1) - new_term.instr_fetching_parsing_err) * new_term.instr_fetching_sel_op_dc_0 * + (FF(1) - instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR) * new_term.instr_fetching_sel_op_dc_0 * (new_term.instr_fetching_bd11 * FF(256) + new_term.instr_fetching_bd12 * FF(1))); tmp *= scaling_factor; - std::get<13>(evals) += typename Accumulator::View(tmp); + std::get<15>(evals) += typename Accumulator::View(tmp); } { // OP6_BYTES_DECOMPOSITION - using Accumulator = typename std::tuple_element_t<14, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<16, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_op6 - - (FF(1) - new_term.instr_fetching_parsing_err) * new_term.instr_fetching_sel_op_dc_1 * + (FF(1) - instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR) * new_term.instr_fetching_sel_op_dc_1 * (new_term.instr_fetching_bd13 * FF(256) + new_term.instr_fetching_bd14 * FF(1))); tmp *= scaling_factor; - std::get<14>(evals) += typename Accumulator::View(tmp); + std::get<16>(evals) += typename Accumulator::View(tmp); } { // OP7_BYTES_DECOMPOSITION - using Accumulator = typename std::tuple_element_t<15, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<17, ContainerOverSubrelations>; auto tmp = (new_term.instr_fetching_op7 - - (FF(1) - new_term.instr_fetching_parsing_err) * new_term.instr_fetching_sel_op_dc_1 * + (FF(1) - instr_fetching_PARSING_ERROR_EXCEPT_TAG_ERROR) * new_term.instr_fetching_sel_op_dc_1 * (new_term.instr_fetching_bd15 * FF(256) + new_term.instr_fetching_bd16 * FF(1))); tmp *= scaling_factor; - std::get<15>(evals) += typename Accumulator::View(tmp); + std::get<17>(evals) += typename Accumulator::View(tmp); } } }; @@ -252,41 +268,44 @@ template class instr_fetching : public Relation SRC_COLUMNS = { + ColumnAndShifts::instr_fetching_pc_abs_diff, ColumnAndShifts::instr_fetching_pc_size_in_bits + }; + static constexpr std::array DST_COLUMNS = { + ColumnAndShifts::range_check_value, ColumnAndShifts::range_check_rng_chk_bits + }; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in._instr_fetching_sel() == 1 || in._range_check_sel() == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in._instr_fetching_sel()); + const auto is_table_entry = View(in._range_check_sel()); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return get_entities(in); + } + + template static inline auto get_entities(AllEntities&& in) + { + return std::forward_as_tuple(in._lookup_instr_fetching_pc_abs_diff_positive_inv(), + in._lookup_instr_fetching_pc_abs_diff_positive_counts(), + in._instr_fetching_sel(), + in._range_check_sel(), + in._instr_fetching_pc_abs_diff(), + in._instr_fetching_pc_size_in_bits(), + in._range_check_value(), + in._range_check_rng_chk_bits()); + } +}; + +template +class lookup_instr_fetching_pc_abs_diff_positive_relation + : public GenericLookupRelation { + public: + using Settings = lookup_instr_fetching_pc_abs_diff_positive_settings; + static constexpr std::string_view NAME = lookup_instr_fetching_pc_abs_diff_positive_settings::NAME; + static constexpr std::string_view RELATION_NAME = + lookup_instr_fetching_pc_abs_diff_positive_settings::RELATION_NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.lookup_instr_fetching_pc_abs_diff_positive_inv.is_zero(); + } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } +}; + /////////////////// lookup_instr_fetching_instr_abs_diff_positive /////////////////// class lookup_instr_fetching_instr_abs_diff_positive_settings { @@ -96,11 +186,11 @@ class lookup_instr_fetching_instr_abs_diff_positive_relation } }; -/////////////////// lookup_instr_fetching_pc_abs_diff_positive /////////////////// +/////////////////// lookup_instr_fetching_tag_value_validation /////////////////// -class lookup_instr_fetching_pc_abs_diff_positive_settings { +class lookup_instr_fetching_tag_value_validation_settings { public: - static constexpr std::string_view NAME = "LOOKUP_INSTR_FETCHING_PC_ABS_DIFF_POSITIVE"; + static constexpr std::string_view NAME = "LOOKUP_INSTR_FETCHING_TAG_VALUE_VALIDATION"; static constexpr std::string_view RELATION_NAME = "instr_fetching"; static constexpr size_t READ_TERMS = 1; @@ -113,28 +203,28 @@ class lookup_instr_fetching_pc_abs_diff_positive_settings { static constexpr size_t WRITE_TERM_DEGREE = 0; // Columns using the Column enum. - static constexpr Column SRC_SELECTOR = Column::instr_fetching_sel; - static constexpr Column DST_SELECTOR = Column::range_check_sel; - static constexpr Column COUNTS = Column::lookup_instr_fetching_pc_abs_diff_positive_counts; - static constexpr Column INVERSES = Column::lookup_instr_fetching_pc_abs_diff_positive_inv; + static constexpr Column SRC_SELECTOR = Column::instr_fetching_sel_has_tag; + static constexpr Column DST_SELECTOR = Column::precomputed_sel_range_8; + static constexpr Column COUNTS = Column::lookup_instr_fetching_tag_value_validation_counts; + static constexpr Column INVERSES = Column::lookup_instr_fetching_tag_value_validation_inv; static constexpr std::array SRC_COLUMNS = { - ColumnAndShifts::instr_fetching_pc_abs_diff, ColumnAndShifts::instr_fetching_pc_size_in_bits + ColumnAndShifts::instr_fetching_tag_value, ColumnAndShifts::instr_fetching_tag_out_of_range }; static constexpr std::array DST_COLUMNS = { - ColumnAndShifts::range_check_value, ColumnAndShifts::range_check_rng_chk_bits + ColumnAndShifts::precomputed_clk, ColumnAndShifts::precomputed_sel_mem_tag_out_of_range }; template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) { - return (in._instr_fetching_sel() == 1 || in._range_check_sel() == 1); + return (in._instr_fetching_sel_has_tag() == 1 || in._precomputed_sel_range_8() == 1); } template static inline auto compute_inverse_exists(const AllEntities& in) { using View = typename Accumulator::View; - const auto is_operation = View(in._instr_fetching_sel()); - const auto is_table_entry = View(in._range_check_sel()); + const auto is_operation = View(in._instr_fetching_sel_has_tag()); + const auto is_table_entry = View(in._precomputed_sel_range_8()); return (is_operation + is_table_entry - is_operation * is_table_entry); } @@ -150,29 +240,29 @@ class lookup_instr_fetching_pc_abs_diff_positive_settings { template static inline auto get_entities(AllEntities&& in) { - return std::forward_as_tuple(in._lookup_instr_fetching_pc_abs_diff_positive_inv(), - in._lookup_instr_fetching_pc_abs_diff_positive_counts(), - in._instr_fetching_sel(), - in._range_check_sel(), - in._instr_fetching_pc_abs_diff(), - in._instr_fetching_pc_size_in_bits(), - in._range_check_value(), - in._range_check_rng_chk_bits()); + return std::forward_as_tuple(in._lookup_instr_fetching_tag_value_validation_inv(), + in._lookup_instr_fetching_tag_value_validation_counts(), + in._instr_fetching_sel_has_tag(), + in._precomputed_sel_range_8(), + in._instr_fetching_tag_value(), + in._instr_fetching_tag_out_of_range(), + in._precomputed_clk(), + in._precomputed_sel_mem_tag_out_of_range()); } }; template -class lookup_instr_fetching_pc_abs_diff_positive_relation - : public GenericLookupRelation { +class lookup_instr_fetching_tag_value_validation_relation + : public GenericLookupRelation { public: - using Settings = lookup_instr_fetching_pc_abs_diff_positive_settings; - static constexpr std::string_view NAME = lookup_instr_fetching_pc_abs_diff_positive_settings::NAME; + using Settings = lookup_instr_fetching_tag_value_validation_settings; + static constexpr std::string_view NAME = lookup_instr_fetching_tag_value_validation_settings::NAME; static constexpr std::string_view RELATION_NAME = - lookup_instr_fetching_pc_abs_diff_positive_settings::RELATION_NAME; + lookup_instr_fetching_tag_value_validation_settings::RELATION_NAME; template inline static bool skip(const AllEntities& in) { - return in.lookup_instr_fetching_pc_abs_diff_positive_inv.is_zero(); + return in.lookup_instr_fetching_tag_value_validation_inv.is_zero(); } static std::string get_subrelation_label(size_t index) @@ -299,7 +389,7 @@ class lookup_instr_fetching_bytes_from_bc_dec_settings { static constexpr size_t WRITE_TERM_DEGREE = 0; // Columns using the Column enum. - static constexpr Column SRC_SELECTOR = Column::instr_fetching_sel_opcode_defined; + static constexpr Column SRC_SELECTOR = Column::instr_fetching_sel_pc_in_range; static constexpr Column DST_SELECTOR = Column::bc_decomposition_sel; static constexpr Column COUNTS = Column::lookup_instr_fetching_bytes_from_bc_dec_counts; static constexpr Column INVERSES = Column::lookup_instr_fetching_bytes_from_bc_dec_inv; @@ -370,14 +460,14 @@ class lookup_instr_fetching_bytes_from_bc_dec_settings { template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) { - return (in._instr_fetching_sel_opcode_defined() == 1 || in._bc_decomposition_sel() == 1); + return (in._instr_fetching_sel_pc_in_range() == 1 || in._bc_decomposition_sel() == 1); } template static inline auto compute_inverse_exists(const AllEntities& in) { using View = typename Accumulator::View; - const auto is_operation = View(in._instr_fetching_sel_opcode_defined()); + const auto is_operation = View(in._instr_fetching_sel_pc_in_range()); const auto is_table_entry = View(in._bc_decomposition_sel()); return (is_operation + is_table_entry - is_operation * is_table_entry); } @@ -396,7 +486,7 @@ class lookup_instr_fetching_bytes_from_bc_dec_settings { { return std::forward_as_tuple(in._lookup_instr_fetching_bytes_from_bc_dec_inv(), in._lookup_instr_fetching_bytes_from_bc_dec_counts(), - in._instr_fetching_sel_opcode_defined(), + in._instr_fetching_sel_pc_in_range(), in._bc_decomposition_sel(), in._instr_fetching_bytecode_id(), in._instr_fetching_pc(), @@ -516,19 +606,20 @@ class lookup_instr_fetching_wire_instruction_info_settings { static constexpr size_t WRITE_TERMS = 1; static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; - static constexpr size_t LOOKUP_TUPLE_SIZE = 22; + static constexpr size_t LOOKUP_TUPLE_SIZE = 24; static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; static constexpr size_t READ_TERM_DEGREE = 0; static constexpr size_t WRITE_TERM_DEGREE = 0; // Columns using the Column enum. - static constexpr Column SRC_SELECTOR = Column::instr_fetching_sel_opcode_defined; + static constexpr Column SRC_SELECTOR = Column::instr_fetching_sel_pc_in_range; static constexpr Column DST_SELECTOR = Column::precomputed_sel_range_8; static constexpr Column COUNTS = Column::lookup_instr_fetching_wire_instruction_info_counts; static constexpr Column INVERSES = Column::lookup_instr_fetching_wire_instruction_info_inv; static constexpr std::array SRC_COLUMNS = { ColumnAndShifts::instr_fetching_bd0, ColumnAndShifts::instr_fetching_opcode_out_of_range, ColumnAndShifts::instr_fetching_exec_opcode, ColumnAndShifts::instr_fetching_instr_size, + ColumnAndShifts::instr_fetching_sel_has_tag, ColumnAndShifts::instr_fetching_sel_tag_is_op2, ColumnAndShifts::instr_fetching_sel_op_dc_0, ColumnAndShifts::instr_fetching_sel_op_dc_1, ColumnAndShifts::instr_fetching_sel_op_dc_2, ColumnAndShifts::instr_fetching_sel_op_dc_3, ColumnAndShifts::instr_fetching_sel_op_dc_4, ColumnAndShifts::instr_fetching_sel_op_dc_5, @@ -542,6 +633,7 @@ class lookup_instr_fetching_wire_instruction_info_settings { static constexpr std::array DST_COLUMNS = { ColumnAndShifts::precomputed_clk, ColumnAndShifts::precomputed_opcode_out_of_range, ColumnAndShifts::precomputed_exec_opcode, ColumnAndShifts::precomputed_instr_size, + ColumnAndShifts::precomputed_sel_has_tag, ColumnAndShifts::precomputed_sel_tag_is_op2, ColumnAndShifts::precomputed_sel_op_dc_0, ColumnAndShifts::precomputed_sel_op_dc_1, ColumnAndShifts::precomputed_sel_op_dc_2, ColumnAndShifts::precomputed_sel_op_dc_3, ColumnAndShifts::precomputed_sel_op_dc_4, ColumnAndShifts::precomputed_sel_op_dc_5, @@ -555,14 +647,14 @@ class lookup_instr_fetching_wire_instruction_info_settings { template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) { - return (in._instr_fetching_sel_opcode_defined() == 1 || in._precomputed_sel_range_8() == 1); + return (in._instr_fetching_sel_pc_in_range() == 1 || in._precomputed_sel_range_8() == 1); } template static inline auto compute_inverse_exists(const AllEntities& in) { using View = typename Accumulator::View; - const auto is_operation = View(in._instr_fetching_sel_opcode_defined()); + const auto is_operation = View(in._instr_fetching_sel_pc_in_range()); const auto is_table_entry = View(in._precomputed_sel_range_8()); return (is_operation + is_table_entry - is_operation * is_table_entry); } @@ -581,12 +673,14 @@ class lookup_instr_fetching_wire_instruction_info_settings { { return std::forward_as_tuple(in._lookup_instr_fetching_wire_instruction_info_inv(), in._lookup_instr_fetching_wire_instruction_info_counts(), - in._instr_fetching_sel_opcode_defined(), + in._instr_fetching_sel_pc_in_range(), in._precomputed_sel_range_8(), in._instr_fetching_bd0(), in._instr_fetching_opcode_out_of_range(), in._instr_fetching_exec_opcode(), in._instr_fetching_instr_size(), + in._instr_fetching_sel_has_tag(), + in._instr_fetching_sel_tag_is_op2(), in._instr_fetching_sel_op_dc_0(), in._instr_fetching_sel_op_dc_1(), in._instr_fetching_sel_op_dc_2(), @@ -609,6 +703,8 @@ class lookup_instr_fetching_wire_instruction_info_settings { in._precomputed_opcode_out_of_range(), in._precomputed_exec_opcode(), in._precomputed_instr_size(), + in._precomputed_sel_has_tag(), + in._precomputed_sel_tag_is_op2(), in._precomputed_sel_op_dc_0(), in._precomputed_sel_op_dc_1(), in._precomputed_sel_op_dc_2(), diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp index a02f4d02e42f..c3e11c7b7d6f 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp @@ -71,12 +71,17 @@ Instruction TxBytecodeManager::read_instruction(BytecodeId bytecode_id, uint32_t instr_fetching_event.bytecode = bytecode_ptr; const auto& bytecode = *bytecode_ptr; - instr_fetching_event.error = InstrDeserializationError::NO_ERROR; // TODO: Propagate instruction fetching error to the upper layer (execution loop) try { instr_fetching_event.instruction = deserialize_instruction(bytecode, pc); + + // If the following code is executed, no error was thrown in deserialize_instruction(). + if (!check_tag(instr_fetching_event.instruction)) { + instr_fetching_event.error = InstrDeserializationError::TAG_OUT_OF_RANGE; + }; } catch (const InstrDeserializationError& error) { + assert(error != InstrDeserializationError::TAG_OUT_OF_RANGE); instr_fetching_event.error = error; } diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/bytecode_events.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/bytecode_events.hpp index aace0ed903c9..cbdeb9ddeaaa 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/bytecode_events.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/bytecode_events.hpp @@ -45,7 +45,7 @@ struct InstructionFetchingEvent { // TODO: Do we want to have a dep on Instruction here or do we redefine what we need? Instruction instruction; std::shared_ptr> bytecode; - InstrDeserializationError error = InstrDeserializationError::NO_ERROR; + std::optional error; // To be used with deduplicating event emitters. using Key = std::tuple; diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.cpp index 0c5c3b84b2c5..e3c973632bce 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.cpp @@ -367,15 +367,14 @@ Instruction deserialize_instruction(std::span bytecode, size_t po const auto bytecode_length = bytecode.size(); if (pos >= bytecode_length) { - vinfo("PC is out of range. Position: " + std::to_string(pos) + - " Bytecode length: " + std::to_string(bytecode_length)); + vinfo("PC is out of range. Position: ", pos, " Bytecode length: ", bytecode_length); throw InstrDeserializationError::PC_OUT_OF_RANGE; } const uint8_t opcode_byte = bytecode[pos]; if (!is_wire_opcode_valid(opcode_byte)) { - vinfo("Invalid wire opcode byte: 0x" + to_hex(opcode_byte) + " at position: " + std::to_string(pos)); + vinfo("Invalid wire opcode byte: 0x", to_hex(opcode_byte), " at position: ", pos); throw InstrDeserializationError::OPCODE_OUT_OF_RANGE; } @@ -410,28 +409,15 @@ Instruction deserialize_instruction(std::span bytecode, size_t po // pos + instruction_size <= bytecode_length switch (op_type) { - case OperandType::TAG: { - uint8_t tag_u8 = bytecode[pos]; - // TODO: To handle in a subsequent PR (not decided if handled in specific opcode gadgets) - // if (tag_u8 > MAX_MEM_TAG) { - // vinfo("Instruction tag is invalid at position " + std::to_string(pos) + - // " value: " + std::to_string(tag_u8) + " for WireOpCode: " + to_string(WireOpCode)); - // return InstructionWithError{ - // .instruction = Instruction(WireOpCode::LAST_WireOpCode_SENTINEL, {}), - // .error = AvmError::INVALID_TAG_VALUE, - // }; - // } - operands.emplace_back(tag_u8); + case OperandType::TAG: + case OperandType::UINT8: { + operands.emplace_back(bytecode[pos]); break; } case OperandType::INDIRECT8: { indirect = bytecode[pos]; break; } - case OperandType::UINT8: { - operands.emplace_back(bytecode[pos]); - break; - } case OperandType::INDIRECT16: { uint16_t operand_u16 = 0; uint8_t const* pos_ptr = &bytecode[pos]; @@ -547,4 +533,60 @@ std::vector Instruction::serialize() const return output; } +bool check_tag(const Instruction& instruction) +{ + if (instruction.opcode == WireOpCode::LAST_OPCODE_SENTINEL) { + vinfo("Instruction does not contain a valid wire opcode."); + return false; + } + + const auto& wire_format = WireOpCode_WIRE_FORMAT.at(instruction.opcode); + + size_t pos = 0; // Position in instruction operands + + for (size_t i = 0; i < wire_format.size(); i++) { + if (wire_format[i] == OperandType::INDIRECT8 || wire_format[i] == OperandType::INDIRECT16) { + continue; // No pos increment + } + + if (wire_format[i] == OperandType::TAG) { + if (pos >= instruction.operands.size()) { + vinfo("Instruction operands size is too small. Tag position: ", + pos, + " size: ", + instruction.operands.size(), + " WireOpCode: ", + instruction.opcode); + return false; + } + + try { + uint8_t tag = static_cast(instruction.operands.at(pos)); // Cast to uint8_t might throw + + if (tag > static_cast(MemoryTag::MAX)) { + vinfo("Instruction tag operand at position: ", + pos, + " is invalid.", + " Tag value: ", + tag, + " WireOpCode: ", + instruction.opcode); + return false; + } + + } catch (const std::runtime_error&) { + vinfo("Instruction operand at position: ", + pos, + " is longer than a byte.", + " WireOpCode: ", + instruction.opcode); + return false; + } + } + + pos++; + } + return true; +} + } // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.hpp index 9452cf3fe7ed..d5627431bee9 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.hpp @@ -83,10 +83,10 @@ struct Instruction { }; enum class InstrDeserializationError : uint8_t { - NO_ERROR, PC_OUT_OF_RANGE, OPCODE_OUT_OF_RANGE, INSTRUCTION_OUT_OF_RANGE, + TAG_OUT_OF_RANGE, }; /** @@ -101,4 +101,15 @@ enum class InstrDeserializationError : uint8_t { */ Instruction deserialize_instruction(std::span bytecode, size_t pos); +/** + * @brief Check whether the instruction must have a tag operand and whether the operand + * value is in the value tag range. This is specified by OPCODE_WIRE_FORMAT. If + * the instruction does not have a valid wire opcode or the relevant tag operand + * is missing, we return false. However, we do not fully validate the instruction. + * + * @param instruction The instruction to be checked upon. + * @return Boolean telling whether instruction complies with the tag specification. + */ +bool check_tag(const Instruction& instruction); + } // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.test.cpp index a68458073384..ec0d01f61837 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.test.cpp @@ -6,6 +6,8 @@ namespace bb::avm2 { namespace { + +using simulation::check_tag; using simulation::deserialize_instruction; using simulation::InstrDeserializationError; using simulation::Instruction; @@ -131,5 +133,45 @@ TEST(SerializationTest, InstructionOutOfRange) } } +// Testing check_tag with a valid instruction for wire opcode SET_128 +TEST(SerializationTest, CheckTagValid) +{ + Instruction instr = { + .opcode = WireOpCode::SET_128, + .indirect = 2, + .operands = { Operand::u16(1002), Operand::u8(static_cast(MemoryTag::U128)), Operand::u128(12345) } + }; + EXPECT_TRUE(check_tag(instr)); +} + +// Testing check_tag with an invalid tag for wire opcode SET_128 +TEST(SerializationTest, CheckTagInvalid) +{ + Instruction instr = { + .opcode = WireOpCode::SET_128, + .indirect = 2, + .operands = { Operand::u16(1002), Operand::u8(static_cast(MemoryTag::MAX) + 1), Operand::u128(12345) } + }; + EXPECT_FALSE(check_tag(instr)); +} + +// Testing check_tag with an invalid instruction for wire opcode SET_128, not enough operands +TEST(SerializationTest, CheckTagInvalidNotEnoughOperands) +{ + Instruction instr = { .opcode = WireOpCode::SET_128, .indirect = 2, .operands = { Operand::u16(1002) } }; + EXPECT_FALSE(check_tag(instr)); +} + +// Testing check_tag with an invalid instruction for wire opcode SET_128, tag is not a byte +TEST(SerializationTest, CheckTagInvalidTagNotByte) +{ + Instruction instr = { + .opcode = WireOpCode::SET_128, + .indirect = 2, + .operands = { Operand::u16(1002), Operand::u16(static_cast(MemoryTag::U128)), Operand::u128(12345) } + }; + EXPECT_FALSE(check_tag(instr)); +} + } // namespace } // namespace bb::avm2 diff --git a/barretenberg/cpp/src/barretenberg/vm2/testing/fixtures.cpp b/barretenberg/cpp/src/barretenberg/vm2/testing/fixtures.cpp index c9f484c883ed..5b8801b991e7 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/testing/fixtures.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/testing/fixtures.cpp @@ -14,9 +14,6 @@ using simulation::Instruction; using simulation::Operand; using simulation::OperandType; -// If MemoryTag enum changes, this value might need to be adjusted. -constexpr uint8_t NUM_MEMORY_TAGS = static_cast(MemoryTag::U128) + 1; - std::vector random_fields(size_t n) { std::vector fields; @@ -52,7 +49,8 @@ Operand random_operand(OperandType operand_type) case OperandType::TAG: { uint8_t operand_u8 = 0; serialize::read(pos_ptr, operand_u8); - return Operand::u8(operand_u8 % NUM_MEMORY_TAGS); // Insecure bias but it is fine for testing purposes. + return Operand::u8(operand_u8 % static_cast(MemoryTag::MAX) + + 1); // Insecure bias but it is fine for testing purposes. } case OperandType::INDIRECT16: // Irrelevant bits might be toggled but they are ignored during address resolution. case OperandType::UINT16: { diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/bytecode_trace.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/bytecode_trace.cpp index c2bc93c246ba..5add4c7a3350 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/bytecode_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/bytecode_trace.cpp @@ -250,9 +250,9 @@ void BytecodeTraceBuilder::process_instruction_fetching( using simulation::BytecodeId; using simulation::InstructionFetchingEvent; using simulation::InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE; - using simulation::InstrDeserializationError::NO_ERROR; using simulation::InstrDeserializationError::OPCODE_OUT_OF_RANGE; using simulation::InstrDeserializationError::PC_OUT_OF_RANGE; + using simulation::InstrDeserializationError::TAG_OUT_OF_RANGE; // We start from row 1 because we need a row of zeroes for the shifts. uint32_t row = 1; @@ -273,12 +273,29 @@ void BytecodeTraceBuilder::process_instruction_fetching( uint32_t size_in_bytes = 0; ExecutionOpCode exec_opcode = static_cast(0); std::array op_dc_selectors{}; + uint8_t has_tag = 0; + uint8_t tag_is_op2 = 0; + uint8_t tag_value = 0; if (wire_opcode_in_range) { const auto& wire_instr_spec = WIRE_INSTRUCTION_SPEC.at(static_cast(wire_opcode)); size_in_bytes = wire_instr_spec.size_in_bytes; exec_opcode = wire_instr_spec.exec_opcode; op_dc_selectors = wire_instr_spec.op_dc_selectors; + + if (wire_instr_spec.tag_operand_idx.has_value()) { + const auto tag_value_idx = wire_instr_spec.tag_operand_idx.value(); + assert((tag_value_idx == 2 || tag_value_idx == 3) && + "Current constraints support only tag for operand index equal to 2 or 3"); + has_tag = 1; + + if (tag_value_idx == 2) { + tag_is_op2 = 1; + tag_value = static_cast(get_operand(1)); // in instruction.operands, op2 has index 1 + } else { + tag_value = static_cast(get_operand(2)); + } + } } const uint32_t bytes_remaining = @@ -352,6 +369,8 @@ void BytecodeTraceBuilder::process_instruction_fetching( // From instruction table. { C::instr_fetching_exec_opcode, static_cast(exec_opcode) }, { C::instr_fetching_instr_size, size_in_bytes }, + { C::instr_fetching_sel_has_tag, has_tag }, + { C::instr_fetching_sel_tag_is_op2, tag_is_op2 }, // Fill operand decomposition selectors { C::instr_fetching_sel_op_dc_0, op_dc_selectors.at(0) }, @@ -377,10 +396,11 @@ void BytecodeTraceBuilder::process_instruction_fetching( { C::instr_fetching_pc_out_of_range, event.error == PC_OUT_OF_RANGE ? 1 : 0 }, { C::instr_fetching_opcode_out_of_range, event.error == OPCODE_OUT_OF_RANGE ? 1 : 0 }, { C::instr_fetching_instr_out_of_range, event.error == INSTRUCTION_OUT_OF_RANGE ? 1 : 0 }, - { C::instr_fetching_parsing_err, event.error != NO_ERROR ? 1 : 0 }, + { C::instr_fetching_tag_out_of_range, event.error == TAG_OUT_OF_RANGE ? 1 : 0 }, + { C::instr_fetching_parsing_err, event.error.has_value() ? 1 : 0 }, // selector for lookups - { C::instr_fetching_sel_opcode_defined, event.error != PC_OUT_OF_RANGE ? 1 : 0 }, + { C::instr_fetching_sel_pc_in_range, event.error != PC_OUT_OF_RANGE ? 1 : 0 }, { C::instr_fetching_bytecode_size, bytecode_size }, { C::instr_fetching_bytes_to_read, bytes_to_read }, @@ -388,6 +408,7 @@ void BytecodeTraceBuilder::process_instruction_fetching( { C::instr_fetching_pc_abs_diff, pc_abs_diff }, { C::instr_fetching_pc_size_in_bits, AVM_PC_SIZE_IN_BITS }, // Remove when we support constants in lookups + { C::instr_fetching_tag_value, tag_value }, } }); row++; } diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/bytecode_trace.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/bytecode_trace.test.cpp index 89b2b2b6b807..b70cfb59a8b5 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/bytecode_trace.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/bytecode_trace.test.cpp @@ -290,8 +290,6 @@ TEST(BytecodeTraceGenTest, BasicHashing) ROW_FIELD_EQ(R, bc_hashing_packed_field, 20))); } -namespace { - std::vector gen_random_instructions(std::span opcodes) { std::vector instructions; @@ -346,8 +344,6 @@ std::vector create_instruction_fetching_events( return events; } -} // namespace - // We build a random InstructionFetchingEvent for each wire opcode. // We then verify that the bytes (bd0, bd1, ...) correspond to the serialized instruction. TEST(BytecodeTraceGenTest, InstrDecompositionInBytesEachOpcode) @@ -462,6 +458,8 @@ TEST(BytecodeTraceGenTest, InstrFetchingSingleBytecode) for (size_t i = 0; i < num_of_opcodes; i++) { const auto pc = pcs.at(i); const auto instr_size = WIRE_INSTRUCTION_SPEC.at(opcodes.at(i)).size_in_bytes; + const auto has_tag = WIRE_INSTRUCTION_SPEC.at(opcodes.at(i)).tag_operand_idx.has_value(); + const auto tag_is_op2 = has_tag ? WIRE_INSTRUCTION_SPEC.at(opcodes.at(i)).tag_operand_idx.value() == 2 : 0; const auto bytes_remaining = bytecode_size - pc; const auto bytes_to_read = std::min(DECOMPOSE_WINDOW_SIZE, bytes_remaining); @@ -486,8 +484,12 @@ TEST(BytecodeTraceGenTest, InstrFetchingSingleBytecode) ROW_FIELD_EQ(R, instr_fetching_pc_out_of_range, 0), ROW_FIELD_EQ(R, instr_fetching_opcode_out_of_range, 0), ROW_FIELD_EQ(R, instr_fetching_instr_out_of_range, 0), + ROW_FIELD_EQ(R, instr_fetching_tag_out_of_range, 0), ROW_FIELD_EQ(R, instr_fetching_parsing_err, 0), - ROW_FIELD_EQ(R, instr_fetching_sel_opcode_defined, 1))); + ROW_FIELD_EQ(R, instr_fetching_sel_pc_in_range, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_has_tag, has_tag), + ROW_FIELD_EQ(R, instr_fetching_sel_tag_is_op2, tag_is_op2), + ROW_FIELD_EQ(R, instr_fetching_sel_pc_in_range, 1))); } } @@ -554,21 +556,18 @@ TEST(BytecodeTraceGenTest, InstrFetchingParsingErrors) events.emplace_back(InstructionFetchingEvent{ .bytecode_id = bytecode_id, .pc = 0, - .instruction = testing::random_instruction(WireOpCode::ADD_8), .bytecode = bytecode_ptr, .error = simulation::InstrDeserializationError::OPCODE_OUT_OF_RANGE, }); events.emplace_back(InstructionFetchingEvent{ .bytecode_id = bytecode_id, .pc = 19, - .instruction = testing::random_instruction(WireOpCode::ADD_8), .bytecode = bytecode_ptr, .error = simulation::InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE, }); events.emplace_back(InstructionFetchingEvent{ .bytecode_id = bytecode_id, .pc = 38, - .instruction = testing::random_instruction(WireOpCode::ADD_8), .bytecode = bytecode_ptr, .error = simulation::InstrDeserializationError::PC_OUT_OF_RANGE, }); @@ -581,7 +580,7 @@ TEST(BytecodeTraceGenTest, InstrFetchingParsingErrors) EXPECT_THAT(rows.at(1), AllOf(ROW_FIELD_EQ(R, instr_fetching_sel, 1), - ROW_FIELD_EQ(R, instr_fetching_sel_opcode_defined, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_pc_in_range, 1), ROW_FIELD_EQ(R, instr_fetching_pc, 0), ROW_FIELD_EQ(R, instr_fetching_bytes_to_read, 20), ROW_FIELD_EQ(R, instr_fetching_instr_size, 0), @@ -589,12 +588,12 @@ TEST(BytecodeTraceGenTest, InstrFetchingParsingErrors) instr_fetching_instr_abs_diff, 20), // instr_size <= bytes_to_read: bytes_to_read - instr_size ROW_FIELD_EQ(R, instr_fetching_parsing_err, 1), - ROW_FIELD_EQ(R, instr_fetching_pc_abs_diff, 19), + ROW_FIELD_EQ(R, instr_fetching_pc_abs_diff, 19), // bytecode_size - pc - 1 if bytecode_size > pc ROW_FIELD_EQ(R, instr_fetching_opcode_out_of_range, 1))); EXPECT_THAT(rows.at(2), AllOf(ROW_FIELD_EQ(R, instr_fetching_sel, 1), - ROW_FIELD_EQ(R, instr_fetching_sel_opcode_defined, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_pc_in_range, 1), ROW_FIELD_EQ(R, instr_fetching_pc, 19), // OR_16 opcode ROW_FIELD_EQ(R, instr_fetching_bytes_to_read, 1), ROW_FIELD_EQ(R, instr_fetching_instr_size, 8), // OR_16 is 8 bytes long @@ -602,20 +601,110 @@ TEST(BytecodeTraceGenTest, InstrFetchingParsingErrors) instr_fetching_instr_abs_diff, 6), // instr_size > bytes_to_read: instr_size - bytes_to_read - 1 ROW_FIELD_EQ(R, instr_fetching_parsing_err, 1), - ROW_FIELD_EQ(R, instr_fetching_pc_abs_diff, 0), + ROW_FIELD_EQ(R, instr_fetching_pc_abs_diff, 0), // bytecode_size - pc - 1 if bytecode_size > pc ROW_FIELD_EQ(R, instr_fetching_instr_out_of_range, 1))); EXPECT_THAT(rows.at(3), AllOf(ROW_FIELD_EQ(R, instr_fetching_sel, 1), - ROW_FIELD_EQ(R, instr_fetching_sel_opcode_defined, 0), + ROW_FIELD_EQ(R, instr_fetching_sel_pc_in_range, 0), ROW_FIELD_EQ(R, instr_fetching_pc, 38), ROW_FIELD_EQ(R, instr_fetching_bytes_to_read, 0), ROW_FIELD_EQ(R, instr_fetching_instr_size, 0), - ROW_FIELD_EQ(R, instr_fetching_instr_abs_diff, 0), + ROW_FIELD_EQ(R, + instr_fetching_instr_abs_diff, + 0), // instr_size <= bytes_to_read: bytes_to_read - instr_size ROW_FIELD_EQ(R, instr_fetching_parsing_err, 1), - ROW_FIELD_EQ(R, instr_fetching_pc_abs_diff, 18), + ROW_FIELD_EQ(R, instr_fetching_pc_abs_diff, 18), // pc - bytecode_size if bytecode_size <= pc ROW_FIELD_EQ(R, instr_fetching_pc_out_of_range, 1))); } +// Test on error tag out of range +TEST(BytecodeTraceGenTest, InstrFetchingErrorTagOutOfRange) +{ + using simulation::deserialize_instruction; + using simulation::Operand; + using testing::random_instruction; + TestTraceContainer trace; + BytecodeTraceBuilder builder; + + auto instr_cast = random_instruction(WireOpCode::CAST_16); + auto instr_set = random_instruction(WireOpCode::SET_64); + constexpr uint32_t cast_size = 7; + constexpr uint32_t set_64_size = 13; + + instr_cast.operands.at(2) = Operand::u8(0x09); // tag operand mutation to 0x09 which is out of range + instr_set.operands.at(1) = Operand::u8(0x0A); // tag operand mutation to 0x0A which is out of range + + auto bytecode = instr_cast.serialize(); + ASSERT_EQ(bytecode.size(), cast_size); + + auto instr_set_bytecode = instr_set.serialize(); + ASSERT_EQ(instr_set_bytecode.size(), set_64_size); + + bytecode.insert(bytecode.end(), instr_set_bytecode.begin(), instr_set_bytecode.end()); + + const auto bytecode_ptr = std::make_shared>(bytecode); + + std::vector events; + events.emplace_back(InstructionFetchingEvent{ + .bytecode_id = 1, + .pc = 0, + .instruction = deserialize_instruction(bytecode, 0), // Reflect more the real code path than passing instr_cast. + .bytecode = bytecode_ptr, + .error = simulation::InstrDeserializationError::TAG_OUT_OF_RANGE, + }); + + events.emplace_back(InstructionFetchingEvent{ + .bytecode_id = 1, + .pc = cast_size, + .instruction = + deserialize_instruction(bytecode, cast_size), // Reflect more the real code path than passing instr_set. + .bytecode = bytecode_ptr, + .error = simulation::InstrDeserializationError::TAG_OUT_OF_RANGE, + }); + + builder.process_instruction_fetching(events, trace); + + // One extra empty row is prepended. + const auto rows = trace.as_rows(); + EXPECT_EQ(rows.size(), 2 + 1); + + EXPECT_THAT(rows.at(1), + AllOf(ROW_FIELD_EQ(R, instr_fetching_sel, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_pc_in_range, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_has_tag, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_tag_is_op2, 0), + ROW_FIELD_EQ(R, instr_fetching_tag_value, 9), + ROW_FIELD_EQ(R, instr_fetching_pc, 0), + ROW_FIELD_EQ(R, instr_fetching_bytes_to_read, cast_size + set_64_size), + ROW_FIELD_EQ(R, instr_fetching_instr_size, cast_size), + ROW_FIELD_EQ(R, + instr_fetching_instr_abs_diff, + set_64_size), // instr_size <= bytes_to_read: bytes_to_read - instr_size + ROW_FIELD_EQ(R, instr_fetching_parsing_err, 1), + ROW_FIELD_EQ(R, + instr_fetching_pc_abs_diff, + cast_size + set_64_size - 1), // bytecode_size - pc - 1 if bytecode_size > pc + ROW_FIELD_EQ(R, instr_fetching_tag_out_of_range, 1))); + + EXPECT_THAT(rows.at(2), + AllOf(ROW_FIELD_EQ(R, instr_fetching_sel, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_pc_in_range, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_has_tag, 1), + ROW_FIELD_EQ(R, instr_fetching_sel_tag_is_op2, 1), + ROW_FIELD_EQ(R, instr_fetching_tag_value, 10), + ROW_FIELD_EQ(R, instr_fetching_pc, cast_size), + ROW_FIELD_EQ(R, instr_fetching_bytes_to_read, set_64_size), + ROW_FIELD_EQ(R, instr_fetching_instr_size, set_64_size), + ROW_FIELD_EQ(R, + instr_fetching_instr_abs_diff, + 0), // instr_size <= bytes_to_read: bytes_to_read - instr_size + ROW_FIELD_EQ(R, instr_fetching_parsing_err, 1), + ROW_FIELD_EQ(R, + instr_fetching_pc_abs_diff, + set_64_size - 1), // bytecode_size - pc - 1 if bytecode_size > pc + ROW_FIELD_EQ(R, instr_fetching_tag_out_of_range, 1))); +} + } // namespace } // namespace bb::avm2::tracegen diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.cpp index f2f500591740..9c22d4369306 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.cpp @@ -218,6 +218,14 @@ void PrecomputedTraceBuilder::process_wire_instruction_spec(TraceContainer& trac static_cast(wire_opcode), static_cast(wire_instruction_spec.exec_opcode)); trace.set(C::precomputed_instr_size, static_cast(wire_opcode), wire_instruction_spec.size_in_bytes); + + if (wire_instruction_spec.tag_operand_idx.has_value()) { + trace.set(C::precomputed_sel_has_tag, static_cast(wire_opcode), 1); + + if (wire_instruction_spec.tag_operand_idx.value() == 2) { + trace.set(C::precomputed_sel_tag_is_op2, static_cast(wire_opcode), 1); + } + } } } @@ -258,4 +266,15 @@ void PrecomputedTraceBuilder::process_to_radix_p_decompositions(TraceContainer& } } +void PrecomputedTraceBuilder::process_memory_tag_range(TraceContainer& trace) +{ + using C = Column; + + constexpr uint32_t num_rows = 1 << 8; // 256 + + for (uint32_t i = static_cast(MemoryTag::MAX) + 1; i < num_rows; i++) { + trace.set(C::precomputed_sel_mem_tag_out_of_range, i, 1); + } +} + } // namespace bb::avm2::tracegen diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.hpp index cd97393f2050..f9f95dcb3498 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/precomputed_trace.hpp @@ -21,6 +21,7 @@ class PrecomputedTraceBuilder final { void process_wire_instruction_spec(TraceContainer& trace); void process_to_radix_safe_limbs(TraceContainer& trace); void process_to_radix_p_decompositions(TraceContainer& trace); + void process_memory_tag_range(TraceContainer& trace); }; } // namespace bb::avm2::tracegen diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp index 75eb6fac280e..97368404b447 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp @@ -81,6 +81,8 @@ auto build_precomputed_columns_jobs(TraceContainer& trace) precomputed_builder.process_to_radix_safe_limbs(trace)); AVM_TRACK_TIME("tracegen/precomputed/to_radix_p_decompositions", precomputed_builder.process_to_radix_p_decompositions(trace)); + AVM_TRACK_TIME("tracegen/precomputed/memory_tag_ranges", + precomputed_builder.process_memory_tag_range(trace)); }, }; } @@ -311,6 +313,7 @@ TraceContainer AvmTraceGenHelper::generate_trace(EventsContainer&& events) std::make_unique>(), std::make_unique>(), std::make_unique>(), + std::make_unique>(), std::make_unique>(), // Class Id Derivation std::make_unique< diff --git a/yarn-project/simulator/src/public/avm/serialization/bytecode_serialization.test.ts b/yarn-project/simulator/src/public/avm/serialization/bytecode_serialization.test.ts index c92cd9f62bb6..7704c2ec6698 100644 --- a/yarn-project/simulator/src/public/avm/serialization/bytecode_serialization.test.ts +++ b/yarn-project/simulator/src/public/avm/serialization/bytecode_serialization.test.ts @@ -200,15 +200,55 @@ describe('Bytecode Serialization', () => { 0x65, // dstTag (invalid tag) ]); + const bufSet8 = Buffer.from([ + Opcode.SET_8, //opcode + 0x02, // indirect + ...Buffer.from('34', 'hex'), // dstOffset + 0x21, //tag (invalid) + ...Buffer.from('23', 'hex'), // value + ]); + const bufSet16 = Buffer.from([ Opcode.SET_16, //opcode 0x02, // indirect ...Buffer.from('3456', 'hex'), // dstOffset - 0x21, //tag (invalid) + 0x09, //tag (invalid) ...Buffer.from('2397', 'hex'), // value ]); - for (const buf of [bufCast8, bufCast16, bufSet16]) { + const bufSet32 = Buffer.from([ + Opcode.SET_32, //opcode + 0x02, // indirect + ...Buffer.from('3456', 'hex'), // dstOffset + 0x0a, //tag (invalid) + ...Buffer.from('12345678', 'hex'), // value + ]); + + const bufSet64 = Buffer.from([ + Opcode.SET_64, //opcode + 0x02, // indirect + ...Buffer.from('3456', 'hex'), // dstOffset + 0x0b, //tag (invalid) + ...Buffer.from('1234567890abcdef', 'hex'), // value + ]); + + const bufSet128 = Buffer.from([ + Opcode.SET_128, //opcode + 0x02, // indirect + ...Buffer.from('3456', 'hex'), // dstOffset + 0x0c, //tag (invalid) + ...Buffer.from('1234567890abcdef1234567890abcdef', 'hex'), // value + ]); + + const bufSetff = Buffer.from([ + Opcode.SET_FF, //opcode + 0x02, // indirect + ...Buffer.from('3456', 'hex'), // dstOffset + 0x0d, //tag (invalid) + ...Buffer.from('1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', 'hex'), // value + ]); + + for (const buf of [bufCast8, bufCast16, bufSet8, bufSet16, bufSet32, bufSet64, bufSet128, bufSetff]) { expect(decodeInvalidTag(buf)).toThrow(InvalidTagValueError); } });