From 5f445729a9480001519c011d5042dc0a7a038276 Mon Sep 17 00:00:00 2001 From: jeanmon Date: Tue, 23 Apr 2024 14:33:57 +0000 Subject: [PATCH] 5953: FDIV opcode --- barretenberg/cpp/pil/avm/avm_main.pil | 42 +-- .../relations/generated/avm/avm_main.hpp | 242 ++++++++++-------- .../relations/generated/avm/declare_views.hpp | 1 + .../vm/avm_trace/avm_deserialization.cpp | 1 + .../vm/avm_trace/avm_execution.cpp | 11 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 24 +- .../barretenberg/vm/avm_trace/avm_trace.hpp | 4 +- .../vm/generated/avm_circuit_builder.hpp | 6 +- .../barretenberg/vm/generated/avm_flavor.hpp | 13 +- .../barretenberg/vm/generated/avm_prover.cpp | 2 + .../vm/generated/avm_verifier.cpp | 2 + .../vm/tests/avm_arithmetic.test.cpp | 99 ++++--- .../vm/tests/avm_execution.test.cpp | 13 +- .../barretenberg/vm/tests/avm_memory.test.cpp | 16 +- 14 files changed, 267 insertions(+), 209 deletions(-) diff --git a/barretenberg/cpp/pil/avm/avm_main.pil b/barretenberg/cpp/pil/avm/avm_main.pil index 74ce4b93574b..8421a871997a 100644 --- a/barretenberg/cpp/pil/avm/avm_main.pil +++ b/barretenberg/cpp/pil/avm/avm_main.pil @@ -47,6 +47,8 @@ namespace avm_main(256); pol commit sel_op_mul; // DIV pol commit sel_op_div; + // FDIV + pol commit sel_op_fdiv; // NOT pol commit sel_op_not; // EQ @@ -137,6 +139,7 @@ namespace avm_main(256); sel_op_sub * (1 - sel_op_sub) = 0; sel_op_mul * (1 - sel_op_mul) = 0; sel_op_div * (1 - sel_op_div) = 0; + sel_op_fdiv * (1 - sel_op_fdiv) = 0; sel_op_not * (1 - sel_op_not) = 0; sel_op_eq * (1 - sel_op_eq) = 0; sel_op_and * (1 - sel_op_and) = 0; @@ -188,39 +191,48 @@ namespace avm_main(256); #[OUTPUT_U8] (sel_op_eq + sel_op_lte + sel_op_lt) * (w_in_tag - 1) = 0; + //====== FDIV OPCODE CONSTRAINTS ============================================ // Relation for division over the finite field // If tag_err == 1 in a division, then ib == 0 and op_err == 1. - #[SUBOP_DIVISION_FF] - sel_op_div * (1 - op_err) * (ic * ib - ia) = 0; + #[SUBOP_FDIV] + sel_op_fdiv * (1 - op_err) * (ic * ib - ia) = 0; - // When sel_op_div == 1, we want ib == 0 <==> op_err == 1 + // When sel_op_fdiv == 1, we want ib == 0 <==> op_err == 1 // This can be achieved with the 2 following relations. // inv is an extra witness to show that we can invert ib, i.e., inv = ib^(-1) // If ib == 0, we have to set inv = 1 to satisfy the second relation, // because op_err == 1 from the first relation. - #[SUBOP_DIVISION_ZERO_ERR1] - sel_op_div * (ib * inv - 1 + op_err) = 0; - #[SUBOP_DIVISION_ZERO_ERR2] - sel_op_div * op_err * (1 - inv) = 0; + #[SUBOP_FDIV_ZERO_ERR1] + sel_op_fdiv * (ib * inv - 1 + op_err) = 0; + #[SUBOP_FDIV_ZERO_ERR2] + sel_op_fdiv * op_err * (1 - inv) = 0; + + // Enforcement that instruction tags are FF (tag constant 6). + // TODO: These 2 conditions might be removed and enforced through + // the bytecode decomposition instead. + #[SUBOP_FDIV_R_IN_TAG_FF] + sel_op_fdiv * (r_in_tag - 6) = 0; + #[SUBOP_FDIV_W_IN_TAG_FF] + sel_op_fdiv * (w_in_tag - 6) = 0; // op_err cannot be maliciously activated for a non-relevant - // operation selector, i.e., op_err == 1 ==> sel_op_div || sel_op_XXX || ... - // op_err * (sel_op_div + sel_op_XXX + ... - 1) == 0 + // operation selector, i.e., op_err == 1 ==> sel_op_fdiv || sel_op_XXX || ... + // op_err * (sel_op_fdiv + sel_op_XXX + ... - 1) == 0 // Note that the above is even a stronger constraint, as it shows // that exactly one sel_op_XXX must be true. // At this time, we have only division producing an error. #[SUBOP_ERROR_RELEVANT_OP] - op_err * (sel_op_div - 1) = 0; + op_err * (sel_op_fdiv - 1) = 0; // TODO: constraint that we stop execution at the first error (tag_err or op_err) // An error can only happen at the last sub-operation row. // OPEN/POTENTIAL OPTIMIZATION: Dedicated error per relevant operation? - // For the division, we could lower the degree from 4 to 3 - // (sel_op_div - op_div_err) * (ic * ib - ia) = 0; + // For the finite field division, we could lower the degree from 4 to 3 + // (sel_op_fdiv - op_fdiv_err) * (ic * ib - ia) = 0; // Same for the relations related to the error activation: - // (ib * inv - 1 + op_div_err) = 0 && op_err * (1 - inv) = 0 - // This works in combination with op_div_err * (sel_op_div - 1) = 0; + // (ib * inv - 1 + op_fdiv_err) = 0 && op_err * (1 - inv) = 0 + // This works in combination with op_fdiv_err * (sel_op_fdiv - 1) = 0; // Drawback is the need to paralllelize the latter. //===== CONTROL FLOW ======================================================= @@ -257,7 +269,7 @@ namespace avm_main(256); //===== CONTROL_FLOW_CONSISTENCY ============================================ pol INTERNAL_CALL_STACK_SELECTORS = (first + sel_internal_call + sel_internal_return + sel_halt); - pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_mul + sel_op_not + pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_fdiv + sel_op_mul + sel_op_not + sel_op_eq + sel_op_and + sel_op_or + sel_op_xor + sel_op_cast); // Program counter must increment if not jumping or returning diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp index 93ab5869174b..eddcc20d4bee 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp @@ -51,6 +51,7 @@ template struct Avm_mainRow { FF avm_main_sel_op_cast{}; FF avm_main_sel_op_div{}; FF avm_main_sel_op_eq{}; + FF avm_main_sel_op_fdiv{}; FF avm_main_sel_op_lt{}; FF avm_main_sel_op_lte{}; FF avm_main_sel_op_mul{}; @@ -67,52 +68,58 @@ template struct Avm_mainRow { inline std::string get_relation_label_avm_main(int index) { switch (index) { - case 35: - return "OUTPUT_U8"; - case 36: - return "SUBOP_DIVISION_FF"; + return "OUTPUT_U8"; case 37: - return "SUBOP_DIVISION_ZERO_ERR1"; + return "SUBOP_FDIV"; case 38: - return "SUBOP_DIVISION_ZERO_ERR2"; + return "SUBOP_FDIV_ZERO_ERR1"; case 39: - return "SUBOP_ERROR_RELEVANT_OP"; + return "SUBOP_FDIV_ZERO_ERR2"; + + case 40: + return "SUBOP_FDIV_R_IN_TAG_FF"; case 41: + return "SUBOP_FDIV_W_IN_TAG_FF"; + + case 42: + return "SUBOP_ERROR_RELEVANT_OP"; + + case 44: return "RETURN_POINTER_INCREMENT"; - case 47: + case 50: return "RETURN_POINTER_DECREMENT"; - case 52: + case 55: return "PC_INCREMENT"; - case 53: + case 56: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 54: + case 57: return "CMOV_CONDITION_RES_1"; - case 55: + case 58: return "CMOV_CONDITION_RES_2"; - case 58: + case 61: return "MOV_SAME_VALUE_A"; - case 59: + case 62: return "MOV_SAME_VALUE_B"; - case 60: + case 63: return "MOV_MAIN_SAME_TAG"; - case 64: + case 67: return "BIN_SEL_1"; - case 65: + case 68: return "BIN_SEL_2"; } return std::to_string(index); @@ -122,9 +129,9 @@ template class avm_mainImpl { 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, 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, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 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, 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, 3, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, }; template @@ -170,7 +177,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = (avm_main_sel_op_not * (-avm_main_sel_op_not + FF(1))); + auto tmp = (avm_main_sel_op_fdiv * (-avm_main_sel_op_fdiv + FF(1))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -178,7 +185,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (avm_main_sel_op_eq * (-avm_main_sel_op_eq + FF(1))); + auto tmp = (avm_main_sel_op_not * (-avm_main_sel_op_not + FF(1))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -186,7 +193,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (avm_main_sel_op_and * (-avm_main_sel_op_and + FF(1))); + auto tmp = (avm_main_sel_op_eq * (-avm_main_sel_op_eq + FF(1))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -194,7 +201,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = (avm_main_sel_op_or * (-avm_main_sel_op_or + FF(1))); + auto tmp = (avm_main_sel_op_and * (-avm_main_sel_op_and + FF(1))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -202,7 +209,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (avm_main_sel_op_xor * (-avm_main_sel_op_xor + FF(1))); + auto tmp = (avm_main_sel_op_or * (-avm_main_sel_op_or + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -210,7 +217,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (avm_main_sel_op_cast * (-avm_main_sel_op_cast + FF(1))); + auto tmp = (avm_main_sel_op_xor * (-avm_main_sel_op_xor + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -218,7 +225,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = (avm_main_sel_op_lt * (-avm_main_sel_op_lt + FF(1))); + auto tmp = (avm_main_sel_op_cast * (-avm_main_sel_op_cast + FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -226,7 +233,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = (avm_main_sel_op_lte * (-avm_main_sel_op_lte + FF(1))); + auto tmp = (avm_main_sel_op_lt * (-avm_main_sel_op_lt + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -234,7 +241,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = (avm_main_sel_op_shl * (-avm_main_sel_op_shl + FF(1))); + auto tmp = (avm_main_sel_op_lte * (-avm_main_sel_op_lte + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -242,7 +249,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (avm_main_sel_op_shr * (-avm_main_sel_op_shr + FF(1))); + auto tmp = (avm_main_sel_op_shl * (-avm_main_sel_op_shl + FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -250,7 +257,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (avm_main_sel_internal_call * (-avm_main_sel_internal_call + FF(1))); + auto tmp = (avm_main_sel_op_shr * (-avm_main_sel_op_shr + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -258,7 +265,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (avm_main_sel_internal_return * (-avm_main_sel_internal_return + FF(1))); + auto tmp = (avm_main_sel_internal_call * (-avm_main_sel_internal_call + FF(1))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -266,7 +273,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = (avm_main_sel_jump * (-avm_main_sel_jump + FF(1))); + auto tmp = (avm_main_sel_internal_return * (-avm_main_sel_internal_return + FF(1))); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -274,7 +281,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = (avm_main_sel_halt * (-avm_main_sel_halt + FF(1))); + auto tmp = (avm_main_sel_jump * (-avm_main_sel_jump + FF(1))); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -282,7 +289,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(18); - auto tmp = (avm_main_sel_mov * (-avm_main_sel_mov + FF(1))); + auto tmp = (avm_main_sel_halt * (-avm_main_sel_halt + FF(1))); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -290,7 +297,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(19); - auto tmp = (avm_main_sel_cmov * (-avm_main_sel_cmov + FF(1))); + auto tmp = (avm_main_sel_mov * (-avm_main_sel_mov + FF(1))); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -298,7 +305,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = (avm_main_op_err * (-avm_main_op_err + FF(1))); + auto tmp = (avm_main_sel_cmov * (-avm_main_sel_cmov + FF(1))); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -306,7 +313,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = (avm_main_tag_err * (-avm_main_tag_err + FF(1))); + auto tmp = (avm_main_op_err * (-avm_main_op_err + FF(1))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -314,7 +321,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (avm_main_id_zero * (-avm_main_id_zero + FF(1))); + auto tmp = (avm_main_tag_err * (-avm_main_tag_err + FF(1))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -322,7 +329,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (avm_main_mem_op_a * (-avm_main_mem_op_a + FF(1))); + auto tmp = (avm_main_id_zero * (-avm_main_id_zero + FF(1))); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -330,7 +337,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = (avm_main_mem_op_b * (-avm_main_mem_op_b + FF(1))); + auto tmp = (avm_main_mem_op_a * (-avm_main_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -338,7 +345,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = (avm_main_mem_op_c * (-avm_main_mem_op_c + FF(1))); + auto tmp = (avm_main_mem_op_b * (-avm_main_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -346,7 +353,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = (avm_main_mem_op_d * (-avm_main_mem_op_d + FF(1))); + auto tmp = (avm_main_mem_op_c * (-avm_main_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -354,7 +361,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = (avm_main_rwa * (-avm_main_rwa + FF(1))); + auto tmp = (avm_main_mem_op_d * (-avm_main_mem_op_d + FF(1))); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -362,7 +369,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (avm_main_rwb * (-avm_main_rwb + FF(1))); + auto tmp = (avm_main_rwa * (-avm_main_rwa + FF(1))); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -370,7 +377,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = (avm_main_rwc * (-avm_main_rwc + FF(1))); + auto tmp = (avm_main_rwb * (-avm_main_rwb + FF(1))); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -378,7 +385,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = (avm_main_rwd * (-avm_main_rwd + FF(1))); + auto tmp = (avm_main_rwc * (-avm_main_rwc + FF(1))); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -386,7 +393,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = (avm_main_ind_op_a * (-avm_main_ind_op_a + FF(1))); + auto tmp = (avm_main_rwd * (-avm_main_rwd + FF(1))); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -394,7 +401,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = (avm_main_ind_op_b * (-avm_main_ind_op_b + FF(1))); + auto tmp = (avm_main_ind_op_a * (-avm_main_ind_op_a + FF(1))); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -402,7 +409,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(33); - auto tmp = (avm_main_ind_op_c * (-avm_main_ind_op_c + FF(1))); + auto tmp = (avm_main_ind_op_b * (-avm_main_ind_op_b + FF(1))); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -410,7 +417,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = (avm_main_ind_op_d * (-avm_main_ind_op_d + FF(1))); + auto tmp = (avm_main_ind_op_c * (-avm_main_ind_op_c + FF(1))); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -418,8 +425,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = - (((avm_main_sel_op_eq + avm_main_sel_op_lte) + avm_main_sel_op_lt) * (avm_main_w_in_tag - FF(1))); + auto tmp = (avm_main_ind_op_d * (-avm_main_ind_op_d + FF(1))); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -428,7 +434,7 @@ template class avm_mainImpl { Avm_DECLARE_VIEWS(36); auto tmp = - ((avm_main_sel_op_div * (-avm_main_op_err + FF(1))) * ((avm_main_ic * avm_main_ib) - avm_main_ia)); + (((avm_main_sel_op_eq + avm_main_sel_op_lte) + avm_main_sel_op_lt) * (avm_main_w_in_tag - FF(1))); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -436,7 +442,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = (avm_main_sel_op_div * (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); + auto tmp = + ((avm_main_sel_op_fdiv * (-avm_main_op_err + FF(1))) * ((avm_main_ic * avm_main_ib) - avm_main_ia)); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -444,7 +451,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = ((avm_main_sel_op_div * avm_main_op_err) * (-avm_main_inv + FF(1))); + auto tmp = (avm_main_sel_op_fdiv * (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -452,7 +459,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = (avm_main_op_err * (avm_main_sel_op_div - FF(1))); + auto tmp = ((avm_main_sel_op_fdiv * avm_main_op_err) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -460,7 +467,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_op_fdiv * (avm_main_r_in_tag - FF(6))); tmp *= scaling_factor; std::get<40>(evals) += tmp; } @@ -468,8 +475,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(41); - auto tmp = (avm_main_sel_internal_call * - (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr + FF(1)))); + auto tmp = (avm_main_sel_op_fdiv * (avm_main_w_in_tag - FF(6))); tmp *= scaling_factor; std::get<41>(evals) += tmp; } @@ -477,7 +483,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); + auto tmp = (avm_main_op_err * (avm_main_sel_op_fdiv - FF(1))); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -485,7 +491,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -493,7 +499,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); + auto tmp = (avm_main_sel_internal_call * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -501,7 +508,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); + auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -509,7 +516,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); + auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -517,8 +524,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = (avm_main_sel_internal_return * - (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); + auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -526,7 +532,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); + auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -534,7 +540,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -542,7 +548,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(50); - auto tmp = (avm_main_sel_internal_return * avm_main_rwa); + auto tmp = (avm_main_sel_internal_return * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<50>(evals) += tmp; } @@ -550,7 +557,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); + auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -558,16 +565,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = - ((((-avm_main_first + FF(1)) * (-avm_main_sel_halt + FF(1))) * - (((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_div) + avm_main_sel_op_mul) + - avm_main_sel_op_not) + - avm_main_sel_op_eq) + - avm_main_sel_op_and) + - avm_main_sel_op_or) + - avm_main_sel_op_xor) + - avm_main_sel_op_cast)) * - (avm_main_pc_shift - (avm_main_pc + FF(1)))); + auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -575,10 +573,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = ((-(((avm_main_first + avm_main_sel_internal_call) + avm_main_sel_internal_return) + - avm_main_sel_halt) + - FF(1)) * - (avm_main_internal_return_ptr_shift - avm_main_internal_return_ptr)); + auto tmp = (avm_main_sel_internal_return * avm_main_rwa); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -586,7 +581,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); + auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -594,7 +589,17 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); + auto tmp = + ((((-avm_main_first + FF(1)) * (-avm_main_sel_halt + FF(1))) * + ((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_div) + avm_main_sel_op_fdiv) + + avm_main_sel_op_mul) + + avm_main_sel_op_not) + + avm_main_sel_op_eq) + + avm_main_sel_op_and) + + avm_main_sel_op_or) + + avm_main_sel_op_xor) + + avm_main_sel_op_cast)) * + (avm_main_pc_shift - (avm_main_pc + FF(1)))); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -602,7 +607,10 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = (avm_main_sel_mov_a - (avm_main_sel_mov + (avm_main_sel_cmov * (-avm_main_id_zero + FF(1))))); + auto tmp = ((-(((avm_main_first + avm_main_sel_internal_call) + avm_main_sel_internal_return) + + avm_main_sel_halt) + + FF(1)) * + (avm_main_internal_return_ptr_shift - avm_main_internal_return_ptr)); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -610,7 +618,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); + auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -618,7 +626,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); + auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -626,7 +634,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); + auto tmp = (avm_main_sel_mov_a - (avm_main_sel_mov + (avm_main_sel_cmov * (-avm_main_id_zero + FF(1))))); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -634,7 +642,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(60); - auto tmp = ((avm_main_sel_mov + avm_main_sel_cmov) * (avm_main_r_in_tag - avm_main_w_in_tag)); + auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); tmp *= scaling_factor; std::get<60>(evals) += tmp; } @@ -642,6 +650,30 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(61); + auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); + tmp *= scaling_factor; + std::get<61>(evals) += tmp; + } + // Contribution 62 + { + Avm_DECLARE_VIEWS(62); + + auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); + tmp *= scaling_factor; + std::get<62>(evals) += tmp; + } + // Contribution 63 + { + Avm_DECLARE_VIEWS(63); + + auto tmp = ((avm_main_sel_mov + avm_main_sel_cmov) * (avm_main_r_in_tag - avm_main_w_in_tag)); + tmp *= scaling_factor; + std::get<63>(evals) += tmp; + } + // Contribution 64 + { + Avm_DECLARE_VIEWS(64); + auto tmp = (avm_main_alu_sel - ((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + @@ -653,11 +685,11 @@ template class avm_mainImpl { avm_main_sel_op_cast) * (-avm_main_tag_err + FF(1)))); tmp *= scaling_factor; - std::get<61>(evals) += tmp; + std::get<64>(evals) += tmp; } - // Contribution 62 + // Contribution 65 { - Avm_DECLARE_VIEWS(62); + Avm_DECLARE_VIEWS(65); auto tmp = (((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + @@ -668,31 +700,31 @@ template class avm_mainImpl { avm_main_sel_op_shl) * (avm_main_alu_in_tag - avm_main_r_in_tag)); tmp *= scaling_factor; - std::get<62>(evals) += tmp; + std::get<65>(evals) += tmp; } - // Contribution 63 + // Contribution 66 { - Avm_DECLARE_VIEWS(63); + Avm_DECLARE_VIEWS(66); auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); tmp *= scaling_factor; - std::get<63>(evals) += tmp; + std::get<66>(evals) += tmp; } - // Contribution 64 + // Contribution 67 { - Avm_DECLARE_VIEWS(64); + Avm_DECLARE_VIEWS(67); auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); tmp *= scaling_factor; - std::get<64>(evals) += tmp; + std::get<67>(evals) += tmp; } - // Contribution 65 + // Contribution 68 { - Avm_DECLARE_VIEWS(65); + Avm_DECLARE_VIEWS(68); auto tmp = (avm_main_bin_sel - ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)); tmp *= scaling_factor; - std::get<65>(evals) += tmp; + std::get<68>(evals) += tmp; } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index 43acfc68dd1c..9dce95990423 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -137,6 +137,7 @@ [[maybe_unused]] auto avm_main_sel_op_cast = View(new_term.avm_main_sel_op_cast); \ [[maybe_unused]] auto avm_main_sel_op_div = View(new_term.avm_main_sel_op_div); \ [[maybe_unused]] auto avm_main_sel_op_eq = View(new_term.avm_main_sel_op_eq); \ + [[maybe_unused]] auto avm_main_sel_op_fdiv = View(new_term.avm_main_sel_op_fdiv); \ [[maybe_unused]] auto avm_main_sel_op_lt = View(new_term.avm_main_sel_op_lt); \ [[maybe_unused]] auto avm_main_sel_op_lte = View(new_term.avm_main_sel_op_lte); \ [[maybe_unused]] auto avm_main_sel_op_mul = View(new_term.avm_main_sel_op_mul); \ diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp index bce4188712dd..5ea815937828 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -26,6 +26,7 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::SUB, three_operand_format }, { OpCode::MUL, three_operand_format }, { OpCode::DIV, three_operand_format }, + { OpCode::FDIV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, // Compute - Comparators { OpCode::EQ, three_operand_format }, { OpCode::LT, three_operand_format }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 85c5ed9ebea1..746003beb501 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -121,12 +121,11 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::DIV: - trace_builder.op_div(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), - std::get(inst.operands.at(1))); + case OpCode::FDIV: + trace_builder.op_fdiv(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; // Compute - Comparators case OpCode::EQ: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index 8b92cfbeddcf..ff7cefbe1f88 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -272,8 +272,8 @@ void AvmTraceBuilder::op_mul( }); } -/** TODO: Implement for non finite field types - * @brief Division with direct or indirect memory access. +/** + * @brief Finite field division with direct or indirect memory access. * * @param indirect A byte encoding information about indirect/direct memory access. * @param a_offset An index in memory pointing to the first operand of the division. @@ -281,8 +281,7 @@ void AvmTraceBuilder::op_mul( * @param dst_offset An index in memory pointing to the output of the division. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_div( - uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag) +void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset) { auto clk = static_cast(main_trace.size()); @@ -290,10 +289,10 @@ void AvmTraceBuilder::op_div( bool tag_match = res.tag_match; // Reading from memory and loading into ia resp. ib. - auto read_a = - mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = - mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); + auto read_a = mem_trace_builder.read_and_load_from_memory( + clk, IntermRegister::IA, res.direct_a_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto read_b = mem_trace_builder.read_and_load_from_memory( + clk, IntermRegister::IB, res.direct_b_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); tag_match = read_a.tag_match && read_b.tag_match; // a * b^(-1) = c @@ -315,7 +314,8 @@ void AvmTraceBuilder::op_div( } // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + mem_trace_builder.write_into_memory( + clk, IntermRegister::IC, res.direct_c_offset, c, AvmMemoryTag::FF, AvmMemoryTag::FF); main_trace.push_back(Row{ .avm_main_clk = clk, @@ -338,11 +338,11 @@ void AvmTraceBuilder::op_div( .avm_main_mem_op_c = FF(1), .avm_main_op_err = tag_match ? error : FF(1), .avm_main_pc = FF(pc++), - .avm_main_r_in_tag = FF(static_cast(in_tag)), + .avm_main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .avm_main_rwc = FF(1), - .avm_main_sel_op_div = FF(1), + .avm_main_sel_op_fdiv = FF(1), .avm_main_tag_err = FF(static_cast(!tag_match)), - .avm_main_w_in_tag = FF(static_cast(in_tag)), + .avm_main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), }); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 059d2fdd6c90..d6ba959df175 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -38,8 +38,8 @@ class AvmTraceBuilder { // Multiplication with direct or indirect memory access. void op_mul(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Division with direct or indirect memory access. - void op_div(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Finite field division with direct or indirect memory access. + void op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset); // Bitwise not with direct or indirect memory access. void op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag in_tag); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index d43ce2b914bb..f7e899242591 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -188,6 +188,7 @@ template struct AvmFullRow { FF avm_main_sel_op_cast{}; FF avm_main_sel_op_div{}; FF avm_main_sel_op_eq{}; + FF avm_main_sel_op_fdiv{}; FF avm_main_sel_op_lt{}; FF avm_main_sel_op_lte{}; FF avm_main_sel_op_mul{}; @@ -334,8 +335,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 269; - static constexpr size_t num_polys = 229; + static constexpr size_t num_fixed_columns = 270; + static constexpr size_t num_polys = 230; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -486,6 +487,7 @@ class AvmCircuitBuilder { polys.avm_main_sel_op_cast[i] = rows[i].avm_main_sel_op_cast; polys.avm_main_sel_op_div[i] = rows[i].avm_main_sel_op_div; polys.avm_main_sel_op_eq[i] = rows[i].avm_main_sel_op_eq; + polys.avm_main_sel_op_fdiv[i] = rows[i].avm_main_sel_op_fdiv; polys.avm_main_sel_op_lt[i] = rows[i].avm_main_sel_op_lt; polys.avm_main_sel_op_lte[i] = rows[i].avm_main_sel_op_lte; polys.avm_main_sel_op_mul[i] = rows[i].avm_main_sel_op_mul; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index bad383523e28..1f16a50834d9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -71,11 +71,11 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 227; + static constexpr size_t NUM_WITNESS_ENTITIES = 228; 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 = 269; + static constexpr size_t NUM_ALL_ENTITIES = 270; using GrandProductRelations = std::tuple, perm_main_bin_relation, @@ -314,6 +314,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -544,6 +545,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -779,6 +781,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -1051,6 +1054,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -1323,6 +1327,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -1854,6 +1859,7 @@ class AvmFlavor { Base::avm_main_sel_op_cast = "AVM_MAIN_SEL_OP_CAST"; Base::avm_main_sel_op_div = "AVM_MAIN_SEL_OP_DIV"; Base::avm_main_sel_op_eq = "AVM_MAIN_SEL_OP_EQ"; + Base::avm_main_sel_op_fdiv = "AVM_MAIN_SEL_OP_FDIV"; Base::avm_main_sel_op_lt = "AVM_MAIN_SEL_OP_LT"; Base::avm_main_sel_op_lte = "AVM_MAIN_SEL_OP_LTE"; Base::avm_main_sel_op_mul = "AVM_MAIN_SEL_OP_MUL"; @@ -2100,6 +2106,7 @@ class AvmFlavor { Commitment avm_main_sel_op_cast; Commitment avm_main_sel_op_div; Commitment avm_main_sel_op_eq; + Commitment avm_main_sel_op_fdiv; Commitment avm_main_sel_op_lt; Commitment avm_main_sel_op_lte; Commitment avm_main_sel_op_mul; @@ -2347,6 +2354,7 @@ class AvmFlavor { avm_main_sel_op_cast = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_div = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_eq = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_sel_op_fdiv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_lt = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_lte = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_mul = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2597,6 +2605,7 @@ class AvmFlavor { serialize_to_buffer(avm_main_sel_op_cast, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_div, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_eq, Transcript::proof_data); + serialize_to_buffer(avm_main_sel_op_fdiv, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_lt, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_lte, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_mul, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index 9343f80ba627..70a86ca34148 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -193,6 +193,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_main_sel_op_cast = commitment_key->commit(key->avm_main_sel_op_cast); witness_commitments.avm_main_sel_op_div = commitment_key->commit(key->avm_main_sel_op_div); witness_commitments.avm_main_sel_op_eq = commitment_key->commit(key->avm_main_sel_op_eq); + witness_commitments.avm_main_sel_op_fdiv = commitment_key->commit(key->avm_main_sel_op_fdiv); witness_commitments.avm_main_sel_op_lt = commitment_key->commit(key->avm_main_sel_op_lt); witness_commitments.avm_main_sel_op_lte = commitment_key->commit(key->avm_main_sel_op_lte); witness_commitments.avm_main_sel_op_mul = commitment_key->commit(key->avm_main_sel_op_mul); @@ -403,6 +404,7 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.avm_main_sel_op_cast, witness_commitments.avm_main_sel_op_cast); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_div, witness_commitments.avm_main_sel_op_div); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_eq, witness_commitments.avm_main_sel_op_eq); + transcript->send_to_verifier(commitment_labels.avm_main_sel_op_fdiv, witness_commitments.avm_main_sel_op_fdiv); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_lt, witness_commitments.avm_main_sel_op_lt); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_lte, witness_commitments.avm_main_sel_op_lte); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_mul, witness_commitments.avm_main_sel_op_mul); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 5edd090d1e64..e71a0cf8833a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -264,6 +264,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_div); commitments.avm_main_sel_op_eq = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_eq); + commitments.avm_main_sel_op_fdiv = + transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_fdiv); commitments.avm_main_sel_op_lt = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_lt); commitments.avm_main_sel_op_lte = diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp index 68fb123ad3c8..8a490e4b9e3d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp @@ -398,17 +398,17 @@ TEST_F(AvmArithmeticTestsFF, multiplicationByZero) } // Test on basic division over finite field type. -TEST_F(AvmArithmeticTestsFF, division) +TEST_F(AvmArithmeticTestsFF, fDivision) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); - // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_div(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] + // Memory layout: [15,315,0,0,0,0,....] + trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] trace_builder.return_op(0, 0, 3); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(row != trace.end()); @@ -421,17 +421,17 @@ TEST_F(AvmArithmeticTestsFF, division) } // Test on division with zero numerator over finite field type. -TEST_F(AvmArithmeticTestsFF, divisionNumeratorZero) +TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) { trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); - // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_div(0, 1, 0, 0, AvmMemoryTag::FF); // [0,0,0,0,0,0....] + // Memory layout: [15,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 1, 0, 0); // [0,0,0,0,0,0....] trace_builder.return_op(0, 0, 3); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(row != trace.end()); @@ -445,17 +445,17 @@ TEST_F(AvmArithmeticTestsFF, divisionNumeratorZero) // Test on division by zero over finite field type. // We check that the operator error flag is raised. -TEST_F(AvmArithmeticTestsFF, divisionByZeroError) +TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) { trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); - // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_div(0, 0, 1, 2, AvmMemoryTag::FF); // [15,0,0,0,0,0....] + // Memory layout: [15,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(row != trace.end()); @@ -470,15 +470,15 @@ TEST_F(AvmArithmeticTestsFF, divisionByZeroError) // Test on division of zero by zero over finite field type. // We check that the operator error flag is raised. -TEST_F(AvmArithmeticTestsFF, divisionZeroByZeroError) +TEST_F(AvmArithmeticTestsFF, fDivisionZeroByZeroError) { - // Memory layout: [0,0,0,0,0,0,....] - trace_builder.op_div(0, 0, 1, 2, AvmMemoryTag::FF); // [0,0,0,0,0,0....] + // Memory layout: [0,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(row != trace.end()); @@ -506,10 +506,9 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) trace_builder.op_add(0, 5, 6, 7, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,0....] trace_builder.op_sub(0, 7, 6, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136,0....] trace_builder.op_mul(0, 8, 8, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136^2,0....] - trace_builder.op_div(0, 3, 5, 1, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] - trace_builder.op_div(0, 1, 1, 9, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] - trace_builder.op_div( - 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.op_fdiv(0, 3, 5, 1); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] + trace_builder.op_fdiv(0, 1, 1, 9); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] + trace_builder.op_fdiv(0, 9, 0, 4); // [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(); @@ -1668,34 +1667,34 @@ TEST_F(AvmArithmeticNegativeTestsFF, multiplication) } // Test on basic incorrect division over finite field type. -TEST_F(AvmArithmeticNegativeTestsFF, divisionFF) +TEST_F(AvmArithmeticNegativeTestsFF, fDivision) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); - // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_div(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] + // Memory layout: [15,315,0,0,0,0,....] + trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - auto select_row = [](Row r) { return r.avm_main_sel_op_div == FF(1); }; + auto select_row = [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }; mutate_ic_in_trace(trace, std::move(select_row), FF(0)); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_DIVISION_FF"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV"); } // Test where division is not by zero but an operation error is wrongly raised // in the trace. -TEST_F(AvmArithmeticNegativeTestsFF, divisionNoZeroButError) +TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); - // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_div(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] + // Memory layout: [15,315,0,0,0,0,....] + trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); size_t const index = static_cast(row - trace.begin()); @@ -1703,47 +1702,47 @@ TEST_F(AvmArithmeticNegativeTestsFF, divisionNoZeroButError) trace[index].avm_main_op_err = FF(1); auto trace2 = trace; - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_DIVISION_ZERO_ERR1"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV_ZERO_ERR1"); // Even more malicious, one makes the first relation passes by setting the inverse to zero. trace2[index].avm_main_inv = FF(0); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace2)), "SUBOP_DIVISION_ZERO_ERR2"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace2)), "SUBOP_FDIV_ZERO_ERR2"); } -// Test with division by zero occurs and no error is raised (remove error flag) -TEST_F(AvmArithmeticNegativeTestsFF, divisionByZeroNoError) +// Test with finite field division by zero occurs and no error is raised (remove error flag) +TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) { trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); - // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_div(0, 0, 1, 2, AvmMemoryTag::FF); // [15,0,0,0,0,0....] + // Memory layout: [15,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Remove the operator error flag row->avm_main_op_err = FF(0); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_DIVISION_FF"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV"); } -// Test with division of zero by zero occurs and no error is raised (remove error flag) -TEST_F(AvmArithmeticNegativeTestsFF, divisionZeroByZeroNoError) +// Test with finite field division of zero by zero occurs and no error is raised (remove error flag) +TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) { - // Memory layout: [0,0,0,0,0,0,....] - trace_builder.op_div(0, 0, 1, 2, AvmMemoryTag::FF); // [0,0,0,0,0,0....] + // Memory layout: [0,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Remove the operator error flag row->avm_main_op_err = FF(0); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_DIVISION_ZERO_ERR1"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV_ZERO_ERR1"); } // Test that error flag cannot be raised for a non-relevant operation such as diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index 2639e9fb979d..f7aec7b173aa 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -382,9 +382,9 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) // Positive test with JUMP and CALLDATACOPY // We test bytecode which first invoke CALLDATACOPY on a FF array of two values. -// Then, a JUMP call skips a SUB opcode to land to a DIV operation and RETURN. +// Then, a JUMP call skips a SUB opcode to land to a FDIV operation and RETURN. // Calldata: [13, 156] -// Bytecode layout: CALLDATACOPY JUMP SUB DIV RETURN +// Bytecode layout: CALLDATACOPY JUMP SUB FDIV RETURN // 0 1 2 3 4 TEST_F(AvmExecutionTests, jumpAndCalldatacopy) { @@ -394,16 +394,15 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) "00000002" // copy_size "0000000A" // dst_offset // M[10] = 13, M[11] = 156 + to_hex(OpCode::JUMP) + // opcode JUMP - "00000003" // jmp_dest (DIV located at 3) + "00000003" // jmp_dest (FDIV located at 3) + to_hex(OpCode::SUB) + // opcode SUB "00" // Indirect flag "06" // FF "0000000B" // addr 11 "0000000A" // addr 10 "00000001" // addr c 1 (If executed would be 156 - 13 = 143) - + to_hex(OpCode::DIV) + // opcode DIV + + to_hex(OpCode::FDIV) + // opcode FDIV "00" // Indirect flag - "06" // FF "0000000B" // addr 11 "0000000A" // addr 10 "00000001" // addr c 1 (156 / 13 = 12) @@ -443,8 +442,8 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) EXPECT_EQ(trace.at(i + 1).avm_main_pc, pc_sequence.at(i)); } - // Find the first row enabling the division selector. - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == 1; }); + // Find the first row enabling the fdiv selector. + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == 1; }); EXPECT_EQ(row->avm_main_ic, 12); // Find the first row enabling the subtraction selector. diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp index 0b365104e165..95c364acd052 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp @@ -258,18 +258,18 @@ TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - trace_builder.op_div(0, 0, 1, 4, AvmMemoryTag::FF); + trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); EXPECT_TRUE(row != trace.end()); auto clk = row->avm_main_clk; - // Find the memory trace position corresponding to the div sub-operation of register ia. + // Find the memory trace position corresponding to the fdiv sub-operation of register ia. row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_mem_clk == clk && r.avm_mem_sub_clk == AvmMemTraceBuilder::SUB_CLK_LOAD_A; }); @@ -284,18 +284,18 @@ TEST_F(AvmMemoryTests, noErrorTagWriteViolation) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - trace_builder.op_div(0, 0, 1, 4, AvmMemoryTag::FF); + trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); ASSERT_TRUE(row != trace.end()); auto clk = row->avm_main_clk; - // Find the memory trace position corresponding to the div sub-operation of register ic. + // Find the memory trace position corresponding to the fdiv sub-operation of register ic. row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_mem_clk == clk && r.avm_mem_sub_clk == AvmMemTraceBuilder::SUB_CLK_STORE_C; });