diff --git a/barretenberg/cpp/pil/avm/avm_mini.pil b/barretenberg/cpp/pil/avm/avm_mini.pil index 1fca367bf959..b2e10e30cca0 100644 --- a/barretenberg/cpp/pil/avm/avm_mini.pil +++ b/barretenberg/cpp/pil/avm/avm_mini.pil @@ -7,6 +7,18 @@ namespace avmMini(256); pol constant clk(i) { i }; pol constant first = [1] + [0]*; // Used mostly to toggle off the first row consisting // only in first element of shifted polynomials. + + //===== CONTROL FLOW ========================================================== + // Program counter + pol commit pc; + // Return Pointer + pol commit internal_return_ptr; + + pol commit sel_internal_call; + pol commit sel_internal_return; + + // Halt program execution + pol commit sel_halt; //===== TABLE SUBOP-TR ======================================================== // Boolean selectors for (sub-)operations. Only one operation is activated at @@ -66,6 +78,10 @@ namespace avmMini(256); sel_op_mul * (1 - sel_op_mul) = 0; sel_op_div * (1 - sel_op_div) = 0; + sel_internal_call * (1 - sel_internal_call) = 0; + sel_internal_return * (1 - sel_internal_return) = 0; + sel_halt * (1 - sel_halt) = 0; + op_err * (1 - op_err) = 0; tag_err * (1 - tag_err) = 0; // Potential optimization (boolean constraint derivation from equivalence check to memTrace)? @@ -131,8 +147,47 @@ namespace avmMini(256); // This works in combination with op_div_err * (sel_op_div - 1) = 0; // Drawback is the need to paralllelize the latter. + + //===== CALL_RETURN ======================================================== + // The program counter in the next row should be equal to the value loaded from the ia register + // This implies that a load from memory must occur at the same time + // Imply that we must load the return location into mem_idx_a + + #[RETURN_POINTER_INCREMENT] + sel_internal_call * ( internal_return_ptr' - ( internal_return_ptr + 1)) = 0; + sel_internal_call * ( internal_return_ptr - mem_idx_a) = 0; + sel_internal_call * ((pc + 1) - ia) = 0; + + // TODO(md): Below relations may be removed through sub-op table lookup + sel_internal_call * (rwa - 1) = 0; + sel_internal_call * (mem_op_a - 1) = 0; + + // We must load the memory pointer to be the internal_return_ptr + #[RETURN_POINTER_DECREMENT] + sel_internal_return * ( internal_return_ptr' - ( internal_return_ptr - 1)) = 0; + sel_internal_return * ( (internal_return_ptr - 1) - mem_idx_a) = 0; + sel_internal_return * (pc' - ia) = 0; + + // TODO(md): Below relations may be removed through sub-op table lookup + sel_internal_return * rwa = 0; + sel_internal_return * (mem_op_a - 1) = 0; + + //===== CONTROL_FLOW_CONSISTENCY ============================================ + pol CONTROL_FLOW_SELECTORS = (first + sel_internal_call + sel_internal_return + sel_halt); + pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_mul); + + // Program counter must increment if not jumping or returning + #[PC_INCREMENT] + (1 - first) * (1 - sel_halt) * OPCODE_SELECTORS * (pc' - (pc + 1)) = 0; + + // first == 0 && sel_internal_call == 0 && sel_internal_return == 0 && sel_halt == 0 ==> internal_return_ptr == internal_return_ptr' + #[INTERNAL_RETURN_POINTER_CONSISTENCY] + (1 - CONTROL_FLOW_SELECTORS) * (internal_return_ptr' - internal_return_ptr) = 0; + + // TODO: we want to set an initial number for the reserved memory of the jump pointer + // Inter-table Constraints // TODO: tag_err {clk} IS memTrace.m_tag_err {memTrace.m_clk} // TODO: Map memory trace with intermediate register values whenever there is no tag error, sthg like: - // mem_op_a * (1 - tag_err) {mem_idx_a, clk, ia, rwa} IS m_sub_clk == 0 && 1 - m_tag_err {m_addr, m_clk, m_val, m_rw} \ No newline at end of file + // mem_op_a * (1 - tag_err) {mem_idx_a, clk, ia, rwa} IS m_sub_clk == 0 && 1 - m_tag_err {m_addr, m_clk, m_val, m_rw} diff --git a/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp index f986f97f168c..d9b5edb8c61c 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp @@ -36,13 +36,13 @@ class AvmMiniFlavor { using VerifierCommitmentKey = pcs::VerifierCommitmentKey; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 32; + static constexpr size_t NUM_WITNESS_ENTITIES = 37; 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 = 38; + static constexpr size_t NUM_ALL_ENTITIES = 45; - using Relations = std::tuple, AvmMini_vm::avm_mini>; + using Relations = std::tuple, AvmMini_vm::mem_trace>; static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); @@ -87,6 +87,11 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + avmMini_pc, + avmMini_internal_return_ptr, + avmMini_sel_internal_call, + avmMini_sel_internal_return, + avmMini_sel_halt, avmMini_sel_op_add, avmMini_sel_op_sub, avmMini_sel_op_mul, @@ -122,6 +127,11 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + avmMini_pc, + avmMini_internal_return_ptr, + avmMini_sel_internal_call, + avmMini_sel_internal_return, + avmMini_sel_halt, avmMini_sel_op_add, avmMini_sel_op_sub, avmMini_sel_op_mul, @@ -163,6 +173,11 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + avmMini_pc, + avmMini_internal_return_ptr, + avmMini_sel_internal_call, + avmMini_sel_internal_return, + avmMini_sel_halt, avmMini_sel_op_add, avmMini_sel_op_sub, avmMini_sel_op_mul, @@ -184,10 +199,12 @@ class AvmMiniFlavor { avmMini_mem_idx_b, avmMini_mem_idx_c, avmMini_last, + avmMini_internal_return_ptr_shift, + avmMini_pc_shift, + memTrace_m_tag_shift, memTrace_m_val_shift, - memTrace_m_addr_shift, memTrace_m_rw_shift, - memTrace_m_tag_shift) + memTrace_m_addr_shift) RefVector get_wires() { @@ -204,6 +221,11 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + avmMini_pc, + avmMini_internal_return_ptr, + avmMini_sel_internal_call, + avmMini_sel_internal_return, + avmMini_sel_halt, avmMini_sel_op_add, avmMini_sel_op_sub, avmMini_sel_op_mul, @@ -225,10 +247,12 @@ class AvmMiniFlavor { avmMini_mem_idx_b, avmMini_mem_idx_c, avmMini_last, + avmMini_internal_return_ptr_shift, + avmMini_pc_shift, + memTrace_m_tag_shift, memTrace_m_val_shift, - memTrace_m_addr_shift, memTrace_m_rw_shift, - memTrace_m_tag_shift }; + memTrace_m_addr_shift }; }; RefVector get_unshifted() { @@ -245,6 +269,11 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + avmMini_pc, + avmMini_internal_return_ptr, + avmMini_sel_internal_call, + avmMini_sel_internal_return, + avmMini_sel_halt, avmMini_sel_op_add, avmMini_sel_op_sub, avmMini_sel_op_mul, @@ -269,11 +298,18 @@ class AvmMiniFlavor { }; RefVector get_to_be_shifted() { - return { memTrace_m_val, memTrace_m_addr, memTrace_m_rw, memTrace_m_tag }; + return { + avmMini_internal_return_ptr, avmMini_pc, memTrace_m_tag, memTrace_m_val, memTrace_m_rw, memTrace_m_addr + }; }; RefVector get_shifted() { - return { memTrace_m_val_shift, memTrace_m_addr_shift, memTrace_m_rw_shift, memTrace_m_tag_shift }; + return { avmMini_internal_return_ptr_shift, + avmMini_pc_shift, + memTrace_m_tag_shift, + memTrace_m_val_shift, + memTrace_m_rw_shift, + memTrace_m_addr_shift }; }; }; @@ -286,7 +322,9 @@ class AvmMiniFlavor { RefVector get_to_be_shifted() { - return { memTrace_m_val, memTrace_m_addr, memTrace_m_rw, memTrace_m_tag }; + return { + avmMini_internal_return_ptr, avmMini_pc, memTrace_m_tag, memTrace_m_val, memTrace_m_rw, memTrace_m_addr + }; }; // The plookup wires that store plookup read data. @@ -376,6 +414,11 @@ class AvmMiniFlavor { Base::memTrace_m_in_tag = "MEMTRACE_M_IN_TAG"; Base::memTrace_m_tag_err = "MEMTRACE_M_TAG_ERR"; Base::memTrace_m_one_min_inv = "MEMTRACE_M_ONE_MIN_INV"; + Base::avmMini_pc = "AVMMINI_PC"; + Base::avmMini_internal_return_ptr = "AVMMINI_INTERNAL_RETURN_PTR"; + Base::avmMini_sel_internal_call = "AVMMINI_SEL_INTERNAL_CALL"; + Base::avmMini_sel_internal_return = "AVMMINI_SEL_INTERNAL_RETURN"; + Base::avmMini_sel_halt = "AVMMINI_SEL_HALT"; Base::avmMini_sel_op_add = "AVMMINI_SEL_OP_ADD"; Base::avmMini_sel_op_sub = "AVMMINI_SEL_OP_SUB"; Base::avmMini_sel_op_mul = "AVMMINI_SEL_OP_MUL"; @@ -427,6 +470,11 @@ class AvmMiniFlavor { Commitment memTrace_m_in_tag; Commitment memTrace_m_tag_err; Commitment memTrace_m_one_min_inv; + Commitment avmMini_pc; + Commitment avmMini_internal_return_ptr; + Commitment avmMini_sel_internal_call; + Commitment avmMini_sel_internal_return; + Commitment avmMini_sel_halt; Commitment avmMini_sel_op_add; Commitment avmMini_sel_op_sub; Commitment avmMini_sel_op_mul; @@ -478,6 +526,11 @@ class AvmMiniFlavor { memTrace_m_in_tag = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); memTrace_m_tag_err = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); memTrace_m_one_min_inv = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + avmMini_pc = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + avmMini_internal_return_ptr = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + avmMini_sel_internal_call = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + avmMini_sel_internal_return = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + avmMini_sel_halt = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); avmMini_sel_op_add = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); avmMini_sel_op_sub = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); avmMini_sel_op_mul = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); @@ -533,6 +586,11 @@ class AvmMiniFlavor { serialize_to_buffer(memTrace_m_in_tag, Transcript::proof_data); serialize_to_buffer(memTrace_m_tag_err, Transcript::proof_data); serialize_to_buffer(memTrace_m_one_min_inv, Transcript::proof_data); + serialize_to_buffer(avmMini_pc, Transcript::proof_data); + serialize_to_buffer(avmMini_internal_return_ptr, Transcript::proof_data); + serialize_to_buffer(avmMini_sel_internal_call, Transcript::proof_data); + serialize_to_buffer(avmMini_sel_internal_return, Transcript::proof_data); + serialize_to_buffer(avmMini_sel_halt, Transcript::proof_data); serialize_to_buffer(avmMini_sel_op_add, Transcript::proof_data); serialize_to_buffer(avmMini_sel_op_sub, Transcript::proof_data); serialize_to_buffer(avmMini_sel_op_mul, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/flavor/generated/Toy_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/generated/Toy_flavor.hpp index cb73871810b5..312dfa7cf940 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/generated/Toy_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/generated/Toy_flavor.hpp @@ -142,8 +142,6 @@ class ToyFlavor { using Base::Base; }; - using RowPolynomials = AllEntities; - /** * @brief A container for the prover polynomials handles. */ @@ -156,7 +154,7 @@ class ToyFlavor { ProverPolynomials(ProverPolynomials&& o) noexcept = default; ProverPolynomials& operator=(ProverPolynomials&& o) noexcept = default; ~ProverPolynomials() = default; - [[nodiscard]] size_t get_polynomial_size() const { return toy_first.size(); } + [[nodiscard]] size_t get_polynomial_size() const { return toy_q_tuple_set.size(); } /** * @brief Returns the evaluations of all prover polynomials at one point on the boolean hypercube, which * represents one row in the execution trace. diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.cpp index e3ee39cff934..60d92a168cc7 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.cpp @@ -19,47 +19,53 @@ void log_avmMini_trace(std::vector const& trace, size_t beg, size_t end) info("Built circuit with ", trace.size(), " rows"); for (size_t i = beg; i < end; i++) { - info("================================================================================"); - info("== ROW ", i); - info("================================================================================"); + info("====================================================================================="); + info("== ROW ", i); + info("====================================================================================="); - info("=======MEMORY TRACE============================================================="); - info("m_addr: ", trace.at(i).memTrace_m_addr); - info("m_clk: ", trace.at(i).memTrace_m_clk); - info("m_sub_clk: ", trace.at(i).memTrace_m_sub_clk); - info("m_val: ", trace.at(i).memTrace_m_val); - info("m_rw: ", trace.at(i).memTrace_m_rw); - info("m_tag: ", trace.at(i).memTrace_m_tag); - info("m_in_tag: ", trace.at(i).memTrace_m_in_tag); - info("m_tag_err: ", trace.at(i).memTrace_m_tag_err); - info("m_one_min_inv:", trace.at(i).memTrace_m_one_min_inv); + info("=======MEMORY TRACE=================================================================="); + info("m_addr: ", trace.at(i).memTrace_m_addr); + info("m_clk: ", trace.at(i).memTrace_m_clk); + info("m_sub_clk: ", trace.at(i).memTrace_m_sub_clk); + info("m_val: ", trace.at(i).memTrace_m_val); + info("m_rw: ", trace.at(i).memTrace_m_rw); + info("m_tag: ", trace.at(i).memTrace_m_tag); + info("m_in_tag: ", trace.at(i).memTrace_m_in_tag); + info("m_tag_err: ", trace.at(i).memTrace_m_tag_err); + info("m_one_min_inv: ", trace.at(i).memTrace_m_one_min_inv); - info("m_lastAccess: ", trace.at(i).memTrace_m_lastAccess); - info("m_last: ", trace.at(i).memTrace_m_last); - info("m_val_shift: ", trace.at(i).memTrace_m_val_shift); + info("m_lastAccess: ", trace.at(i).memTrace_m_lastAccess); + info("m_last: ", trace.at(i).memTrace_m_last); + info("m_val_shift: ", trace.at(i).memTrace_m_val_shift); - info("=======MAIN TRACE==============================================================="); - info("ia: ", trace.at(i).avmMini_ia); - info("ib: ", trace.at(i).avmMini_ib); - info("ic: ", trace.at(i).avmMini_ic); - info("first: ", trace.at(i).avmMini_first); - info("last: ", trace.at(i).avmMini_last); + info("=======CONTROL_FLOW==================================================================="); + info("pc: ", trace.at(i).avmMini_pc); + info("internal_call: ", trace.at(i).avmMini_sel_internal_call); + info("internal_return: ", trace.at(i).avmMini_sel_internal_return); + info("internal_return_ptr:", trace.at(i).avmMini_internal_return_ptr); - info("=======MEM_OP_A================================================================="); - info("clk: ", trace.at(i).avmMini_clk); - info("mem_op_a: ", trace.at(i).avmMini_mem_op_a); - info("mem_idx_a: ", trace.at(i).avmMini_mem_idx_a); - info("rwa: ", trace.at(i).avmMini_rwa); + info("=======MAIN TRACE===================================================================="); + info("ia: ", trace.at(i).avmMini_ia); + info("ib: ", trace.at(i).avmMini_ib); + info("ic: ", trace.at(i).avmMini_ic); + info("first: ", trace.at(i).avmMini_first); + info("last: ", trace.at(i).avmMini_last); - info("=======MEM_OP_B================================================================="); - info("mem_op_b: ", trace.at(i).avmMini_mem_op_b); - info("mem_idx_b: ", trace.at(i).avmMini_mem_idx_b); - info("rwb: ", trace.at(i).avmMini_rwb); + info("=======MEM_OP_A======================================================================"); + info("clk: ", trace.at(i).avmMini_clk); + info("mem_op_a: ", trace.at(i).avmMini_mem_op_a); + info("mem_idx_a: ", trace.at(i).avmMini_mem_idx_a); + info("rwa: ", trace.at(i).avmMini_rwa); - info("=======MEM_OP_C================================================================="); - info("mem_op_c: ", trace.at(i).avmMini_mem_op_c); - info("mem_idx_c: ", trace.at(i).avmMini_mem_idx_c); - info("rwc: ", trace.at(i).avmMini_rwc); + info("=======MEM_OP_B======================================================================"); + info("mem_op_b: ", trace.at(i).avmMini_mem_op_b); + info("mem_idx_b: ", trace.at(i).avmMini_mem_idx_b); + info("rwb: ", trace.at(i).avmMini_rwb); + + info("=======MEM_OP_C======================================================================"); + info("mem_op_c: ", trace.at(i).avmMini_mem_op_c); + info("mem_idx_c: ", trace.at(i).avmMini_mem_idx_c); + info("rwc: ", trace.at(i).avmMini_rwc); info("\n"); } } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp index fd4c46ffef5f..9c6721160f8b 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp @@ -191,6 +191,8 @@ void AvmMiniTraceBuilder::add(uint32_t aOffset, uint32_t bOffset, uint32_t dstOf mainTrace.push_back(Row{ .avmMini_clk = clk, + .avmMini_pc = FF(pc++), + .avmMini_internal_return_ptr = FF(internal_return_ptr), .avmMini_sel_op_add = FF(1), .avmMini_in_tag = FF(static_cast(inTag)), .avmMini_tag_err = FF(static_cast(!tagMatch)), @@ -233,6 +235,8 @@ void AvmMiniTraceBuilder::sub(uint32_t aOffset, uint32_t bOffset, uint32_t dstOf mainTrace.push_back(Row{ .avmMini_clk = clk, + .avmMini_pc = FF(pc++), + .avmMini_internal_return_ptr = FF(internal_return_ptr), .avmMini_sel_op_sub = FF(1), .avmMini_in_tag = FF(static_cast(inTag)), .avmMini_tag_err = FF(static_cast(!tagMatch)), @@ -275,6 +279,8 @@ void AvmMiniTraceBuilder::mul(uint32_t aOffset, uint32_t bOffset, uint32_t dstOf mainTrace.push_back(Row{ .avmMini_clk = clk, + .avmMini_pc = FF(pc++), + .avmMini_internal_return_ptr = FF(internal_return_ptr), .avmMini_sel_op_mul = FF(1), .avmMini_in_tag = FF(static_cast(inTag)), .avmMini_tag_err = FF(static_cast(!tagMatch)), @@ -331,6 +337,8 @@ void AvmMiniTraceBuilder::div(uint32_t aOffset, uint32_t bOffset, uint32_t dstOf mainTrace.push_back(Row{ .avmMini_clk = clk, + .avmMini_pc = FF(pc++), + .avmMini_internal_return_ptr = FF(internal_return_ptr), .avmMini_sel_op_div = FF(1), .avmMini_in_tag = FF(static_cast(inTag)), .avmMini_op_err = tagMatch ? error : FF(1), @@ -427,6 +435,8 @@ void AvmMiniTraceBuilder::callDataCopy(uint32_t cdOffset, mainTrace.push_back(Row{ .avmMini_clk = clk, + .avmMini_pc = FF(pc++), + .avmMini_internal_return_ptr = FF(internal_return_ptr), .avmMini_in_tag = FF(static_cast(AvmMemoryTag::ff)), .avmMini_ia = ia, .avmMini_ib = ib, @@ -514,6 +524,9 @@ std::vector AvmMiniTraceBuilder::returnOP(uint32_t retOffset, uint32_t retSi mainTrace.push_back(Row{ .avmMini_clk = clk, + .avmMini_pc = FF(pc), + .avmMini_internal_return_ptr = FF(internal_return_ptr), + .avmMini_sel_halt = FF(1), .avmMini_in_tag = FF(static_cast(AvmMemoryTag::ff)), .avmMini_ia = ia, .avmMini_ib = ib, @@ -536,7 +549,104 @@ std::vector AvmMiniTraceBuilder::returnOP(uint32_t retOffset, uint32_t retSi } /** - * @brief Helper to initialize memory. (Testing purpose mostly.) + * @brief HALT opcode + * This opcode effectively stops program execution, and is used in the relation that + * ensures the program counter increments on each opcode. + * i.e.ythe program counter should freeze and the halt flag is set to 1. + */ +void AvmMiniTraceBuilder::halt() +{ + auto clk = mainTrace.size(); + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_pc = FF(pc), + .avmMini_internal_return_ptr = FF(internal_return_ptr), + .avmMini_sel_halt = FF(1), + }); +} + +/** + * @brief INTERNAL_CALL OPCODE + * This opcode effectively jumps to a new `jmpDest` and stores the return program counter + * (current program counter + 1) onto a call stack. + * This function must: + * - Set the next program counter to the provided `jmpDest`. + * - Store the current `pc` + 1 onto the call stack (emulated in memory) + * - Increment the return stack pointer (a pointer to where the call stack is in memory) + * + * Note: We use intermediate register to perform memory storage operations. + * + * @param jmpDest - The destination to jump to + */ +void AvmMiniTraceBuilder::internal_call(uint32_t jmpDest) +{ + auto clk = mainTrace.size(); + + // We store the next instruction as the return location + uint32_t stored_pc = pc + 1; + internal_call_stack.push(stored_pc); + + // Add the return location to the memory trace + storeInMemTrace(IntermRegister::ia, internal_return_ptr, FF(stored_pc), AvmMemoryTag::ff); + memory.at(internal_return_ptr) = stored_pc; + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_pc = FF(pc), + .avmMini_internal_return_ptr = FF(internal_return_ptr), + .avmMini_sel_internal_call = FF(1), + .avmMini_ia = stored_pc, + .avmMini_mem_op_a = FF(1), + .avmMini_rwa = FF(1), + .avmMini_mem_idx_a = FF(internal_return_ptr), + }); + + // Adjust parameters for the next row + pc = jmpDest; + internal_return_ptr++; +} + +/** + * @brief INTERNAL_RETURN OPCODE + * The opcode returns from an internal call. + * This function must: + * - Read the return location from the internal_return_ptr + * - Set the next program counter to the return location + * - Decrement the return stack pointer + * + * TODO(https://github.com/AztecProtocol/aztec-packages/issues/3740): This function MUST come after a call instruction. + */ +void AvmMiniTraceBuilder::internal_return() +{ + auto clk = mainTrace.size(); + + // Internal return pointer is decremented + FF a = memory.at(internal_return_ptr - 1); + + // We want to load the value pointed by the internal pointer + loadInMemTrace(IntermRegister::ia, internal_return_ptr - 1, FF(a), AvmMemoryTag::ff); + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_pc = pc, + .avmMini_internal_return_ptr = FF(internal_return_ptr), + .avmMini_sel_internal_return = FF(1), + .avmMini_ia = a, + .avmMini_mem_op_a = FF(1), + .avmMini_rwa = FF(0), + .avmMini_mem_idx_a = FF(internal_return_ptr - 1), + }); + + // We want the next row to be the one pointed by jmpDest + // The next pc should be from the top of the internal call stack + 1 + pc = internal_call_stack.top(); + internal_call_stack.pop(); + internal_return_ptr--; +} + +/** + * @brief Helper to initialize ffMemory. (Testing purpose mostly.) * */ void AvmMiniTraceBuilder::setFFMem(size_t idx, FF el, AvmMemoryTag tag) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp index 5f5f7e8353db..f7dd66f3b3e2 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "barretenberg/common/throw_or_abort.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp" @@ -28,6 +30,7 @@ class AvmMiniTraceBuilder { // Number of rows static const size_t N = 256; static const size_t MEM_SIZE = 1024; + static const size_t CALLSTACK_OFFSET = 896; // TODO(md): Temporary reserved area 896 - 1024 static const uint32_t SUB_CLK_LOAD_A = 0; static const uint32_t SUB_CLK_LOAD_B = 1; @@ -56,6 +59,16 @@ class AvmMiniTraceBuilder { // Division with direct memory access. void div(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset, AvmMemoryTag inTag); + // Jump to a given program counter. + // TODO(md): this program counter MUST be an operand to the OPCODE. + void internal_call(uint32_t jmpDest); + + // Return from a jump. + void internal_return(); + + // Halt -> stop program execution. + void halt(); + // CALLDATACOPY opcode with direct memory access, i.e., // M[dstOffset:dstOffset+copySize] = calldata[cdOffset:cdOffset+copySize] void callDataCopy(uint32_t cdOffset, uint32_t copySize, uint32_t dstOffset, std::vector const& callDataMem); @@ -83,6 +96,10 @@ class AvmMiniTraceBuilder { std::array memoryTag{}; // The tag of the corresponding memory // entry (aligned with the memory array). + uint32_t pc = 0; + uint32_t internal_return_ptr = CALLSTACK_OFFSET; + std::stack internal_call_stack = {}; + static bool compareMemEntries(const MemoryTraceEntry& left, const MemoryTraceEntry& right); void insertInMemTrace( uint32_t m_clk, uint32_t m_sub_clk, uint32_t m_addr, FF m_val, AvmMemoryTag m_in_tag, bool m_rw); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp index 02aaed70a5a1..a41fb694b9c5 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp @@ -32,6 +32,11 @@ template struct AvmMiniFullRow { FF memTrace_m_in_tag{}; FF memTrace_m_tag_err{}; FF memTrace_m_one_min_inv{}; + FF avmMini_pc{}; + FF avmMini_internal_return_ptr{}; + FF avmMini_sel_internal_call{}; + FF avmMini_sel_internal_return{}; + FF avmMini_sel_halt{}; FF avmMini_sel_op_add{}; FF avmMini_sel_op_sub{}; FF avmMini_sel_op_mul{}; @@ -53,10 +58,12 @@ template struct AvmMiniFullRow { FF avmMini_mem_idx_b{}; FF avmMini_mem_idx_c{}; FF avmMini_last{}; + FF avmMini_internal_return_ptr_shift{}; + FF avmMini_pc_shift{}; + FF memTrace_m_tag_shift{}; FF memTrace_m_val_shift{}; - FF memTrace_m_addr_shift{}; FF memTrace_m_rw_shift{}; - FF memTrace_m_tag_shift{}; + FF memTrace_m_addr_shift{}; }; class AvmMiniCircuitBuilder { @@ -69,8 +76,8 @@ class AvmMiniCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 38; - static constexpr size_t num_polys = 34; + static constexpr size_t num_fixed_columns = 45; + static constexpr size_t num_polys = 39; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -99,6 +106,11 @@ class AvmMiniCircuitBuilder { polys.memTrace_m_in_tag[i] = rows[i].memTrace_m_in_tag; polys.memTrace_m_tag_err[i] = rows[i].memTrace_m_tag_err; polys.memTrace_m_one_min_inv[i] = rows[i].memTrace_m_one_min_inv; + polys.avmMini_pc[i] = rows[i].avmMini_pc; + polys.avmMini_internal_return_ptr[i] = rows[i].avmMini_internal_return_ptr; + polys.avmMini_sel_internal_call[i] = rows[i].avmMini_sel_internal_call; + polys.avmMini_sel_internal_return[i] = rows[i].avmMini_sel_internal_return; + polys.avmMini_sel_halt[i] = rows[i].avmMini_sel_halt; polys.avmMini_sel_op_add[i] = rows[i].avmMini_sel_op_add; polys.avmMini_sel_op_sub[i] = rows[i].avmMini_sel_op_sub; polys.avmMini_sel_op_mul[i] = rows[i].avmMini_sel_op_mul; @@ -122,10 +134,12 @@ class AvmMiniCircuitBuilder { polys.avmMini_last[i] = rows[i].avmMini_last; } + polys.avmMini_internal_return_ptr_shift = Polynomial(polys.avmMini_internal_return_ptr.shifted()); + polys.avmMini_pc_shift = Polynomial(polys.avmMini_pc.shifted()); + polys.memTrace_m_tag_shift = Polynomial(polys.memTrace_m_tag.shifted()); polys.memTrace_m_val_shift = Polynomial(polys.memTrace_m_val.shifted()); - polys.memTrace_m_addr_shift = Polynomial(polys.memTrace_m_addr.shifted()); polys.memTrace_m_rw_shift = Polynomial(polys.memTrace_m_rw.shifted()); - polys.memTrace_m_tag_shift = Polynomial(polys.memTrace_m_tag.shifted()); + polys.memTrace_m_addr_shift = Polynomial(polys.memTrace_m_addr.shifted()); return polys; } @@ -163,14 +177,14 @@ class AvmMiniCircuitBuilder { return true; }; - if (!evaluate_relation.template operator()>( - "mem_trace", AvmMini_vm::get_relation_label_mem_trace)) { - return false; - } if (!evaluate_relation.template operator()>("avm_mini", AvmMini_vm::get_relation_label_avm_mini)) { return false; } + if (!evaluate_relation.template operator()>( + "mem_trace", AvmMini_vm::get_relation_label_mem_trace)) { + return false; + } return true; } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Toy_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Toy_circuit_builder.hpp index bba7cf3268a7..e8d337389a59 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Toy_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Toy_circuit_builder.hpp @@ -91,7 +91,8 @@ class ToyCircuitBuilder { ProverPolynomials polys = compute_polynomials(); const size_t num_rows = polys.get_polynomial_size(); - const auto evaluate_relation = [&](const std::string& relation_name) { + const auto evaluate_relation = [&](const std::string& relation_name, + std::string (*debug_label)(int)) { typename Relation::SumcheckArrayOfValuesOverSubrelations result; for (auto& r : result) { r = 0; @@ -104,8 +105,9 @@ class ToyCircuitBuilder { bool x = true; for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { if (result[j] != 0) { + std::string row_name = debug_label(static_cast(j)); throw_or_abort( - format("Relation ", relation_name, ", subrelation index ", j, " failed at row ", i)); + format("Relation ", relation_name, ", subrelation index ", row_name, " failed at row ", i)); x = false; } } @@ -131,14 +133,15 @@ class ToyCircuitBuilder { } for (auto r : permutation_result) { if (r != 0) { - info("Tuple", permutation_name, "failed."); + info("Tuple ", permutation_name, " failed."); return false; } } return true; }; - if (!evaluate_relation.template operator()>("toy_avm")) { + if (!evaluate_relation.template operator()>("toy_avm", + Toy_vm::get_relation_label_toy_avm)) { return false; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/avm_mini.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/avm_mini.hpp index d590365b76a3..46d9a5bc9e95 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/avm_mini.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/avm_mini.hpp @@ -7,46 +7,67 @@ namespace proof_system::AvmMini_vm { template struct Avm_miniRow { - FF avmMini_sel_op_sub{}; FF avmMini_rwa{}; + FF avmMini_sel_op_div{}; + FF avmMini_inv{}; + FF avmMini_internal_return_ptr{}; + FF avmMini_sel_internal_call{}; FF avmMini_ic{}; - FF avmMini_op_err{}; FF avmMini_rwb{}; - FF avmMini_ia{}; - FF avmMini_inv{}; - FF avmMini_sel_op_div{}; - FF avmMini_tag_err{}; - FF avmMini_sel_op_mul{}; + FF avmMini_sel_halt{}; FF avmMini_sel_op_add{}; - FF avmMini_mem_op_c{}; + FF avmMini_mem_op_b{}; + FF avmMini_op_err{}; FF avmMini_rwc{}; FF avmMini_ib{}; + FF avmMini_mem_idx_a{}; + FF avmMini_sel_op_sub{}; + FF avmMini_sel_op_mul{}; + FF avmMini_ia{}; + FF avmMini_internal_return_ptr_shift{}; + FF avmMini_pc{}; + FF avmMini_pc_shift{}; + FF avmMini_tag_err{}; + FF avmMini_mem_op_c{}; FF avmMini_mem_op_a{}; - FF avmMini_mem_op_b{}; + FF avmMini_sel_internal_return{}; + FF avmMini_first{}; }; inline std::string get_relation_label_avm_mini(int index) { switch (index) { - case 18: - return "SUBOP_DIVISION_FF"; - - case 17: + case 20: return "SUBOP_MULTIPLICATION_FF"; - case 16: - return "SUBOP_SUBTRACTION_FF"; - - case 19: + case 22: return "SUBOP_DIVISION_ZERO_ERR1"; - case 20: + case 23: return "SUBOP_DIVISION_ZERO_ERR2"; - case 21: + case 24: return "SUBOP_ERROR_RELEVANT_OP"; - case 15: + case 25: + return "RETURN_POINTER_INCREMENT"; + + case 30: + return "RETURN_POINTER_DECREMENT"; + + case 35: + return "PC_INCREMENT"; + + case 19: + return "SUBOP_SUBTRACTION_FF"; + + case 21: + return "SUBOP_DIVISION_FF"; + + case 36: + return "INTERNAL_RETURN_POINTER_CONSISTENCY"; + + case 18: return "SUBOP_ADDITION_FF"; } return std::to_string(index); @@ -56,8 +77,8 @@ template class avm_miniImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 4, 3, + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, }; template @@ -103,7 +124,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(4); - auto tmp = (avmMini_op_err * (-avmMini_op_err + FF(1))); + auto tmp = (avmMini_sel_internal_call * (-avmMini_sel_internal_call + FF(1))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -111,7 +132,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(5); - auto tmp = (avmMini_tag_err * (-avmMini_tag_err + FF(1))); + auto tmp = (avmMini_sel_internal_return * (-avmMini_sel_internal_return + FF(1))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -119,7 +140,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(6); - auto tmp = (avmMini_mem_op_a * (-avmMini_mem_op_a + FF(1))); + auto tmp = (avmMini_sel_halt * (-avmMini_sel_halt + FF(1))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -127,7 +148,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(7); - auto tmp = (avmMini_mem_op_b * (-avmMini_mem_op_b + FF(1))); + auto tmp = (avmMini_op_err * (-avmMini_op_err + FF(1))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -135,7 +156,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(8); - auto tmp = (avmMini_mem_op_c * (-avmMini_mem_op_c + FF(1))); + auto tmp = (avmMini_tag_err * (-avmMini_tag_err + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -143,7 +164,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(9); - auto tmp = (avmMini_rwa * (-avmMini_rwa + FF(1))); + auto tmp = (avmMini_mem_op_a * (-avmMini_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -151,7 +172,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(10); - auto tmp = (avmMini_rwb * (-avmMini_rwb + FF(1))); + auto tmp = (avmMini_mem_op_b * (-avmMini_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -159,7 +180,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(11); - auto tmp = (avmMini_rwc * (-avmMini_rwc + FF(1))); + auto tmp = (avmMini_mem_op_c * (-avmMini_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -167,7 +188,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(12); - auto tmp = (avmMini_tag_err * avmMini_ia); + auto tmp = (avmMini_rwa * (-avmMini_rwa + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -175,7 +196,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(13); - auto tmp = (avmMini_tag_err * avmMini_ib); + auto tmp = (avmMini_rwb * (-avmMini_rwb + FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -183,7 +204,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(14); - auto tmp = (avmMini_tag_err * avmMini_ic); + auto tmp = (avmMini_rwc * (-avmMini_rwc + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -191,7 +212,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(15); - auto tmp = (avmMini_sel_op_add * ((avmMini_ia + avmMini_ib) - avmMini_ic)); + auto tmp = (avmMini_tag_err * avmMini_ia); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -199,7 +220,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(16); - auto tmp = (avmMini_sel_op_sub * ((avmMini_ia - avmMini_ib) - avmMini_ic)); + auto tmp = (avmMini_tag_err * avmMini_ib); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -207,7 +228,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(17); - auto tmp = (avmMini_sel_op_mul * ((avmMini_ia * avmMini_ib) - avmMini_ic)); + auto tmp = (avmMini_tag_err * avmMini_ic); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -215,7 +236,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(18); - auto tmp = ((avmMini_sel_op_div * (-avmMini_op_err + FF(1))) * ((avmMini_ic * avmMini_ib) - avmMini_ia)); + auto tmp = (avmMini_sel_op_add * ((avmMini_ia + avmMini_ib) - avmMini_ic)); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -223,7 +244,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(19); - auto tmp = (avmMini_sel_op_div * (((avmMini_ib * avmMini_inv) - FF(1)) + avmMini_op_err)); + auto tmp = (avmMini_sel_op_sub * ((avmMini_ia - avmMini_ib) - avmMini_ic)); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -231,7 +252,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(20); - auto tmp = ((avmMini_sel_op_div * avmMini_op_err) * (-avmMini_inv + FF(1))); + auto tmp = (avmMini_sel_op_mul * ((avmMini_ia * avmMini_ib) - avmMini_ic)); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -239,10 +260,137 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(21); - auto tmp = (avmMini_op_err * (avmMini_sel_op_div - FF(1))); + auto tmp = ((avmMini_sel_op_div * (-avmMini_op_err + FF(1))) * ((avmMini_ic * avmMini_ib) - avmMini_ia)); tmp *= scaling_factor; std::get<21>(evals) += tmp; } + // Contribution 22 + { + AvmMini_DECLARE_VIEWS(22); + + auto tmp = (avmMini_sel_op_div * (((avmMini_ib * avmMini_inv) - FF(1)) + avmMini_op_err)); + tmp *= scaling_factor; + std::get<22>(evals) += tmp; + } + // Contribution 23 + { + AvmMini_DECLARE_VIEWS(23); + + auto tmp = ((avmMini_sel_op_div * avmMini_op_err) * (-avmMini_inv + FF(1))); + tmp *= scaling_factor; + std::get<23>(evals) += tmp; + } + // Contribution 24 + { + AvmMini_DECLARE_VIEWS(24); + + auto tmp = (avmMini_op_err * (avmMini_sel_op_div - FF(1))); + tmp *= scaling_factor; + std::get<24>(evals) += tmp; + } + // Contribution 25 + { + AvmMini_DECLARE_VIEWS(25); + + auto tmp = (avmMini_sel_internal_call * + (avmMini_internal_return_ptr_shift - (avmMini_internal_return_ptr + FF(1)))); + tmp *= scaling_factor; + std::get<25>(evals) += tmp; + } + // Contribution 26 + { + AvmMini_DECLARE_VIEWS(26); + + auto tmp = (avmMini_sel_internal_call * (avmMini_internal_return_ptr - avmMini_mem_idx_a)); + tmp *= scaling_factor; + std::get<26>(evals) += tmp; + } + // Contribution 27 + { + AvmMini_DECLARE_VIEWS(27); + + auto tmp = (avmMini_sel_internal_call * ((avmMini_pc + FF(1)) - avmMini_ia)); + tmp *= scaling_factor; + std::get<27>(evals) += tmp; + } + // Contribution 28 + { + AvmMini_DECLARE_VIEWS(28); + + auto tmp = (avmMini_sel_internal_call * (avmMini_rwa - FF(1))); + tmp *= scaling_factor; + std::get<28>(evals) += tmp; + } + // Contribution 29 + { + AvmMini_DECLARE_VIEWS(29); + + auto tmp = (avmMini_sel_internal_call * (avmMini_mem_op_a - FF(1))); + tmp *= scaling_factor; + std::get<29>(evals) += tmp; + } + // Contribution 30 + { + AvmMini_DECLARE_VIEWS(30); + + auto tmp = (avmMini_sel_internal_return * + (avmMini_internal_return_ptr_shift - (avmMini_internal_return_ptr - FF(1)))); + tmp *= scaling_factor; + std::get<30>(evals) += tmp; + } + // Contribution 31 + { + AvmMini_DECLARE_VIEWS(31); + + auto tmp = (avmMini_sel_internal_return * ((avmMini_internal_return_ptr - FF(1)) - avmMini_mem_idx_a)); + tmp *= scaling_factor; + std::get<31>(evals) += tmp; + } + // Contribution 32 + { + AvmMini_DECLARE_VIEWS(32); + + auto tmp = (avmMini_sel_internal_return * (avmMini_pc_shift - avmMini_ia)); + tmp *= scaling_factor; + std::get<32>(evals) += tmp; + } + // Contribution 33 + { + AvmMini_DECLARE_VIEWS(33); + + auto tmp = (avmMini_sel_internal_return * avmMini_rwa); + tmp *= scaling_factor; + std::get<33>(evals) += tmp; + } + // Contribution 34 + { + AvmMini_DECLARE_VIEWS(34); + + auto tmp = (avmMini_sel_internal_return * (avmMini_mem_op_a - FF(1))); + tmp *= scaling_factor; + std::get<34>(evals) += tmp; + } + // Contribution 35 + { + AvmMini_DECLARE_VIEWS(35); + + auto tmp = ((((-avmMini_first + FF(1)) * (-avmMini_sel_halt + FF(1))) * + (((avmMini_sel_op_add + avmMini_sel_op_sub) + avmMini_sel_op_div) + avmMini_sel_op_mul)) * + (avmMini_pc_shift - (avmMini_pc + FF(1)))); + tmp *= scaling_factor; + std::get<35>(evals) += tmp; + } + // Contribution 36 + { + AvmMini_DECLARE_VIEWS(36); + + auto tmp = + ((-(((avmMini_first + avmMini_sel_internal_call) + avmMini_sel_internal_return) + avmMini_sel_halt) + + FF(1)) * + (avmMini_internal_return_ptr_shift - avmMini_internal_return_ptr)); + tmp *= scaling_factor; + std::get<36>(evals) += tmp; + } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/declare_views.hpp index 9d23bb0f8f1b..0c711d834290 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/declare_views.hpp @@ -15,6 +15,11 @@ [[maybe_unused]] auto memTrace_m_in_tag = View(new_term.memTrace_m_in_tag); \ [[maybe_unused]] auto memTrace_m_tag_err = View(new_term.memTrace_m_tag_err); \ [[maybe_unused]] auto memTrace_m_one_min_inv = View(new_term.memTrace_m_one_min_inv); \ + [[maybe_unused]] auto avmMini_pc = View(new_term.avmMini_pc); \ + [[maybe_unused]] auto avmMini_internal_return_ptr = View(new_term.avmMini_internal_return_ptr); \ + [[maybe_unused]] auto avmMini_sel_internal_call = View(new_term.avmMini_sel_internal_call); \ + [[maybe_unused]] auto avmMini_sel_internal_return = View(new_term.avmMini_sel_internal_return); \ + [[maybe_unused]] auto avmMini_sel_halt = View(new_term.avmMini_sel_halt); \ [[maybe_unused]] auto avmMini_sel_op_add = View(new_term.avmMini_sel_op_add); \ [[maybe_unused]] auto avmMini_sel_op_sub = View(new_term.avmMini_sel_op_sub); \ [[maybe_unused]] auto avmMini_sel_op_mul = View(new_term.avmMini_sel_op_mul); \ @@ -36,7 +41,9 @@ [[maybe_unused]] auto avmMini_mem_idx_b = View(new_term.avmMini_mem_idx_b); \ [[maybe_unused]] auto avmMini_mem_idx_c = View(new_term.avmMini_mem_idx_c); \ [[maybe_unused]] auto avmMini_last = View(new_term.avmMini_last); \ + [[maybe_unused]] auto avmMini_internal_return_ptr_shift = View(new_term.avmMini_internal_return_ptr_shift); \ + [[maybe_unused]] auto avmMini_pc_shift = View(new_term.avmMini_pc_shift); \ + [[maybe_unused]] auto memTrace_m_tag_shift = View(new_term.memTrace_m_tag_shift); \ [[maybe_unused]] auto memTrace_m_val_shift = View(new_term.memTrace_m_val_shift); \ - [[maybe_unused]] auto memTrace_m_addr_shift = View(new_term.memTrace_m_addr_shift); \ [[maybe_unused]] auto memTrace_m_rw_shift = View(new_term.memTrace_m_rw_shift); \ - [[maybe_unused]] auto memTrace_m_tag_shift = View(new_term.memTrace_m_tag_shift); + [[maybe_unused]] auto memTrace_m_addr_shift = View(new_term.memTrace_m_addr_shift); diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/mem_trace.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/mem_trace.hpp index 9880acfa6316..2adc17baf9fb 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/mem_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/mem_trace.hpp @@ -7,41 +7,41 @@ namespace proof_system::AvmMini_vm { template struct Mem_traceRow { + FF memTrace_m_tag_shift{}; + FF memTrace_m_tag{}; FF memTrace_m_rw{}; - FF memTrace_m_addr{}; - FF memTrace_m_val_shift{}; + FF memTrace_m_lastAccess{}; FF memTrace_m_last{}; FF memTrace_m_tag_err{}; - FF memTrace_m_addr_shift{}; FF memTrace_m_val{}; - FF memTrace_m_lastAccess{}; - FF memTrace_m_tag{}; - FF memTrace_m_in_tag{}; - FF memTrace_m_rw_shift{}; FF memTrace_m_one_min_inv{}; - FF memTrace_m_tag_shift{}; + FF memTrace_m_val_shift{}; + FF memTrace_m_addr{}; + FF memTrace_m_rw_shift{}; + FF memTrace_m_addr_shift{}; + FF memTrace_m_in_tag{}; }; inline std::string get_relation_label_mem_trace(int index) { switch (index) { - case 4: - return "MEM_LAST_ACCESS_DELIMITER"; - - case 6: - return "MEM_READ_WRITE_TAG_CONSISTENCY"; - - case 9: - return "MEM_IN_TAG_CONSISTENCY_2"; - case 5: return "MEM_READ_WRITE_VAL_CONSISTENCY"; case 7: return "MEM_ZERO_INIT"; + case 9: + return "MEM_IN_TAG_CONSISTENCY_2"; + case 8: return "MEM_IN_TAG_CONSISTENCY_1"; + + case 4: + return "MEM_LAST_ACCESS_DELIMITER"; + + case 6: + return "MEM_READ_WRITE_TAG_CONSISTENCY"; } return std::to_string(index); } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/Toy/toy_avm.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/Toy/toy_avm.hpp index 40eb15cb6b3a..4364cb843ae0 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/Toy/toy_avm.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/Toy/toy_avm.hpp @@ -7,10 +7,16 @@ namespace proof_system::Toy_vm { template struct Toy_avmRow { - FF toy_x_shift{}; FF toy_x{}; + FF toy_x_shift{}; }; +inline std::string get_relation_label_toy_avm(int index) +{ + switch (index) {} + return std::to_string(index); +} + template class toy_avmImpl { public: using FF = FF_; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp index ff07a0754195..5673710fa24b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp @@ -73,6 +73,15 @@ bool AvmMiniVerifier::verify_proof(const plonk::proof& proof) transcript->template receive_from_prover(commitment_labels.memTrace_m_tag_err); commitments.memTrace_m_one_min_inv = transcript->template receive_from_prover(commitment_labels.memTrace_m_one_min_inv); + commitments.avmMini_pc = transcript->template receive_from_prover(commitment_labels.avmMini_pc); + commitments.avmMini_internal_return_ptr = + transcript->template receive_from_prover(commitment_labels.avmMini_internal_return_ptr); + commitments.avmMini_sel_internal_call = + transcript->template receive_from_prover(commitment_labels.avmMini_sel_internal_call); + commitments.avmMini_sel_internal_return = + transcript->template receive_from_prover(commitment_labels.avmMini_sel_internal_return); + commitments.avmMini_sel_halt = + transcript->template receive_from_prover(commitment_labels.avmMini_sel_halt); commitments.avmMini_sel_op_add = transcript->template receive_from_prover(commitment_labels.avmMini_sel_op_add); commitments.avmMini_sel_op_sub = diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Toy_composer.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Toy_composer.cpp index 4d2ec73e1181..c74903fb6353 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Toy_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Toy_composer.cpp @@ -17,14 +17,10 @@ void ToyComposer::compute_witness(CircuitConstructor& circuit) auto polynomials = circuit.compute_polynomials(); - proving_key->toy_first = polynomials.toy_first; - proving_key->toy_q_tuple_set = polynomials.toy_q_tuple_set; - proving_key->toy_set_1_column_1 = polynomials.toy_set_1_column_1; - proving_key->toy_set_1_column_2 = polynomials.toy_set_1_column_2; - proving_key->toy_set_2_column_1 = polynomials.toy_set_2_column_1; - proving_key->toy_set_2_column_2 = polynomials.toy_set_2_column_2; - proving_key->toy_x = polynomials.toy_x; - proving_key->two_column_perm = polynomials.two_column_perm; + for (auto [key_poly, prover_poly] : zip_view(proving_key->get_all(), polynomials.get_unshifted())) { + ASSERT(flavor_get_label(*proving_key, key_poly) == flavor_get_label(polynomials, prover_poly)); + key_poly = prover_poly; + } computed_witness = true; } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Toy_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Toy_prover.cpp index 3d74e03f6881..a29c274d1e49 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Toy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Toy_prover.cpp @@ -28,7 +28,6 @@ ToyProver::ToyProver(std::shared_ptr input_key, std::shared_ : key(input_key) , commitment_key(commitment_key) { - // TODO: take every polynomial and assign it to the key!! for (auto [prover_poly, key_poly] : zip_view(prover_polynomials.get_unshifted(), key->get_all())) { ASSERT(proof_system::flavor_get_label(prover_polynomials, prover_poly) == proof_system::flavor_get_label(*key, key_poly)); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_arithmetic.test.cpp index ad7b43424690..a75e798292c3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_arithmetic.test.cpp @@ -61,6 +61,7 @@ class AvmMiniArithmeticNegativeTests : public AvmMiniArithmeticTests {}; // Test on basic addition over finite field type. TEST_F(AvmMiniArithmeticTests, additionFF) { + // trace_builder trace_builder.callDataCopy(0, 3, 0, std::vector{ 37, 4, 11 }); // Memory layout: [37,4,11,0,0,0,....] @@ -204,6 +205,7 @@ TEST_F(AvmMiniArithmeticTests, divisionByZeroErrorFF) // Memory layout: [15,0,0,0,0,0,....] trace_builder.div(0, 1, 2, AvmMemoryTag::ff); // [15,0,0,0,0,0....] + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the first row enabling the division selector @@ -226,6 +228,7 @@ TEST_F(AvmMiniArithmeticTests, divisionZeroByZeroErrorFF) { // Memory layout: [0,0,0,0,0,0,....] trace_builder.div(0, 1, 2, AvmMemoryTag::ff); // [0,0,0,0,0,0....] + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the first row enabling the division selector @@ -261,6 +264,7 @@ TEST_F(AvmMiniArithmeticTests, arithmeticFFWithError) trace_builder.div(1, 1, 9, AvmMemoryTag::ff); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] trace_builder.div( 9, 0, 4, AvmMemoryTag::ff); // [0,23*136^(-1),45,23,1/0,136,0,136,136^2,1,0....] Error: division by 0 + trace_builder.halt(); auto trace = trace_builder.finalize(); validateTraceProof(std::move(trace)); @@ -380,6 +384,7 @@ TEST_F(AvmMiniArithmeticNegativeTests, divisionByZeroNoErrorFF) // Memory layout: [15,0,0,0,0,0,....] trace_builder.div(0, 1, 2, AvmMemoryTag::ff); // [15,0,0,0,0,0....] + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the first row enabling the division selector diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_control_flow.test.cpp new file mode 100644 index 000000000000..376f7ed1e5fc --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_control_flow.test.cpp @@ -0,0 +1,253 @@ +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/flavor/generated/AvmMini_flavor.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/proof_system/circuit_builder/AvmMini_helper.hpp" +#include "barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp" +#include "barretenberg/vm/generated/AvmMini_composer.hpp" +#include "barretenberg/vm/generated/AvmMini_prover.hpp" +#include "barretenberg/vm/generated/AvmMini_verifier.hpp" +#include "helpers.test.hpp" + +#include +#include +#include +#include +#include + +using namespace proof_system; + +namespace tests_avm { + +class AvmMiniControlFlowTests : public ::testing::Test { + public: + AvmMiniTraceBuilder trace_builder; + + protected: + // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. + void SetUp() override + { + barretenberg::srs::init_crs_factory("../srs_db/ignition"); + trace_builder = AvmMiniTraceBuilder(); // Clean instance for every run. + }; +}; + +/****************************************************************************** + * + * POSITIVE TESTS - Control Flow + * + *****************************************************************************/ + +TEST_F(AvmMiniControlFlowTests, simpleCall) +{ + uint32_t const CALL_ADDRESS = 4; + + // trace_builder for the following operation + // pc opcode + // 0 INTERNAL_CALL(pc=4) + // 4 HALT + trace_builder.internal_call(CALL_ADDRESS); + trace_builder.halt(); + + auto trace = trace_builder.finalize(); + + // Check call + { + auto call_row = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_internal_call == FF(1); }); + EXPECT_TRUE(call_row != trace.end()); + EXPECT_EQ(call_row->avmMini_pc, FF(0)); + EXPECT_EQ(call_row->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET)); + EXPECT_EQ(call_row->avmMini_ia, FF(1)); + EXPECT_EQ(call_row->avmMini_mem_idx_a, + FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET)); // Store the return address (0) in memory + } + + // Check halt + { + auto halt_row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_halt == FF(1); }); + + // Check that the correct result is stored at the expected memory location. + EXPECT_TRUE(halt_row != trace.end()); + EXPECT_EQ(halt_row->avmMini_pc, FF(CALL_ADDRESS)); + EXPECT_EQ(halt_row->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 1)); + } + validateTraceProof(std::move(trace)); +} + +TEST_F(AvmMiniControlFlowTests, simpleCallAndReturn) +{ + uint32_t const CALL_ADDRESS = 20; + uint32_t const RETURN_ADDRESS = 1; + // trace_builder for the following operation + // pc opcode + // 0 INTERNAL_CALL(pc=20) + // 20 INTERNAL_RETURN + // 1 HALT + trace_builder.internal_call(CALL_ADDRESS); + trace_builder.internal_return(); + trace_builder.halt(); + + auto trace = trace_builder.finalize(); + + // Check call + { + auto call_row = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_internal_call == FF(1); }); + EXPECT_TRUE(call_row != trace.end()); + EXPECT_EQ(call_row->avmMini_pc, FF(0)); + EXPECT_EQ(call_row->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET)); + EXPECT_EQ(call_row->avmMini_ia, FF(1)); + EXPECT_EQ(call_row->avmMini_mem_idx_a, + FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET)); // Store the return address (0) in memory + } + + // Check return + { + auto return_row = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_internal_return == FF(1); }); + + // Check that the correct result is stored at the expected memory location. + EXPECT_TRUE(return_row != trace.end()); + EXPECT_EQ(return_row->avmMini_pc, FF(CALL_ADDRESS)); + EXPECT_EQ(return_row->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 1)); + } + + // Check halt + { + auto halt_row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_halt == FF(1); }); + + EXPECT_TRUE(halt_row != trace.end()); + EXPECT_EQ(halt_row->avmMini_pc, FF(RETURN_ADDRESS)); + } + + validateTraceProof(std::move(trace)); +} + +TEST_F(AvmMiniControlFlowTests, multipleCallsAndReturns) +{ + uint32_t const CALL_ADDRESS_1 = 420; + uint32_t const CALL_ADDRESS_2 = 69; + uint32_t const CALL_ADDRESS_3 = 1337; + uint32_t const CALL_ADDRESS_4 = 4; + + // trace_builder for the following operation + // pc opcode + // 0 INTERNAL_CALL(pc=420) + // 420 INTERNAL_CALL(pc=69) + // 69 INTERNAL_CALL(pc=1337) + // 1337 INTERNAL_RETURN + // 70 INTERNAL_CALL(pc=4) + // 4 INTERNAL_RETURN + // 71 INTERNAL_RETURN + // 421 INTERNAL_RETURN + // 1 HALT + trace_builder.internal_call(CALL_ADDRESS_1); + trace_builder.internal_call(CALL_ADDRESS_2); + trace_builder.internal_call(CALL_ADDRESS_3); + trace_builder.internal_return(); + trace_builder.internal_call(CALL_ADDRESS_4); + trace_builder.internal_return(); + trace_builder.internal_return(); + trace_builder.internal_return(); + trace_builder.halt(); + + auto trace = trace_builder.finalize(); + + // Check call 1 + { + auto call_1 = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { + return r.avmMini_sel_internal_call == FF(1) && r.avmMini_ia == FF(1); + }); + EXPECT_TRUE(call_1 != trace.end()); + EXPECT_EQ(call_1->avmMini_pc, FF(0)); + EXPECT_EQ(call_1->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET)); + EXPECT_EQ(call_1->avmMini_mem_idx_a, + FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET)); // Store the return address (0) in memory + } + + // Call 2 + { + auto call_2 = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { + return r.avmMini_sel_internal_call == FF(1) && r.avmMini_pc == FF(CALL_ADDRESS_1); + }); + EXPECT_TRUE(call_2 != trace.end()); + EXPECT_EQ(call_2->avmMini_ia, FF(CALL_ADDRESS_1 + 1)); + EXPECT_EQ(call_2->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 1)); + EXPECT_EQ(call_2->avmMini_mem_idx_a, + FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 1)); // Store the return address (0) in memory + } + + // Call 3 + { + auto call_3 = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { + return r.avmMini_sel_internal_call == FF(1) && r.avmMini_pc == FF(CALL_ADDRESS_2); + }); + EXPECT_TRUE(call_3 != trace.end()); + EXPECT_EQ(call_3->avmMini_ia, FF(CALL_ADDRESS_2 + 1)); + EXPECT_EQ(call_3->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 2)); + EXPECT_EQ(call_3->avmMini_mem_idx_a, + FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 2)); // Store the return address (0) in memory + } + + // Return 1 + { + auto return_1 = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_internal_return == FF(1); }); + EXPECT_TRUE(return_1 != trace.end()); + EXPECT_EQ(return_1->avmMini_pc, FF(CALL_ADDRESS_3)); + EXPECT_EQ(return_1->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 3)); + } + + // Call 4 + { + auto call_4 = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { + return r.avmMini_sel_internal_call == FF(1) && r.avmMini_pc == FF(CALL_ADDRESS_2 + 1); + }); + EXPECT_TRUE(call_4 != trace.end()); + EXPECT_EQ(call_4->avmMini_ia, FF(CALL_ADDRESS_2 + 2)); + EXPECT_EQ(call_4->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 2)); + EXPECT_EQ(call_4->avmMini_mem_idx_a, + FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 2)); // Store the return address (0) in memory + } + + // Return 2 + { + auto return_2 = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { + return r.avmMini_sel_internal_return == FF(1) && r.avmMini_pc == FF(CALL_ADDRESS_4); + }); + EXPECT_TRUE(return_2 != trace.end()); + EXPECT_EQ(return_2->avmMini_ia, FF(CALL_ADDRESS_2 + 2)); + EXPECT_EQ(return_2->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 3)); + } + + // Return 3 + { + auto return_3 = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { + return r.avmMini_sel_internal_return == FF(1) && r.avmMini_pc == FF(CALL_ADDRESS_2 + 2); + }); + EXPECT_TRUE(return_3 != trace.end()); + EXPECT_EQ(return_3->avmMini_ia, FF(CALL_ADDRESS_1 + 1)); + EXPECT_EQ(return_3->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 2)); + } + + // Return 4 + { + auto return_4 = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { + return r.avmMini_sel_internal_return == FF(1) && r.avmMini_pc == FF(CALL_ADDRESS_1 + 1); + }); + EXPECT_TRUE(return_4 != trace.end()); + EXPECT_EQ(return_4->avmMini_ia, FF(1)); + EXPECT_EQ(return_4->avmMini_internal_return_ptr, FF(AvmMiniTraceBuilder::CALLSTACK_OFFSET + 1)); + } + + // Halt row + auto halt_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_halt == FF(1); }); + + EXPECT_TRUE(halt_row != trace.end()); + EXPECT_EQ(halt_row->avmMini_pc, FF(1)); + + validateTraceProof(std::move(trace)); +} +} // namespace tests_avm \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_memory.test.cpp index 31c3355a5ee7..893216fb71e4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_memory.test.cpp @@ -52,6 +52,7 @@ TEST_F(AvmMiniMemoryTests, mismatchedTag) trace_builder.callDataCopy(0, 2, 0, std::vector{ 98, 12 }); trace_builder.add(0, 1, 4, AvmMemoryTag::u8); + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -99,6 +100,7 @@ TEST_F(AvmMiniMemoryTests, mLastAccessViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.sub(1, 0, 2, AvmMemoryTag::u8); // [4,9,5,0,0,0.....] + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the row with subtraction operation @@ -198,6 +200,7 @@ TEST_F(AvmMiniMemoryTests, mismatchedTagErrorViolation) trace_builder.callDataCopy(0, 2, 0, std::vector{ 98, 12 }); trace_builder.sub(0, 1, 4, AvmMemoryTag::u8); + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -231,6 +234,7 @@ TEST_F(AvmMiniMemoryTests, consistentTagNoErrorViolation) trace_builder.callDataCopy(0, 2, 0, std::vector{ 84, 7 }); trace_builder.div(0, 1, 4, AvmMemoryTag::ff); + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the first row enabling the division selector