From b190ae9bae79207f9221558bd5542f58fb85ba84 Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Fri, 8 Dec 2023 17:57:08 +0100 Subject: [PATCH] feat(avm-mini): add sub, mul, div and error handling for finite fields (#3612) Resolves #3546 Resolves #3548 ### Description This PR introduces the following opcodes for the finite field type: - SUB: subtraction - MUL: multiplication - DIV: division For division, error is raised whenever the numerator is zero. A boolean column op_err was introduced for this purpose. --- barretenberg/cpp/pil/avm/avm_mini.pil | 71 ++++- barretenberg/cpp/pil/avm/avm_mini_opt.pil | 21 +- .../flavor/generated/AvmMini_flavor.hpp | 242 ++++++++-------- .../circuit_builder/AvmMini_trace.cpp | 267 ++++++++++++++---- .../circuit_builder/AvmMini_trace.hpp | 35 ++- .../generated/AvmMini_circuit_builder.hpp | 26 +- .../relations/generated/AvmMini/avm_mini.hpp | 115 +++++++- .../generated/AvmMini/declare_views.hpp | 11 +- .../relations/generated/AvmMini/mem_trace.hpp | 12 +- .../vm/generated/AvmMini_composer.cpp | 7 +- .../vm/generated/AvmMini_composer.test.cpp | 21 +- .../vm/generated/AvmMini_prover.cpp | 17 +- .../vm/generated/AvmMini_verifier.cpp | 11 +- 13 files changed, 608 insertions(+), 248 deletions(-) diff --git a/barretenberg/cpp/pil/avm/avm_mini.pil b/barretenberg/cpp/pil/avm/avm_mini.pil index f9b8f2fe23a..3bd9bc11b86 100644 --- a/barretenberg/cpp/pil/avm/avm_mini.pil +++ b/barretenberg/cpp/pil/avm/avm_mini.pil @@ -9,11 +9,25 @@ namespace avmMini(256); // only in first element of shifted polynomials. //===== TABLE SUBOP-TR ======================================================== - // Enum over sub operations - // 0: VOID - // 1: ADD - pol commit subop; - + // Boolean selectors for (sub-)operations. Only one operation is activated at + // a time. + + // ADD + pol commit sel_op_add; + // SUB + pol commit sel_op_sub; + // MUL + pol commit sel_op_mul; + // DIV + pol commit sel_op_div; + + // Error boolean flag pertaining to an operation + pol commit op_err; + + // A helper witness being the inverse of some value + // to show a non-zero equality + pol commit inv; + // Intermediate register values pol commit ia; pol commit ib; @@ -42,15 +56,56 @@ namespace avmMini(256); pol commit last; // Relations on type constraints - subop * (1 - subop) = 0; + + sel_op_add * (1 - sel_op_add) = 0; + sel_op_sub * (1 - sel_op_sub) = 0; + sel_op_mul * (1 - sel_op_mul) = 0; + sel_op_div * (1 - sel_op_div) = 0; + + op_err * (1 - op_err) = 0; + mem_op_a * (1 - mem_op_a) = 0; mem_op_b * (1 - mem_op_b) = 0; mem_op_c * (1 - mem_op_c) = 0; + rwa * (1 - rwa) = 0; rwb * (1 - rwb) = 0; rwc * (1 - rwc) = 0; // Relation for addition over the finite field - subop * (ia + ib - ic) = 0; + sel_op_add * (ia + ib - ic) = 0; - \ No newline at end of file + // Relation for subtraction over the finite field + sel_op_sub * (ia - ib - ic) = 0; + + // Relation for multiplication over the finite field + sel_op_mul * (ia * ib - ic) = 0; + + // Relation for division over the finite field + sel_op_div * (1 - op_err) * (ic * ib - ia) = 0; + + // When sel_op_div == 1, we want ib == 0 <==> op_err == 1 + // This can be achieved with the 2 following relations. + // inv is an extra witness to show that we can invert ib, i.e., inv = ib^(-1) + // If ib == 0, we have to set inv = 1 to satisfy the second relation. + sel_op_div * (ib * inv - 1 + op_err) = 0; + sel_op_div * op_err * (1 - inv) = 0; + + // op_err cannot be maliciously activated for a non-relevant + // operation selector, i.e., op_err == 1 ==> sel_op_div || sel_op_XXX || ... + // op_err * (sel_op_div + sel_op_XXX + ... - 1) == 0 + // Note that the above is even a stronger constraint, as it shows + // that exactly one sel_op_XXX must be true. + // At this time, we have only division producing an error. + op_err * (sel_op_div - 1) = 0; + + // TODO: constraint that we stop execution at the first error + // An error can only happen at the last sub-operation row. + + // OPEN/POTENTIAL OPTIMIZATION: Dedicated error per relevant operation? + // For the division, we could lower the degree from 4 to 3 + // (sel_op_div - op_div_err) * (ic * ib - ia) = 0; + // Same for the relations related to the error activation: + // (ib * inv - 1 + op_div_err) = 0 && op_err * (1 - inv) = 0 + // This works in combination with op_div_err * (sel_op_div - 1) = 0; + // Drawback is the need to paralllelize the latter. \ No newline at end of file diff --git a/barretenberg/cpp/pil/avm/avm_mini_opt.pil b/barretenberg/cpp/pil/avm/avm_mini_opt.pil index ffa516ca9ef..56019fb7197 100644 --- a/barretenberg/cpp/pil/avm/avm_mini_opt.pil +++ b/barretenberg/cpp/pil/avm/avm_mini_opt.pil @@ -12,7 +12,12 @@ namespace memTrace(256); namespace avmMini(256); col fixed clk(i) { i }; col fixed first = [1] + [0]*; - col witness subop; + col witness sel_op_add; + col witness sel_op_sub; + col witness sel_op_mul; + col witness sel_op_div; + col witness op_err; + col witness inv; col witness ia; col witness ib; col witness ic; @@ -26,11 +31,21 @@ namespace avmMini(256); col witness mem_idx_b; col witness mem_idx_c; col witness last; - (avmMini.subop * (1 - avmMini.subop)) = 0; + (avmMini.sel_op_add * (1 - avmMini.sel_op_add)) = 0; + (avmMini.sel_op_sub * (1 - avmMini.sel_op_sub)) = 0; + (avmMini.sel_op_mul * (1 - avmMini.sel_op_mul)) = 0; + (avmMini.sel_op_div * (1 - avmMini.sel_op_div)) = 0; + (avmMini.op_err * (1 - avmMini.op_err)) = 0; (avmMini.mem_op_a * (1 - avmMini.mem_op_a)) = 0; (avmMini.mem_op_b * (1 - avmMini.mem_op_b)) = 0; (avmMini.mem_op_c * (1 - avmMini.mem_op_c)) = 0; (avmMini.rwa * (1 - avmMini.rwa)) = 0; (avmMini.rwb * (1 - avmMini.rwb)) = 0; (avmMini.rwc * (1 - avmMini.rwc)) = 0; - (avmMini.subop * ((avmMini.ia + avmMini.ib) - avmMini.ic)) = 0; \ No newline at end of file + (avmMini.sel_op_add * ((avmMini.ia + avmMini.ib) - avmMini.ic)) = 0; + (avmMini.sel_op_sub * ((avmMini.ia - avmMini.ib) - avmMini.ic)) = 0; + (avmMini.sel_op_mul * ((avmMini.ia * avmMini.ib) - avmMini.ic)) = 0; + ((avmMini.sel_op_div * (1 - avmMini.op_err)) * ((avmMini.ic * avmMini.ib) - avmMini.ia)) = 0; + (avmMini.sel_op_div * (((avmMini.ib * avmMini.inv) - 1) + avmMini.op_err)) = 0; + ((avmMini.sel_op_div * avmMini.op_err) * (1 - avmMini.inv)) = 0; + (avmMini.op_err * (avmMini.sel_op_div - 1)) = 0; diff --git a/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp index 718d61f3c89..c3b00281f70 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp @@ -34,11 +34,11 @@ class AvmMiniFlavor { using VerifierCommitmentKey = pcs::VerifierCommitmentKey; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 20; + static constexpr size_t NUM_WITNESS_ENTITIES = 25; 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 = 25; + static constexpr size_t NUM_ALL_ENTITIES = 30; using Relations = std::tuple, AvmMini_vm::mem_trace>; @@ -65,14 +65,7 @@ class AvmMiniFlavor { DEFINE_FLAVOR_MEMBERS(DataType, avmMini_clk, avmMini_first) - RefVector get_selectors() - { - return { - avmMini_clk, - avmMini_first, - }; - }; - + RefVector get_selectors() { return { avmMini_clk, avmMini_first }; }; RefVector get_sigma_polynomials() { return {}; }; RefVector get_id_polynomials() { return {}; }; RefVector get_table_polynomials() { return {}; }; @@ -87,7 +80,12 @@ class AvmMiniFlavor { memTrace_m_val, memTrace_m_lastAccess, memTrace_m_rw, - avmMini_subop, + avmMini_sel_op_add, + avmMini_sel_op_sub, + avmMini_sel_op_mul, + avmMini_sel_op_div, + avmMini_op_err, + avmMini_inv, avmMini_ia, avmMini_ib, avmMini_ic, @@ -105,14 +103,13 @@ class AvmMiniFlavor { RefVector get_wires() { return { - memTrace_m_clk, memTrace_m_sub_clk, memTrace_m_addr, memTrace_m_val, memTrace_m_lastAccess, - memTrace_m_rw, avmMini_subop, avmMini_ia, avmMini_ib, avmMini_ic, - avmMini_mem_op_a, avmMini_mem_op_b, avmMini_mem_op_c, avmMini_rwa, avmMini_rwb, - avmMini_rwc, avmMini_mem_idx_a, avmMini_mem_idx_b, avmMini_mem_idx_c, avmMini_last, - + memTrace_m_clk, memTrace_m_sub_clk, memTrace_m_addr, memTrace_m_val, memTrace_m_lastAccess, + memTrace_m_rw, avmMini_sel_op_add, avmMini_sel_op_sub, avmMini_sel_op_mul, avmMini_sel_op_div, + avmMini_op_err, avmMini_inv, avmMini_ia, avmMini_ib, avmMini_ic, + avmMini_mem_op_a, avmMini_mem_op_b, avmMini_mem_op_c, avmMini_rwa, avmMini_rwb, + avmMini_rwc, avmMini_mem_idx_a, avmMini_mem_idx_b, avmMini_mem_idx_c, avmMini_last }; }; - RefVector get_sorted_polynomials() { return {}; }; }; @@ -127,7 +124,12 @@ class AvmMiniFlavor { memTrace_m_val, memTrace_m_lastAccess, memTrace_m_rw, - avmMini_subop, + avmMini_sel_op_add, + avmMini_sel_op_sub, + avmMini_sel_op_mul, + avmMini_sel_op_div, + avmMini_op_err, + avmMini_inv, avmMini_ia, avmMini_ib, avmMini_ic, @@ -142,88 +144,76 @@ class AvmMiniFlavor { avmMini_mem_idx_c, avmMini_last, memTrace_m_rw_shift, - memTrace_m_addr_shift, - memTrace_m_val_shift) + memTrace_m_val_shift, + memTrace_m_addr_shift) RefVector get_wires() { - return { - avmMini_clk, - avmMini_first, - memTrace_m_clk, - memTrace_m_sub_clk, - memTrace_m_addr, - memTrace_m_val, - memTrace_m_lastAccess, - memTrace_m_rw, - avmMini_subop, - avmMini_ia, - avmMini_ib, - avmMini_ic, - avmMini_mem_op_a, - avmMini_mem_op_b, - avmMini_mem_op_c, - avmMini_rwa, - avmMini_rwb, - avmMini_rwc, - avmMini_mem_idx_a, - avmMini_mem_idx_b, - avmMini_mem_idx_c, - avmMini_last, - memTrace_m_rw_shift, - memTrace_m_addr_shift, - memTrace_m_val_shift, - - }; + return { avmMini_clk, + avmMini_first, + memTrace_m_clk, + memTrace_m_sub_clk, + memTrace_m_addr, + memTrace_m_val, + memTrace_m_lastAccess, + memTrace_m_rw, + avmMini_sel_op_add, + avmMini_sel_op_sub, + avmMini_sel_op_mul, + avmMini_sel_op_div, + avmMini_op_err, + avmMini_inv, + avmMini_ia, + avmMini_ib, + avmMini_ic, + avmMini_mem_op_a, + avmMini_mem_op_b, + avmMini_mem_op_c, + avmMini_rwa, + avmMini_rwb, + avmMini_rwc, + avmMini_mem_idx_a, + avmMini_mem_idx_b, + avmMini_mem_idx_c, + avmMini_last, + memTrace_m_rw_shift, + memTrace_m_val_shift, + memTrace_m_addr_shift }; }; - RefVector get_unshifted() { - return { - avmMini_clk, - avmMini_first, - memTrace_m_clk, - memTrace_m_sub_clk, - memTrace_m_addr, - memTrace_m_val, - memTrace_m_lastAccess, - memTrace_m_rw, - avmMini_subop, - avmMini_ia, - avmMini_ib, - avmMini_ic, - avmMini_mem_op_a, - avmMini_mem_op_b, - avmMini_mem_op_c, - avmMini_rwa, - avmMini_rwb, - avmMini_rwc, - avmMini_mem_idx_a, - avmMini_mem_idx_b, - avmMini_mem_idx_c, - avmMini_last, - - }; - }; - - RefVector get_to_be_shifted() - { - return { - memTrace_m_rw, - memTrace_m_addr, - memTrace_m_val, - - }; + return { avmMini_clk, + avmMini_first, + memTrace_m_clk, + memTrace_m_sub_clk, + memTrace_m_addr, + memTrace_m_val, + memTrace_m_lastAccess, + memTrace_m_rw, + avmMini_sel_op_add, + avmMini_sel_op_sub, + avmMini_sel_op_mul, + avmMini_sel_op_div, + avmMini_op_err, + avmMini_inv, + avmMini_ia, + avmMini_ib, + avmMini_ic, + avmMini_mem_op_a, + avmMini_mem_op_b, + avmMini_mem_op_c, + avmMini_rwa, + avmMini_rwb, + avmMini_rwc, + avmMini_mem_idx_a, + avmMini_mem_idx_b, + avmMini_mem_idx_c, + avmMini_last }; }; - + RefVector get_to_be_shifted() { return { memTrace_m_rw, memTrace_m_val, memTrace_m_addr }; }; RefVector get_shifted() { - return { - memTrace_m_rw_shift, - memTrace_m_addr_shift, - memTrace_m_val_shift, - - }; + return { memTrace_m_rw_shift, memTrace_m_val_shift, memTrace_m_addr_shift }; }; }; @@ -296,28 +286,33 @@ class AvmMiniFlavor { CommitmentLabels() : AllEntities() { - Base::avmMini_clk = "avmMini_clk"; - Base::avmMini_first = "avmMini_first"; - Base::memTrace_m_clk = "memTrace_m_clk"; - Base::memTrace_m_sub_clk = "memTrace_m_sub_clk"; - Base::memTrace_m_addr = "memTrace_m_addr"; - Base::memTrace_m_val = "memTrace_m_val"; - Base::memTrace_m_lastAccess = "memTrace_m_lastAccess"; - Base::memTrace_m_rw = "memTrace_m_rw"; - Base::avmMini_subop = "avmMini_subop"; - Base::avmMini_ia = "avmMini_ia"; - Base::avmMini_ib = "avmMini_ib"; - Base::avmMini_ic = "avmMini_ic"; - Base::avmMini_mem_op_a = "avmMini_mem_op_a"; - Base::avmMini_mem_op_b = "avmMini_mem_op_b"; - Base::avmMini_mem_op_c = "avmMini_mem_op_c"; - Base::avmMini_rwa = "avmMini_rwa"; - Base::avmMini_rwb = "avmMini_rwb"; - Base::avmMini_rwc = "avmMini_rwc"; - Base::avmMini_mem_idx_a = "avmMini_mem_idx_a"; - Base::avmMini_mem_idx_b = "avmMini_mem_idx_b"; - Base::avmMini_mem_idx_c = "avmMini_mem_idx_c"; - Base::avmMini_last = "avmMini_last"; + Base::avmMini_clk = "AVMMINI_CLK"; + Base::avmMini_first = "AVMMINI_FIRST"; + Base::memTrace_m_clk = "MEMTRACE_M_CLK"; + Base::memTrace_m_sub_clk = "MEMTRACE_M_SUB_CLK"; + Base::memTrace_m_addr = "MEMTRACE_M_ADDR"; + Base::memTrace_m_val = "MEMTRACE_M_VAL"; + Base::memTrace_m_lastAccess = "MEMTRACE_M_LASTACCESS"; + Base::memTrace_m_rw = "MEMTRACE_M_RW"; + 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"; + Base::avmMini_sel_op_div = "AVMMINI_SEL_OP_DIV"; + Base::avmMini_op_err = "AVMMINI_OP_ERR"; + Base::avmMini_inv = "AVMMINI_INV"; + Base::avmMini_ia = "AVMMINI_IA"; + Base::avmMini_ib = "AVMMINI_IB"; + Base::avmMini_ic = "AVMMINI_IC"; + Base::avmMini_mem_op_a = "AVMMINI_MEM_OP_A"; + Base::avmMini_mem_op_b = "AVMMINI_MEM_OP_B"; + Base::avmMini_mem_op_c = "AVMMINI_MEM_OP_C"; + Base::avmMini_rwa = "AVMMINI_RWA"; + Base::avmMini_rwb = "AVMMINI_RWB"; + Base::avmMini_rwc = "AVMMINI_RWC"; + Base::avmMini_mem_idx_a = "AVMMINI_MEM_IDX_A"; + Base::avmMini_mem_idx_b = "AVMMINI_MEM_IDX_B"; + Base::avmMini_mem_idx_c = "AVMMINI_MEM_IDX_C"; + Base::avmMini_last = "AVMMINI_LAST"; }; }; @@ -343,7 +338,12 @@ class AvmMiniFlavor { Commitment memTrace_m_val; Commitment memTrace_m_lastAccess; Commitment memTrace_m_rw; - Commitment avmMini_subop; + Commitment avmMini_sel_op_add; + Commitment avmMini_sel_op_sub; + Commitment avmMini_sel_op_mul; + Commitment avmMini_sel_op_div; + Commitment avmMini_op_err; + Commitment avmMini_inv; Commitment avmMini_ia; Commitment avmMini_ib; Commitment avmMini_ic; @@ -382,7 +382,12 @@ class AvmMiniFlavor { memTrace_m_val = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); memTrace_m_lastAccess = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); memTrace_m_rw = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); - avmMini_subop = 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); + avmMini_sel_op_div = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + avmMini_op_err = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + avmMini_inv = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); avmMini_ia = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); avmMini_ib = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); avmMini_ic = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); @@ -425,7 +430,12 @@ class AvmMiniFlavor { serialize_to_buffer(memTrace_m_val, Transcript::proof_data); serialize_to_buffer(memTrace_m_lastAccess, Transcript::proof_data); serialize_to_buffer(memTrace_m_rw, Transcript::proof_data); - serialize_to_buffer(avmMini_subop, 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); + serialize_to_buffer(avmMini_sel_op_div, Transcript::proof_data); + serialize_to_buffer(avmMini_op_err, Transcript::proof_data); + serialize_to_buffer(avmMini_inv, Transcript::proof_data); serialize_to_buffer(avmMini_ia, Transcript::proof_data); serialize_to_buffer(avmMini_ib, Transcript::proof_data); serialize_to_buffer(avmMini_ic, Transcript::proof_data); 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 01089a78395..8562a72c41c 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 @@ -94,7 +94,7 @@ void AvmMiniTraceBuilder::insertInMemTrace(uint32_t m_clk, uint32_t m_sub_clk, u */ void AvmMiniTraceBuilder::loadAInMemTrace(uint32_t addr, FF val) { - insertInMemTrace(static_cast(mainTrace.size()), SubClkLoadA, addr, val, false); + insertInMemTrace(static_cast(mainTrace.size()), SUB_CLK_LOAD_A, addr, val, false); } /** @@ -106,7 +106,7 @@ void AvmMiniTraceBuilder::loadAInMemTrace(uint32_t addr, FF val) */ void AvmMiniTraceBuilder::loadBInMemTrace(uint32_t addr, FF val) { - insertInMemTrace(static_cast(mainTrace.size()), SubClkLoadB, addr, val, false); + insertInMemTrace(static_cast(mainTrace.size()), SUB_CLK_LOAD_B, addr, val, false); } /** @@ -118,7 +118,7 @@ void AvmMiniTraceBuilder::loadBInMemTrace(uint32_t addr, FF val) */ void AvmMiniTraceBuilder::loadCInMemTrace(uint32_t addr, FF val) { - insertInMemTrace(static_cast(mainTrace.size()), SubClkLoadC, addr, val, false); + insertInMemTrace(static_cast(mainTrace.size()), SUB_CLK_LOAD_C, addr, val, false); } /** @@ -130,7 +130,7 @@ void AvmMiniTraceBuilder::loadCInMemTrace(uint32_t addr, FF val) */ void AvmMiniTraceBuilder::storeAInMemTrace(uint32_t addr, FF val) { - insertInMemTrace(static_cast(mainTrace.size()), SubClkStoreA, addr, val, true); + insertInMemTrace(static_cast(mainTrace.size()), SUB_CLK_STORE_A, addr, val, true); } /** @@ -142,7 +142,7 @@ void AvmMiniTraceBuilder::storeAInMemTrace(uint32_t addr, FF val) */ void AvmMiniTraceBuilder::storeBInMemTrace(uint32_t addr, FF val) { - insertInMemTrace(static_cast(mainTrace.size()), SubClkStoreB, addr, val, true); + insertInMemTrace(static_cast(mainTrace.size()), SUB_CLK_STORE_B, addr, val, true); } /** @@ -154,38 +154,38 @@ void AvmMiniTraceBuilder::storeBInMemTrace(uint32_t addr, FF val) */ void AvmMiniTraceBuilder::storeCInMemTrace(uint32_t addr, FF val) { - insertInMemTrace(static_cast(mainTrace.size()), SubClkStoreC, addr, val, true); + insertInMemTrace(static_cast(mainTrace.size()), SUB_CLK_STORE_C, addr, val, true); } /** * @brief Addition over finite field with direct memory access. * - * @param s0 An index in ffMemory pointing to the first operand of the addition. - * @param s1 An index in ffMemory pointing to the second operand of the addition. - * @param d0 An index in ffMemory pointing to the output of the addition. + * @param aOffset An index in ffMemory pointing to the first operand of the addition. + * @param bOffset An index in ffMemory pointing to the second operand of the addition. + * @param dstOffset An index in ffMemory pointing to the output of the addition. */ -void AvmMiniTraceBuilder::add(uint32_t s0, uint32_t s1, uint32_t d0) +void AvmMiniTraceBuilder::add(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset) { // a + b = c - FF a = ffMemory.at(s0); - FF b = ffMemory.at(s1); + FF a = ffMemory.at(aOffset); + FF b = ffMemory.at(bOffset); FF c = a + b; - ffMemory.at(d0) = c; + ffMemory.at(dstOffset) = c; auto clk = mainTrace.size(); // Loading into Ia - loadAInMemTrace(s0, a); + loadAInMemTrace(aOffset, a); // Loading into Ib - loadBInMemTrace(s1, b); + loadBInMemTrace(bOffset, b); // Storing from Ic - storeCInMemTrace(d0, c); + storeCInMemTrace(dstOffset, c); mainTrace.push_back(Row{ .avmMini_clk = clk, - .avmMini_subop = FF(1), + .avmMini_sel_op_add = FF(1), .avmMini_ia = a, .avmMini_ib = b, .avmMini_ic = c, @@ -193,15 +193,157 @@ void AvmMiniTraceBuilder::add(uint32_t s0, uint32_t s1, uint32_t d0) .avmMini_mem_op_b = FF(1), .avmMini_mem_op_c = FF(1), .avmMini_rwc = FF(1), - .avmMini_mem_idx_a = FF(s0), - .avmMini_mem_idx_b = FF(s1), - .avmMini_mem_idx_c = FF(d0), + .avmMini_mem_idx_a = FF(aOffset), + .avmMini_mem_idx_b = FF(bOffset), + .avmMini_mem_idx_c = FF(dstOffset), }); }; +/** + * @brief Subtraction over finite field with direct memory access. + * + * @param aOffset An index in ffMemory pointing to the first operand of the subtraction. + * @param bOffset An index in ffMemory pointing to the second operand of the subtraction. + * @param dstOffset An index in ffMemory pointing to the output of the subtraction. + */ +void AvmMiniTraceBuilder::sub(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset) +{ + // a - b = c + FF a = ffMemory.at(aOffset); + FF b = ffMemory.at(bOffset); + FF c = a - b; + ffMemory.at(dstOffset) = c; + + auto clk = mainTrace.size(); + + // Loading into Ia + loadAInMemTrace(aOffset, a); + + // Loading into Ib + loadBInMemTrace(bOffset, b); + + // Storing from Ic + storeCInMemTrace(dstOffset, c); + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_sel_op_sub = FF(1), + .avmMini_ia = a, + .avmMini_ib = b, + .avmMini_ic = c, + .avmMini_mem_op_a = FF(1), + .avmMini_mem_op_b = FF(1), + .avmMini_mem_op_c = FF(1), + .avmMini_rwc = FF(1), + .avmMini_mem_idx_a = FF(aOffset), + .avmMini_mem_idx_b = FF(bOffset), + .avmMini_mem_idx_c = FF(dstOffset), + }); +}; + +/** + * @brief Multiplication over finite field with direct memory access. + * + * @param aOffset An index in ffMemory pointing to the first operand of the multiplication. + * @param bOffset An index in ffMemory pointing to the second operand of the multiplication. + * @param dstOffset An index in ffMemory pointing to the output of the multiplication. + */ +void AvmMiniTraceBuilder::mul(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset) +{ + // a * b = c + FF a = ffMemory.at(aOffset); + FF b = ffMemory.at(bOffset); + FF c = a * b; + ffMemory.at(dstOffset) = c; + + auto clk = mainTrace.size(); + + // Loading into Ia + loadAInMemTrace(aOffset, a); + + // Loading into Ib + loadBInMemTrace(bOffset, b); + + // Storing from Ic + storeCInMemTrace(dstOffset, c); + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_sel_op_mul = FF(1), + .avmMini_ia = a, + .avmMini_ib = b, + .avmMini_ic = c, + .avmMini_mem_op_a = FF(1), + .avmMini_mem_op_b = FF(1), + .avmMini_mem_op_c = FF(1), + .avmMini_rwc = FF(1), + .avmMini_mem_idx_a = FF(aOffset), + .avmMini_mem_idx_b = FF(bOffset), + .avmMini_mem_idx_c = FF(dstOffset), + }); +} + +/** + * @brief Division over finite field with direct memory access. + * + * @param aOffset An index in ffMemory pointing to the first operand of the division. + * @param bOffset An index in ffMemory pointing to the second operand of the division. + * @param dstOffset An index in ffMemory pointing to the output of the division. + */ +void AvmMiniTraceBuilder::div(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset) +{ + // a * b^(-1) = c + FF a = ffMemory.at(aOffset); + FF b = ffMemory.at(bOffset); + FF c; + FF inv; + FF error; + + if (!b.is_zero()) { + + inv = b.invert(); + c = a * inv; + error = 0; + } else { + inv = 1; + c = 0; + error = 1; + } + + ffMemory.at(dstOffset) = c; + + auto clk = mainTrace.size(); + + // Loading into Ia + loadAInMemTrace(aOffset, a); + + // Loading into Ib + loadBInMemTrace(bOffset, b); + + // Storing from Ic + storeCInMemTrace(dstOffset, c); + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_sel_op_div = FF(1), + .avmMini_op_err = error, + .avmMini_inv = inv, + .avmMini_ia = a, + .avmMini_ib = b, + .avmMini_ic = c, + .avmMini_mem_op_a = FF(1), + .avmMini_mem_op_b = FF(1), + .avmMini_mem_op_c = FF(1), + .avmMini_rwc = FF(1), + .avmMini_mem_idx_a = FF(aOffset), + .avmMini_mem_idx_b = FF(bOffset), + .avmMini_mem_idx_c = FF(dstOffset), + }); +} + /** * @brief CALLDATACOPY opcode with direct memory access, i.e., - * M_F[d0:d0+s1] = M_calldata[s0:s0+s1] + * M[dstOffset:dstOffset+copySize] = calldata[cdOffset:cdOffset+copySize] * Simplified version with exclusively memory store operations and * values from M_calldata passed by an array and loaded into * intermediate registers. @@ -211,22 +353,26 @@ void AvmMiniTraceBuilder::add(uint32_t s0, uint32_t s1, uint32_t d0) * TODO: taking care of intermediate register values consistency and propagating their * values to the next row when not overwritten. * - * @param s0 The starting index of the region in calldata to be copied. - * @param s1 The number of finite field elements to be copied into memory. - * @param d0 The starting index of memory where calldata will be copied to. + * @param cdOffset The starting index of the region in calldata to be copied. + * @param copySize The number of finite field elements to be copied into memory. + * @param dstOffset The starting index of memory where calldata will be copied to. * @param callDataMem The vector containing calldata. */ -void AvmMiniTraceBuilder::callDataCopy(uint32_t s0, uint32_t s1, uint32_t d0, std::vector const& callDataMem) +void AvmMiniTraceBuilder::callDataCopy(uint32_t cdOffset, + uint32_t copySize, + uint32_t dstOffset, + std::vector const& callDataMem) { // We parallelize storing memory operations in chunk of 3, i.e., 1 per intermediate register. - // This offset points to the first storing operation (pertaining to intermediate register Ia). - // s0 + offset: Ia memory store operation - // s0 + offset + 1: Ib memory store operation - // s0 + offset + 2: Ic memory store operation + // The variable pos is an index pointing to the first storing operation (pertaining to intermediate + // register Ia) relative to cdOffset: + // cdOffset + pos: Ia memory store operation + // cdOffset + pos + 1: Ib memory store operation + // cdOffset + pos + 2: Ic memory store operation - uint32_t offset = 0; + uint32_t pos = 0; - while (offset < s1) { + while (pos < copySize) { FF ib(0); FF ic(0); uint32_t mem_op_b(0); @@ -237,19 +383,19 @@ void AvmMiniTraceBuilder::callDataCopy(uint32_t s0, uint32_t s1, uint32_t d0, st uint32_t rwc(0); auto clk = mainTrace.size(); - FF ia = callDataMem.at(s0 + offset); + FF ia = callDataMem.at(cdOffset + pos); uint32_t mem_op_a(1); - uint32_t mem_idx_a = d0 + offset; + uint32_t mem_idx_a = dstOffset + pos; uint32_t rwa = 1; // Storing from Ia ffMemory.at(mem_idx_a) = ia; storeAInMemTrace(mem_idx_a, ia); - if (s1 - offset > 1) { - ib = callDataMem.at(s0 + offset + 1); + if (copySize - pos > 1) { + ib = callDataMem.at(cdOffset + pos + 1); mem_op_b = 1; - mem_idx_b = d0 + offset + 1; + mem_idx_b = dstOffset + pos + 1; rwb = 1; // Storing from Ib @@ -257,10 +403,10 @@ void AvmMiniTraceBuilder::callDataCopy(uint32_t s0, uint32_t s1, uint32_t d0, st storeBInMemTrace(mem_idx_b, ib); } - if (s1 - offset > 2) { - ic = callDataMem.at(s0 + offset + 2); + if (copySize - pos > 2) { + ic = callDataMem.at(cdOffset + pos + 2); mem_op_c = 1; - mem_idx_c = d0 + offset + 2; + mem_idx_c = dstOffset + pos + 2; rwc = 1; // Storing from Ic @@ -284,39 +430,40 @@ void AvmMiniTraceBuilder::callDataCopy(uint32_t s0, uint32_t s1, uint32_t d0, st .avmMini_mem_idx_c = FF(mem_idx_c), }); - if (s1 - offset > 2) { // Guard to prevent overflow if s1 is close to uint32_t maximum value. - offset += 3; + if (copySize - pos > 2) { // Guard to prevent overflow if copySize is close to uint32_t maximum value. + pos += 3; } else { - offset = s1; + pos = copySize; } } } /** * @brief RETURN opcode with direct memory access, i.e., - * return M_F[s0:s0+s1] + * return(M[retOffset:retOffset+retSize]) * Simplified version with exclusively memory load operations into * intermediate registers and then values are copied to the returned vector. * TODO: Implement the indirect memory version (maybe not required) * TODO: taking care of flagging this row as the last one? Special STOP flag? * - * @param s0 The starting index of the memory region to be returned. - * @param s1 The number of elements to be returned. + * @param retOffset The starting index of the memory region to be returned. + * @param retSize The number of elements to be returned. * @return The returned memory region as a std::vector. */ -std::vector AvmMiniTraceBuilder::returnOP(uint32_t s0, uint32_t s1) +std::vector AvmMiniTraceBuilder::returnOP(uint32_t retOffset, uint32_t retSize) { // We parallelize loading memory operations in chunk of 3, i.e., 1 per intermediate register. - // This offset points to the first loading operation (pertaining to intermediate register Ia). - // s0 + offset: Ia memory load operation - // s0 + offset + 1: Ib memory load operation - // s0 + offset + 2: Ic memory load operation + // The variable pos is an index pointing to the first storing operation (pertaining to intermediate + // register Ia) relative to retOffset: + // retOffset + pos: Ia memory load operation + // retOffset + pos + 1: Ib memory load operation + // retOffset + pos + 2: Ic memory load operation - uint32_t offset = 0; + uint32_t pos = 0; std::vector returnMem; - while (offset < s1) { + while (pos < retSize) { FF ib(0); FF ic(0); uint32_t mem_op_b(0); @@ -326,16 +473,16 @@ std::vector AvmMiniTraceBuilder::returnOP(uint32_t s0, uint32_t s1) auto clk = mainTrace.size(); uint32_t mem_op_a(1); - uint32_t mem_idx_a = s0 + offset; + uint32_t mem_idx_a = retOffset + pos; FF ia = ffMemory.at(mem_idx_a); // Loading from Ia returnMem.push_back(ia); loadAInMemTrace(mem_idx_a, ia); - if (s1 - offset > 1) { + if (retSize - pos > 1) { mem_op_b = 1; - mem_idx_b = s0 + offset + 1; + mem_idx_b = retOffset + pos + 1; ib = ffMemory.at(mem_idx_b); // Loading from Ib @@ -343,9 +490,9 @@ std::vector AvmMiniTraceBuilder::returnOP(uint32_t s0, uint32_t s1) loadBInMemTrace(mem_idx_b, ib); } - if (s1 - offset > 2) { + if (retSize - pos > 2) { mem_op_c = 1; - mem_idx_c = s0 + offset + 2; + mem_idx_c = retOffset + pos + 2; ic = ffMemory.at(mem_idx_c); // Loading from Ic @@ -366,10 +513,10 @@ std::vector AvmMiniTraceBuilder::returnOP(uint32_t s0, uint32_t s1) .avmMini_mem_idx_c = FF(mem_idx_c), }); - if (s1 - offset > 2) { // Guard to prevent overflow if s1 is close to uint32_t maximum value. - offset += 3; + if (retSize - pos > 2) { // Guard to prevent overflow if retSize is close to uint32_t maximum value. + pos += 3; } else { - offset = s1; + pos = retSize; } } return returnMem; 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 781d798cd6e..a4621c22e19 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 @@ -24,14 +24,14 @@ class AvmMiniTraceBuilder { public: // Number of rows static const size_t N = 256; - static const size_t MemSize = 1024; + static const size_t MEM_SIZE = 1024; - static const uint32_t SubClkLoadA = 0; - static const uint32_t SubClkLoadB = 1; - static const uint32_t SubClkLoadC = 2; - static const uint32_t SubClkStoreA = 3; - static const uint32_t SubClkStoreB = 4; - static const uint32_t SubClkStoreC = 5; + static const uint32_t SUB_CLK_LOAD_A = 0; + static const uint32_t SUB_CLK_LOAD_B = 1; + static const uint32_t SUB_CLK_LOAD_C = 2; + static const uint32_t SUB_CLK_STORE_A = 3; + static const uint32_t SUB_CLK_STORE_B = 4; + static const uint32_t SUB_CLK_STORE_C = 5; AvmMiniTraceBuilder(); @@ -42,15 +42,24 @@ class AvmMiniTraceBuilder { void reset(); // Addition over finite field with direct memory access. - void add(uint32_t s0, uint32_t s1, uint32_t d0); + void add(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset); + + // Subtraction over finite field with direct memory access. + void sub(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset); + + // Multiplication over finite field with direct memory access. + void mul(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset); + + // Division over finite field with direct memory access. + void div(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset); // CALLDATACOPY opcode with direct memory access, i.e., - // M_F[d0:d0+s1] = M_calldata[s0:s0+s1] - void callDataCopy(uint32_t s0, uint32_t s1, uint32_t d0, std::vector const& callDataMem); + // M[dstOffset:dstOffset+copySize] = calldata[cdOffset:cdOffset+copySize] + void callDataCopy(uint32_t cdOffset, uint32_t copySize, uint32_t dstOffset, std::vector const& callDataMem); // RETURN opcode with direct memory access, i.e., - // return M_F[s0:s0+s1] - std::vector returnOP(uint32_t s0, uint32_t s1); + // return(M[retOffset:retOffset+retSize]) + std::vector returnOP(uint32_t retOffset, uint32_t retSize); private: struct MemoryTraceEntry { @@ -63,7 +72,7 @@ class AvmMiniTraceBuilder { std::vector mainTrace; std::vector memTrace; // Entries will be sorted by m_clk, m_sub_clk after finalize(). - std::array ffMemory{}; // Memory table for finite field elements + std::array ffMemory{}; // Memory table for finite field elements // Used for simulation of memory table static bool compareMemEntries(const MemoryTraceEntry& left, const MemoryTraceEntry& right); 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 77cae117e47..46cabaa1a0e 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 @@ -24,7 +24,12 @@ template struct AvmMiniFullRow { FF memTrace_m_val{}; FF memTrace_m_lastAccess{}; FF memTrace_m_rw{}; - FF avmMini_subop{}; + FF avmMini_sel_op_add{}; + FF avmMini_sel_op_sub{}; + FF avmMini_sel_op_mul{}; + FF avmMini_sel_op_div{}; + FF avmMini_op_err{}; + FF avmMini_inv{}; FF avmMini_ia{}; FF avmMini_ib{}; FF avmMini_ic{}; @@ -38,9 +43,9 @@ template struct AvmMiniFullRow { FF avmMini_mem_idx_b{}; FF avmMini_mem_idx_c{}; FF avmMini_last{}; - FF memTrace_m_addr_shift{}; FF memTrace_m_rw_shift{}; FF memTrace_m_val_shift{}; + FF memTrace_m_addr_shift{}; }; class AvmMiniCircuitBuilder { @@ -53,8 +58,8 @@ class AvmMiniCircuitBuilder { using Polynomial = Flavor::Polynomial; using AllPolynomials = Flavor::AllPolynomials; - static constexpr size_t num_fixed_columns = 25; - static constexpr size_t num_polys = 22; + static constexpr size_t num_fixed_columns = 30; + static constexpr size_t num_polys = 27; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -78,7 +83,12 @@ class AvmMiniCircuitBuilder { polys.memTrace_m_val[i] = rows[i].memTrace_m_val; polys.memTrace_m_lastAccess[i] = rows[i].memTrace_m_lastAccess; polys.memTrace_m_rw[i] = rows[i].memTrace_m_rw; - polys.avmMini_subop[i] = rows[i].avmMini_subop; + 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; + polys.avmMini_sel_op_div[i] = rows[i].avmMini_sel_op_div; + polys.avmMini_op_err[i] = rows[i].avmMini_op_err; + polys.avmMini_inv[i] = rows[i].avmMini_inv; polys.avmMini_ia[i] = rows[i].avmMini_ia; polys.avmMini_ib[i] = rows[i].avmMini_ib; polys.avmMini_ic[i] = rows[i].avmMini_ic; @@ -94,9 +104,9 @@ class AvmMiniCircuitBuilder { polys.avmMini_last[i] = rows[i].avmMini_last; } - 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_val_shift = Polynomial(polys.memTrace_m_val.shifted()); + polys.memTrace_m_addr_shift = Polynomial(polys.memTrace_m_addr.shifted()); return polys; } @@ -131,10 +141,10 @@ class AvmMiniCircuitBuilder { return true; }; - if (!evaluate_relation.template operator()>("mem_trace")) { + if (!evaluate_relation.template operator()>("avm_mini")) { return false; } - if (!evaluate_relation.template operator()>("avm_mini")) { + if (!evaluate_relation.template operator()>("mem_trace")) { 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 14909b98be3..5596bbc94cf 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/avm_mini.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/avm_mini.hpp @@ -7,24 +7,29 @@ namespace proof_system::AvmMini_vm { template struct Avm_miniRow { - FF avmMini_rwc{}; - FF avmMini_rwa{}; FF avmMini_mem_op_b{}; FF avmMini_ib{}; - FF avmMini_rwb{}; - FF avmMini_subop{}; + FF avmMini_ic{}; + FF avmMini_sel_op_sub{}; FF avmMini_mem_op_c{}; + FF avmMini_op_err{}; FF avmMini_ia{}; - FF avmMini_ic{}; + FF avmMini_inv{}; + FF avmMini_sel_op_div{}; FF avmMini_mem_op_a{}; + FF avmMini_rwa{}; + FF avmMini_sel_op_mul{}; + FF avmMini_rwc{}; + FF avmMini_sel_op_add{}; + FF avmMini_rwb{}; }; template class avm_miniImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 3, 3, 3, 3, 3, 3, 3, 3, + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 4, 3, }; template @@ -38,7 +43,7 @@ template class avm_miniImpl { { DECLARE_VIEWS(0); - auto tmp = (avmMini_subop * (-avmMini_subop + FF(1))); + auto tmp = (avmMini_sel_op_add * (-avmMini_sel_op_add + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -46,7 +51,7 @@ template class avm_miniImpl { { DECLARE_VIEWS(1); - auto tmp = (avmMini_mem_op_a * (-avmMini_mem_op_a + FF(1))); + auto tmp = (avmMini_sel_op_sub * (-avmMini_sel_op_sub + FF(1))); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -54,7 +59,7 @@ template class avm_miniImpl { { DECLARE_VIEWS(2); - auto tmp = (avmMini_mem_op_b * (-avmMini_mem_op_b + FF(1))); + auto tmp = (avmMini_sel_op_mul * (-avmMini_sel_op_mul + FF(1))); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -62,7 +67,7 @@ template class avm_miniImpl { { DECLARE_VIEWS(3); - auto tmp = (avmMini_mem_op_c * (-avmMini_mem_op_c + FF(1))); + auto tmp = (avmMini_sel_op_div * (-avmMini_sel_op_div + FF(1))); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -70,7 +75,7 @@ template class avm_miniImpl { { DECLARE_VIEWS(4); - auto tmp = (avmMini_rwa * (-avmMini_rwa + FF(1))); + auto tmp = (avmMini_op_err * (-avmMini_op_err + FF(1))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -78,7 +83,7 @@ template class avm_miniImpl { { DECLARE_VIEWS(5); - auto tmp = (avmMini_rwb * (-avmMini_rwb + FF(1))); + auto tmp = (avmMini_mem_op_a * (-avmMini_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -86,7 +91,7 @@ template class avm_miniImpl { { DECLARE_VIEWS(6); - auto tmp = (avmMini_rwc * (-avmMini_rwc + FF(1))); + auto tmp = (avmMini_mem_op_b * (-avmMini_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -94,10 +99,90 @@ template class avm_miniImpl { { DECLARE_VIEWS(7); - auto tmp = (avmMini_subop * ((avmMini_ia + avmMini_ib) - avmMini_ic)); + auto tmp = (avmMini_mem_op_c * (-avmMini_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } + // Contribution 8 + { + DECLARE_VIEWS(8); + + auto tmp = (avmMini_rwa * (-avmMini_rwa + FF(1))); + tmp *= scaling_factor; + std::get<8>(evals) += tmp; + } + // Contribution 9 + { + DECLARE_VIEWS(9); + + auto tmp = (avmMini_rwb * (-avmMini_rwb + FF(1))); + tmp *= scaling_factor; + std::get<9>(evals) += tmp; + } + // Contribution 10 + { + DECLARE_VIEWS(10); + + auto tmp = (avmMini_rwc * (-avmMini_rwc + FF(1))); + tmp *= scaling_factor; + std::get<10>(evals) += tmp; + } + // Contribution 11 + { + DECLARE_VIEWS(11); + + auto tmp = (avmMini_sel_op_add * ((avmMini_ia + avmMini_ib) - avmMini_ic)); + tmp *= scaling_factor; + std::get<11>(evals) += tmp; + } + // Contribution 12 + { + DECLARE_VIEWS(12); + + auto tmp = (avmMini_sel_op_sub * ((avmMini_ia - avmMini_ib) - avmMini_ic)); + tmp *= scaling_factor; + std::get<12>(evals) += tmp; + } + // Contribution 13 + { + DECLARE_VIEWS(13); + + auto tmp = (avmMini_sel_op_mul * ((avmMini_ia * avmMini_ib) - avmMini_ic)); + tmp *= scaling_factor; + std::get<13>(evals) += tmp; + } + // Contribution 14 + { + DECLARE_VIEWS(14); + + auto tmp = ((avmMini_sel_op_div * (-avmMini_op_err + FF(1))) * ((avmMini_ic * avmMini_ib) - avmMini_ia)); + tmp *= scaling_factor; + std::get<14>(evals) += tmp; + } + // Contribution 15 + { + DECLARE_VIEWS(15); + + auto tmp = (avmMini_sel_op_div * (((avmMini_ib * avmMini_inv) - FF(1)) + avmMini_op_err)); + tmp *= scaling_factor; + std::get<15>(evals) += tmp; + } + // Contribution 16 + { + DECLARE_VIEWS(16); + + auto tmp = ((avmMini_sel_op_div * avmMini_op_err) * (-avmMini_inv + FF(1))); + tmp *= scaling_factor; + std::get<16>(evals) += tmp; + } + // Contribution 17 + { + DECLARE_VIEWS(17); + + auto tmp = (avmMini_op_err * (avmMini_sel_op_div - FF(1))); + tmp *= scaling_factor; + std::get<17>(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 cad793a7b5f..b5d9a61651e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/declare_views.hpp @@ -10,7 +10,12 @@ [[maybe_unused]] auto memTrace_m_val = View(new_term.memTrace_m_val); \ [[maybe_unused]] auto memTrace_m_lastAccess = View(new_term.memTrace_m_lastAccess); \ [[maybe_unused]] auto memTrace_m_rw = View(new_term.memTrace_m_rw); \ - [[maybe_unused]] auto avmMini_subop = View(new_term.avmMini_subop); \ + [[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); \ + [[maybe_unused]] auto avmMini_sel_op_div = View(new_term.avmMini_sel_op_div); \ + [[maybe_unused]] auto avmMini_op_err = View(new_term.avmMini_op_err); \ + [[maybe_unused]] auto avmMini_inv = View(new_term.avmMini_inv); \ [[maybe_unused]] auto avmMini_ia = View(new_term.avmMini_ia); \ [[maybe_unused]] auto avmMini_ib = View(new_term.avmMini_ib); \ [[maybe_unused]] auto avmMini_ic = View(new_term.avmMini_ic); \ @@ -24,6 +29,6 @@ [[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 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_val_shift = View(new_term.memTrace_m_val_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); 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 2a7960abd72..dde059dedc6 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/mem_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/mem_trace.hpp @@ -7,15 +7,15 @@ namespace proof_system::AvmMini_vm { template struct Mem_traceRow { - FF avmMini_last{}; + FF memTrace_m_rw_shift{}; + FF memTrace_m_lastAccess{}; FF memTrace_m_addr{}; - FF memTrace_m_val{}; + FF memTrace_m_val_shift{}; + FF memTrace_m_rw{}; FF avmMini_first{}; FF memTrace_m_addr_shift{}; - FF memTrace_m_rw{}; - FF memTrace_m_rw_shift{}; - FF memTrace_m_val_shift{}; - FF memTrace_m_lastAccess{}; + FF avmMini_last{}; + FF memTrace_m_val{}; }; template class mem_traceImpl { diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.cpp index 6b6bb8f5550..d07684fc3ec 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.cpp @@ -25,7 +25,12 @@ void AvmMiniComposer::compute_witness(CircuitConstructor& circuit) proving_key->memTrace_m_val = polynomials.memTrace_m_val; proving_key->memTrace_m_lastAccess = polynomials.memTrace_m_lastAccess; proving_key->memTrace_m_rw = polynomials.memTrace_m_rw; - proving_key->avmMini_subop = polynomials.avmMini_subop; + proving_key->avmMini_sel_op_add = polynomials.avmMini_sel_op_add; + proving_key->avmMini_sel_op_sub = polynomials.avmMini_sel_op_sub; + proving_key->avmMini_sel_op_mul = polynomials.avmMini_sel_op_mul; + proving_key->avmMini_sel_op_div = polynomials.avmMini_sel_op_div; + proving_key->avmMini_op_err = polynomials.avmMini_op_err; + proving_key->avmMini_inv = polynomials.avmMini_inv; proving_key->avmMini_ia = polynomials.avmMini_ia; proving_key->avmMini_ib = polynomials.avmMini_ib; proving_key->avmMini_ic = polynomials.avmMini_ic; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.test.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.test.cpp index 4429aec7357..daa17a2599f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.test.cpp @@ -35,29 +35,36 @@ TEST_F(AvmMiniTests, basic) trace_builder.callDataCopy(0, 3, 2, std::vector{ 45, 23, 12 }); - trace_builder.add(2, 3, 4); - trace_builder.add(4, 5, 5); - trace_builder.add(5, 5, 5); - trace_builder.add(5, 6, 7); + // Memory layout: [0,0,45,23,12,0,0,0,....] + trace_builder.add(2, 3, 4); // [0,0,45,23,68,0,0,0,....] + trace_builder.add(4, 5, 5); // [0,0,45,23,68,68,0,0,....] + trace_builder.add(5, 5, 5); // [0,0,45,23,68,136,0,0,....] + trace_builder.add(5, 6, 7); // [0,0,45,23,68,136,0,136,0....] + trace_builder.sub(7, 6, 8); // [0,0,45,23,68,136,0,136,136,0....] + trace_builder.mul(8, 8, 8); // [0,0,45,23,68,136,0,136,136^2,0....] + trace_builder.div(3, 5, 1); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] + trace_builder.div(1, 1, 9); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] + trace_builder.div(9, 0, 4); // [0,23*136^(-1),45,23,1/0,136,0,136,136^2,1,0....] Error: division by 0 trace_builder.returnOP(1, 8); auto trace = trace_builder.finalize(); circuit_builder.set_trace(std::move(trace)); - ASSERT_TRUE(circuit_builder.check_circuit()); + EXPECT_TRUE(circuit_builder.check_circuit()); auto composer = AvmMiniComposer(); auto prover = composer.create_prover(circuit_builder); auto proof = prover.construct_proof(); + auto verifier = composer.create_verifier(circuit_builder); bool verified = verifier.verify_proof(proof); - ASSERT_TRUE(verified); - if (!verified) { proof_system::log_avmMini_trace(circuit_builder.rows, 0, 10); } + + EXPECT_TRUE(verified); } } // namespace example_relation_honk_composer \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp index b7daa36ddb3..da10ff83a40 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp @@ -3,7 +3,6 @@ #include "AvmMini_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" -#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/honk/proof_system/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp" @@ -30,7 +29,6 @@ AvmMiniProver::AvmMiniProver(std::shared_ptr input_key, , commitment_key(commitment_key) { // TODO: take every polynomial and assign it to the key!! - prover_polynomials.avmMini_clk = key->avmMini_clk; prover_polynomials.avmMini_first = key->avmMini_first; prover_polynomials.memTrace_m_clk = key->memTrace_m_clk; @@ -39,7 +37,12 @@ AvmMiniProver::AvmMiniProver(std::shared_ptr input_key, prover_polynomials.memTrace_m_val = key->memTrace_m_val; prover_polynomials.memTrace_m_lastAccess = key->memTrace_m_lastAccess; prover_polynomials.memTrace_m_rw = key->memTrace_m_rw; - prover_polynomials.avmMini_subop = key->avmMini_subop; + prover_polynomials.avmMini_sel_op_add = key->avmMini_sel_op_add; + prover_polynomials.avmMini_sel_op_sub = key->avmMini_sel_op_sub; + prover_polynomials.avmMini_sel_op_mul = key->avmMini_sel_op_mul; + prover_polynomials.avmMini_sel_op_div = key->avmMini_sel_op_div; + prover_polynomials.avmMini_op_err = key->avmMini_op_err; + prover_polynomials.avmMini_inv = key->avmMini_inv; prover_polynomials.avmMini_ia = key->avmMini_ia; prover_polynomials.avmMini_ib = key->avmMini_ib; prover_polynomials.avmMini_ic = key->avmMini_ic; @@ -54,15 +57,15 @@ AvmMiniProver::AvmMiniProver(std::shared_ptr input_key, prover_polynomials.avmMini_mem_idx_c = key->avmMini_mem_idx_c; prover_polynomials.avmMini_last = key->avmMini_last; - prover_polynomials.memTrace_m_addr = key->memTrace_m_addr; - prover_polynomials.memTrace_m_addr_shift = key->memTrace_m_addr.shifted(); - prover_polynomials.memTrace_m_rw = key->memTrace_m_rw; prover_polynomials.memTrace_m_rw_shift = key->memTrace_m_rw.shifted(); prover_polynomials.memTrace_m_val = key->memTrace_m_val; prover_polynomials.memTrace_m_val_shift = key->memTrace_m_val.shifted(); + prover_polynomials.memTrace_m_addr = key->memTrace_m_addr; + prover_polynomials.memTrace_m_addr_shift = key->memTrace_m_addr.shifted(); + // prover_polynomials.lookup_inverses = key->lookup_inverses; // key->z_perm = Polynomial(key->circuit_size); // prover_polynomials.z_perm = key->z_perm; @@ -130,7 +133,7 @@ plonk::proof& AvmMiniProver::export_proof() plonk::proof& AvmMiniProver::construct_proof() { - // Add circuit size public input size and public inputs to transcript-> + // Add circuit size public input size and public inputs to transcript. execute_preamble_round(); // Compute wire commitments diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp index b0b9da4ec44..4014eec57bb 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp @@ -64,7 +64,16 @@ bool AvmMiniVerifier::verify_proof(const plonk::proof& proof) commitments.memTrace_m_lastAccess = transcript->template receive_from_prover(commitment_labels.memTrace_m_lastAccess); commitments.memTrace_m_rw = transcript->template receive_from_prover(commitment_labels.memTrace_m_rw); - commitments.avmMini_subop = transcript->template receive_from_prover(commitment_labels.avmMini_subop); + commitments.avmMini_sel_op_add = + transcript->template receive_from_prover(commitment_labels.avmMini_sel_op_add); + commitments.avmMini_sel_op_sub = + transcript->template receive_from_prover(commitment_labels.avmMini_sel_op_sub); + commitments.avmMini_sel_op_mul = + transcript->template receive_from_prover(commitment_labels.avmMini_sel_op_mul); + commitments.avmMini_sel_op_div = + transcript->template receive_from_prover(commitment_labels.avmMini_sel_op_div); + commitments.avmMini_op_err = transcript->template receive_from_prover(commitment_labels.avmMini_op_err); + commitments.avmMini_inv = transcript->template receive_from_prover(commitment_labels.avmMini_inv); commitments.avmMini_ia = transcript->template receive_from_prover(commitment_labels.avmMini_ia); commitments.avmMini_ib = transcript->template receive_from_prover(commitment_labels.avmMini_ib); commitments.avmMini_ic = transcript->template receive_from_prover(commitment_labels.avmMini_ic);