From 457a3f9b0c05f58cc88ef43763c5d55b6debaf05 Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:13:51 +0100 Subject: [PATCH] feat(3738): AVM basic arithmetic operations for non ff types (#3881) Resolves #3738 Resolves #3996 --- barretenberg/cpp/pil/avm/README.txt | 21 + barretenberg/cpp/pil/avm/alu_chip.pil | 201 +++ barretenberg/cpp/pil/avm/avm_mini.pil | 13 +- .../flavor/generated/AvmMini_flavor.hpp | 300 +++- .../generated/AvmMini_circuit_builder.hpp | 93 +- .../relations/generated/AvmMini/alu_chip.hpp | 280 ++++ .../relations/generated/AvmMini/avm_mini.hpp | 140 +- .../generated/AvmMini/declare_views.hpp | 40 +- .../relations/generated/AvmMini/mem_trace.hpp | 24 +- .../vm/avm_trace/AvmMini_alu_trace.cpp | 347 ++++ .../vm/avm_trace/AvmMini_alu_trace.hpp | 49 + .../vm/avm_trace/AvmMini_common.hpp | 4 +- .../vm/avm_trace/AvmMini_helper.cpp | 6 + .../vm/avm_trace/AvmMini_mem_trace.cpp | 48 +- .../vm/avm_trace/AvmMini_mem_trace.hpp | 43 +- .../vm/avm_trace/AvmMini_trace.cpp | 170 +- .../vm/avm_trace/AvmMini_trace.hpp | 5 + .../vm/generated/AvmMini_prover.cpp | 2 + .../vm/generated/AvmMini_verifier.cpp | 51 + .../vm/tests/AvmMini_arithmetic.test.cpp | 1452 +++++++++++++++-- .../vm/tests/AvmMini_common.test.hpp | 13 + .../vm/tests/AvmMini_control_flow.test.cpp | 12 +- .../vm/tests/AvmMini_memory.test.cpp | 34 +- .../barretenberg/vm/tests/helpers.test.cpp | 23 +- .../barretenberg/vm/tests/helpers.test.hpp | 5 +- 25 files changed, 2978 insertions(+), 398 deletions(-) create mode 100644 barretenberg/cpp/pil/avm/README.txt create mode 100644 barretenberg/cpp/pil/avm/alu_chip.pil create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/alu_chip.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_alu_trace.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_alu_trace.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_common.test.hpp diff --git a/barretenberg/cpp/pil/avm/README.txt b/barretenberg/cpp/pil/avm/README.txt new file mode 100644 index 00000000000..cf63996a3c2 --- /dev/null +++ b/barretenberg/cpp/pil/avm/README.txt @@ -0,0 +1,21 @@ +This folder contains PIL relations for the AVM. + +Applied heuristic to assess the cost of a relation is given below. +This will be used to determine whether it is worth to merge some +relations into one. + +N_mul = number of mulitplication in the relation +N_add = number of additions/subtraction in the relation +deg = degree of the relation (total degree of the polynomial) + +Relation cost: degree * (N_mul + N_add/4) + +Remark: addition/multiplication with a constant counts as well in the above metrics +Remark: For edge case, we prefer keep a good readability rather than merging. + +Future: There is an optimization in sumcheck protocol allowing to skip some + rows for relations which are not enabled for them (applies when not + enabled over 2 adjacent rows). However, this feature is not yet enabled + in the AVM context. This might change the decision on whether some relations + should be merged or not. Basically, merging relations would decrease the + likelihood to be disabled over adjacent rows. \ No newline at end of file diff --git a/barretenberg/cpp/pil/avm/alu_chip.pil b/barretenberg/cpp/pil/avm/alu_chip.pil new file mode 100644 index 00000000000..09cf037b016 --- /dev/null +++ b/barretenberg/cpp/pil/avm/alu_chip.pil @@ -0,0 +1,201 @@ +include "avm_mini.pil"; + +namespace aluChip(256); + + // ========= Table ALU-TR ================================================= + + // References to main trace table of sub-operations, clk, intermediate + // registers, operation selectors. + // TODO: Think on optimizations to decrease the number of such "copied" columns + pol commit alu_clk; + pol commit alu_ia; // Intermediate registers + pol commit alu_ib; + pol commit alu_ic; + pol commit alu_op_add; // Operation selectors + pol commit alu_op_sub; + pol commit alu_op_mul; + pol commit alu_op_div; + + // Flattened boolean instruction tags + pol commit alu_ff_tag; + pol commit alu_u8_tag; + pol commit alu_u16_tag; + pol commit alu_u32_tag; + pol commit alu_u64_tag; + pol commit alu_u128_tag; + + // 8-bit slice registers + pol commit alu_u8_r0; + pol commit alu_u8_r1; + + // 16-bit slice registers + pol commit alu_u16_r0; + pol commit alu_u16_r1; + pol commit alu_u16_r2; + pol commit alu_u16_r3; + pol commit alu_u16_r4; + pol commit alu_u16_r5; + pol commit alu_u16_r6; + pol commit alu_u16_r7; + + // 64-bit slice register + pol commit alu_u64_r0; + + // Carry flag + pol commit alu_cf; + + // ========= Type Constraints ============================================= + // TODO: Range constraints + // - for slice registers + // - intermediate registers ia and ib (inputs) depending on flag (or inherited from previous ops?) + // - intermediate register ic (in some operations it might be inherited based on ia and ib ranges. To be checked.) + // Carry flag: We will have to constraint to ensure that the + // arithmetic expressions are not overflowing finite field size + // Remark: Operation selectors are constrained in the main trace. + // TODO: Enforce the equivalence check for the selectors between both tables. + + // Boolean flattened instructions tags + alu_ff_tag * (1 - alu_ff_tag) = 0; + alu_u8_tag * (1 - alu_u8_tag) = 0; + alu_u16_tag * (1 - alu_u16_tag) = 0; + alu_u32_tag * (1 - alu_u32_tag) = 0; + alu_u64_tag * (1 - alu_u64_tag) = 0; + alu_u128_tag * (1 - alu_u128_tag) = 0; + + // Operation selectors are copied from main table and do not need to be constrained here. + // TODO: Ensure mutual exclusion of alu_op_add and alu_op_sub as some relations below + // requires it. + // TODO: Similarly, ensure the mutual exclusion of instruction tags + + // ========= Inter-table Constraints ====================================== + // TODO: Equivalence between intermediate registers, clk, type flag, operation + // An ALU chiplet flag will be introduced in main trace to select relevant rows. + + + // ========= EXPLANATIONS ================================================= + // Main trick for arithmetic operations modulo 2^k is to perform the operation + // over the integers and expressing the result as low + high * 2^k with low + // smaller than 2^k. low is used as the output. This works as long this does + // not underflow/overflow the underlying finite field order (u128 multiplication + // will be handled differently). If we want to prove that c = OP(a,b) where OP + // denotes an arithmetic operation modulo 2^k, we can achieve this with two relations: + // (1) low + high * 2^k - OP'(a,b) = 0 + // (2) low - c = 0 + // + // where OP' denotes the same operation as OP but over the integers (not mod 2^k). + // We support u8, u16, u32, u64, u128 types and decompose low into + // smaller bit slices, e.g., 16. For instance, low = s_0 + s_1 * 2^16 + s_2 * 2^32 + ... + // The slices have to be range constrained and there is a trade-off between the + // number of registers and complexity of the range constraints. + // + // Optimization: We will capture the relation (1) for all types under the same umbrella + // by re-using the decomposition used for u128 type for the lower types. + // This works because any larger power of 2^k divides 2^l whenever k <= l. + // To be able to express "low" for u8, we need a 8-bit limb for the lowest + // bits. A bit decomposition covering all types is: + // s8_0 + s8_1 * 2^8 + s16_0 * 2^16 + s16_1 * 2^32 ... + s16_6 * 2^112 + carry * 2^128 - OP'(a,b) = 0 + // where s8_i's are 8-bit registers and s16's 16-bit registers. + // For type uk, we set low to the k-bit truncated part of register decomposition. + // As example, for u32: low = s8_0 + s8_1 * 2^8 + s16_0 * 2^16 + // and for u8: low = s8_0 + // + // TODO: It is open whether we might get efficiency gain to use larger registers for the higher + // parts of the bit decomposition. + + // ============= Helper polynomial terms ============================ + // These are intermediate polynomial terms which are not commited but + // serves to an algebraic expression of commited polynomials in a more concise way. + + // Bit slices partial sums + pol sum_8 = alu_u8_r0; + pol sum_16 = sum_8 + alu_u8_r1 * 2**8; + pol sum_32 = sum_16 + alu_u16_r0 * 2**16; + pol sum_64 = sum_32 + alu_u16_r1 * 2**32 + alu_u16_r2 * 2**48; + pol sum_96 = sum_64 + alu_u16_r3 * 2**64 + alu_u16_r4 * 2**80; + pol sum_128 = sum_96 + alu_u16_r5 * 2**96 + alu_u16_r6 * 2**112; + + // ========= ADDITION/SUBTRACTION Operation Constraints =============================== + // + // Addition and subtraction relations are very similar and will be consolidated. + // For the addition we have to replace OP'(a,b) in the above relation by a+b and + // for subtraction by a-b. Using operation selector values to toggle "+b" vs. "-b" + // makes the deal with the adaptation that the carry term needs to be subtracted + // instead of being added. To sumarize, for the first relation, addition needs to + // satisfy: + // sum_128 + carry * 2^128 - a - b = 0 + // while the subtraction satisfies: + // sum_128 - carry * 2^128 - a + b = 0 + // + // Finally, we would like this relation to also satisfy the addition over the finite field. + // For this, we add c in the relation conditoned by the ff type selector alu_ff_tag. We emphasize + // that this relation alone for FF will not imply correctness of the FF addition. We only want + // it to be satisfied. A separate relation will ensure correctness of it. + // + // The second relation will consist in showing that sum_N - c = 0 for N = 8, 16, 32, 64, 128. + + #[ALU_ADD_SUB_1] + (alu_op_add + alu_op_sub) * (sum_128 - alu_ia + alu_ff_tag * alu_ic) + (alu_op_add - alu_op_sub) * (alu_cf * 2**128 - alu_ib) = 0; + + // Helper polynomial + pol sum_tag = alu_u8_tag * sum_8 + alu_u16_tag * sum_16 + alu_u32_tag * sum_32 + alu_u64_tag * sum_64 + alu_u128_tag * sum_128; + + #[ALU_ADD_SUB_2] + (alu_op_add + alu_op_sub) * (sum_tag + alu_ff_tag * alu_ia - alu_ic) + alu_ff_tag * (alu_op_add - alu_op_sub) * alu_ib = 0; + + // ========= MULTIPLICATION Operation Constraints =============================== + + // ff multiplication + #[ALU_MULTIPLICATION_FF] + alu_ff_tag * alu_op_mul * (alu_ia * alu_ib - alu_ic) = 0; + + + // We need 2k bits to express the product (a*b) over the integer, i.e., for type uk + // we express the product as sum_k (u8 is an exception as we need 8-bit registers) + + // We group relations for u8, u16, u32, u64 together. + + // Helper polynomial + pol sum_tag_no_128 = alu_u8_tag * sum_8 + alu_u16_tag * sum_16 + alu_u32_tag * sum_32 + alu_u64_tag * sum_64; + + #[ALU_MUL_COMMON_1] + (1 - alu_ff_tag - alu_u128_tag) * alu_op_mul * (sum_128 - alu_ia * alu_ib) = 0; + + #[ALU_MUL_COMMON_2] + alu_op_mul * (sum_tag_no_128 - (1 - alu_ff_tag - alu_u128_tag) * alu_ic) = 0; + + // ========= u128 MULTIPLICATION Operation Constraints =============================== + // + // We express a, b in 64-bit slices: a = a_l + a_h * 2^64 + // b = b_l + b_h * 2^64 + // We show that c satisfies: a_l * b_l + (a_h * b_l + a_l * b_h) * 2^64 = R * 2^128 + c + // for a R < 2^65. Equivalently: + // a * b_l + a_l * b_h * 2^64 = (CF * 2^64 + R') * 2^128 + c + // for a bit carry flag CF and R' range constrained to 64 bits. + // We use two lines in the execution trace. First line represents a + // as decomposed over 16-bit registers. Second line represents b. + // Selector flag is only toggled in the first line and we access b through + // shifted polynomials. + // R' is stored in alu_u64_r0 + + // 64-bit lower limb + pol sum_low_64 = alu_u16_r0 + alu_u16_r1 * 2**16 + alu_u16_r2 * 2**32 + alu_u16_r3 * 2**48; + + // 64-bit higher limb + pol sum_high_64 = alu_u16_r4 + alu_u16_r5 * 2**16 + alu_u16_r6 * 2**32 + alu_u16_r7 * 2**48; + + // 64-bit lower limb for next row + pol sum_low_shifted_64 = alu_u16_r0' + alu_u16_r1' * 2**16 + alu_u16_r2' * 2**32 + alu_u16_r3' * 2**48; + + // 64-bit higher limb for next row + pol sum_high_shifted_64 = alu_u16_r4' + alu_u16_r5' * 2**16 + alu_u16_r6' * 2**32 + alu_u16_r7' * 2**48; + + // Arithmetic relations + alu_u128_tag * alu_op_mul * (sum_low_64 + sum_high_64 * 2**64 - alu_ia) = 0; + alu_u128_tag * alu_op_mul * (sum_low_shifted_64 + sum_high_shifted_64 * 2**64 - alu_ib) = 0; + #[ALU_MULTIPLICATION_OUT_U128] + alu_u128_tag * alu_op_mul * ( + alu_ia * sum_low_shifted_64 + + sum_low_64 * sum_high_shifted_64 * 2**64 + - (alu_cf * 2**64 + alu_u64_r0) * 2**128 + - alu_ic + ) = 0; diff --git a/barretenberg/cpp/pil/avm/avm_mini.pil b/barretenberg/cpp/pil/avm/avm_mini.pil index cd3fb8f29e4..26268fe25cd 100644 --- a/barretenberg/cpp/pil/avm/avm_mini.pil +++ b/barretenberg/cpp/pil/avm/avm_mini.pil @@ -1,5 +1,6 @@ include "mem_trace.pil"; +include "alu_chip.pil"; namespace avmMini(256); @@ -102,18 +103,6 @@ namespace avmMini(256); tag_err * ib = 0; tag_err * ic = 0; - // Relation for addition over the finite field - #[SUBOP_ADDITION_FF] - sel_op_add * (ia + ib - ic) = 0; - - // Relation for subtraction over the finite field - #[SUBOP_SUBTRACTION_FF] - sel_op_sub * (ia - ib - ic) = 0; - - // Relation for multiplication over the finite field - #[SUBOP_MULTIPLICATION_FF] - sel_op_mul * (ia * ib - ic) = 0; - // Relation for division over the finite field // If tag_err == 1 in a division, then ib == 0 and op_err == 1. #[SUBOP_DIVISION_FF] diff --git a/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp index f0ec7f92ee8..c1f672eb177 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp @@ -13,6 +13,7 @@ #include "barretenberg/flavor/flavor_macros.hpp" #include "barretenberg/polynomials/evaluation_domain.hpp" #include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/relations/generated/AvmMini/alu_chip.hpp" #include "barretenberg/relations/generated/AvmMini/avm_mini.hpp" #include "barretenberg/relations/generated/AvmMini/mem_trace.hpp" #include "barretenberg/transcript/transcript.hpp" @@ -36,13 +37,13 @@ class AvmMiniFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 38; + static constexpr size_t NUM_WITNESS_ENTITIES = 64; 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 = 46; + static constexpr size_t NUM_ALL_ENTITIES = 80; - using Relations = std::tuple, AvmMini_vm::avm_mini>; + using Relations = std::tuple, AvmMini_vm::avm_mini, AvmMini_vm::mem_trace>; static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); @@ -87,6 +88,32 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + aluChip_alu_clk, + aluChip_alu_ia, + aluChip_alu_ib, + aluChip_alu_ic, + aluChip_alu_op_add, + aluChip_alu_op_sub, + aluChip_alu_op_mul, + aluChip_alu_op_div, + aluChip_alu_ff_tag, + aluChip_alu_u8_tag, + aluChip_alu_u16_tag, + aluChip_alu_u32_tag, + aluChip_alu_u64_tag, + aluChip_alu_u128_tag, + aluChip_alu_u8_r0, + aluChip_alu_u8_r1, + aluChip_alu_u16_r0, + aluChip_alu_u16_r1, + aluChip_alu_u16_r2, + aluChip_alu_u16_r3, + aluChip_alu_u16_r4, + aluChip_alu_u16_r5, + aluChip_alu_u16_r6, + aluChip_alu_u16_r7, + aluChip_alu_u64_r0, + aluChip_alu_cf, avmMini_pc, avmMini_internal_return_ptr, avmMini_sel_internal_call, @@ -128,6 +155,32 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + aluChip_alu_clk, + aluChip_alu_ia, + aluChip_alu_ib, + aluChip_alu_ic, + aluChip_alu_op_add, + aluChip_alu_op_sub, + aluChip_alu_op_mul, + aluChip_alu_op_div, + aluChip_alu_ff_tag, + aluChip_alu_u8_tag, + aluChip_alu_u16_tag, + aluChip_alu_u32_tag, + aluChip_alu_u64_tag, + aluChip_alu_u128_tag, + aluChip_alu_u8_r0, + aluChip_alu_u8_r1, + aluChip_alu_u16_r0, + aluChip_alu_u16_r1, + aluChip_alu_u16_r2, + aluChip_alu_u16_r3, + aluChip_alu_u16_r4, + aluChip_alu_u16_r5, + aluChip_alu_u16_r6, + aluChip_alu_u16_r7, + aluChip_alu_u64_r0, + aluChip_alu_cf, avmMini_pc, avmMini_internal_return_ptr, avmMini_sel_internal_call, @@ -175,6 +228,32 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + aluChip_alu_clk, + aluChip_alu_ia, + aluChip_alu_ib, + aluChip_alu_ic, + aluChip_alu_op_add, + aluChip_alu_op_sub, + aluChip_alu_op_mul, + aluChip_alu_op_div, + aluChip_alu_ff_tag, + aluChip_alu_u8_tag, + aluChip_alu_u16_tag, + aluChip_alu_u32_tag, + aluChip_alu_u64_tag, + aluChip_alu_u128_tag, + aluChip_alu_u8_r0, + aluChip_alu_u8_r1, + aluChip_alu_u16_r0, + aluChip_alu_u16_r1, + aluChip_alu_u16_r2, + aluChip_alu_u16_r3, + aluChip_alu_u16_r4, + aluChip_alu_u16_r5, + aluChip_alu_u16_r6, + aluChip_alu_u16_r7, + aluChip_alu_u64_r0, + aluChip_alu_cf, avmMini_pc, avmMini_internal_return_ptr, avmMini_sel_internal_call, @@ -202,12 +281,20 @@ class AvmMiniFlavor { avmMini_mem_idx_b, avmMini_mem_idx_c, avmMini_last, - memTrace_m_rw_shift, + aluChip_alu_u16_r1_shift, + aluChip_alu_u16_r0_shift, + aluChip_alu_u16_r4_shift, + aluChip_alu_u16_r7_shift, + aluChip_alu_u16_r5_shift, + aluChip_alu_u16_r2_shift, + aluChip_alu_u16_r6_shift, + aluChip_alu_u16_r3_shift, + avmMini_pc_shift, + avmMini_internal_return_ptr_shift, memTrace_m_tag_shift, memTrace_m_addr_shift, memTrace_m_val_shift, - avmMini_internal_return_ptr_shift, - avmMini_pc_shift) + memTrace_m_rw_shift) RefVector get_wires() { @@ -224,6 +311,32 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + aluChip_alu_clk, + aluChip_alu_ia, + aluChip_alu_ib, + aluChip_alu_ic, + aluChip_alu_op_add, + aluChip_alu_op_sub, + aluChip_alu_op_mul, + aluChip_alu_op_div, + aluChip_alu_ff_tag, + aluChip_alu_u8_tag, + aluChip_alu_u16_tag, + aluChip_alu_u32_tag, + aluChip_alu_u64_tag, + aluChip_alu_u128_tag, + aluChip_alu_u8_r0, + aluChip_alu_u8_r1, + aluChip_alu_u16_r0, + aluChip_alu_u16_r1, + aluChip_alu_u16_r2, + aluChip_alu_u16_r3, + aluChip_alu_u16_r4, + aluChip_alu_u16_r5, + aluChip_alu_u16_r6, + aluChip_alu_u16_r7, + aluChip_alu_u64_r0, + aluChip_alu_cf, avmMini_pc, avmMini_internal_return_ptr, avmMini_sel_internal_call, @@ -251,12 +364,20 @@ class AvmMiniFlavor { avmMini_mem_idx_b, avmMini_mem_idx_c, avmMini_last, - memTrace_m_rw_shift, + aluChip_alu_u16_r1_shift, + aluChip_alu_u16_r0_shift, + aluChip_alu_u16_r4_shift, + aluChip_alu_u16_r7_shift, + aluChip_alu_u16_r5_shift, + aluChip_alu_u16_r2_shift, + aluChip_alu_u16_r6_shift, + aluChip_alu_u16_r3_shift, + avmMini_pc_shift, + avmMini_internal_return_ptr_shift, memTrace_m_tag_shift, memTrace_m_addr_shift, memTrace_m_val_shift, - avmMini_internal_return_ptr_shift, - avmMini_pc_shift }; + memTrace_m_rw_shift }; }; RefVector get_unshifted() { @@ -273,6 +394,32 @@ class AvmMiniFlavor { memTrace_m_in_tag, memTrace_m_tag_err, memTrace_m_one_min_inv, + aluChip_alu_clk, + aluChip_alu_ia, + aluChip_alu_ib, + aluChip_alu_ic, + aluChip_alu_op_add, + aluChip_alu_op_sub, + aluChip_alu_op_mul, + aluChip_alu_op_div, + aluChip_alu_ff_tag, + aluChip_alu_u8_tag, + aluChip_alu_u16_tag, + aluChip_alu_u32_tag, + aluChip_alu_u64_tag, + aluChip_alu_u128_tag, + aluChip_alu_u8_r0, + aluChip_alu_u8_r1, + aluChip_alu_u16_r0, + aluChip_alu_u16_r1, + aluChip_alu_u16_r2, + aluChip_alu_u16_r3, + aluChip_alu_u16_r4, + aluChip_alu_u16_r5, + aluChip_alu_u16_r6, + aluChip_alu_u16_r7, + aluChip_alu_u64_r0, + aluChip_alu_cf, avmMini_pc, avmMini_internal_return_ptr, avmMini_sel_internal_call, @@ -303,17 +450,23 @@ class AvmMiniFlavor { }; RefVector get_to_be_shifted() { - return { memTrace_m_rw, memTrace_m_tag, memTrace_m_addr, memTrace_m_val, avmMini_internal_return_ptr, - avmMini_pc }; + return { aluChip_alu_u16_r1, aluChip_alu_u16_r0, + aluChip_alu_u16_r4, aluChip_alu_u16_r7, + aluChip_alu_u16_r5, aluChip_alu_u16_r2, + aluChip_alu_u16_r6, aluChip_alu_u16_r3, + avmMini_pc, avmMini_internal_return_ptr, + memTrace_m_tag, memTrace_m_addr, + memTrace_m_val, memTrace_m_rw }; }; RefVector get_shifted() { - return { memTrace_m_rw_shift, - memTrace_m_tag_shift, - memTrace_m_addr_shift, - memTrace_m_val_shift, - avmMini_internal_return_ptr_shift, - avmMini_pc_shift }; + return { aluChip_alu_u16_r1_shift, aluChip_alu_u16_r0_shift, + aluChip_alu_u16_r4_shift, aluChip_alu_u16_r7_shift, + aluChip_alu_u16_r5_shift, aluChip_alu_u16_r2_shift, + aluChip_alu_u16_r6_shift, aluChip_alu_u16_r3_shift, + avmMini_pc_shift, avmMini_internal_return_ptr_shift, + memTrace_m_tag_shift, memTrace_m_addr_shift, + memTrace_m_val_shift, memTrace_m_rw_shift }; }; }; @@ -326,8 +479,13 @@ class AvmMiniFlavor { RefVector get_to_be_shifted() { - return { memTrace_m_rw, memTrace_m_tag, memTrace_m_addr, memTrace_m_val, avmMini_internal_return_ptr, - avmMini_pc }; + return { aluChip_alu_u16_r1, aluChip_alu_u16_r0, + aluChip_alu_u16_r4, aluChip_alu_u16_r7, + aluChip_alu_u16_r5, aluChip_alu_u16_r2, + aluChip_alu_u16_r6, aluChip_alu_u16_r3, + avmMini_pc, avmMini_internal_return_ptr, + memTrace_m_tag, memTrace_m_addr, + memTrace_m_val, memTrace_m_rw }; }; // The plookup wires that store plookup read data. @@ -417,6 +575,32 @@ 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::aluChip_alu_clk = "ALUCHIP_ALU_CLK"; + Base::aluChip_alu_ia = "ALUCHIP_ALU_IA"; + Base::aluChip_alu_ib = "ALUCHIP_ALU_IB"; + Base::aluChip_alu_ic = "ALUCHIP_ALU_IC"; + Base::aluChip_alu_op_add = "ALUCHIP_ALU_OP_ADD"; + Base::aluChip_alu_op_sub = "ALUCHIP_ALU_OP_SUB"; + Base::aluChip_alu_op_mul = "ALUCHIP_ALU_OP_MUL"; + Base::aluChip_alu_op_div = "ALUCHIP_ALU_OP_DIV"; + Base::aluChip_alu_ff_tag = "ALUCHIP_ALU_FF_TAG"; + Base::aluChip_alu_u8_tag = "ALUCHIP_ALU_U8_TAG"; + Base::aluChip_alu_u16_tag = "ALUCHIP_ALU_U16_TAG"; + Base::aluChip_alu_u32_tag = "ALUCHIP_ALU_U32_TAG"; + Base::aluChip_alu_u64_tag = "ALUCHIP_ALU_U64_TAG"; + Base::aluChip_alu_u128_tag = "ALUCHIP_ALU_U128_TAG"; + Base::aluChip_alu_u8_r0 = "ALUCHIP_ALU_U8_R0"; + Base::aluChip_alu_u8_r1 = "ALUCHIP_ALU_U8_R1"; + Base::aluChip_alu_u16_r0 = "ALUCHIP_ALU_U16_R0"; + Base::aluChip_alu_u16_r1 = "ALUCHIP_ALU_U16_R1"; + Base::aluChip_alu_u16_r2 = "ALUCHIP_ALU_U16_R2"; + Base::aluChip_alu_u16_r3 = "ALUCHIP_ALU_U16_R3"; + Base::aluChip_alu_u16_r4 = "ALUCHIP_ALU_U16_R4"; + Base::aluChip_alu_u16_r5 = "ALUCHIP_ALU_U16_R5"; + Base::aluChip_alu_u16_r6 = "ALUCHIP_ALU_U16_R6"; + Base::aluChip_alu_u16_r7 = "ALUCHIP_ALU_U16_R7"; + Base::aluChip_alu_u64_r0 = "ALUCHIP_ALU_U64_R0"; + Base::aluChip_alu_cf = "ALUCHIP_ALU_CF"; Base::avmMini_pc = "AVMMINI_PC"; Base::avmMini_internal_return_ptr = "AVMMINI_INTERNAL_RETURN_PTR"; Base::avmMini_sel_internal_call = "AVMMINI_SEL_INTERNAL_CALL"; @@ -474,6 +658,32 @@ class AvmMiniFlavor { Commitment memTrace_m_in_tag; Commitment memTrace_m_tag_err; Commitment memTrace_m_one_min_inv; + Commitment aluChip_alu_clk; + Commitment aluChip_alu_ia; + Commitment aluChip_alu_ib; + Commitment aluChip_alu_ic; + Commitment aluChip_alu_op_add; + Commitment aluChip_alu_op_sub; + Commitment aluChip_alu_op_mul; + Commitment aluChip_alu_op_div; + Commitment aluChip_alu_ff_tag; + Commitment aluChip_alu_u8_tag; + Commitment aluChip_alu_u16_tag; + Commitment aluChip_alu_u32_tag; + Commitment aluChip_alu_u64_tag; + Commitment aluChip_alu_u128_tag; + Commitment aluChip_alu_u8_r0; + Commitment aluChip_alu_u8_r1; + Commitment aluChip_alu_u16_r0; + Commitment aluChip_alu_u16_r1; + Commitment aluChip_alu_u16_r2; + Commitment aluChip_alu_u16_r3; + Commitment aluChip_alu_u16_r4; + Commitment aluChip_alu_u16_r5; + Commitment aluChip_alu_u16_r6; + Commitment aluChip_alu_u16_r7; + Commitment aluChip_alu_u64_r0; + Commitment aluChip_alu_cf; Commitment avmMini_pc; Commitment avmMini_internal_return_ptr; Commitment avmMini_sel_internal_call; @@ -531,6 +741,32 @@ 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); + aluChip_alu_clk = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_ia = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_ib = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_ic = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_op_add = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_op_sub = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_op_mul = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_op_div = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_ff_tag = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u8_tag = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_tag = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u32_tag = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u64_tag = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u128_tag = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u8_r0 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u8_r1 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_r0 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_r1 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_r2 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_r3 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_r4 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_r5 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_r6 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u16_r7 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_u64_r0 = deserialize_from_buffer(Transcript::proof_data, num_bytes_read); + aluChip_alu_cf = 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); @@ -592,6 +828,32 @@ 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(aluChip_alu_clk, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_ia, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_ib, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_ic, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_op_add, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_op_sub, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_op_mul, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_op_div, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_ff_tag, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u8_tag, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_tag, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u32_tag, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u64_tag, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u128_tag, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u8_r0, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u8_r1, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_r0, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_r1, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_r2, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_r3, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_r4, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_r5, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_r6, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u16_r7, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_u64_r0, Transcript::proof_data); + serialize_to_buffer(aluChip_alu_cf, 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); 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 de70d2c0857..baef5adc856 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 @@ -12,6 +12,7 @@ #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" #include "barretenberg/flavor/generated/AvmMini_flavor.hpp" +#include "barretenberg/relations/generated/AvmMini/alu_chip.hpp" #include "barretenberg/relations/generated/AvmMini/avm_mini.hpp" #include "barretenberg/relations/generated/AvmMini/mem_trace.hpp" @@ -33,6 +34,32 @@ template struct AvmMiniFullRow { FF memTrace_m_in_tag{}; FF memTrace_m_tag_err{}; FF memTrace_m_one_min_inv{}; + FF aluChip_alu_clk{}; + FF aluChip_alu_ia{}; + FF aluChip_alu_ib{}; + FF aluChip_alu_ic{}; + FF aluChip_alu_op_add{}; + FF aluChip_alu_op_sub{}; + FF aluChip_alu_op_mul{}; + FF aluChip_alu_op_div{}; + FF aluChip_alu_ff_tag{}; + FF aluChip_alu_u8_tag{}; + FF aluChip_alu_u16_tag{}; + FF aluChip_alu_u32_tag{}; + FF aluChip_alu_u64_tag{}; + FF aluChip_alu_u128_tag{}; + FF aluChip_alu_u8_r0{}; + FF aluChip_alu_u8_r1{}; + FF aluChip_alu_u16_r0{}; + FF aluChip_alu_u16_r1{}; + FF aluChip_alu_u16_r2{}; + FF aluChip_alu_u16_r3{}; + FF aluChip_alu_u16_r4{}; + FF aluChip_alu_u16_r5{}; + FF aluChip_alu_u16_r6{}; + FF aluChip_alu_u16_r7{}; + FF aluChip_alu_u64_r0{}; + FF aluChip_alu_cf{}; FF avmMini_pc{}; FF avmMini_internal_return_ptr{}; FF avmMini_sel_internal_call{}; @@ -60,12 +87,20 @@ template struct AvmMiniFullRow { FF avmMini_mem_idx_b{}; FF avmMini_mem_idx_c{}; FF avmMini_last{}; - FF memTrace_m_rw_shift{}; + FF aluChip_alu_u16_r1_shift{}; + FF aluChip_alu_u16_r0_shift{}; + FF aluChip_alu_u16_r4_shift{}; + FF aluChip_alu_u16_r7_shift{}; + FF aluChip_alu_u16_r5_shift{}; + FF aluChip_alu_u16_r2_shift{}; + FF aluChip_alu_u16_r6_shift{}; + FF aluChip_alu_u16_r3_shift{}; + FF avmMini_pc_shift{}; + FF avmMini_internal_return_ptr_shift{}; FF memTrace_m_tag_shift{}; FF memTrace_m_addr_shift{}; FF memTrace_m_val_shift{}; - FF avmMini_internal_return_ptr_shift{}; - FF avmMini_pc_shift{}; + FF memTrace_m_rw_shift{}; }; class AvmMiniCircuitBuilder { @@ -78,8 +113,8 @@ class AvmMiniCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 46; - static constexpr size_t num_polys = 40; + static constexpr size_t num_fixed_columns = 80; + static constexpr size_t num_polys = 66; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -108,6 +143,32 @@ 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.aluChip_alu_clk[i] = rows[i].aluChip_alu_clk; + polys.aluChip_alu_ia[i] = rows[i].aluChip_alu_ia; + polys.aluChip_alu_ib[i] = rows[i].aluChip_alu_ib; + polys.aluChip_alu_ic[i] = rows[i].aluChip_alu_ic; + polys.aluChip_alu_op_add[i] = rows[i].aluChip_alu_op_add; + polys.aluChip_alu_op_sub[i] = rows[i].aluChip_alu_op_sub; + polys.aluChip_alu_op_mul[i] = rows[i].aluChip_alu_op_mul; + polys.aluChip_alu_op_div[i] = rows[i].aluChip_alu_op_div; + polys.aluChip_alu_ff_tag[i] = rows[i].aluChip_alu_ff_tag; + polys.aluChip_alu_u8_tag[i] = rows[i].aluChip_alu_u8_tag; + polys.aluChip_alu_u16_tag[i] = rows[i].aluChip_alu_u16_tag; + polys.aluChip_alu_u32_tag[i] = rows[i].aluChip_alu_u32_tag; + polys.aluChip_alu_u64_tag[i] = rows[i].aluChip_alu_u64_tag; + polys.aluChip_alu_u128_tag[i] = rows[i].aluChip_alu_u128_tag; + polys.aluChip_alu_u8_r0[i] = rows[i].aluChip_alu_u8_r0; + polys.aluChip_alu_u8_r1[i] = rows[i].aluChip_alu_u8_r1; + polys.aluChip_alu_u16_r0[i] = rows[i].aluChip_alu_u16_r0; + polys.aluChip_alu_u16_r1[i] = rows[i].aluChip_alu_u16_r1; + polys.aluChip_alu_u16_r2[i] = rows[i].aluChip_alu_u16_r2; + polys.aluChip_alu_u16_r3[i] = rows[i].aluChip_alu_u16_r3; + polys.aluChip_alu_u16_r4[i] = rows[i].aluChip_alu_u16_r4; + polys.aluChip_alu_u16_r5[i] = rows[i].aluChip_alu_u16_r5; + polys.aluChip_alu_u16_r6[i] = rows[i].aluChip_alu_u16_r6; + polys.aluChip_alu_u16_r7[i] = rows[i].aluChip_alu_u16_r7; + polys.aluChip_alu_u64_r0[i] = rows[i].aluChip_alu_u64_r0; + polys.aluChip_alu_cf[i] = rows[i].aluChip_alu_cf; 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; @@ -137,12 +198,20 @@ class AvmMiniCircuitBuilder { polys.avmMini_last[i] = rows[i].avmMini_last; } - polys.memTrace_m_rw_shift = Polynomial(polys.memTrace_m_rw.shifted()); + polys.aluChip_alu_u16_r1_shift = Polynomial(polys.aluChip_alu_u16_r1.shifted()); + polys.aluChip_alu_u16_r0_shift = Polynomial(polys.aluChip_alu_u16_r0.shifted()); + polys.aluChip_alu_u16_r4_shift = Polynomial(polys.aluChip_alu_u16_r4.shifted()); + polys.aluChip_alu_u16_r7_shift = Polynomial(polys.aluChip_alu_u16_r7.shifted()); + polys.aluChip_alu_u16_r5_shift = Polynomial(polys.aluChip_alu_u16_r5.shifted()); + polys.aluChip_alu_u16_r2_shift = Polynomial(polys.aluChip_alu_u16_r2.shifted()); + polys.aluChip_alu_u16_r6_shift = Polynomial(polys.aluChip_alu_u16_r6.shifted()); + polys.aluChip_alu_u16_r3_shift = Polynomial(polys.aluChip_alu_u16_r3.shifted()); + polys.avmMini_pc_shift = Polynomial(polys.avmMini_pc.shifted()); + polys.avmMini_internal_return_ptr_shift = Polynomial(polys.avmMini_internal_return_ptr.shifted()); polys.memTrace_m_tag_shift = Polynomial(polys.memTrace_m_tag.shifted()); polys.memTrace_m_addr_shift = Polynomial(polys.memTrace_m_addr.shifted()); polys.memTrace_m_val_shift = Polynomial(polys.memTrace_m_val.shifted()); - 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_rw_shift = Polynomial(polys.memTrace_m_rw.shifted()); return polys; } @@ -180,14 +249,18 @@ class AvmMiniCircuitBuilder { return true; }; - if (!evaluate_relation.template operator()>( - "mem_trace", AvmMini_vm::get_relation_label_mem_trace)) { + if (!evaluate_relation.template operator()>("alu_chip", + AvmMini_vm::get_relation_label_alu_chip)) { 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/relations/generated/AvmMini/alu_chip.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/alu_chip.hpp new file mode 100644 index 00000000000..c1cd8a6e970 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/alu_chip.hpp @@ -0,0 +1,280 @@ + +#pragma once +#include "../../relation_parameters.hpp" +#include "../../relation_types.hpp" +#include "./declare_views.hpp" + +namespace bb::AvmMini_vm { + +template struct Alu_chipRow { + FF aluChip_alu_u16_r0{}; + FF aluChip_alu_u16_r3{}; + FF aluChip_alu_u16_r5{}; + FF aluChip_alu_u16_r1_shift{}; + FF aluChip_alu_u16_r0_shift{}; + FF aluChip_alu_op_add{}; + FF aluChip_alu_ia{}; + FF aluChip_alu_u16_r4_shift{}; + FF aluChip_alu_ib{}; + FF aluChip_alu_u16_r7{}; + FF aluChip_alu_u8_r0{}; + FF aluChip_alu_u16_r7_shift{}; + FF aluChip_alu_op_sub{}; + FF aluChip_alu_u16_r6{}; + FF aluChip_alu_u16_r5_shift{}; + FF aluChip_alu_op_mul{}; + FF aluChip_alu_u64_tag{}; + FF aluChip_alu_u16_r2_shift{}; + FF aluChip_alu_u64_r0{}; + FF aluChip_alu_ff_tag{}; + FF aluChip_alu_u32_tag{}; + FF aluChip_alu_u16_tag{}; + FF aluChip_alu_u16_r4{}; + FF aluChip_alu_u16_r6_shift{}; + FF aluChip_alu_u16_r2{}; + FF aluChip_alu_ic{}; + FF aluChip_alu_u8_tag{}; + FF aluChip_alu_cf{}; + FF aluChip_alu_u16_r3_shift{}; + FF aluChip_alu_u8_r1{}; + FF aluChip_alu_u16_r1{}; + FF aluChip_alu_u128_tag{}; +}; + +inline std::string get_relation_label_alu_chip(int index) +{ + switch (index) { + case 9: + return "ALU_MUL_COMMON_1"; + + case 8: + return "ALU_MULTIPLICATION_FF"; + + case 6: + return "ALU_ADD_SUB_1"; + + case 7: + return "ALU_ADD_SUB_2"; + + case 10: + return "ALU_MUL_COMMON_2"; + + case 13: + return "ALU_MULTIPLICATION_OUT_U128"; + } + return std::to_string(index); +} + +template class alu_chipImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 6, 6, 8, + }; + + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& new_term, + [[maybe_unused]] const RelationParameters&, + [[maybe_unused]] const FF& scaling_factor) + { + + // Contribution 0 + { + AvmMini_DECLARE_VIEWS(0); + + auto tmp = (aluChip_alu_ff_tag * (-aluChip_alu_ff_tag + FF(1))); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + // Contribution 1 + { + AvmMini_DECLARE_VIEWS(1); + + auto tmp = (aluChip_alu_u8_tag * (-aluChip_alu_u8_tag + FF(1))); + tmp *= scaling_factor; + std::get<1>(evals) += tmp; + } + // Contribution 2 + { + AvmMini_DECLARE_VIEWS(2); + + auto tmp = (aluChip_alu_u16_tag * (-aluChip_alu_u16_tag + FF(1))); + tmp *= scaling_factor; + std::get<2>(evals) += tmp; + } + // Contribution 3 + { + AvmMini_DECLARE_VIEWS(3); + + auto tmp = (aluChip_alu_u32_tag * (-aluChip_alu_u32_tag + FF(1))); + tmp *= scaling_factor; + std::get<3>(evals) += tmp; + } + // Contribution 4 + { + AvmMini_DECLARE_VIEWS(4); + + auto tmp = (aluChip_alu_u64_tag * (-aluChip_alu_u64_tag + FF(1))); + tmp *= scaling_factor; + std::get<4>(evals) += tmp; + } + // Contribution 5 + { + AvmMini_DECLARE_VIEWS(5); + + auto tmp = (aluChip_alu_u128_tag * (-aluChip_alu_u128_tag + FF(1))); + tmp *= scaling_factor; + std::get<5>(evals) += tmp; + } + // Contribution 6 + { + AvmMini_DECLARE_VIEWS(6); + + auto tmp = + (((aluChip_alu_op_add + aluChip_alu_op_sub) * + ((((((((((aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))) + (aluChip_alu_u16_r0 * FF(65536))) + + (aluChip_alu_u16_r1 * FF(4294967296UL))) + + (aluChip_alu_u16_r2 * FF(281474976710656UL))) + + (aluChip_alu_u16_r3 * FF(uint256_t{ 0, 1, 0, 0 }))) + + (aluChip_alu_u16_r4 * FF(uint256_t{ 0, 65536, 0, 0 }))) + + (aluChip_alu_u16_r5 * FF(uint256_t{ 0, 4294967296, 0, 0 }))) + + (aluChip_alu_u16_r6 * FF(uint256_t{ 0, 281474976710656, 0, 0 }))) - + aluChip_alu_ia) + + (aluChip_alu_ff_tag * aluChip_alu_ic))) + + ((aluChip_alu_op_add - aluChip_alu_op_sub) * + ((aluChip_alu_cf * FF(uint256_t{ 0, 0, 1, 0 })) - aluChip_alu_ib))); + tmp *= scaling_factor; + std::get<6>(evals) += tmp; + } + // Contribution 7 + { + AvmMini_DECLARE_VIEWS(7); + + auto tmp = + (((aluChip_alu_op_add + aluChip_alu_op_sub) * + (((((((aluChip_alu_u8_tag * aluChip_alu_u8_r0) + + (aluChip_alu_u16_tag * (aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))))) + + (aluChip_alu_u32_tag * + ((aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))) + (aluChip_alu_u16_r0 * FF(65536))))) + + (aluChip_alu_u64_tag * + ((((aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))) + (aluChip_alu_u16_r0 * FF(65536))) + + (aluChip_alu_u16_r1 * FF(4294967296UL))) + + (aluChip_alu_u16_r2 * FF(281474976710656UL))))) + + (aluChip_alu_u128_tag * + ((((((((aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))) + (aluChip_alu_u16_r0 * FF(65536))) + + (aluChip_alu_u16_r1 * FF(4294967296UL))) + + (aluChip_alu_u16_r2 * FF(281474976710656UL))) + + (aluChip_alu_u16_r3 * FF(uint256_t{ 0, 1, 0, 0 }))) + + (aluChip_alu_u16_r4 * FF(uint256_t{ 0, 65536, 0, 0 }))) + + (aluChip_alu_u16_r5 * FF(uint256_t{ 0, 4294967296, 0, 0 }))) + + (aluChip_alu_u16_r6 * FF(uint256_t{ 0, 281474976710656, 0, 0 }))))) + + (aluChip_alu_ff_tag * aluChip_alu_ia)) - + aluChip_alu_ic)) + + ((aluChip_alu_ff_tag * (aluChip_alu_op_add - aluChip_alu_op_sub)) * aluChip_alu_ib)); + tmp *= scaling_factor; + std::get<7>(evals) += tmp; + } + // Contribution 8 + { + AvmMini_DECLARE_VIEWS(8); + + auto tmp = + ((aluChip_alu_ff_tag * aluChip_alu_op_mul) * ((aluChip_alu_ia * aluChip_alu_ib) - aluChip_alu_ic)); + tmp *= scaling_factor; + std::get<8>(evals) += tmp; + } + // Contribution 9 + { + AvmMini_DECLARE_VIEWS(9); + + auto tmp = + ((((-aluChip_alu_ff_tag + FF(1)) - aluChip_alu_u128_tag) * aluChip_alu_op_mul) * + (((((((((aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))) + (aluChip_alu_u16_r0 * FF(65536))) + + (aluChip_alu_u16_r1 * FF(4294967296UL))) + + (aluChip_alu_u16_r2 * FF(281474976710656UL))) + + (aluChip_alu_u16_r3 * FF(uint256_t{ 0, 1, 0, 0 }))) + + (aluChip_alu_u16_r4 * FF(uint256_t{ 0, 65536, 0, 0 }))) + + (aluChip_alu_u16_r5 * FF(uint256_t{ 0, 4294967296, 0, 0 }))) + + (aluChip_alu_u16_r6 * FF(uint256_t{ 0, 281474976710656, 0, 0 }))) - + (aluChip_alu_ia * aluChip_alu_ib))); + tmp *= scaling_factor; + std::get<9>(evals) += tmp; + } + // Contribution 10 + { + AvmMini_DECLARE_VIEWS(10); + + auto tmp = (aluChip_alu_op_mul * + (((((aluChip_alu_u8_tag * aluChip_alu_u8_r0) + + (aluChip_alu_u16_tag * (aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))))) + + (aluChip_alu_u32_tag * + ((aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))) + (aluChip_alu_u16_r0 * FF(65536))))) + + (aluChip_alu_u64_tag * + ((((aluChip_alu_u8_r0 + (aluChip_alu_u8_r1 * FF(256))) + (aluChip_alu_u16_r0 * FF(65536))) + + (aluChip_alu_u16_r1 * FF(4294967296UL))) + + (aluChip_alu_u16_r2 * FF(281474976710656UL))))) - + (((-aluChip_alu_ff_tag + FF(1)) - aluChip_alu_u128_tag) * aluChip_alu_ic))); + tmp *= scaling_factor; + std::get<10>(evals) += tmp; + } + // Contribution 11 + { + AvmMini_DECLARE_VIEWS(11); + + auto tmp = ((aluChip_alu_u128_tag * aluChip_alu_op_mul) * + (((((aluChip_alu_u16_r0 + (aluChip_alu_u16_r1 * FF(65536))) + + (aluChip_alu_u16_r2 * FF(4294967296UL))) + + (aluChip_alu_u16_r3 * FF(281474976710656UL))) + + ((((aluChip_alu_u16_r4 + (aluChip_alu_u16_r5 * FF(65536))) + + (aluChip_alu_u16_r6 * FF(4294967296UL))) + + (aluChip_alu_u16_r7 * FF(281474976710656UL))) * + FF(uint256_t{ 0, 1, 0, 0 }))) - + aluChip_alu_ia)); + tmp *= scaling_factor; + std::get<11>(evals) += tmp; + } + // Contribution 12 + { + AvmMini_DECLARE_VIEWS(12); + + auto tmp = ((aluChip_alu_u128_tag * aluChip_alu_op_mul) * + (((((aluChip_alu_u16_r0_shift + (aluChip_alu_u16_r1_shift * FF(65536))) + + (aluChip_alu_u16_r2_shift * FF(4294967296UL))) + + (aluChip_alu_u16_r3_shift * FF(281474976710656UL))) + + ((((aluChip_alu_u16_r4_shift + (aluChip_alu_u16_r5_shift * FF(65536))) + + (aluChip_alu_u16_r6_shift * FF(4294967296UL))) + + (aluChip_alu_u16_r7_shift * FF(281474976710656UL))) * + FF(uint256_t{ 0, 1, 0, 0 }))) - + aluChip_alu_ib)); + tmp *= scaling_factor; + std::get<12>(evals) += tmp; + } + // Contribution 13 + { + AvmMini_DECLARE_VIEWS(13); + + auto tmp = ((aluChip_alu_u128_tag * aluChip_alu_op_mul) * + ((((aluChip_alu_ia * (((aluChip_alu_u16_r0_shift + (aluChip_alu_u16_r1_shift * FF(65536))) + + (aluChip_alu_u16_r2_shift * FF(4294967296UL))) + + (aluChip_alu_u16_r3_shift * FF(281474976710656UL)))) + + (((((aluChip_alu_u16_r0 + (aluChip_alu_u16_r1 * FF(65536))) + + (aluChip_alu_u16_r2 * FF(4294967296UL))) + + (aluChip_alu_u16_r3 * FF(281474976710656UL))) * + (((aluChip_alu_u16_r4_shift + (aluChip_alu_u16_r5_shift * FF(65536))) + + (aluChip_alu_u16_r6_shift * FF(4294967296UL))) + + (aluChip_alu_u16_r7_shift * FF(281474976710656UL)))) * + FF(uint256_t{ 0, 1, 0, 0 }))) - + (((aluChip_alu_cf * FF(uint256_t{ 0, 1, 0, 0 })) + aluChip_alu_u64_r0) * + FF(uint256_t{ 0, 0, 1, 0 }))) - + aluChip_alu_ic)); + tmp *= scaling_factor; + std::get<13>(evals) += tmp; + } + } +}; + +template using alu_chip = Relation>; + +} // namespace bb::AvmMini_vm \ No newline at end of file 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 d78c623933c..3347e38ff96 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/avm_mini.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/avm_mini.hpp @@ -7,70 +7,61 @@ namespace bb::AvmMini_vm { template struct Avm_miniRow { - FF avmMini_rwa{}; + FF avmMini_sel_op_sub{}; + FF avmMini_inv{}; + FF avmMini_first{}; + FF avmMini_tag_err{}; + FF avmMini_pc_shift{}; FF avmMini_mem_op_a{}; - FF avmMini_sel_op_mul{}; + FF avmMini_rwb{}; FF avmMini_mem_op_c{}; FF avmMini_internal_return_ptr_shift{}; + FF avmMini_rwc{}; FF avmMini_sel_op_div{}; - FF avmMini_rwb{}; - FF avmMini_pc_shift{}; FF avmMini_internal_return_ptr{}; - FF avmMini_sel_internal_call{}; + FF avmMini_pc{}; FF avmMini_ia{}; - FF avmMini_mem_idx_a{}; - FF avmMini_sel_op_add{}; + FF avmMini_sel_op_mul{}; FF avmMini_mem_op_b{}; - FF avmMini_inv{}; - FF avmMini_tag_err{}; - FF avmMini_op_err{}; FF avmMini_ib{}; - FF avmMini_pc{}; - FF avmMini_sel_internal_return{}; FF avmMini_sel_jump{}; - FF avmMini_rwc{}; - FF avmMini_first{}; FF avmMini_sel_halt{}; - FF avmMini_ic{}; + FF avmMini_sel_internal_return{}; + FF avmMini_op_err{}; + FF avmMini_mem_idx_a{}; FF avmMini_mem_idx_b{}; - FF avmMini_sel_op_sub{}; + FF avmMini_sel_internal_call{}; + FF avmMini_sel_op_add{}; + FF avmMini_rwa{}; + FF avmMini_ic{}; }; inline std::string get_relation_label_avm_mini(int index) { switch (index) { - case 19: - return "SUBOP_ADDITION_FF"; + case 20: + return "SUBOP_DIVISION_ZERO_ERR1"; - case 21: - return "SUBOP_MULTIPLICATION_FF"; + case 22: + return "SUBOP_ERROR_RELEVANT_OP"; - case 33: + case 30: return "RETURN_POINTER_DECREMENT"; - case 39: + case 36: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 27: - return "RETURN_POINTER_INCREMENT"; - - case 24: + case 21: return "SUBOP_DIVISION_ZERO_ERR2"; - case 20: - return "SUBOP_SUBTRACTION_FF"; - - case 22: - return "SUBOP_DIVISION_FF"; - - case 25: - return "SUBOP_ERROR_RELEVANT_OP"; + case 35: + return "PC_INCREMENT"; - case 23: - return "SUBOP_DIVISION_ZERO_ERR1"; + case 24: + return "RETURN_POINTER_INCREMENT"; - case 38: - return "PC_INCREMENT"; + case 19: + return "SUBOP_DIVISION_FF"; } return std::to_string(index); } @@ -79,9 +70,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, 3, 3, 3, - 3, 4, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 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, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, }; template @@ -247,7 +237,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(19); - auto tmp = (avmMini_sel_op_add * ((avmMini_ia + avmMini_ib) - avmMini_ic)); + auto tmp = ((avmMini_sel_op_div * (-avmMini_op_err + FF(1))) * ((avmMini_ic * avmMini_ib) - avmMini_ia)); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -255,7 +245,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(20); - auto tmp = (avmMini_sel_op_sub * ((avmMini_ia - avmMini_ib) - avmMini_ic)); + auto tmp = (avmMini_sel_op_div * (((avmMini_ib * avmMini_inv) - FF(1)) + avmMini_op_err)); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -263,7 +253,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(21); - auto tmp = (avmMini_sel_op_mul * ((avmMini_ia * avmMini_ib) - avmMini_ic)); + auto tmp = ((avmMini_sel_op_div * avmMini_op_err) * (-avmMini_inv + FF(1))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -271,7 +261,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(22); - auto tmp = ((avmMini_sel_op_div * (-avmMini_op_err + FF(1))) * ((avmMini_ic * avmMini_ib) - avmMini_ia)); + auto tmp = (avmMini_op_err * (avmMini_sel_op_div - FF(1))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -279,7 +269,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(23); - auto tmp = (avmMini_sel_op_div * (((avmMini_ib * avmMini_inv) - FF(1)) + avmMini_op_err)); + auto tmp = (avmMini_sel_jump * (avmMini_pc_shift - avmMini_ia)); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -287,7 +277,8 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(24); - auto tmp = ((avmMini_sel_op_div * avmMini_op_err) * (-avmMini_inv + FF(1))); + auto tmp = (avmMini_sel_internal_call * + (avmMini_internal_return_ptr_shift - (avmMini_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -295,7 +286,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(25); - auto tmp = (avmMini_op_err * (avmMini_sel_op_div - FF(1))); + auto tmp = (avmMini_sel_internal_call * (avmMini_internal_return_ptr - avmMini_mem_idx_b)); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -303,7 +294,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(26); - auto tmp = (avmMini_sel_jump * (avmMini_pc_shift - avmMini_ia)); + auto tmp = (avmMini_sel_internal_call * (avmMini_pc_shift - avmMini_ia)); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -311,8 +302,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(27); - auto tmp = (avmMini_sel_internal_call * - (avmMini_internal_return_ptr_shift - (avmMini_internal_return_ptr + FF(1)))); + auto tmp = (avmMini_sel_internal_call * ((avmMini_pc + FF(1)) - avmMini_ib)); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -320,7 +310,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(28); - auto tmp = (avmMini_sel_internal_call * (avmMini_internal_return_ptr - avmMini_mem_idx_b)); + auto tmp = (avmMini_sel_internal_call * (avmMini_rwb - FF(1))); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -328,7 +318,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(29); - auto tmp = (avmMini_sel_internal_call * (avmMini_pc_shift - avmMini_ia)); + auto tmp = (avmMini_sel_internal_call * (avmMini_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -336,7 +326,8 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(30); - auto tmp = (avmMini_sel_internal_call * ((avmMini_pc + FF(1)) - avmMini_ib)); + 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; } @@ -344,7 +335,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(31); - auto tmp = (avmMini_sel_internal_call * (avmMini_rwb - FF(1))); + auto tmp = (avmMini_sel_internal_return * ((avmMini_internal_return_ptr - FF(1)) - avmMini_mem_idx_a)); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -352,7 +343,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(32); - auto tmp = (avmMini_sel_internal_call * (avmMini_mem_op_b - FF(1))); + auto tmp = (avmMini_sel_internal_return * (avmMini_pc_shift - avmMini_ia)); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -360,8 +351,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(33); - auto tmp = (avmMini_sel_internal_return * - (avmMini_internal_return_ptr_shift - (avmMini_internal_return_ptr - FF(1)))); + auto tmp = (avmMini_sel_internal_return * avmMini_rwa); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -369,7 +359,7 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(34); - auto tmp = (avmMini_sel_internal_return * ((avmMini_internal_return_ptr - FF(1)) - avmMini_mem_idx_a)); + auto tmp = (avmMini_sel_internal_return * (avmMini_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -377,46 +367,22 @@ template class avm_miniImpl { { AvmMini_DECLARE_VIEWS(35); - auto tmp = (avmMini_sel_internal_return * (avmMini_pc_shift - avmMini_ia)); - tmp *= scaling_factor; - std::get<35>(evals) += tmp; - } - // Contribution 36 - { - AvmMini_DECLARE_VIEWS(36); - - auto tmp = (avmMini_sel_internal_return * avmMini_rwa); - tmp *= scaling_factor; - std::get<36>(evals) += tmp; - } - // Contribution 37 - { - AvmMini_DECLARE_VIEWS(37); - - auto tmp = (avmMini_sel_internal_return * (avmMini_mem_op_a - FF(1))); - tmp *= scaling_factor; - std::get<37>(evals) += tmp; - } - // Contribution 38 - { - AvmMini_DECLARE_VIEWS(38); - 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<38>(evals) += tmp; + std::get<35>(evals) += tmp; } - // Contribution 39 + // Contribution 36 { - AvmMini_DECLARE_VIEWS(39); + 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<39>(evals) += tmp; + 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 bf4df9cb83e..1b036e25919 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,32 @@ [[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 aluChip_alu_clk = View(new_term.aluChip_alu_clk); \ + [[maybe_unused]] auto aluChip_alu_ia = View(new_term.aluChip_alu_ia); \ + [[maybe_unused]] auto aluChip_alu_ib = View(new_term.aluChip_alu_ib); \ + [[maybe_unused]] auto aluChip_alu_ic = View(new_term.aluChip_alu_ic); \ + [[maybe_unused]] auto aluChip_alu_op_add = View(new_term.aluChip_alu_op_add); \ + [[maybe_unused]] auto aluChip_alu_op_sub = View(new_term.aluChip_alu_op_sub); \ + [[maybe_unused]] auto aluChip_alu_op_mul = View(new_term.aluChip_alu_op_mul); \ + [[maybe_unused]] auto aluChip_alu_op_div = View(new_term.aluChip_alu_op_div); \ + [[maybe_unused]] auto aluChip_alu_ff_tag = View(new_term.aluChip_alu_ff_tag); \ + [[maybe_unused]] auto aluChip_alu_u8_tag = View(new_term.aluChip_alu_u8_tag); \ + [[maybe_unused]] auto aluChip_alu_u16_tag = View(new_term.aluChip_alu_u16_tag); \ + [[maybe_unused]] auto aluChip_alu_u32_tag = View(new_term.aluChip_alu_u32_tag); \ + [[maybe_unused]] auto aluChip_alu_u64_tag = View(new_term.aluChip_alu_u64_tag); \ + [[maybe_unused]] auto aluChip_alu_u128_tag = View(new_term.aluChip_alu_u128_tag); \ + [[maybe_unused]] auto aluChip_alu_u8_r0 = View(new_term.aluChip_alu_u8_r0); \ + [[maybe_unused]] auto aluChip_alu_u8_r1 = View(new_term.aluChip_alu_u8_r1); \ + [[maybe_unused]] auto aluChip_alu_u16_r0 = View(new_term.aluChip_alu_u16_r0); \ + [[maybe_unused]] auto aluChip_alu_u16_r1 = View(new_term.aluChip_alu_u16_r1); \ + [[maybe_unused]] auto aluChip_alu_u16_r2 = View(new_term.aluChip_alu_u16_r2); \ + [[maybe_unused]] auto aluChip_alu_u16_r3 = View(new_term.aluChip_alu_u16_r3); \ + [[maybe_unused]] auto aluChip_alu_u16_r4 = View(new_term.aluChip_alu_u16_r4); \ + [[maybe_unused]] auto aluChip_alu_u16_r5 = View(new_term.aluChip_alu_u16_r5); \ + [[maybe_unused]] auto aluChip_alu_u16_r6 = View(new_term.aluChip_alu_u16_r6); \ + [[maybe_unused]] auto aluChip_alu_u16_r7 = View(new_term.aluChip_alu_u16_r7); \ + [[maybe_unused]] auto aluChip_alu_u64_r0 = View(new_term.aluChip_alu_u64_r0); \ + [[maybe_unused]] auto aluChip_alu_cf = View(new_term.aluChip_alu_cf); \ [[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); \ @@ -42,9 +68,17 @@ [[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_rw_shift = View(new_term.memTrace_m_rw_shift); \ + [[maybe_unused]] auto aluChip_alu_u16_r1_shift = View(new_term.aluChip_alu_u16_r1_shift); \ + [[maybe_unused]] auto aluChip_alu_u16_r0_shift = View(new_term.aluChip_alu_u16_r0_shift); \ + [[maybe_unused]] auto aluChip_alu_u16_r4_shift = View(new_term.aluChip_alu_u16_r4_shift); \ + [[maybe_unused]] auto aluChip_alu_u16_r7_shift = View(new_term.aluChip_alu_u16_r7_shift); \ + [[maybe_unused]] auto aluChip_alu_u16_r5_shift = View(new_term.aluChip_alu_u16_r5_shift); \ + [[maybe_unused]] auto aluChip_alu_u16_r2_shift = View(new_term.aluChip_alu_u16_r2_shift); \ + [[maybe_unused]] auto aluChip_alu_u16_r6_shift = View(new_term.aluChip_alu_u16_r6_shift); \ + [[maybe_unused]] auto aluChip_alu_u16_r3_shift = View(new_term.aluChip_alu_u16_r3_shift); \ + [[maybe_unused]] auto avmMini_pc_shift = View(new_term.avmMini_pc_shift); \ + [[maybe_unused]] auto avmMini_internal_return_ptr_shift = View(new_term.avmMini_internal_return_ptr_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); \ [[maybe_unused]] auto memTrace_m_val_shift = View(new_term.memTrace_m_val_shift); \ - [[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_rw_shift = View(new_term.memTrace_m_rw_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 abb9e853978..49cc8062e82 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/mem_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini/mem_trace.hpp @@ -8,18 +8,18 @@ namespace bb::AvmMini_vm { template struct Mem_traceRow { FF memTrace_m_val{}; - FF memTrace_m_lastAccess{}; - FF memTrace_m_tag_err{}; - FF memTrace_m_rw_shift{}; + FF memTrace_m_last{}; FF memTrace_m_in_tag{}; + FF memTrace_m_tag{}; FF memTrace_m_rw{}; FF memTrace_m_tag_shift{}; - FF memTrace_m_last{}; FF memTrace_m_addr_shift{}; - FF memTrace_m_tag{}; + FF memTrace_m_tag_err{}; FF memTrace_m_one_min_inv{}; FF memTrace_m_val_shift{}; + FF memTrace_m_lastAccess{}; FF memTrace_m_addr{}; + FF memTrace_m_rw_shift{}; }; inline std::string get_relation_label_mem_trace(int index) @@ -28,11 +28,8 @@ inline std::string get_relation_label_mem_trace(int index) case 8: return "MEM_IN_TAG_CONSISTENCY_1"; - case 7: - return "MEM_ZERO_INIT"; - - case 6: - return "MEM_READ_WRITE_TAG_CONSISTENCY"; + case 9: + return "MEM_IN_TAG_CONSISTENCY_2"; case 5: return "MEM_READ_WRITE_VAL_CONSISTENCY"; @@ -40,8 +37,11 @@ inline std::string get_relation_label_mem_trace(int index) case 4: return "MEM_LAST_ACCESS_DELIMITER"; - case 9: - return "MEM_IN_TAG_CONSISTENCY_2"; + case 6: + return "MEM_READ_WRITE_TAG_CONSISTENCY"; + + case 7: + return "MEM_ZERO_INIT"; } return std::to_string(index); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_alu_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_alu_trace.cpp new file mode 100644 index 00000000000..7da44d916bd --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_alu_trace.cpp @@ -0,0 +1,347 @@ +#include "AvmMini_alu_trace.hpp" + +namespace avm_trace { + +/** + * @brief Constructor of Alu trace builder of AVM. Only serves to set the capacity of the + * underlying trace. + */ +AvmMiniAluTraceBuilder::AvmMiniAluTraceBuilder() +{ + alu_trace.reserve(AVM_TRACE_SIZE); +} + +/** + * @brief Resetting the internal state so that a new Alu trace can be rebuilt using the same object. + * + */ +void AvmMiniAluTraceBuilder::reset() +{ + alu_trace.clear(); +} + +/** + * @brief Prepare the Alu trace to be incorporated into the main trace. + * + * @return The Alu trace (which is moved). + */ +std::vector AvmMiniAluTraceBuilder::finalize() +{ + return std::move(alu_trace); +} + +/** + * @brief Build Alu trace and compute the result of an addition of type defined by in_tag. + * Besides the addition calculation, for the types u8, u16, u32, u64, and u128, we + * have to store the result of the addition modulo 2^128 decomposed into 8-bit and + * 16-bit registers, i.e., + * a+b mod. 2^128 = alu_u8_r0 + alu_u8_r1 * 2^8 + alu_u16_r0 * 2^16 ... + alu_u16_r6 * 2^112 + * + * @param a Left operand of the addition + * @param b Right operand of the addition + * @param in_tag Instruction tag defining the number of bits on which the addition applies. + * It is assumed that the caller never uses the type u0. + * @param clk Clock referring to the operation in the main trace. + * + * @return FF The result of the addition casted in a finite field element + */ +FF AvmMiniAluTraceBuilder::add(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t const clk) +{ + FF c{}; + bool carry = false; + uint8_t alu_u8_r0{}; + uint8_t alu_u8_r1{}; + std::array alu_u16_reg{}; + + uint128_t a_u128{ a }; + uint128_t b_u128{ b }; + uint128_t c_u128 = a_u128 + b_u128; + + switch (in_tag) { + case AvmMemoryTag::FF: + c = a + b; + break; + case AvmMemoryTag::U8: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U16: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U32: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U64: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U128: + c = FF{ uint256_t::from_uint128(c_u128) }; + break; + case AvmMemoryTag::U0: // Unsupported as instruction tag + return FF{ 0 }; + } + + if (in_tag != AvmMemoryTag::FF) { + // a_u128 + b_u128 >= 2^128 <==> c_u128 < a_u128 + if (c_u128 < a_u128) { + carry = true; + } + + uint128_t c_trunc_128 = c_u128; + alu_u8_r0 = static_cast(c_trunc_128); + c_trunc_128 >>= 8; + alu_u8_r1 = static_cast(c_trunc_128); + c_trunc_128 >>= 8; + + for (size_t i = 0; i < 7; i++) { + alu_u16_reg.at(i) = static_cast(c_trunc_128); + c_trunc_128 >>= 16; + } + } + + alu_trace.push_back(AvmMiniAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_add = true, + .alu_ff_tag = in_tag == AvmMemoryTag::FF, + .alu_u8_tag = in_tag == AvmMemoryTag::U8, + .alu_u16_tag = in_tag == AvmMemoryTag::U16, + .alu_u32_tag = in_tag == AvmMemoryTag::U32, + .alu_u64_tag = in_tag == AvmMemoryTag::U64, + .alu_u128_tag = in_tag == AvmMemoryTag::U128, + .alu_ia = a, + .alu_ib = b, + .alu_ic = c, + .alu_cf = carry, + .alu_u8_r0 = alu_u8_r0, + .alu_u8_r1 = alu_u8_r1, + .alu_u16_reg = alu_u16_reg, + }); + + return c; +} + +/** + * @brief Build Alu trace and compute the result of a subtraction of type defined by in_tag. + * Besides the subtraction calculation, for the types u8, u16, u32, u64, and u128, we + * have to store the result of the subtraction modulo 2^128 decomposed into 8-bit and + * 16-bit registers, i.e., + * a-b mod. 2^128 = alu_u8_r0 + alu_u8_r1 * 2^8 + alu_u16_r0 * 2^16 ... + alu_u16_r6 * 2^112 + * + * @param a Left operand of the subtraction + * @param b Right operand of the subtraction + * @param in_tag Instruction tag defining the number of bits on which the subtracttion applies. + * It is assumed that the caller never uses the type u0. + * @param clk Clock referring to the operation in the main trace. + * + * @return FF The result of the subtraction casted in a finite field element + */ +FF AvmMiniAluTraceBuilder::sub(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t const clk) +{ + FF c{}; + bool carry = false; + uint8_t alu_u8_r0{}; + uint8_t alu_u8_r1{}; + std::array alu_u16_reg{}; + uint128_t a_u128{ a }; + uint128_t b_u128{ b }; + uint128_t c_u128 = a_u128 - b_u128; + + switch (in_tag) { + case AvmMemoryTag::FF: + c = a - b; + break; + case AvmMemoryTag::U8: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U16: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U32: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U64: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U128: + c = FF{ uint256_t::from_uint128(c_u128) }; + break; + case AvmMemoryTag::U0: // Unsupported as instruction tag + return FF{ 0 }; + } + + if (in_tag != AvmMemoryTag::FF) { + // Underflow when a_u128 < b_u128 + if (a_u128 < b_u128) { + carry = true; + } + + uint128_t c_trunc_128 = c_u128; + alu_u8_r0 = static_cast(c_trunc_128); + c_trunc_128 >>= 8; + alu_u8_r1 = static_cast(c_trunc_128); + c_trunc_128 >>= 8; + + for (size_t i = 0; i < 7; i++) { + alu_u16_reg.at(i) = static_cast(c_trunc_128); + c_trunc_128 >>= 16; + } + } + + alu_trace.push_back(AvmMiniAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_sub = true, + .alu_ff_tag = in_tag == AvmMemoryTag::FF, + .alu_u8_tag = in_tag == AvmMemoryTag::U8, + .alu_u16_tag = in_tag == AvmMemoryTag::U16, + .alu_u32_tag = in_tag == AvmMemoryTag::U32, + .alu_u64_tag = in_tag == AvmMemoryTag::U64, + .alu_u128_tag = in_tag == AvmMemoryTag::U128, + .alu_ia = a, + .alu_ib = b, + .alu_ic = c, + .alu_cf = carry, + .alu_u8_r0 = alu_u8_r0, + .alu_u8_r1 = alu_u8_r1, + .alu_u16_reg = alu_u16_reg, + }); + + return c; +} + +/** + * @brief Build Alu trace and compute the result of an multiplication of type defined by in_tag. + * + * @param a Left operand of the multiplication + * @param b Right operand of the multiplication + * @param in_tag Instruction tag defining the number of bits on which the multiplication applies. + * It is assumed that the caller never uses the type u0. + * @param clk Clock referring to the operation in the main trace. + * + * @return FF The result of the multiplication casted in a finite field element + */ +FF AvmMiniAluTraceBuilder::mul(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t const clk) +{ + FF c{}; + bool carry = false; + uint8_t alu_u8_r0{}; + uint8_t alu_u8_r1{}; + + std::array alu_u16_reg{}; + + uint128_t a_u128{ a }; + uint128_t b_u128{ b }; + uint128_t c_u128 = a_u128 * b_u128; // Multiplication over the integers (not mod. 2^64) + + switch (in_tag) { + case AvmMemoryTag::FF: + c = a * b; + break; + case AvmMemoryTag::U8: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U16: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U32: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U64: + c = FF{ static_cast(c_u128) }; + break; + case AvmMemoryTag::U128: { + uint256_t a_u256{ a }; + uint256_t b_u256{ b }; + uint256_t c_u256 = a_u256 * b_u256; // Multiplication over the integers (not mod. 2^128) + + uint128_t a_u128{ a_u256 }; + uint128_t b_u128{ b_u256 }; + + uint128_t c_u128 = a_u128 * b_u128; + + // Decompose a_u128 and b_u128 over 8 16-bit registers. + std::array alu_u16_reg_a{}; + std::array alu_u16_reg_b{}; + uint128_t a_trunc_128 = a_u128; + uint128_t b_trunc_128 = b_u128; + + for (size_t i = 0; i < 8; i++) { + alu_u16_reg_a.at(i) = static_cast(a_trunc_128); + alu_u16_reg_b.at(i) = static_cast(b_trunc_128); + a_trunc_128 >>= 16; + b_trunc_128 >>= 16; + } + + // Represent a, b with 64-bit limbs: a = a_l + 2^64 * a_h, b = b_l + 2^64 * b_h, + // c_high := 2^128 * a_h * b_h + uint256_t c_high = ((a_u256 >> 64) * (b_u256 >> 64)) << 128; + + // From PIL relation in alu_chip.pil, we need to determine the bit CF and 64-bit value R' in + // a * b_l + a_l * b_h * 2^64 = (CF * 2^64 + R') * 2^128 + c + // LHS is c_u256 - c_high + + // CF bit + carry = ((c_u256 - c_high) >> 192) > 0; + // R' value + uint64_t alu_u64_r0 = static_cast(((c_u256 - c_high) >> 128) & uint256_t(UINT64_MAX)); + + c = FF{ uint256_t::from_uint128(c_u128) }; + + alu_trace.push_back(AvmMiniAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_mul = true, + .alu_u128_tag = in_tag == AvmMemoryTag::U128, + .alu_ia = a, + .alu_ib = b, + .alu_ic = c, + .alu_cf = carry, + .alu_u16_reg = alu_u16_reg_a, + .alu_u64_r0 = alu_u64_r0, + }); + + alu_trace.push_back(AvmMiniAluTraceBuilder::AluTraceEntry{ + .alu_u16_reg = alu_u16_reg_b, + }); + + return c; + } + case AvmMemoryTag::U0: // Unsupported as instruction tag + return FF{ 0 }; + } + + // Following code executed for: u8, u16, u32, u64 (u128 returned handled specifically) + if (in_tag != AvmMemoryTag::FF) { + // Decomposition of c_u128 into 8-bit and 16-bit registers as follows: + // alu_u8_r0 + alu_u8_r1 * 2^8 + alu_u16_r0 * 2^16 ... + alu_u16_r6 * 2^112 + uint128_t c_trunc_128 = c_u128; + alu_u8_r0 = static_cast(c_trunc_128); + c_trunc_128 >>= 8; + alu_u8_r1 = static_cast(c_trunc_128); + c_trunc_128 >>= 8; + + for (size_t i = 0; i < 7; i++) { + alu_u16_reg.at(i) = static_cast(c_trunc_128); + c_trunc_128 >>= 16; + } + } + + // Following code executed for: ff, u8, u16, u32, u64 (u128 returned handled specifically) + alu_trace.push_back(AvmMiniAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_mul = true, + .alu_ff_tag = in_tag == AvmMemoryTag::FF, + .alu_u8_tag = in_tag == AvmMemoryTag::U8, + .alu_u16_tag = in_tag == AvmMemoryTag::U16, + .alu_u32_tag = in_tag == AvmMemoryTag::U32, + .alu_u64_tag = in_tag == AvmMemoryTag::U64, + .alu_ia = a, + .alu_ib = b, + .alu_ic = c, + .alu_cf = carry, + .alu_u8_r0 = alu_u8_r0, + .alu_u8_r1 = alu_u8_r1, + .alu_u16_reg = alu_u16_reg, + }); + + return c; +} + +} // namespace avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_alu_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_alu_trace.hpp new file mode 100644 index 00000000000..cda0263cb8d --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_alu_trace.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "AvmMini_common.hpp" + +namespace avm_trace { + +class AvmMiniAluTraceBuilder { + + public: + struct AluTraceEntry { + uint32_t alu_clk{}; + + bool alu_op_add = false; + bool alu_op_sub = false; + bool alu_op_mul = false; + + bool alu_ff_tag = false; + bool alu_u8_tag = false; + bool alu_u16_tag = false; + bool alu_u32_tag = false; + bool alu_u64_tag = false; + bool alu_u128_tag = false; + + FF alu_ia{}; + FF alu_ib{}; + FF alu_ic{}; + + bool alu_cf = false; + + uint8_t alu_u8_r0{}; + uint8_t alu_u8_r1{}; + + std::array alu_u16_reg{}; + + uint64_t alu_u64_r0{}; + }; + + AvmMiniAluTraceBuilder(); + void reset(); + std::vector finalize(); + + FF add(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); + FF sub(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); + FF mul(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); + + private: + std::vector alu_trace; +}; +} // namespace avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_common.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_common.hpp index 8588b632b87..10b3c347330 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_common.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_common.hpp @@ -11,7 +11,7 @@ namespace avm_trace { // Number of rows static const size_t AVM_TRACE_SIZE = 256; -enum class IntermRegister : uint32_t { ia = 0, ib = 1, ic = 2 }; -enum class AvmMemoryTag : uint32_t { u0 = 0, u8 = 1, u16 = 2, u32 = 3, u64 = 4, u128 = 5, ff = 6 }; +enum class IntermRegister : uint32_t { IA = 0, IB = 1, IC = 2 }; +enum class AvmMemoryTag : uint32_t { U0 = 0, U8 = 1, U16 = 2, U32 = 3, U64 = 4, U128 = 5, FF = 6 }; } // namespace avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_helper.cpp index 207485ac63d..9e1fd096c89 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_helper.cpp @@ -39,6 +39,12 @@ void log_avmMini_trace(std::vector const& trace, size_t beg, size_t end) info("internal_return: ", trace.at(i).avmMini_sel_internal_return); info("internal_return_ptr:", trace.at(i).avmMini_internal_return_ptr); + info("=======ALU TRACE====================================================================="); + info("alu_clk ", trace.at(i).aluChip_alu_clk); + info("alu_ia ", trace.at(i).aluChip_alu_ia); + info("alu_ib ", trace.at(i).aluChip_alu_ib); + info("alu_ic ", trace.at(i).aluChip_alu_ic); + info("=======MAIN TRACE===================================================================="); info("ia: ", trace.at(i).avmMini_ia); info("ib: ", trace.at(i).avmMini_ib); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_mem_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_mem_trace.cpp index f55d7e9d8b6..557244116b1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_mem_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_mem_trace.cpp @@ -21,38 +21,6 @@ void AvmMiniMemTraceBuilder::reset() memory.fill(FF(0)); } -/** - * @brief A comparator on MemoryTraceEntry to be used by sorting algorithm. We sort first by - * ascending address (m_addr), then by clock (m_clk) and finally sub-clock (m_sub_clk). - * - * @param left The left hand side memory trace entry - * @param right The right hand side memory trace entry - * - * @return A boolean indicating whether left member is smaller than right member. - */ -bool AvmMiniMemTraceBuilder::compare_mem_entries(const MemoryTraceEntry& left, const MemoryTraceEntry& right) -{ - if (left.m_addr < right.m_addr) { - return true; - } - - if (left.m_addr > right.m_addr) { - return false; - } - - if (left.m_clk < right.m_clk) { - return true; - } - - if (left.m_clk > right.m_clk) { - return false; - } - - // No safeguard in case they are equal. The caller should ensure this property. - // Otherwise, relation will not be satisfied. - return left.m_sub_clk < right.m_sub_clk; -} - /** * @brief Prepare the memory trace to be incorporated into the main trace. * @@ -61,7 +29,7 @@ bool AvmMiniMemTraceBuilder::compare_mem_entries(const MemoryTraceEntry& left, c std::vector AvmMiniMemTraceBuilder::finalize() { // Sort memTrace - std::sort(mem_trace.begin(), mem_trace.end(), compare_mem_entries); + std::sort(mem_trace.begin(), mem_trace.end()); return std::move(mem_trace); } @@ -144,19 +112,19 @@ bool AvmMiniMemTraceBuilder::load_in_mem_trace( { uint32_t sub_clk = 0; switch (interm_reg) { - case IntermRegister::ia: + case IntermRegister::IA: sub_clk = SUB_CLK_LOAD_A; break; - case IntermRegister::ib: + case IntermRegister::IB: sub_clk = SUB_CLK_LOAD_B; break; - case IntermRegister::ic: + case IntermRegister::IC: sub_clk = SUB_CLK_LOAD_C; break; } auto m_tag = memory_tag.at(addr); - if (m_tag == AvmMemoryTag::u0 || m_tag == m_in_tag) { + if (m_tag == AvmMemoryTag::U0 || m_tag == m_in_tag) { insert_in_mem_trace(clk, sub_clk, addr, val, m_in_tag, false); return true; } @@ -181,13 +149,13 @@ void AvmMiniMemTraceBuilder::store_in_mem_trace( { uint32_t sub_clk = 0; switch (interm_reg) { - case IntermRegister::ia: + case IntermRegister::IA: sub_clk = SUB_CLK_STORE_A; break; - case IntermRegister::ib: + case IntermRegister::IB: sub_clk = SUB_CLK_STORE_B; break; - case IntermRegister::ic: + case IntermRegister::IC: sub_clk = SUB_CLK_STORE_C; break; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_mem_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_mem_trace.hpp index 6a06dcee1fb..0cf1bcaca48 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_mem_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_mem_trace.hpp @@ -16,21 +16,48 @@ class AvmMiniMemTraceBuilder { static const uint32_t SUB_CLK_STORE_C = 5; struct MemoryTraceEntry { - uint32_t m_clk; - uint32_t m_sub_clk; - uint32_t m_addr; + uint32_t m_clk{}; + uint32_t m_sub_clk{}; + uint32_t m_addr{}; FF m_val{}; - AvmMemoryTag m_tag; - AvmMemoryTag m_in_tag; + AvmMemoryTag m_tag{}; + AvmMemoryTag m_in_tag{}; bool m_rw = false; bool m_tag_err = false; FF m_one_min_inv{}; + + /** + * @brief A comparator on MemoryTraceEntry to be used by sorting algorithm. We sort first by + * ascending address (m_addr), then by clock (m_clk) and finally sub-clock (m_sub_clk). + */ + bool operator<(const MemoryTraceEntry& other) const + { + if (m_addr < other.m_addr) { + return true; + } + + if (m_addr > other.m_addr) { + return false; + } + + if (m_clk < other.m_clk) { + return true; + } + + if (m_clk > other.m_clk) { + return false; + } + + // No safeguard in case they are equal. The caller should ensure this property. + // Otherwise, relation will not be satisfied. + return m_sub_clk < other.m_sub_clk; + } }; // Structure to return value and tag matching boolean after a memory read. struct MemRead { - bool tag_match; - FF val; + bool tag_match = false; + FF val{}; }; AvmMiniMemTraceBuilder(); @@ -49,8 +76,6 @@ class AvmMiniMemTraceBuilder { std::array memory_tag{}; // The tag of the corresponding memory // entry (aligned with the memory array). - static bool compare_mem_entries(const MemoryTraceEntry& left, const MemoryTraceEntry& right); - void insert_in_mem_trace( uint32_t m_clk, uint32_t m_sub_clk, uint32_t m_addr, FF const& m_val, AvmMemoryTag m_in_tag, bool m_rw); void load_mismatch_tag_in_mem_trace(uint32_t m_clk, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_trace.cpp index c38a615560f..771a1590ea1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_trace.cpp @@ -29,9 +29,10 @@ void AvmMiniTraceBuilder::reset() { main_trace.clear(); mem_trace_builder.reset(); + alu_trace_builder.reset(); } -/** TODO: Implement for non finite field types +/** * @brief Addition with direct memory access. * * @param a_offset An index in memory pointing to the first operand of the addition. @@ -44,17 +45,17 @@ void AvmMiniTraceBuilder::add(uint32_t a_offset, uint32_t b_offset, uint32_t dst auto clk = static_cast(main_trace.size()); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ia, a_offset, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ib, b_offset, in_tag); + auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, a_offset, in_tag); + auto read_b = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, b_offset, in_tag); bool tag_match = read_a.tag_match && read_b.tag_match; // a + b = c - FF a = read_a.val; - FF b = read_b.val; - FF c = a + b; + FF a = tag_match ? read_a.val : FF(0); + FF b = tag_match ? read_b.val : FF(0); + FF c = alu_trace_builder.add(a, b, in_tag, clk); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(clk, IntermRegister::ic, dst_offset, c, in_tag); + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, dst_offset, c, in_tag); main_trace.push_back(Row{ .avmMini_clk = clk, @@ -63,9 +64,9 @@ void AvmMiniTraceBuilder::add(uint32_t a_offset, uint32_t b_offset, uint32_t dst .avmMini_sel_op_add = FF(1), .avmMini_in_tag = FF(static_cast(in_tag)), .avmMini_tag_err = FF(static_cast(!tag_match)), - .avmMini_ia = tag_match ? a : FF(0), - .avmMini_ib = tag_match ? b : FF(0), - .avmMini_ic = tag_match ? c : FF(0), + .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), @@ -76,7 +77,7 @@ void AvmMiniTraceBuilder::add(uint32_t a_offset, uint32_t b_offset, uint32_t dst }); }; -/** TODO: Implement for non finite field types +/** * @brief Subtraction with direct memory access. * * @param a_offset An index in memory pointing to the first operand of the subtraction. @@ -89,17 +90,17 @@ void AvmMiniTraceBuilder::sub(uint32_t a_offset, uint32_t b_offset, uint32_t dst auto clk = static_cast(main_trace.size()); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ia, a_offset, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ib, b_offset, in_tag); + auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, a_offset, in_tag); + auto read_b = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, b_offset, in_tag); bool tag_match = read_a.tag_match && read_b.tag_match; // a - b = c - FF a = read_a.val; - FF b = read_b.val; - FF c = a - b; + FF a = tag_match ? read_a.val : FF(0); + FF b = tag_match ? read_b.val : FF(0); + FF c = alu_trace_builder.sub(a, b, in_tag, clk); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(clk, IntermRegister::ic, dst_offset, c, in_tag); + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, dst_offset, c, in_tag); main_trace.push_back(Row{ .avmMini_clk = clk, @@ -108,9 +109,9 @@ void AvmMiniTraceBuilder::sub(uint32_t a_offset, uint32_t b_offset, uint32_t dst .avmMini_sel_op_sub = FF(1), .avmMini_in_tag = FF(static_cast(in_tag)), .avmMini_tag_err = FF(static_cast(!tag_match)), - .avmMini_ia = tag_match ? a : FF(0), - .avmMini_ib = tag_match ? b : FF(0), - .avmMini_ic = tag_match ? c : FF(0), + .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), @@ -121,7 +122,7 @@ void AvmMiniTraceBuilder::sub(uint32_t a_offset, uint32_t b_offset, uint32_t dst }); }; -/** TODO: Implement for non finite field types +/** * @brief Multiplication with direct memory access. * * @param a_offset An index in memory pointing to the first operand of the multiplication. @@ -134,17 +135,17 @@ void AvmMiniTraceBuilder::mul(uint32_t a_offset, uint32_t b_offset, uint32_t dst auto clk = static_cast(main_trace.size()); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ia, a_offset, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ib, b_offset, in_tag); + auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, a_offset, in_tag); + auto read_b = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, b_offset, in_tag); bool tag_match = read_a.tag_match && read_b.tag_match; // a * b = c - FF a = read_a.val; - FF b = read_b.val; - FF c = a * b; + FF a = tag_match ? read_a.val : FF(0); + FF b = tag_match ? read_b.val : FF(0); + FF c = alu_trace_builder.mul(a, b, in_tag, clk); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(clk, IntermRegister::ic, dst_offset, c, in_tag); + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, dst_offset, c, in_tag); main_trace.push_back(Row{ .avmMini_clk = clk, @@ -153,9 +154,9 @@ void AvmMiniTraceBuilder::mul(uint32_t a_offset, uint32_t b_offset, uint32_t dst .avmMini_sel_op_mul = FF(1), .avmMini_in_tag = FF(static_cast(in_tag)), .avmMini_tag_err = FF(static_cast(!tag_match)), - .avmMini_ia = tag_match ? a : FF(0), - .avmMini_ib = tag_match ? b : FF(0), - .avmMini_ic = tag_match ? c : FF(0), + .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), @@ -179,8 +180,8 @@ void AvmMiniTraceBuilder::div(uint32_t a_offset, uint32_t b_offset, uint32_t dst auto clk = static_cast(main_trace.size()); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ia, a_offset, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ib, b_offset, in_tag); + auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, a_offset, in_tag); + auto read_b = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, b_offset, in_tag); bool tag_match = read_a.tag_match && read_b.tag_match; // a * b^(-1) = c @@ -202,7 +203,7 @@ void AvmMiniTraceBuilder::div(uint32_t a_offset, uint32_t b_offset, uint32_t dst } // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(clk, IntermRegister::ic, dst_offset, c, in_tag); + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, dst_offset, c, in_tag); main_trace.push_back(Row{ .avmMini_clk = clk, @@ -226,6 +227,38 @@ void AvmMiniTraceBuilder::div(uint32_t a_offset, uint32_t b_offset, uint32_t dst }); } +// TODO: Finish SET opcode implementation. This is a partial implementation +// facilitating testing of arithmetic operations over non finite field types. +// We add an entry in the memory trace and a simplified one in the main trace +// without operation selector. +// TODO: PIL relations for the SET opcode need to be implemented. +// No check is performed that val pertains to type defined by in_tag. +/** + * @brief Set a constant from bytecode with direct memory access. + * + * @param val The constant to be written upcasted to u128 + * @param dst_offset Memory destination offset where val is written to + * @param in_tag The instruction memory tag + */ +void AvmMiniTraceBuilder::set(uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag) +{ + auto clk = static_cast(main_trace.size()); + auto val_ff = FF{ uint256_t::from_uint128(val) }; + + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, dst_offset, val_ff, in_tag); + + main_trace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_pc = FF(pc++), + .avmMini_internal_return_ptr = FF(internal_return_ptr), + .avmMini_in_tag = FF(static_cast(in_tag)), + .avmMini_ic = val_ff, + .avmMini_mem_op_c = FF(1), + .avmMini_rwc = FF(1), + .avmMini_mem_idx_c = FF(dst_offset), + }); +} + /** * @brief CALLDATACOPY opcode with direct memory access, i.e., * M[dst_offset:dst_offset+copy_size] = calldata[cd_offset:cd_offset+copy_size] @@ -237,6 +270,9 @@ void AvmMiniTraceBuilder::div(uint32_t a_offset, uint32_t b_offset, uint32_t dst * TODO: Implement the indirect memory version (maybe not required) * TODO: taking care of intermediate register values consistency and propagating their * values to the next row when not overwritten. + * TODO: error handling if dst_offset + copy_size > 2^32 which would lead to + * out-of-bound memory write. Similarly, if cd_offset + copy_size is larger + * than call_data_mem.size() * * @param cd_offset The starting index of the region in calldata to be copied. * @param copy_size The number of finite field elements to be copied into memory. @@ -274,7 +310,7 @@ void AvmMiniTraceBuilder::call_data_copy(uint32_t cd_offset, uint32_t rwa = 1; // Storing from Ia - mem_trace_builder.write_into_memory(clk, IntermRegister::ia, mem_idx_a, ia, AvmMemoryTag::ff); + mem_trace_builder.write_into_memory(clk, IntermRegister::IA, mem_idx_a, ia, AvmMemoryTag::FF); if (copy_size - pos > 1) { ib = call_data_mem.at(cd_offset + pos + 1); @@ -283,7 +319,7 @@ void AvmMiniTraceBuilder::call_data_copy(uint32_t cd_offset, rwb = 1; // Storing from Ib - mem_trace_builder.write_into_memory(clk, IntermRegister::ib, mem_idx_b, ib, AvmMemoryTag::ff); + mem_trace_builder.write_into_memory(clk, IntermRegister::IB, mem_idx_b, ib, AvmMemoryTag::FF); } if (copy_size - pos > 2) { @@ -293,14 +329,14 @@ void AvmMiniTraceBuilder::call_data_copy(uint32_t cd_offset, rwc = 1; // Storing from Ic - mem_trace_builder.write_into_memory(clk, IntermRegister::ic, mem_idx_c, ic, AvmMemoryTag::ff); + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, mem_idx_c, ic, AvmMemoryTag::FF); } main_trace.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_in_tag = FF(static_cast(AvmMemoryTag::FF)), .avmMini_ia = ia, .avmMini_ib = ib, .avmMini_ic = ic, @@ -330,12 +366,13 @@ void AvmMiniTraceBuilder::call_data_copy(uint32_t cd_offset, * 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? + * TODO: error handling if ret_offset + ret_size > 2^32 which would lead to + * out-of-bound memory read. * * @param ret_offset The starting index of the memory region to be returned. * @param ret_size The number of elements to be returned. * @return The returned memory region as a std::vector. */ - std::vector AvmMiniTraceBuilder::return_op(uint32_t ret_offset, uint32_t ret_size) { // We parallelize loading memory operations in chunk of 3, i.e., 1 per intermediate register. @@ -361,7 +398,7 @@ std::vector AvmMiniTraceBuilder::return_op(uint32_t ret_offset, uint32_t ret uint32_t mem_idx_a = ret_offset + pos; // Reading and loading to Ia - auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ia, mem_idx_a, AvmMemoryTag::ff); + auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, mem_idx_a, AvmMemoryTag::FF); FF ia = read_a.val; returnMem.push_back(ia); @@ -371,7 +408,7 @@ std::vector AvmMiniTraceBuilder::return_op(uint32_t ret_offset, uint32_t ret // Reading and loading to Ib auto read_b = - mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ib, mem_idx_b, AvmMemoryTag::ff); + mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, mem_idx_b, AvmMemoryTag::FF); FF ib = read_b.val; returnMem.push_back(ib); } @@ -382,7 +419,7 @@ std::vector AvmMiniTraceBuilder::return_op(uint32_t ret_offset, uint32_t ret // Reading and loading to Ic auto read_c = - mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ic, mem_idx_c, AvmMemoryTag::ff); + mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IC, mem_idx_c, AvmMemoryTag::FF); FF ic = read_c.val; returnMem.push_back(ic); } @@ -392,7 +429,7 @@ std::vector AvmMiniTraceBuilder::return_op(uint32_t ret_offset, uint32_t ret .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_in_tag = FF(static_cast(AvmMemoryTag::FF)), .avmMini_ia = ia, .avmMini_ib = ib, .avmMini_ic = ic, @@ -417,7 +454,7 @@ std::vector AvmMiniTraceBuilder::return_op(uint32_t ret_offset, uint32_t ret * @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. + * i.e. the program counter should freeze and the halt flag is set to 1. */ void AvmMiniTraceBuilder::halt() { @@ -477,7 +514,7 @@ void AvmMiniTraceBuilder::internal_call(uint32_t jmp_dest) internal_call_stack.push(stored_pc); // Add the return location to the memory trace - mem_trace_builder.write_into_memory(clk, IntermRegister::ib, internal_return_ptr, FF(stored_pc), AvmMemoryTag::ff); + mem_trace_builder.write_into_memory(clk, IntermRegister::IB, internal_return_ptr, FF(stored_pc), AvmMemoryTag::FF); main_trace.push_back(Row{ .avmMini_clk = clk, @@ -513,7 +550,7 @@ void AvmMiniTraceBuilder::internal_return() // Internal return pointer is decremented // We want to load the value pointed by the internal pointer auto read_a = - mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::ia, internal_return_ptr - 1, AvmMemoryTag::ff); + mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, internal_return_ptr - 1, AvmMemoryTag::FF); main_trace.push_back(Row{ .avmMini_clk = clk, @@ -544,14 +581,17 @@ void AvmMiniTraceBuilder::internal_return() std::vector AvmMiniTraceBuilder::finalize() { auto mem_trace = mem_trace_builder.finalize(); + auto alu_trace = alu_trace_builder.finalize(); size_t mem_trace_size = mem_trace.size(); size_t main_trace_size = main_trace.size(); + size_t alu_trace_size = alu_trace.size(); // TODO: We will have to handle this through error handling and not an assertion // Smaller than N because we have to add an extra initial row to support shifted // elements assert(mem_trace_size < AVM_TRACE_SIZE); assert(main_trace_size < AVM_TRACE_SIZE); + assert(alu_trace_size < AVM_TRACE_SIZE); // Fill the rest with zeros. size_t zero_rows_num = AVM_TRACE_SIZE - main_trace_size - 1; @@ -561,6 +601,7 @@ std::vector AvmMiniTraceBuilder::finalize() main_trace.at(main_trace_size - 1).avmMini_last = FF(1); + // Memory trace inclusion for (size_t i = 0; i < mem_trace_size; i++) { auto const& src = mem_trace.at(i); auto& dest = main_trace.at(i); @@ -584,6 +625,45 @@ std::vector AvmMiniTraceBuilder::finalize() } } + // Alu trace inclusion + for (size_t i = 0; i < alu_trace_size; i++) { + auto const& src = alu_trace.at(i); + auto& dest = main_trace.at(i); + + dest.aluChip_alu_clk = FF(static_cast(src.alu_clk)); + + dest.aluChip_alu_op_add = FF(static_cast(src.alu_op_add)); + dest.aluChip_alu_op_sub = FF(static_cast(src.alu_op_sub)); + dest.aluChip_alu_op_mul = FF(static_cast(src.alu_op_mul)); + + dest.aluChip_alu_ff_tag = FF(static_cast(src.alu_ff_tag)); + dest.aluChip_alu_u8_tag = FF(static_cast(src.alu_u8_tag)); + dest.aluChip_alu_u16_tag = FF(static_cast(src.alu_u16_tag)); + dest.aluChip_alu_u32_tag = FF(static_cast(src.alu_u32_tag)); + dest.aluChip_alu_u64_tag = FF(static_cast(src.alu_u64_tag)); + dest.aluChip_alu_u128_tag = FF(static_cast(src.alu_u128_tag)); + + dest.aluChip_alu_ia = src.alu_ia; + dest.aluChip_alu_ib = src.alu_ib; + dest.aluChip_alu_ic = src.alu_ic; + + dest.aluChip_alu_cf = FF(static_cast(src.alu_cf)); + + dest.aluChip_alu_u8_r0 = FF(src.alu_u8_r0); + dest.aluChip_alu_u8_r1 = FF(src.alu_u8_r1); + + dest.aluChip_alu_u16_r0 = FF(src.alu_u16_reg.at(0)); + dest.aluChip_alu_u16_r1 = FF(src.alu_u16_reg.at(1)); + dest.aluChip_alu_u16_r2 = FF(src.alu_u16_reg.at(2)); + dest.aluChip_alu_u16_r3 = FF(src.alu_u16_reg.at(3)); + dest.aluChip_alu_u16_r4 = FF(src.alu_u16_reg.at(4)); + dest.aluChip_alu_u16_r5 = FF(src.alu_u16_reg.at(5)); + dest.aluChip_alu_u16_r6 = FF(src.alu_u16_reg.at(6)); + dest.aluChip_alu_u16_r7 = FF(src.alu_u16_reg.at(7)); + + dest.aluChip_alu_u64_r0 = FF(src.alu_u64_r0); + } + // Adding extra row for the shifted values at the top of the execution trace. Row first_row = Row{ .avmMini_first = FF(1), .memTrace_m_lastAccess = FF(1) }; main_trace.insert(main_trace.begin(), first_row); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_trace.hpp index ef8e51b65bf..af09f2e4d14 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/AvmMini_trace.hpp @@ -2,6 +2,7 @@ #include +#include "AvmMini_alu_trace.hpp" #include "AvmMini_common.hpp" #include "AvmMini_mem_trace.hpp" #include "barretenberg/common/throw_or_abort.hpp" @@ -36,6 +37,9 @@ class AvmMiniTraceBuilder { // Division with direct memory access. void div(uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Set a constant from bytecode with direct memory access. + void set(uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag); + // Jump to a given program counter. void jump(uint32_t jmp_dest); @@ -63,6 +67,7 @@ class AvmMiniTraceBuilder { private: std::vector main_trace; AvmMiniMemTraceBuilder mem_trace_builder; + AvmMiniAluTraceBuilder alu_trace_builder; uint32_t pc = 0; uint32_t internal_return_ptr = CALLSTACK_OFFSET; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp index aec530be757..552582558c4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp @@ -72,8 +72,10 @@ void AvmMiniProver::execute_relation_check_rounds() using Sumcheck = sumcheck::SumcheckProver; auto sumcheck = Sumcheck(key->circuit_size, transcript); + FF alpha = transcript->get_challenge("Sumcheck:alpha"); std::vector gate_challenges(numeric::get_msb(key->circuit_size)); + for (size_t idx = 0; idx < gate_challenges.size(); idx++) { gate_challenges[idx] = transcript->get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp index 2da2112a9b3..09beb8a866e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp @@ -72,6 +72,54 @@ 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.aluChip_alu_clk = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_clk); + commitments.aluChip_alu_ia = transcript->template receive_from_prover(commitment_labels.aluChip_alu_ia); + commitments.aluChip_alu_ib = transcript->template receive_from_prover(commitment_labels.aluChip_alu_ib); + commitments.aluChip_alu_ic = transcript->template receive_from_prover(commitment_labels.aluChip_alu_ic); + commitments.aluChip_alu_op_add = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_op_add); + commitments.aluChip_alu_op_sub = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_op_sub); + commitments.aluChip_alu_op_mul = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_op_mul); + commitments.aluChip_alu_op_div = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_op_div); + commitments.aluChip_alu_ff_tag = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_ff_tag); + commitments.aluChip_alu_u8_tag = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u8_tag); + commitments.aluChip_alu_u16_tag = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_tag); + commitments.aluChip_alu_u32_tag = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u32_tag); + commitments.aluChip_alu_u64_tag = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u64_tag); + commitments.aluChip_alu_u128_tag = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u128_tag); + commitments.aluChip_alu_u8_r0 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u8_r0); + commitments.aluChip_alu_u8_r1 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u8_r1); + commitments.aluChip_alu_u16_r0 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_r0); + commitments.aluChip_alu_u16_r1 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_r1); + commitments.aluChip_alu_u16_r2 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_r2); + commitments.aluChip_alu_u16_r3 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_r3); + commitments.aluChip_alu_u16_r4 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_r4); + commitments.aluChip_alu_u16_r5 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_r5); + commitments.aluChip_alu_u16_r6 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_r6); + commitments.aluChip_alu_u16_r7 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u16_r7); + commitments.aluChip_alu_u64_r0 = + transcript->template receive_from_prover(commitment_labels.aluChip_alu_u64_r0); + commitments.aluChip_alu_cf = transcript->template receive_from_prover(commitment_labels.aluChip_alu_cf); 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); @@ -119,11 +167,14 @@ bool AvmMiniVerifier::verify_proof(const plonk::proof& proof) // Execute Sumcheck Verifier const size_t log_circuit_size = numeric::get_msb(circuit_size); auto sumcheck = SumcheckVerifier(log_circuit_size, transcript); + FF alpha = transcript->get_challenge("Sumcheck:alpha"); + auto gate_challenges = std::vector(log_circuit_size); for (size_t idx = 0; idx < log_circuit_size; idx++) { gate_challenges[idx] = transcript->get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } + auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); 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 46ed56f37f3..57060f411e1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_arithmetic.test.cpp @@ -1,14 +1,187 @@ -#include "barretenberg/vm/avm_trace/AvmMini_helper.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 +#include "AvmMini_common.test.hpp" + +#include "barretenberg/numeric/uint128/uint128.hpp" + +using namespace numeric; +namespace { + +void common_validate_arithmetic_op(Row const& main_row, + Row const& alu_row, + FF const& a, + FF const& b, + FF const& c, + FF const& addr_a, + FF const& addr_b, + FF const& addr_c, + avm_trace::AvmMemoryTag const tag) +{ + // Check that the correct result is stored at the expected memory location. + EXPECT_EQ(main_row.avmMini_ic, c); + EXPECT_EQ(main_row.avmMini_mem_idx_c, addr_c); + EXPECT_EQ(main_row.avmMini_mem_op_c, FF(1)); + EXPECT_EQ(main_row.avmMini_rwc, FF(1)); + + // Check that ia and ib registers are correctly set with memory load operations. + EXPECT_EQ(main_row.avmMini_ia, a); + EXPECT_EQ(main_row.avmMini_mem_idx_a, addr_a); + EXPECT_EQ(main_row.avmMini_mem_op_a, FF(1)); + EXPECT_EQ(main_row.avmMini_rwa, FF(0)); + EXPECT_EQ(main_row.avmMini_ib, b); + EXPECT_EQ(main_row.avmMini_mem_idx_b, addr_b); + EXPECT_EQ(main_row.avmMini_mem_op_b, FF(1)); + EXPECT_EQ(main_row.avmMini_rwb, FF(0)); + + // Check the instruction tag + EXPECT_EQ(main_row.avmMini_in_tag, FF(static_cast(tag))); + + // Check that intermediate rgiesters are correctly copied in Alu trace + EXPECT_EQ(alu_row.aluChip_alu_ia, a); + EXPECT_EQ(alu_row.aluChip_alu_ib, b); + EXPECT_EQ(alu_row.aluChip_alu_ic, c); +} + +Row common_validate_add(std::vector const& trace, + FF const& a, + FF const& b, + FF const& c, + FF const& addr_a, + FF const& addr_b, + FF const& addr_c, + avm_trace::AvmMemoryTag const tag) +{ + // Find the first row enabling the addition selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_op_add == FF(1); }); + + // Find the corresponding Alu trace row + auto clk = row->avmMini_clk; + auto alu_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.aluChip_alu_clk == clk; }); + + // Check that both rows were found + EXPECT_TRUE(row != trace.end()); + EXPECT_TRUE(alu_row != trace.end()); + + common_validate_arithmetic_op(*row, *alu_row, a, b, c, addr_a, addr_b, addr_c, tag); + + // Check that addition selector is set. + EXPECT_EQ(row->avmMini_sel_op_add, FF(1)); + EXPECT_EQ(alu_row->aluChip_alu_op_add, FF(1)); + + return *alu_row; +} + +Row common_validate_sub(std::vector const& trace, + FF const& a, + FF const& b, + FF const& c, + FF const& addr_a, + FF const& addr_b, + FF const& addr_c, + avm_trace::AvmMemoryTag const tag) +{ + // Find the first row enabling the subtraction selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_op_sub == FF(1); }); + + // Find the corresponding Alu trace row + auto clk = row->avmMini_clk; + auto alu_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.aluChip_alu_clk == clk; }); + + // Check that both rows were found + EXPECT_TRUE(row != trace.end()); + EXPECT_TRUE(alu_row != trace.end()); + + common_validate_arithmetic_op(*row, *alu_row, a, b, c, addr_a, addr_b, addr_c, tag); + + // Check that subtraction selector is set. + EXPECT_EQ(row->avmMini_sel_op_sub, FF(1)); + EXPECT_EQ(alu_row->aluChip_alu_op_sub, FF(1)); + + return *alu_row; +} + +size_t common_validate_mul(std::vector const& trace, + FF const& a, + FF const& b, + FF const& c, + FF const& addr_a, + FF const& addr_b, + FF const& addr_c, + avm_trace::AvmMemoryTag const tag) +{ + // Find the first row enabling the multiplication selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_op_mul == FF(1); }); + + // Find the corresponding Alu trace row + auto clk = row->avmMini_clk; + auto alu_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.aluChip_alu_clk == clk; }); + + // Check that both rows were found + EXPECT_TRUE(row != trace.end()); + EXPECT_TRUE(alu_row != trace.end()); + + common_validate_arithmetic_op(*row, *alu_row, a, b, c, addr_a, addr_b, addr_c, tag); + + // Check that multiplication selector is set. + EXPECT_EQ(row->avmMini_sel_op_mul, FF(1)); + EXPECT_EQ(alu_row->aluChip_alu_op_mul, FF(1)); + + return static_cast(alu_row - trace.begin()); +} + +// This function generates a mutated trace of an addition where a and b are the passed inputs. +// a and b are stored in memory indices 0 and 1. c_mutated is the wrong result of the addition +// and the memory and alu trace are created consistently with the wrong value c_mutated. +std::vector gen_mutated_trace_add(FF const& a, FF const& b, FF const& c_mutated, avm_trace::AvmMemoryTag tag) +{ + auto trace_builder = avm_trace::AvmMiniTraceBuilder(); + trace_builder.set(uint128_t{ a }, 0, tag); + trace_builder.set(uint128_t{ b }, 1, tag); + trace_builder.add(0, 1, 2, tag); + trace_builder.halt(); + auto trace = trace_builder.finalize(); + + auto select_row = [](Row r) { return r.avmMini_sel_op_add == FF(1); }; + tests_avm::mutate_ic_in_trace(trace, select_row, c_mutated, true); + + return trace; +} + +// This function generates a mutated trace of a subtraction where a and b are the passed inputs. +// a and b are stored in memory indices 0 and 1. c_mutated is the wrong result of the subtraction +// and the memory and alu trace are created consistently with the wrong value c_mutated. +std::vector gen_mutated_trace_sub(FF const& a, FF const& b, FF const& c_mutated, avm_trace::AvmMemoryTag tag) +{ + auto trace_builder = avm_trace::AvmMiniTraceBuilder(); + trace_builder.set(uint128_t{ a }, 0, tag); + trace_builder.set(uint128_t{ b }, 1, tag); + trace_builder.sub(0, 1, 2, tag); + trace_builder.halt(); + auto trace = trace_builder.finalize(); + + auto select_row = [](Row r) { return r.avmMini_sel_op_sub == FF(1); }; + tests_avm::mutate_ic_in_trace(trace, select_row, c_mutated, true); + + return trace; +} + +// This function generates a mutated trace of a multiplication where a and b are the passed inputs. +// a and b are stored in memory indices 0 and 1. c_mutated is the wrong result of the multiplication +// and the memory and alu trace are created consistently with the wrong value c_mutated. +std::vector gen_mutated_trace_mul(FF const& a, FF const& b, FF const& c_mutated, avm_trace::AvmMemoryTag tag) +{ + auto trace_builder = avm_trace::AvmMiniTraceBuilder(); + trace_builder.set(uint128_t{ a }, 0, tag); + trace_builder.set(uint128_t{ b }, 1, tag); + trace_builder.mul(0, 1, 2, tag); + trace_builder.halt(); + auto trace = trace_builder.finalize(); + + auto select_row = [](Row r) { return r.avmMini_sel_op_mul == FF(1); }; + tests_avm::mutate_ic_in_trace(trace, select_row, c_mutated, true); + + return trace; +} + +} // anonymous namespace namespace tests_avm { using namespace avm_trace; @@ -26,11 +199,23 @@ class AvmMiniArithmeticTests : public ::testing::Test { }; }; -class AvmMiniArithmeticNegativeTests : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticTestsFF : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticTestsU8 : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticTestsU16 : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticTestsU32 : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticTestsU64 : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticTestsU128 : public AvmMiniArithmeticTests {}; + +class AvmMiniArithmeticNegativeTestsFF : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticNegativeTestsU8 : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticNegativeTestsU16 : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticNegativeTestsU32 : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticNegativeTestsU64 : public AvmMiniArithmeticTests {}; +class AvmMiniArithmeticNegativeTestsU128 : public AvmMiniArithmeticTests {}; /****************************************************************************** * - * POSITIVE TESTS - Finite Field Type + * POSITIVE TESTS * ****************************************************************************** * The positive tests aim at testing that a genuinely generated execution trace @@ -52,106 +237,96 @@ class AvmMiniArithmeticNegativeTests : public AvmMiniArithmeticTests {}; * will still correctly work along the development of the AVM. ******************************************************************************/ +/****************************************************************************** + * Positive Tests - FF + ******************************************************************************/ + // Test on basic addition over finite field type. -TEST_F(AvmMiniArithmeticTests, additionFF) +TEST_F(AvmMiniArithmeticTestsFF, addition) { // trace_builder trace_builder.call_data_copy(0, 3, 0, std::vector{ 37, 4, 11 }); // Memory layout: [37,4,11,0,0,0,....] - trace_builder.add(0, 1, 4, AvmMemoryTag::ff); // [37,4,11,0,41,0,....] + trace_builder.add(0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] trace_builder.return_op(0, 5); auto trace = trace_builder.finalize(); - // Find the first row enabling the addition selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_op_add == FF(1); }); + auto alu_row = common_validate_add(trace, FF(37), FF(4), FF(41), FF(0), FF(1), FF(4), AvmMemoryTag::FF); - // Check that the correct result is stored at the expected memory location. - EXPECT_TRUE(row != trace.end()); - EXPECT_EQ(row->avmMini_ic, FF(41)); - EXPECT_EQ(row->avmMini_mem_idx_c, FF(4)); - EXPECT_EQ(row->avmMini_mem_op_c, FF(1)); - EXPECT_EQ(row->avmMini_rwc, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_ff_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0)); validate_trace_proof(std::move(trace)); } // Test on basic subtraction over finite field type. -TEST_F(AvmMiniArithmeticTests, subtractionFF) +TEST_F(AvmMiniArithmeticTestsFF, subtraction) { trace_builder.call_data_copy(0, 3, 0, std::vector{ 8, 4, 17 }); // Memory layout: [8,4,17,0,0,0,....] - trace_builder.sub(2, 0, 1, AvmMemoryTag::ff); // [8,9,17,0,0,0....] + trace_builder.sub(2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] trace_builder.return_op(0, 3); auto trace = trace_builder.finalize(); - // Find the first row enabling the subtraction selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_op_sub == FF(1); }); + auto alu_row = common_validate_sub(trace, FF(17), FF(8), FF(9), FF(2), FF(0), FF(1), AvmMemoryTag::FF); - // Check that the correct result is stored at the expected memory location. - EXPECT_TRUE(row != trace.end()); - EXPECT_EQ(row->avmMini_ic, FF(9)); - EXPECT_EQ(row->avmMini_mem_idx_c, FF(1)); - EXPECT_EQ(row->avmMini_mem_op_c, FF(1)); - EXPECT_EQ(row->avmMini_rwc, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_ff_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0)); validate_trace_proof(std::move(trace)); } // Test on basic multiplication over finite field type. -TEST_F(AvmMiniArithmeticTests, multiplicationFF) +TEST_F(AvmMiniArithmeticTestsFF, multiplication) { trace_builder.call_data_copy(0, 3, 0, std::vector{ 5, 0, 20 }); // Memory layout: [5,0,20,0,0,0,....] - trace_builder.mul(2, 0, 1, AvmMemoryTag::ff); // [5,100,20,0,0,0....] + trace_builder.mul(2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] trace_builder.return_op(0, 3); auto trace = trace_builder.finalize(); - // Find the first row enabling the multiplication selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_op_mul == FF(1); }); + auto alu_row_index = common_validate_mul(trace, FF(20), FF(5), FF(100), FF(2), FF(0), FF(1), AvmMemoryTag::FF); + auto alu_row = trace.at(alu_row_index); - // Check that the correct result is stored at the expected memory location. - EXPECT_TRUE(row != trace.end()); - EXPECT_EQ(row->avmMini_ic, FF(100)); - EXPECT_EQ(row->avmMini_mem_idx_c, FF(1)); - EXPECT_EQ(row->avmMini_mem_op_c, FF(1)); - EXPECT_EQ(row->avmMini_rwc, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_ff_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0)); validate_trace_proof(std::move(trace)); } // Test on multiplication by zero over finite field type. -TEST_F(AvmMiniArithmeticTests, multiplicationByZeroFF) +TEST_F(AvmMiniArithmeticTestsFF, multiplicationByZero) { trace_builder.call_data_copy(0, 1, 0, std::vector{ 127 }); // Memory layout: [127,0,0,0,0,0,....] - trace_builder.mul(0, 1, 2, AvmMemoryTag::ff); // [127,0,0,0,0,0....] + trace_builder.mul(0, 1, 2, AvmMemoryTag::FF); // [127,0,0,0,0,0....] trace_builder.return_op(0, 3); auto trace = trace_builder.finalize(); - // Find the first row enabling the multiplication selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avmMini_sel_op_mul == FF(1); }); + auto alu_row_index = common_validate_mul(trace, FF(127), FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::FF); + auto alu_row = trace.at(alu_row_index); - // Check that the correct result is stored at the expected memory location. - EXPECT_TRUE(row != trace.end()); - EXPECT_EQ(row->avmMini_ic, FF(0)); - EXPECT_EQ(row->avmMini_mem_idx_c, FF(2)); - EXPECT_EQ(row->avmMini_mem_op_c, FF(1)); - EXPECT_EQ(row->avmMini_rwc, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_ff_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0)); validate_trace_proof(std::move(trace)); } // Test on basic division over finite field type. -TEST_F(AvmMiniArithmeticTests, divisionFF) +TEST_F(AvmMiniArithmeticTestsFF, division) { trace_builder.call_data_copy(0, 2, 0, std::vector{ 15, 315 }); // Memory layout: [15,315,0,0,0,0,....] - trace_builder.div(1, 0, 2, AvmMemoryTag::ff); // [15,315,21,0,0,0....] + trace_builder.div(1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] trace_builder.return_op(0, 3); auto trace = trace_builder.finalize(); @@ -169,12 +344,12 @@ TEST_F(AvmMiniArithmeticTests, divisionFF) } // Test on division with zero numerator over finite field type. -TEST_F(AvmMiniArithmeticTests, divisionNumeratorZeroFF) +TEST_F(AvmMiniArithmeticTestsFF, divisionNumeratorZero) { trace_builder.call_data_copy(0, 1, 0, std::vector{ 15 }); // Memory layout: [15,0,0,0,0,0,....] - trace_builder.div(1, 0, 0, AvmMemoryTag::ff); // [0,0,0,0,0,0....] + trace_builder.div(1, 0, 0, AvmMemoryTag::FF); // [0,0,0,0,0,0....] trace_builder.return_op(0, 3); auto trace = trace_builder.finalize(); @@ -193,12 +368,12 @@ TEST_F(AvmMiniArithmeticTests, divisionNumeratorZeroFF) // Test on division by zero over finite field type. // We check that the operator error flag is raised. -TEST_F(AvmMiniArithmeticTests, divisionByZeroErrorFF) +TEST_F(AvmMiniArithmeticTestsFF, divisionByZeroError) { trace_builder.call_data_copy(0, 1, 0, std::vector{ 15 }); // Memory layout: [15,0,0,0,0,0,....] - trace_builder.div(0, 1, 2, AvmMemoryTag::ff); // [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(); @@ -218,10 +393,10 @@ TEST_F(AvmMiniArithmeticTests, divisionByZeroErrorFF) // Test on division of zero by zero over finite field type. // We check that the operator error flag is raised. -TEST_F(AvmMiniArithmeticTests, divisionZeroByZeroErrorFF) +TEST_F(AvmMiniArithmeticTestsFF, divisionZeroByZeroError) { // Memory layout: [0,0,0,0,0,0,....] - trace_builder.div(0, 1, 2, AvmMemoryTag::ff); // [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(); @@ -243,27 +418,937 @@ TEST_F(AvmMiniArithmeticTests, divisionZeroByZeroErrorFF) // and finishing with a division by zero. The chosen combination is arbitrary. // We only test that the proof can be correctly generated and verified. // No check on the evaluation is performed here. -TEST_F(AvmMiniArithmeticTests, arithmeticFFWithError) +TEST_F(AvmMiniArithmeticTestsFF, mixedOperationsWithError) { trace_builder.call_data_copy(0, 3, 2, std::vector{ 45, 23, 12 }); // Memory layout: [0,0,45,23,12,0,0,0,....] - trace_builder.add(2, 3, 4, AvmMemoryTag::ff); // [0,0,45,23,68,0,0,0,....] - trace_builder.add(4, 5, 5, AvmMemoryTag::ff); // [0,0,45,23,68,68,0,0,....] - trace_builder.add(5, 5, 5, AvmMemoryTag::ff); // [0,0,45,23,68,136,0,0,....] - trace_builder.add(5, 6, 7, AvmMemoryTag::ff); // [0,0,45,23,68,136,0,136,0....] - trace_builder.sub(7, 6, 8, AvmMemoryTag::ff); // [0,0,45,23,68,136,0,136,136,0....] - trace_builder.mul(8, 8, 8, AvmMemoryTag::ff); // [0,0,45,23,68,136,0,136,136^2,0....] - trace_builder.div(3, 5, 1, AvmMemoryTag::ff); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] - trace_builder.div(1, 1, 9, AvmMemoryTag::ff); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] + trace_builder.add(2, 3, 4, AvmMemoryTag::FF); // [0,0,45,23,68,0,0,0,....] + trace_builder.add(4, 5, 5, AvmMemoryTag::FF); // [0,0,45,23,68,68,0,0,....] + trace_builder.add(5, 5, 5, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,0,....] + trace_builder.add(5, 6, 7, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,0....] + trace_builder.sub(7, 6, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136,0....] + trace_builder.mul(8, 8, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136^2,0....] + trace_builder.div(3, 5, 1, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] + 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 + 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(); validate_trace_proof(std::move(trace)); } +/****************************************************************************** + * Positive Tests - U8 + ******************************************************************************/ + +// Test on basic addition over u8 type. +TEST_F(AvmMiniArithmeticTestsU8, addition) +{ + // trace_builder + trace_builder.set(62, 0, AvmMemoryTag::U8); + trace_builder.set(29, 1, AvmMemoryTag::U8); + + // Memory layout: [62,29,0,0,0,....] + trace_builder.add(0, 1, 2, AvmMemoryTag::U8); // [62,29,91,0,0,....] + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_add(trace, FF(62), FF(29), FF(91), FF(0), FF(1), FF(2), AvmMemoryTag::U8); + + EXPECT_EQ(alu_row.aluChip_alu_u8_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(91)); + validate_trace_proof(std::move(trace)); +} + +// Test on basic addition over u8 type with carry. +TEST_F(AvmMiniArithmeticTestsU8, additionCarry) +{ + // trace_builder + trace_builder.set(159, 0, AvmMemoryTag::U8); + trace_builder.set(100, 1, AvmMemoryTag::U8); + + // Memory layout: [159,100,0,0,0,....] + trace_builder.add(0, 1, 2, AvmMemoryTag::U8); // [159,100,3,0,0,....] + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_add(trace, FF(159), FF(100), FF(3), FF(0), FF(1), FF(2), AvmMemoryTag::U8); + + EXPECT_EQ(alu_row.aluChip_alu_u8_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(3)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(1)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u8 type. +TEST_F(AvmMiniArithmeticTestsU8, subtraction) +{ + // trace_builder + trace_builder.set(162, 0, AvmMemoryTag::U8); + trace_builder.set(29, 1, AvmMemoryTag::U8); + + // Memory layout: [162,29,0,0,0,....] + trace_builder.sub(0, 1, 2, AvmMemoryTag::U8); // [162,29,133,0,0,....] + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_sub(trace, FF(162), FF(29), FF(133), FF(0), FF(1), FF(2), AvmMemoryTag::U8); + + EXPECT_EQ(alu_row.aluChip_alu_u8_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(133)); + + validate_trace_proof(std::move(trace)); +} + +// Test on subtraction over u8 type with carry. +// For a subtraction a - b = c, there is a carry flag iff a < b (equivalent to a < c) +TEST_F(AvmMiniArithmeticTestsU8, subtractionCarry) +{ + // trace_builder + trace_builder.set(5, 0, AvmMemoryTag::U8); + trace_builder.set(29, 1, AvmMemoryTag::U8); + + // Memory layout: [5,29,0,0,0,....] + trace_builder.sub(0, 1, 2, AvmMemoryTag::U8); // [5,29,232,0,0,....] + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_sub(trace, FF(5), FF(29), FF(232), FF(0), FF(1), FF(2), AvmMemoryTag::U8); + + EXPECT_EQ(alu_row.aluChip_alu_u8_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(232)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(UINT8_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(UINT16_MAX)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic multiplication over u8 type. +TEST_F(AvmMiniArithmeticTestsU8, multiplication) +{ + // trace_builder + trace_builder.set(13, 0, AvmMemoryTag::U8); + trace_builder.set(15, 1, AvmMemoryTag::U8); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U8); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = common_validate_mul(trace, FF(13), FF(15), FF(195), FF(0), FF(1), FF(2), AvmMemoryTag::U8); + auto alu_row = trace.at(alu_row_index); + + EXPECT_EQ(alu_row.aluChip_alu_u8_tag, FF(1)); + + // Decomposition of integer multiplication in 8-bit registers + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(195)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on multiplication over u8 type with overflow. +TEST_F(AvmMiniArithmeticTestsU8, multiplicationOverflow) +{ + // trace_builder + trace_builder.set(200, 0, AvmMemoryTag::U8); + trace_builder.set(170, 1, AvmMemoryTag::U8); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U8); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = common_validate_mul(trace, FF(200), FF(170), FF(208), FF(0), FF(1), FF(2), AvmMemoryTag::U8); + auto alu_row = trace.at(alu_row_index); + + EXPECT_EQ(alu_row.aluChip_alu_u8_tag, FF(1)); + + // Decomposition of integer multiplication in 8-bit registers + // 34'000 = 208 + 132 * 256 + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(208)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(132)); + + validate_trace_proof(std::move(trace)); +} + +/****************************************************************************** + * Positive Tests - U16 + ******************************************************************************/ + +// Test on basic addition over u16 type. +TEST_F(AvmMiniArithmeticTestsU16, addition) +{ + // trace_builder + trace_builder.set(1775, 119, AvmMemoryTag::U16); + trace_builder.set(33005, 546, AvmMemoryTag::U16); + + trace_builder.add(546, 119, 5, AvmMemoryTag::U16); + trace_builder.return_op(5, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = + common_validate_add(trace, FF(33005), FF(1775), FF(34780), FF(546), FF(119), FF(5), AvmMemoryTag::U16); + + EXPECT_EQ(alu_row.aluChip_alu_u16_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0xDC)); // 34780 = 0x87DC + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0x87)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic addition over u16 type with carry. +TEST_F(AvmMiniArithmeticTestsU16, additionCarry) +{ + // trace_builder + trace_builder.set(UINT16_MAX - 982, 0, AvmMemoryTag::U16); + trace_builder.set(1000, 1, AvmMemoryTag::U16); + + trace_builder.add(1, 0, 0, AvmMemoryTag::U16); + trace_builder.return_op(0, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = + common_validate_add(trace, FF(1000), FF(UINT16_MAX - 982), FF(17), FF(1), FF(0), FF(0), AvmMemoryTag::U16); + + EXPECT_EQ(alu_row.aluChip_alu_u16_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(17)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u16 type. +TEST_F(AvmMiniArithmeticTestsU16, subtraction) +{ + // trace_builder + trace_builder.set(1775, 119, AvmMemoryTag::U16); + trace_builder.set(33005, 546, AvmMemoryTag::U16); + + trace_builder.sub(546, 119, 5, AvmMemoryTag::U16); + trace_builder.return_op(5, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = + common_validate_sub(trace, FF(33005), FF(1775), FF(31230), FF(546), FF(119), FF(5), AvmMemoryTag::U16); + + EXPECT_EQ(alu_row.aluChip_alu_u16_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0xFE)); // 31230 in Hex: 79FE + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0x79)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u16 type with carry. +// For a subtraction a - b = c, there is a carry flag iff a < b (equivalent to a < c) +TEST_F(AvmMiniArithmeticTestsU16, subtractionCarry) +{ + // trace_builder + trace_builder.set(UINT16_MAX - 982, 0, AvmMemoryTag::U16); + trace_builder.set(1000, 1, AvmMemoryTag::U16); + + trace_builder.sub(1, 0, 0, AvmMemoryTag::U16); + trace_builder.return_op(0, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = + common_validate_sub(trace, FF(1000), FF(UINT16_MAX - 982), FF(1983), FF(1), FF(0), FF(0), AvmMemoryTag::U16); + + EXPECT_EQ(alu_row.aluChip_alu_u16_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0xBF)); // 1983 = 0x7BF + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(7)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(UINT16_MAX)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic multiplication over u16 type. +TEST_F(AvmMiniArithmeticTestsU16, multiplication) +{ + // trace_builder + trace_builder.set(200, 0, AvmMemoryTag::U16); + trace_builder.set(245, 1, AvmMemoryTag::U16); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U16); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = + common_validate_mul(trace, FF(200), FF(245), FF(49000), FF(0), FF(1), FF(2), AvmMemoryTag::U16); + auto alu_row = trace.at(alu_row_index); + + EXPECT_EQ(alu_row.aluChip_alu_u16_tag, FF(1)); + + // Decomposition of integer multiplication in 8-bit and 16-bit registers + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0x68)); // 49000 = 0xBF68 + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0xBF)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on multiplication over u16 type with overflow. +TEST_F(AvmMiniArithmeticTestsU16, multiplicationOverflow) +{ + // trace_builder + trace_builder.set(512, 0, AvmMemoryTag::U16); + trace_builder.set(1024, 1, AvmMemoryTag::U16); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U16); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = common_validate_mul(trace, FF(512), FF(1024), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U16); + auto alu_row = trace.at(alu_row_index); + + EXPECT_EQ(alu_row.aluChip_alu_u16_tag, FF(1)); + + // Decomposition of integer multiplication in 8-bit and 16-bit registers + // 512 * 1024 = 0 + 8 * 2^16 + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(8)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +/****************************************************************************** + * Positive Tests - U32 + ******************************************************************************/ + +// Test on basic addition over u32 type. +TEST_F(AvmMiniArithmeticTestsU32, addition) +{ + // trace_builder + trace_builder.set(1000000000, 8, AvmMemoryTag::U32); + trace_builder.set(1234567891, 9, AvmMemoryTag::U32); + + trace_builder.add(8, 9, 0, AvmMemoryTag::U32); + trace_builder.return_op(0, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_add( + trace, FF(1000000000), FF(1234567891), FF(2234567891LLU), FF(8), FF(9), FF(0), AvmMemoryTag::U32); + + EXPECT_EQ(alu_row.aluChip_alu_u32_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(2234567891LLU & UINT8_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF((2234567891LLU >> 8) & UINT8_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(2234567891LLU >> 16)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic addition over u32 type with carry. +TEST_F(AvmMiniArithmeticTestsU32, additionCarry) +{ + // trace_builder + trace_builder.set(UINT32_MAX - 1293, 8, AvmMemoryTag::U32); + trace_builder.set(2293, 9, AvmMemoryTag::U32); + + trace_builder.add(8, 9, 0, AvmMemoryTag::U32); + trace_builder.return_op(0, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = + common_validate_add(trace, FF(UINT32_MAX - 1293), FF(2293), FF(999), FF(8), FF(9), FF(0), AvmMemoryTag::U32); + + EXPECT_EQ(alu_row.aluChip_alu_u32_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(231)); // 999 = 3 * 256 + 231 + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(3)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u32 type. +TEST_F(AvmMiniArithmeticTestsU32, subtraction) +{ + // trace_builder + trace_builder.set(1345678991, 8, AvmMemoryTag::U32); + trace_builder.set(1234567891, 9, AvmMemoryTag::U32); + + trace_builder.sub(8, 9, 0, AvmMemoryTag::U32); + trace_builder.return_op(0, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_sub( + trace, FF(1345678991), FF(1234567891), FF(111111100), FF(8), FF(9), FF(0), AvmMemoryTag::U32); + + EXPECT_EQ(alu_row.aluChip_alu_u32_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + + // 111111100 = 0x69F6BBC + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0xBC)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0x6B)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0x69F)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u32 type with carry. +// For a subtraction a - b = c, there is a carry flag iff a < b (equivalent to a < c) +TEST_F(AvmMiniArithmeticTestsU32, subtractionCarry) +{ + // trace_builder + trace_builder.set(UINT32_MAX - 99, 8, AvmMemoryTag::U32); + trace_builder.set(3210987654, 9, AvmMemoryTag::U32); + + trace_builder.sub(9, 8, 0, AvmMemoryTag::U32); + trace_builder.return_op(0, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_sub( + trace, FF(3210987654LLU), FF(UINT32_MAX - 99), FF(3210987754LLU), FF(9), FF(8), FF(0), AvmMemoryTag::U32); + + EXPECT_EQ(alu_row.aluChip_alu_u32_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(1)); + + // 3210987754 = 0xBF63C8EA + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0xEA)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0xC8)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0xBF63)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(UINT16_MAX)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic multiplication over u32 type. +TEST_F(AvmMiniArithmeticTestsU32, multiplication) +{ + // trace_builder + trace_builder.set(11111, 0, AvmMemoryTag::U32); + trace_builder.set(11111, 1, AvmMemoryTag::U32); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U32); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = + common_validate_mul(trace, FF(11111), FF(11111), FF(123454321), FF(0), FF(1), FF(2), AvmMemoryTag::U32); + auto alu_row = trace.at(alu_row_index); + + EXPECT_EQ(alu_row.aluChip_alu_u32_tag, FF(1)); + + // Decomposition of integer multiplication in 8-bit and 16-bit registers + // 123454321 = 0x75BC371 + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0x71)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0xC3)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0x75B)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on multiplication over u32 type with overflow. +TEST_F(AvmMiniArithmeticTestsU32, multiplicationOverflow) +{ + // trace_builder + trace_builder.set(11 << 25, 0, AvmMemoryTag::U32); + trace_builder.set(13 << 22, 1, AvmMemoryTag::U32); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U32); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = + common_validate_mul(trace, FF(11 << 25), FF(13 << 22), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U32); + auto alu_row = trace.at(alu_row_index); + + EXPECT_EQ(alu_row.aluChip_alu_u32_tag, FF(1)); + + // Decomposition of integer multiplication in 8-bit and 16-bit registers + // 143 * 2^47 = 0 + 0 * 2^16 + 2^15 * 2^32 + 71 * 2^48 + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(32768)); // 2^15 + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(71)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +/****************************************************************************** + * Positive Tests - U64 + ******************************************************************************/ + +// Test on basic addition over u64 type. +TEST_F(AvmMiniArithmeticTestsU64, addition) +{ + uint64_t const a = 7813981340746672LLU; + uint64_t const b = 2379061066771309LLU; + uint64_t const c = 10193042407517981LLU; + + // trace_builder + trace_builder.set(a, 8, AvmMemoryTag::U64); + trace_builder.set(b, 9, AvmMemoryTag::U64); + + trace_builder.add(8, 9, 9, AvmMemoryTag::U64); + trace_builder.return_op(9, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_add(trace, FF(a), FF(b), FF(c), FF(8), FF(9), FF(9), AvmMemoryTag::U64); + + EXPECT_EQ(alu_row.aluChip_alu_u64_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + + // c in HEX: 2436849FE16F1D + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0x1D)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0x6F)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0x9FE1)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0x3684)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0x24)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic addition over u64 type with carry. +TEST_F(AvmMiniArithmeticTestsU64, additionCarry) +{ + uint64_t const a = UINT64_MAX - 77LLU; + uint64_t const b = UINT64_MAX - 123LLU; + uint64_t const c = UINT64_MAX - 201LLU; + + // trace_builder + trace_builder.set(a, 0, AvmMemoryTag::U64); + trace_builder.set(b, 1, AvmMemoryTag::U64); + + trace_builder.add(0, 1, 0, AvmMemoryTag::U64); + trace_builder.return_op(0, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_add(trace, FF(a), FF(b), FF(c), FF(0), FF(1), FF(0), AvmMemoryTag::U64); + + EXPECT_EQ(alu_row.aluChip_alu_u64_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(UINT8_MAX - 201)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(UINT8_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(UINT16_MAX)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u64 type. +TEST_F(AvmMiniArithmeticTestsU64, subtraction) +{ + uint64_t const a = 9876543210123456789LLU; + uint64_t const b = 9866543210123456789LLU; + uint64_t const c = 10000000000000000LLU; + + // trace_builder + trace_builder.set(a, 8, AvmMemoryTag::U64); + trace_builder.set(b, 9, AvmMemoryTag::U64); + + trace_builder.sub(8, 9, 9, AvmMemoryTag::U64); + trace_builder.return_op(9, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_sub(trace, FF(a), FF(b), FF(c), FF(8), FF(9), FF(9), AvmMemoryTag::U64); + + EXPECT_EQ(alu_row.aluChip_alu_u64_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + + // 10000000000000000 = 0x2386F26FC10000 + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0X6FC1)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0X86F2)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0X23)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u64 type with carry. +// For a subtraction a - b = c, there is a carry flag iff a < b (equivalent to a < c) +TEST_F(AvmMiniArithmeticTestsU64, subtractionCarry) +{ + uint64_t const a = UINT64_MAX - 77LLU; + uint64_t const b = UINT64_MAX - 2LLU; + uint64_t const c = UINT64_MAX - 74; + + // trace_builder + trace_builder.set(a, 0, AvmMemoryTag::U64); + trace_builder.set(b, 1, AvmMemoryTag::U64); + + trace_builder.sub(0, 1, 0, AvmMemoryTag::U64); + trace_builder.return_op(0, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_sub(trace, FF(a), FF(b), FF(c), FF(0), FF(1), FF(0), AvmMemoryTag::U64); + + EXPECT_EQ(alu_row.aluChip_alu_u64_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(1)); + + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(UINT8_MAX - 74)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(UINT8_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(UINT16_MAX)); + validate_trace_proof(std::move(trace)); +} + +// Test on basic multiplication over u64 type. +TEST_F(AvmMiniArithmeticTestsU64, multiplication) +{ + // trace_builder + trace_builder.set(999888777, 0, AvmMemoryTag::U64); + trace_builder.set(555444333, 1, AvmMemoryTag::U64); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U64); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = common_validate_mul( + trace, FF(999888777), FF(555444333), FF(555382554814950741LLU), FF(0), FF(1), FF(2), AvmMemoryTag::U64); + auto alu_row = trace.at(alu_row_index); + + EXPECT_EQ(alu_row.aluChip_alu_u64_tag, FF(1)); + + // Decomposition of integer multiplication in 8-bit and 16-bit registers + // 555,382,554,814,950,741 = 0x 7B5 1D7D B631 AD55 + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0x55)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0xAD)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0xB631)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0x1D7D)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0x7B5)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on multiplication over u64 type with overflow. +TEST_F(AvmMiniArithmeticTestsU64, multiplicationOverflow) +{ + uint64_t const a = UINT64_MAX; + uint64_t const b = UINT64_MAX; + // (2^64 - 1)^2 = 2^128 - 2^65 + 1 (mod. 2^64) = 1 + + // trace_builder + trace_builder.set(a, 0, AvmMemoryTag::U64); + trace_builder.set(b, 1, AvmMemoryTag::U64); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U64); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = common_validate_mul(trace, FF(a), FF(b), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U64); + auto alu_row = trace.at(alu_row_index); + + EXPECT_EQ(alu_row.aluChip_alu_u64_tag, FF(1)); + + // Decomposition of integer multiplication in 8-bit and 16-bit registers + // 2^128 - 2^65 + 1 + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(UINT16_MAX - 1)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(UINT16_MAX)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(UINT16_MAX)); + + validate_trace_proof(std::move(trace)); +} + +/****************************************************************************** + * Positive Tests - U128 + ******************************************************************************/ + +// Test on basic addition over u128 type. +TEST_F(AvmMiniArithmeticTestsU128, addition) +{ + uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; + uint128_t const b = (uint128_t{ 0x3333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; + uint128_t const c = (uint128_t{ 0x8888444466665555LLU } << 64) + uint128_t{ 0xDDDDAAAAFFFFEEEELLU }; + + // trace_builder + trace_builder.set(a, 8, AvmMemoryTag::U128); + trace_builder.set(b, 9, AvmMemoryTag::U128); + + trace_builder.add(8, 9, 9, AvmMemoryTag::U128); + trace_builder.return_op(9, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_add(trace, + FF(uint256_t::from_uint128(a)), + FF(uint256_t::from_uint128(b)), + FF(uint256_t::from_uint128(c)), + FF(8), + FF(9), + FF(9), + AvmMemoryTag::U128); + + EXPECT_EQ(alu_row.aluChip_alu_u128_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0xEE)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0xEE)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0xFFFF)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0xAAAA)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0xDDDD)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(0x5555)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(0x6666)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(0x4444)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(0x8888)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic addition over u128 type with carry. +TEST_F(AvmMiniArithmeticTestsU128, additionCarry) +{ + uint128_t const a = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 72948899 }; + uint128_t const b = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 36177344 }; + uint128_t const c = + (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 36177345 } - uint128_t{ 72948899 }; + + // trace_builder + trace_builder.set(a, 8, AvmMemoryTag::U128); + trace_builder.set(b, 9, AvmMemoryTag::U128); + + trace_builder.add(8, 9, 9, AvmMemoryTag::U128); + trace_builder.return_op(9, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_add(trace, + FF(uint256_t::from_uint128(a)), + FF(uint256_t::from_uint128(b)), + FF(uint256_t::from_uint128(c)), + FF(8), + FF(9), + FF(9), + AvmMemoryTag::U128); + + EXPECT_EQ(alu_row.aluChip_alu_u128_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0x9B)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0xDD)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0xF97E)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0xFFFF)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0xFFFF)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(0xFFFF)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(0xFFFF)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(0xFFFF)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(0xFFFF)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u128 type. +TEST_F(AvmMiniArithmeticTestsU128, subtraction) +{ + uint128_t const a = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 36177344 }; + uint128_t const b = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 72948899 }; + uint128_t const c = 36771555; // 72948899 - 36177344 + + // trace_builder + trace_builder.set(a, 8, AvmMemoryTag::U128); + trace_builder.set(b, 9, AvmMemoryTag::U128); + + trace_builder.sub(8, 9, 9, AvmMemoryTag::U128); + trace_builder.return_op(9, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_sub(trace, + FF(uint256_t::from_uint128(a)), + FF(uint256_t::from_uint128(b)), + FF(uint256_t::from_uint128(c)), + FF(8), + FF(9), + FF(9), + AvmMemoryTag::U128); + + EXPECT_EQ(alu_row.aluChip_alu_u128_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + + // 36771555 = 23116E3 + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0xE3)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0x16)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0x231)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r7, FF(0)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic subtraction over u128 type with carry. +TEST_F(AvmMiniArithmeticTestsU128, subtractionCarry) +{ + uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; + uint128_t const b = (uint128_t{ 0x3333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; + uint128_t const c = (uint128_t{ 0x2222000000003333LLU } << 64) + uint128_t{ 0x3333888855558888LLU }; + + // trace_builder + trace_builder.set(a, 8, AvmMemoryTag::U128); + trace_builder.set(b, 9, AvmMemoryTag::U128); + + trace_builder.sub(8, 9, 9, AvmMemoryTag::U128); + trace_builder.return_op(9, 1); + auto trace = trace_builder.finalize(); + + auto alu_row = common_validate_sub(trace, + FF(uint256_t::from_uint128(a)), + FF(uint256_t::from_uint128(b)), + FF(uint256_t::from_uint128(c)), + FF(8), + FF(9), + FF(9), + AvmMemoryTag::U128); + + EXPECT_EQ(alu_row.aluChip_alu_u128_tag, FF(1)); + EXPECT_EQ(alu_row.aluChip_alu_cf, FF(0)); + + EXPECT_EQ(alu_row.aluChip_alu_u8_r0, FF(0x88)); + EXPECT_EQ(alu_row.aluChip_alu_u8_r1, FF(0x88)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r0, FF(0x5555)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r1, FF(0x8888)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r2, FF(0x3333)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r3, FF(0x3333)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r4, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r5, FF(0)); + EXPECT_EQ(alu_row.aluChip_alu_u16_r6, FF(0x2222)); + + validate_trace_proof(std::move(trace)); +} + +// Test on basic multiplication over u128 type. +TEST_F(AvmMiniArithmeticTestsU128, multiplication) +{ + // trace_builder + trace_builder.set(0x38D64BF685FFBLLU, 0, AvmMemoryTag::U128); + trace_builder.set(0x1F92C762C98DFLLU, 1, AvmMemoryTag::U128); + // Integer multiplication output in HEX: 70289AEB0A7DDA0BAE60CA3A5 + FF c{ uint256_t{ 0xA7DDA0BAE60CA3A5, 0x70289AEB0, 0, 0 } }; + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U128); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = common_validate_mul( + trace, FF(0x38D64BF685FFBLLU), FF(555444333222111LLU), c, FF(0), FF(1), FF(2), AvmMemoryTag::U128); + auto alu_row_first = trace.at(alu_row_index); + + EXPECT_EQ(alu_row_first.aluChip_alu_u128_tag, FF(1)); + + // Decomposition of the first operand in 16-bit registers + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r0, FF(0x5FFB)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r1, FF(0xBF68)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r2, FF(0x8D64)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r3, FF(0x3)); + + // Decomposition of the second operand in 16-bit registers + auto alu_row_second = trace.at(alu_row_index + 1); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r0, FF(0x98DF)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r1, FF(0x762C)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r2, FF(0xF92C)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r3, FF(0x1)); + validate_trace_proof(std::move(trace)); +} + +// Test on multiplication over u128 type with overflow. +TEST_F(AvmMiniArithmeticTestsU128, multiplicationOverflow) +{ + // (2^128 - 2) * (2^128 - 4) = 2^256 - 2^130 - 2^129 + 2^3 + // The above modulo 2^128 = 8 + uint128_t const a = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX - 1 }; + uint128_t const b = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX - 3 }; + + // trace_builder + trace_builder.set(a, 0, AvmMemoryTag::U128); + trace_builder.set(b, 1, AvmMemoryTag::U128); + + trace_builder.mul(0, 1, 2, AvmMemoryTag::U128); + trace_builder.return_op(2, 1); + auto trace = trace_builder.finalize(); + + auto alu_row_index = common_validate_mul(trace, + FF{ uint256_t::from_uint128(a) }, + FF{ uint256_t::from_uint128(b) }, + FF{ 8 }, + FF(0), + FF(1), + FF(2), + AvmMemoryTag::U128); + auto alu_row_first = trace.at(alu_row_index); + + EXPECT_EQ(alu_row_first.aluChip_alu_u128_tag, FF(1)); + + // Decomposition of the first operand in 16-bit registers + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r0, FF(0xFFFE)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r1, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r2, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r3, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r4, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r5, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r6, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_first.aluChip_alu_u16_r7, FF(UINT16_MAX)); + + // Decomposition of the second operand in 16-bit registers + auto alu_row_second = trace.at(alu_row_index + 1); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r0, FF(0xFFFC)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r1, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r2, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r3, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r4, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r5, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r6, FF(UINT16_MAX)); + EXPECT_EQ(alu_row_second.aluChip_alu_u16_r7, FF(UINT16_MAX)); + + // Other registers involved in the relevant relations + // PIL relation (alu_chip.pil): a * b_l + a_l * b_h * 2^64 = (CF * 2^64 + R') * 2^128 + c + // (2^128 - 2) * (2^64 - 4) + (2^64 - 2) * (2^64 - 1) * 2^64 = + // 2 * 2^192 + (- 4 - 2 - 1) * 2^128 + (-2 + 2) * 2^64 + 8 = (2^65 - 7) * 2^128 + 8 + // Therefore, CF = 1 and R' = 2^64 - 7 + EXPECT_EQ(alu_row_first.aluChip_alu_u64_r0, FF{ UINT64_MAX - 6 }); // 2^64 - 7 + EXPECT_EQ(alu_row_first.aluChip_alu_cf, FF(1)); + + validate_trace_proof(std::move(trace)); +} + /****************************************************************************** * * NEGATIVE TESTS - Finite Field Type @@ -277,7 +1362,7 @@ TEST_F(AvmMiniArithmeticTests, arithmeticFFWithError) * and division by having dedicated unit test for each of them. * A typical pattern is to wrongly mutate the result of the operation. The memory trace * is consistently adapted so that the negative test is applying to the relation - * if the arithmetic operation and not the layout of the memory trace. + * of the arithmetic operation and not the layout of the memory trace. * * Finding the row pertaining to the arithmetic operation is done through * a scan of all rows and stopping at the first one with the corresponding @@ -285,58 +1370,39 @@ TEST_F(AvmMiniArithmeticTests, arithmeticFFWithError) * will still correctly work along the development of the AVM. ******************************************************************************/ +/****************************************************************************** + * Negative Tests - FF + ******************************************************************************/ + // Test on basic incorrect addition over finite field type. -TEST_F(AvmMiniArithmeticNegativeTests, additionFF) +TEST_F(AvmMiniArithmeticNegativeTestsFF, addition) { - trace_builder.call_data_copy(0, 3, 0, std::vector{ 37, 4, 11 }); - - // Memory layout: [37,4,11,0,0,0,....] - trace_builder.add(0, 1, 4, AvmMemoryTag::ff); // [37,4,11,0,41,0,....] - auto trace = trace_builder.finalize(); - - auto select_row = [](Row r) { return r.avmMini_sel_op_add == FF(1); }; - mutate_ic_in_trace(trace, std::move(select_row), FF(40)); - - EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "SUBOP_ADDITION_FF"); + auto trace = gen_mutated_trace_add(FF(37), FF(4), FF(40), AvmMemoryTag::FF); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_1"); } // Test on basic incorrect subtraction over finite field type. -TEST_F(AvmMiniArithmeticNegativeTests, subtractionFF) +TEST_F(AvmMiniArithmeticNegativeTestsFF, subtraction) { - trace_builder.call_data_copy(0, 3, 0, std::vector{ 8, 4, 17 }); - - // Memory layout: [8,4,17,0,0,0,....] - trace_builder.sub(2, 0, 1, AvmMemoryTag::ff); // [8,9,17,0,0,0....] - auto trace = trace_builder.finalize(); - - auto select_row = [](Row r) { return r.avmMini_sel_op_sub == FF(1); }; - mutate_ic_in_trace(trace, std::move(select_row), FF(-9)); - - EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "SUBOP_SUBTRACTION_FF"); + auto trace = gen_mutated_trace_sub(FF(17), FF(8), FF(-9), AvmMemoryTag::FF); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_1"); } // Test on basic incorrect multiplication over finite field type. -TEST_F(AvmMiniArithmeticNegativeTests, multiplicationFF) +TEST_F(AvmMiniArithmeticNegativeTestsFF, multiplication) { - trace_builder.call_data_copy(0, 3, 0, std::vector{ 5, 0, 20 }); - - // Memory layout: [5,0,20,0,0,0,....] - trace_builder.mul(2, 0, 1, AvmMemoryTag::ff); // [5,100,20,0,0,0....] - auto trace = trace_builder.finalize(); - - auto select_row = [](Row r) { return r.avmMini_sel_op_mul == FF(1); }; - mutate_ic_in_trace(trace, std::move(select_row), FF(1000)); - - EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "SUBOP_MULTIPLICATION_FF"); + auto trace = gen_mutated_trace_mul(FF(9), FF(100), FF(9000000), AvmMemoryTag::FF); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_MULTIPLICATION_FF"); } // Test on basic incorrect division over finite field type. -TEST_F(AvmMiniArithmeticNegativeTests, divisionFF) +TEST_F(AvmMiniArithmeticNegativeTestsFF, divisionFF) { trace_builder.call_data_copy(0, 2, 0, std::vector{ 15, 315 }); // Memory layout: [15,315,0,0,0,0,....] - trace_builder.div(1, 0, 2, AvmMemoryTag::ff); // [15,315,21,0,0,0....] + trace_builder.div(1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] + trace_builder.halt(); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.avmMini_sel_op_div == FF(1); }; @@ -347,12 +1413,13 @@ TEST_F(AvmMiniArithmeticNegativeTests, divisionFF) // Test where division is not by zero but an operation error is wrongly raised // in the trace. -TEST_F(AvmMiniArithmeticNegativeTests, divisionNoZeroButErrorFF) +TEST_F(AvmMiniArithmeticNegativeTestsFF, divisionNoZeroButError) { trace_builder.call_data_copy(0, 2, 0, std::vector{ 15, 315 }); // Memory layout: [15,315,0,0,0,0,....] - trace_builder.div(1, 0, 2, AvmMemoryTag::ff); // [15,315,21,0,0,0....] + trace_builder.div(1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the first row enabling the division selector @@ -372,12 +1439,12 @@ TEST_F(AvmMiniArithmeticNegativeTests, divisionNoZeroButErrorFF) } // Test with division by zero occurs and no error is raised (remove error flag) -TEST_F(AvmMiniArithmeticNegativeTests, divisionByZeroNoErrorFF) +TEST_F(AvmMiniArithmeticNegativeTestsFF, divisionByZeroNoError) { trace_builder.call_data_copy(0, 1, 0, std::vector{ 15 }); // Memory layout: [15,0,0,0,0,0,....] - trace_builder.div(0, 1, 2, AvmMemoryTag::ff); // [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(); @@ -391,10 +1458,11 @@ TEST_F(AvmMiniArithmeticNegativeTests, divisionByZeroNoErrorFF) } // Test with division of zero by zero occurs and no error is raised (remove error flag) -TEST_F(AvmMiniArithmeticNegativeTests, divisionZeroByZeroNoErrorFF) +TEST_F(AvmMiniArithmeticNegativeTestsFF, divisionZeroByZeroNoError) { // Memory layout: [0,0,0,0,0,0,....] - trace_builder.div(0, 1, 2, AvmMemoryTag::ff); // [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 @@ -408,13 +1476,14 @@ TEST_F(AvmMiniArithmeticNegativeTests, divisionZeroByZeroNoErrorFF) // Test that error flag cannot be raised for a non-relevant operation such as // the addition, subtraction, multiplication. -TEST_F(AvmMiniArithmeticNegativeTests, operationWithErrorFlagFF) +TEST_F(AvmMiniArithmeticNegativeTestsFF, operationWithErrorFlag) { trace_builder.call_data_copy(0, 3, 0, std::vector{ 37, 4, 11 }); // Memory layout: [37,4,11,0,0,0,....] - trace_builder.add(0, 1, 4, AvmMemoryTag::ff); // [37,4,11,0,41,0,....] + trace_builder.add(0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] trace_builder.return_op(0, 5); + trace_builder.halt(); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -430,7 +1499,7 @@ TEST_F(AvmMiniArithmeticNegativeTests, operationWithErrorFlagFF) trace_builder.call_data_copy(0, 3, 0, std::vector{ 8, 4, 17 }); // Memory layout: [8,4,17,0,0,0,....] - trace_builder.sub(2, 0, 1, AvmMemoryTag::ff); // [8,9,17,0,0,0....] + trace_builder.sub(2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] trace_builder.return_op(0, 3); trace = trace_builder.finalize(); @@ -447,7 +1516,7 @@ TEST_F(AvmMiniArithmeticNegativeTests, operationWithErrorFlagFF) trace_builder.call_data_copy(0, 3, 0, std::vector{ 5, 0, 20 }); // Memory layout: [5,0,20,0,0,0,....] - trace_builder.mul(2, 0, 1, AvmMemoryTag::ff); // [5,100,20,0,0,0....] + trace_builder.mul(2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] trace_builder.return_op(0, 3); trace = trace_builder.finalize(); @@ -460,4 +1529,153 @@ TEST_F(AvmMiniArithmeticNegativeTests, operationWithErrorFlagFF) EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "SUBOP_ERROR_RELEVANT_OP"); } +/****************************************************************************** + * Negative Tests - U8 + ******************************************************************************/ + +// Test on basic incorrect addition over U8. +TEST_F(AvmMiniArithmeticNegativeTestsU8, addition) +{ + auto trace = gen_mutated_trace_add(FF(234), FF(22), FF(1), AvmMemoryTag::U8); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect subtraction over U8. +TEST_F(AvmMiniArithmeticNegativeTestsU8, subtraction) +{ + auto trace = gen_mutated_trace_sub(FF(100), FF(104), FF(253), AvmMemoryTag::U8); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect multiplication over U8. +TEST_F(AvmMiniArithmeticNegativeTestsU8, multiplication) +{ + auto trace = gen_mutated_trace_mul(FF(9), FF(100), FF(55), AvmMemoryTag::U8); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_MUL_COMMON_2"); +} + +/****************************************************************************** + * Negative Tests - U16 + ******************************************************************************/ + +// Test on basic incorrect addition over U16. +TEST_F(AvmMiniArithmeticNegativeTestsU16, addition) +{ + auto trace = gen_mutated_trace_add(FF(8234), FF(7428), FF(653), AvmMemoryTag::U16); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect subtraction over U16. +TEST_F(AvmMiniArithmeticNegativeTestsU16, subtraction) +{ + auto trace = gen_mutated_trace_sub(FF(100), FF(932), FF(25373), AvmMemoryTag::U16); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect multiplication over U16. +TEST_F(AvmMiniArithmeticNegativeTestsU16, multiplication) +{ + auto trace = gen_mutated_trace_mul(FF(8096), FF(1024), FF(1), AvmMemoryTag::U16); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_MUL_COMMON_2"); +} + +/****************************************************************************** + * Negative Tests - U32 + ******************************************************************************/ + +// Test on basic incorrect addition over U32. +TEST_F(AvmMiniArithmeticNegativeTestsU32, addition) +{ + auto trace = gen_mutated_trace_add(FF(1972382341), FF(1111133221), FF(1222222222), AvmMemoryTag::U32); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect subtraction over U32. +TEST_F(AvmMiniArithmeticNegativeTestsU32, subtraction) +{ + auto trace = gen_mutated_trace_sub(FF(3999888777LLU), FF(UINT32_MAX), FF(2537332433LLU), AvmMemoryTag::U32); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect multiplication over U32. +TEST_F(AvmMiniArithmeticNegativeTestsU32, multiplication) +{ + auto trace = gen_mutated_trace_mul(FF(UINT32_MAX), FF(UINT32_MAX), FF(0), AvmMemoryTag::U32); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_MUL_COMMON_2"); +} + +/****************************************************************************** + * Negative Tests - U64 + ******************************************************************************/ + +// Test on basic incorrect addition over U64. +TEST_F(AvmMiniArithmeticNegativeTestsU64, addition) +{ + auto trace = gen_mutated_trace_add( + FF(3324236423198282341LLU), FF(999999991111133221LLU), FF(1222222222236LLU), AvmMemoryTag::U64); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect subtraction over U64. +TEST_F(AvmMiniArithmeticNegativeTestsU64, subtraction) +{ + auto trace = + gen_mutated_trace_sub(FF(399988877723434LLU), FF(UINT64_MAX), FF(25373324332342LLU), AvmMemoryTag::U64); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect multiplication over U64. +TEST_F(AvmMiniArithmeticNegativeTestsU64, multiplication) +{ + auto trace = + gen_mutated_trace_mul(FF(399988877723434LLU), FF(9998887772343LLU), FF(9283674827534LLU), AvmMemoryTag::U64); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_MUL_COMMON_2"); +} + +/****************************************************************************** + * Negative Tests - U128 + ******************************************************************************/ + +// Test on basic incorrect addition over U128. +TEST_F(AvmMiniArithmeticNegativeTestsU128, addition) +{ + uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; + uint128_t const b = (uint128_t{ 0x3333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; + uint128_t const c = (uint128_t{ 0x8888444466665555LLU } << 64) + uint128_t{ 0xDDDDAAAAFFFFEEEFLLU }; + + auto trace = gen_mutated_trace_add(FF{ uint256_t::from_uint128(a) }, + FF{ uint256_t::from_uint128(b) }, + FF{ uint256_t::from_uint128(c) }, + AvmMemoryTag::U128); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect subtraction over U128. +TEST_F(AvmMiniArithmeticNegativeTestsU128, subtraction) +{ + uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; + uint128_t const b = (uint128_t{ 0x7333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; + uint128_t const c = (uint128_t{ 0x8888444466665555LLU } << 64) + uint128_t{ 0xDDDDALLU }; + + auto trace = gen_mutated_trace_sub(FF{ uint256_t::from_uint128(a) }, + FF{ uint256_t::from_uint128(b) }, + FF{ uint256_t::from_uint128(c) }, + AvmMemoryTag::U128); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_ADD_SUB_2"); +} + +// Test on basic incorrect multiplication over U128. +TEST_F(AvmMiniArithmeticNegativeTestsU128, multiplication) +{ + uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; + uint128_t const b = (uint128_t{ 0x7333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; + uint128_t const c = (uint128_t{ 0x8888444466665555LLU } << 64) + uint128_t{ 0xDDDDALLU }; + + auto trace = gen_mutated_trace_mul(FF{ uint256_t::from_uint128(a) }, + FF{ uint256_t::from_uint128(b) }, + FF{ uint256_t::from_uint128(c) }, + AvmMemoryTag::U128); + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "ALU_MULTIPLICATION_OUT_U128"); +} + } // namespace tests_avm \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_common.test.hpp b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_common.test.hpp new file mode 100644 index 00000000000..4d7154552af --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_common.test.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "barretenberg/vm/avm_trace/AvmMini_helper.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 \ No newline at end of file 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 index eba7e312f21..b1712c08b81 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_control_flow.test.cpp @@ -1,14 +1,4 @@ -#include "barretenberg/vm/avm_trace/AvmMini_helper.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 +#include "AvmMini_common.test.hpp" namespace tests_avm { using namespace avm_trace; 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 79a3b03c96a..0f709e6ba20 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/AvmMini_memory.test.cpp @@ -1,14 +1,4 @@ -#include "barretenberg/vm/avm_trace/AvmMini_helper.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 +#include "AvmMini_common.test.hpp" namespace tests_avm { using namespace avm_trace; @@ -45,7 +35,7 @@ TEST_F(AvmMiniMemoryTests, mismatchedTag) { trace_builder.call_data_copy(0, 2, 0, std::vector{ 98, 12 }); - trace_builder.add(0, 1, 4, AvmMemoryTag::u8); + trace_builder.add(0, 1, 4, AvmMemoryTag::U8); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -69,8 +59,8 @@ TEST_F(AvmMiniMemoryTests, mismatchedTag) EXPECT_TRUE(row != trace.end()); EXPECT_EQ(row->memTrace_m_tag_err, FF(1)); // Error is raised - EXPECT_EQ(row->memTrace_m_in_tag, FF(static_cast(AvmMemoryTag::u8))); - EXPECT_EQ(row->memTrace_m_tag, FF(static_cast(AvmMemoryTag::ff))); + EXPECT_EQ(row->memTrace_m_in_tag, FF(static_cast(AvmMemoryTag::U8))); + EXPECT_EQ(row->memTrace_m_tag, FF(static_cast(AvmMemoryTag::FF))); // Find the memory trace position corresponding to the add sub-operation of register ib. row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { @@ -80,8 +70,8 @@ TEST_F(AvmMiniMemoryTests, mismatchedTag) EXPECT_TRUE(row != trace.end()); EXPECT_EQ(row->memTrace_m_tag_err, FF(1)); // Error is raised - EXPECT_EQ(row->memTrace_m_in_tag, FF(static_cast(AvmMemoryTag::u8))); - EXPECT_EQ(row->memTrace_m_tag, FF(static_cast(AvmMemoryTag::ff))); + EXPECT_EQ(row->memTrace_m_in_tag, FF(static_cast(AvmMemoryTag::U8))); + EXPECT_EQ(row->memTrace_m_tag, FF(static_cast(AvmMemoryTag::FF))); validate_trace_proof(std::move(trace)); } @@ -93,7 +83,7 @@ TEST_F(AvmMiniMemoryTests, mLastAccessViolation) trace_builder.call_data_copy(0, 2, 0, std::vector{ 4, 9 }); // Memory layout: [4,9,0,0,0,0,....] - trace_builder.sub(1, 0, 2, AvmMemoryTag::u8); // [4,9,5,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(); @@ -123,7 +113,7 @@ TEST_F(AvmMiniMemoryTests, readWriteConsistencyValViolation) trace_builder.call_data_copy(0, 2, 0, std::vector{ 4, 9 }); // Memory layout: [4,9,0,0,0,0,....] - trace_builder.mul(1, 0, 2, AvmMemoryTag::u8); // [4,9,36,0,0,0.....] + trace_builder.mul(1, 0, 2, AvmMemoryTag::U8); // [4,9,36,0,0,0.....] trace_builder.return_op(2, 1); // Return single memory word at position 2 (36) auto trace = trace_builder.finalize(); @@ -153,7 +143,7 @@ TEST_F(AvmMiniMemoryTests, readWriteConsistencyTagViolation) trace_builder.call_data_copy(0, 2, 0, std::vector{ 4, 9 }); // Memory layout: [4,9,0,0,0,0,....] - trace_builder.mul(1, 0, 2, AvmMemoryTag::u8); // [4,9,36,0,0,0.....] + trace_builder.mul(1, 0, 2, AvmMemoryTag::U8); // [4,9,36,0,0,0.....] trace_builder.return_op(2, 1); // Return single memory word at position 2 (36) auto trace = trace_builder.finalize(); @@ -171,7 +161,7 @@ TEST_F(AvmMiniMemoryTests, readWriteConsistencyTagViolation) EXPECT_TRUE(row != trace.end()); - row->memTrace_m_tag = static_cast(AvmMemoryTag::u16); + row->memTrace_m_tag = static_cast(AvmMemoryTag::U16); EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "MEM_READ_WRITE_TAG_CONSISTENCY"); } @@ -193,7 +183,7 @@ TEST_F(AvmMiniMemoryTests, mismatchedTagErrorViolation) { trace_builder.call_data_copy(0, 2, 0, std::vector{ 98, 12 }); - trace_builder.sub(0, 1, 4, AvmMemoryTag::u8); + trace_builder.sub(0, 1, 4, AvmMemoryTag::U8); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -227,7 +217,7 @@ TEST_F(AvmMiniMemoryTests, consistentTagNoErrorViolation) { trace_builder.call_data_copy(0, 2, 0, std::vector{ 84, 7 }); - trace_builder.div(0, 1, 4, AvmMemoryTag::ff); + trace_builder.div(0, 1, 4, AvmMemoryTag::FF); trace_builder.halt(); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp index 8257b93eec8..8948c17d18b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp @@ -1,9 +1,4 @@ -#include "helpers.test.hpp" -#include "barretenberg/vm/avm_trace/AvmMini_helper.hpp" -#include "barretenberg/vm/generated/AvmMini_composer.hpp" -#include "barretenberg/vm/generated/AvmMini_prover.hpp" -#include "barretenberg/vm/generated/AvmMini_verifier.hpp" -#include +#include "AvmMini_common.test.hpp" namespace tests_avm { using namespace avm_trace; @@ -39,8 +34,9 @@ void validate_trace_proof(std::vector&& trace) * @param trace Execution trace * @param selectRow Lambda serving to select the row in trace * @param newValue The value that will be written in intermediate register Ic at the selected row. + * @param alu A boolean telling whether we mutate the ic value in alu as well. */ -void mutate_ic_in_trace(std::vector& trace, std::function&& selectRow, FF const& newValue) +void mutate_ic_in_trace(std::vector& trace, std::function&& selectRow, FF const& newValue, bool alu) { // Find the first row matching the criteria defined by selectRow auto row = std::ranges::find_if(trace.begin(), trace.end(), selectRow); @@ -51,7 +47,18 @@ void mutate_ic_in_trace(std::vector& trace, std::function&& sele // Mutate the correct result in the main trace row->avmMini_ic = newValue; - // Adapt the memory trace to be consistent with the wrongly computed addition + // Optionally mutate the corresponding ic value in alu + if (alu) { + auto const clk = row->avmMini_clk; + // Find the relevant alu trace entry. + auto alu_row = + std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.aluChip_alu_clk == clk; }); + + EXPECT_TRUE(alu_row != trace.end()); + alu_row->aluChip_alu_ic = newValue; + } + + // Adapt the memory trace to be consistent with the wrong result auto const clk = row->avmMini_clk; auto const addr = row->avmMini_mem_idx_c; diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp index 145eb171457..10debc85891 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp @@ -14,6 +14,9 @@ namespace tests_avm { void validate_trace_proof(std::vector&& trace); -void mutate_ic_in_trace(std::vector& trace, std::function&& selectRow, FF const& newValue); +void mutate_ic_in_trace(std::vector& trace, + std::function&& selectRow, + FF const& newValue, + bool alu = false); } // namespace tests_avm \ No newline at end of file