From 89dd25f2b25f720def6cac003ce204e92de66c47 Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Wed, 15 May 2024 14:51:38 +0100 Subject: [PATCH] feat(avm): to_radix gadget (#6368) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- barretenberg/cpp/pil/avm/avm_main.pil | 11 + .../cpp/pil/avm/gadgets/avm_conversion.pil | 21 ++ .../generated/avm/avm_conversion.hpp | 47 +++ .../relations/generated/avm/avm_main.hpp | 289 +++++++++--------- .../relations/generated/avm/declare_views.hpp | 7 + .../generated/avm/perm_main_conv.hpp | 102 +++++++ .../vm/avm_trace/avm_deserialization.cpp | 3 + .../vm/avm_trace/avm_execution.cpp | 33 +- .../vm/avm_trace/avm_execution.hpp | 3 + .../vm/avm_trace/avm_mem_trace.cpp | 2 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 174 ++++++++++- .../barretenberg/vm/avm_trace/avm_trace.hpp | 7 + .../gadgets/avm_conversion_trace.cpp | 61 ++++ .../gadgets/avm_conversion_trace.hpp | 30 ++ .../vm/generated/avm_circuit_builder.hpp | 36 ++- .../barretenberg/vm/generated/avm_flavor.hpp | 74 ++++- .../barretenberg/vm/generated/avm_prover.cpp | 17 ++ .../vm/generated/avm_verifier.cpp | 17 +- .../vm/tests/avm_execution.test.cpp | 71 +++++ 19 files changed, 848 insertions(+), 157 deletions(-) create mode 100644 barretenberg/cpp/pil/avm/gadgets/avm_conversion.pil create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_conversion.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_conv.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.hpp diff --git a/barretenberg/cpp/pil/avm/avm_main.pil b/barretenberg/cpp/pil/avm/avm_main.pil index 2ead092ce20..3fa436221c4 100644 --- a/barretenberg/cpp/pil/avm/avm_main.pil +++ b/barretenberg/cpp/pil/avm/avm_main.pil @@ -3,6 +3,7 @@ include "avm_mem.pil"; include "avm_alu.pil"; include "avm_binary.pil"; include "avm_kernel.pil"; +include "gadgets/avm_conversion.pil"; namespace avm_main(256); // Kernel lookup selector opcodes @@ -25,6 +26,9 @@ namespace avm_main(256); pol commit sel_op_coinbase; pol commit sel_op_timestamp; + //===== Gadget Selectors ====================================================== + pol commit sel_op_radix_le; + //===== CONSTANT POLYNOMIALS ================================================== pol constant clk(i) { i }; pol constant first = [1] + [0]*; // Used mostly to toggle off the first row consisting @@ -167,6 +171,8 @@ namespace avm_main(256); sel_op_fee_per_da_gas * (1 - sel_op_fee_per_da_gas) = 0; sel_op_transaction_fee * (1 - sel_op_transaction_fee) = 0; + sel_op_radix_le * (1 - sel_op_radix_le) = 0; + sel_op_add * (1 - sel_op_add) = 0; sel_op_sub * (1 - sel_op_sub) = 0; sel_op_mul * (1 - sel_op_mul) = 0; @@ -451,6 +457,11 @@ namespace avm_main(256); is avm_binary.start {avm_binary.clk, avm_binary.acc_ia, avm_binary.acc_ib, avm_binary.acc_ic, avm_binary.op_id, avm_binary.in_tag}; + #[PERM_MAIN_CONV] + sel_op_radix_le {clk, ia, ic, id} + is + avm_conversion.to_radix_le_sel {avm_conversion.clk, avm_conversion.input, avm_conversion.radix, avm_conversion.num_limbs}; + #[PERM_MAIN_MEM_A] mem_op_a {clk, mem_idx_a, ia, rwa , r_in_tag, w_in_tag, sel_mov_a, sel_cmov} diff --git a/barretenberg/cpp/pil/avm/gadgets/avm_conversion.pil b/barretenberg/cpp/pil/avm/gadgets/avm_conversion.pil new file mode 100644 index 00000000000..abd2e5c6121 --- /dev/null +++ b/barretenberg/cpp/pil/avm/gadgets/avm_conversion.pil @@ -0,0 +1,21 @@ +include "../avm_main.pil"; + +namespace avm_conversion(256); + + pol commit clk; + + // Selector for Radix Operation + pol commit to_radix_le_sel; + to_radix_le_sel * (1 - to_radix_le_sel) = 0; + + // ===== DRAFT: Planned Constraints for To Radix LE + // Similar to the binary trace; multi-row decomposition of the input using the number of limbs specified as the row count. + // (1) limb_ctr' - limb_ctr + 1 = 0; // Next row decrements the limb_ctr + // (2) Check equality to 0 of limb_ctr to terminate the operations. + // (3) An accumulation column to track the partial re-composition of the limbs + // (4) Range check each row.limb < radix + // (5) TODO: Is there a risk of over/under flow. + + pol commit input; + pol commit radix; + pol commit num_limbs; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_conversion.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_conversion.hpp new file mode 100644 index 00000000000..9ecfc59cfc4 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_conversion.hpp @@ -0,0 +1,47 @@ + +#pragma once +#include "../../relation_parameters.hpp" +#include "../../relation_types.hpp" +#include "./declare_views.hpp" + +namespace bb::Avm_vm { + +template struct Avm_conversionRow { + FF avm_conversion_to_radix_le_sel{}; +}; + +inline std::string get_relation_label_avm_conversion(int index) +{ + switch (index) {} + return std::to_string(index); +} + +template class avm_conversionImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 3, + }; + + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& new_term, + [[maybe_unused]] const RelationParameters&, + [[maybe_unused]] const FF& scaling_factor) + { + + // Contribution 0 + { + Avm_DECLARE_VIEWS(0); + + auto tmp = (avm_conversion_to_radix_le_sel * (-avm_conversion_to_radix_le_sel + FF(1))); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + } +}; + +template using avm_conversion = Relation>; + +} // namespace bb::Avm_vm \ No newline at end of file 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 d5c60d139de..724f3dedbf7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp @@ -66,6 +66,7 @@ template struct Avm_mainRow { FF avm_main_sel_op_not{}; FF avm_main_sel_op_or{}; FF avm_main_sel_op_portal{}; + FF avm_main_sel_op_radix_le{}; FF avm_main_sel_op_sender{}; FF avm_main_sel_op_shl{}; FF avm_main_sel_op_shr{}; @@ -81,94 +82,94 @@ template struct Avm_mainRow { inline std::string get_relation_label_avm_main(int index) { switch (index) { - case 47: + case 48: return "OUTPUT_U8"; - case 48: + case 49: return "SUBOP_FDIV"; - case 49: + case 50: return "SUBOP_FDIV_ZERO_ERR1"; - case 50: + case 51: return "SUBOP_FDIV_ZERO_ERR2"; - case 51: + case 52: return "SUBOP_FDIV_R_IN_TAG_FF"; - case 52: + case 53: return "SUBOP_FDIV_W_IN_TAG_FF"; - case 53: + case 54: return "SUBOP_ERROR_RELEVANT_OP"; - case 54: + case 55: return "KERNEL_ACTIVE_CHECK"; - case 56: + case 57: return "RETURN_POINTER_INCREMENT"; - case 62: + case 63: return "RETURN_POINTER_DECREMENT"; - case 67: + case 68: return "PC_INCREMENT"; - case 68: + case 69: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 69: + case 70: return "CMOV_CONDITION_RES_1"; - case 70: + case 71: return "CMOV_CONDITION_RES_2"; - case 73: + case 74: return "MOV_SAME_VALUE_A"; - case 74: + case 75: return "MOV_SAME_VALUE_B"; - case 75: + case 76: return "MOV_MAIN_SAME_TAG"; - case 79: + case 80: return "SENDER_KERNEL"; - case 80: + case 81: return "ADDRESS_KERNEL"; - case 81: + case 82: return "PORTAL_KERNEL"; - case 82: + case 83: return "FEE_DA_GAS_KERNEL"; - case 83: + case 84: return "FEE_L2_GAS_KERNEL"; - case 84: + case 85: return "FEE_TRANSACTION_FEE_KERNEL"; - case 85: + case 86: return "CHAIN_ID_KERNEL"; - case 86: + case 87: return "VERSION_KERNEL"; - case 87: + case 88: return "BLOCK_NUMBER_KERNEL"; - case 88: + case 89: return "COINBASE_KERNEL"; - case 89: + case 90: return "TIMESTAMP_KERNEL"; - case 90: + case 91: return "BIN_SEL_1"; - case 91: + case 92: return "BIN_SEL_2"; } return std::to_string(index); @@ -178,10 +179,10 @@ template class avm_mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 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, 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, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 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, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, }; template @@ -283,7 +284,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = (avm_main_sel_op_add * (-avm_main_sel_op_add + FF(1))); + auto tmp = (avm_main_sel_op_radix_le * (-avm_main_sel_op_radix_le + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -291,7 +292,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = (avm_main_sel_op_sub * (-avm_main_sel_op_sub + FF(1))); + auto tmp = (avm_main_sel_op_add * (-avm_main_sel_op_add + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -299,7 +300,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (avm_main_sel_op_mul * (-avm_main_sel_op_mul + FF(1))); + auto tmp = (avm_main_sel_op_sub * (-avm_main_sel_op_sub + FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -307,7 +308,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (avm_main_sel_op_div * (-avm_main_sel_op_div + FF(1))); + auto tmp = (avm_main_sel_op_mul * (-avm_main_sel_op_mul + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -315,7 +316,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (avm_main_sel_op_fdiv * (-avm_main_sel_op_fdiv + FF(1))); + auto tmp = (avm_main_sel_op_div * (-avm_main_sel_op_div + FF(1))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -323,7 +324,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(16); - 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<16>(evals) += tmp; } @@ -331,7 +332,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(17); - 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<17>(evals) += tmp; } @@ -339,7 +340,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(18); - 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<18>(evals) += tmp; } @@ -347,7 +348,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(19); - 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<19>(evals) += tmp; } @@ -355,7 +356,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(20); - 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<20>(evals) += tmp; } @@ -363,7 +364,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(21); - 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<21>(evals) += tmp; } @@ -371,7 +372,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(22); - 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<22>(evals) += tmp; } @@ -379,7 +380,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(23); - 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<23>(evals) += tmp; } @@ -387,7 +388,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(24); - 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<24>(evals) += tmp; } @@ -395,7 +396,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(25); - 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<25>(evals) += tmp; } @@ -403,7 +404,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(26); - 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<26>(evals) += tmp; } @@ -411,7 +412,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(27); - 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<27>(evals) += tmp; } @@ -419,7 +420,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(28); - 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<28>(evals) += tmp; } @@ -427,7 +428,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(29); - 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<29>(evals) += tmp; } @@ -435,7 +436,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(30); - 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<30>(evals) += tmp; } @@ -443,7 +444,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(31); - 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<31>(evals) += tmp; } @@ -451,7 +452,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(32); - 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<32>(evals) += tmp; } @@ -459,7 +460,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(33); - 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<33>(evals) += tmp; } @@ -467,7 +468,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(34); - 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<34>(evals) += tmp; } @@ -475,7 +476,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(35); - 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<35>(evals) += tmp; } @@ -483,7 +484,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(36); - 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<36>(evals) += tmp; } @@ -491,7 +492,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(37); - 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<37>(evals) += tmp; } @@ -499,7 +500,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(38); - 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<38>(evals) += tmp; } @@ -507,7 +508,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(39); - 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<39>(evals) += tmp; } @@ -515,7 +516,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(40); - 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<40>(evals) += tmp; } @@ -523,7 +524,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(41); - 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<41>(evals) += tmp; } @@ -531,7 +532,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(42); - 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<42>(evals) += tmp; } @@ -539,7 +540,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(43); - 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<43>(evals) += tmp; } @@ -547,7 +548,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(44); - 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<44>(evals) += tmp; } @@ -555,7 +556,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(45); - 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<45>(evals) += tmp; } @@ -563,7 +564,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(46); - 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<46>(evals) += tmp; } @@ -571,8 +572,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(47); - 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<47>(evals) += tmp; } @@ -581,7 +581,7 @@ template class avm_mainImpl { Avm_DECLARE_VIEWS(48); auto tmp = - ((avm_main_sel_op_fdiv * (-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<48>(evals) += tmp; } @@ -589,8 +589,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = ((avm_main_sel_op_fdiv + 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<49>(evals) += tmp; } @@ -598,7 +598,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(50); - auto tmp = (((avm_main_sel_op_fdiv + avm_main_sel_op_div) * avm_main_op_err) * (-avm_main_inv + FF(1))); + auto tmp = ((avm_main_sel_op_fdiv + avm_main_sel_op_div) * + (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); tmp *= scaling_factor; std::get<50>(evals) += tmp; } @@ -606,7 +607,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = (avm_main_sel_op_fdiv * (avm_main_r_in_tag - FF(6))); + auto tmp = (((avm_main_sel_op_fdiv + avm_main_sel_op_div) * avm_main_op_err) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -614,7 +615,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = (avm_main_sel_op_fdiv * (avm_main_w_in_tag - FF(6))); + auto tmp = (avm_main_sel_op_fdiv * (avm_main_r_in_tag - FF(6))); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -622,7 +623,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = (avm_main_op_err * ((avm_main_sel_op_fdiv + avm_main_sel_op_div) - FF(1))); + auto tmp = (avm_main_sel_op_fdiv * (avm_main_w_in_tag - FF(6))); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -630,6 +631,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(54); + auto tmp = (avm_main_op_err * ((avm_main_sel_op_fdiv + avm_main_sel_op_div) - FF(1))); + tmp *= scaling_factor; + std::get<54>(evals) += tmp; + } + // Contribution 55 + { + Avm_DECLARE_VIEWS(55); + auto tmp = (((((((((((avm_main_sel_op_sender + avm_main_sel_op_address) + avm_main_sel_op_portal) + avm_main_sel_op_chain_id) + avm_main_sel_op_version) + @@ -641,22 +650,13 @@ template class avm_mainImpl { avm_main_sel_op_transaction_fee) * (-avm_main_q_kernel_lookup + FF(1))); tmp *= scaling_factor; - std::get<54>(evals) += tmp; - } - // Contribution 55 - { - Avm_DECLARE_VIEWS(55); - - auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); - tmp *= scaling_factor; std::get<55>(evals) += tmp; } // Contribution 56 { Avm_DECLARE_VIEWS(56); - 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_jump * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -664,7 +664,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); + 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<57>(evals) += tmp; } @@ -672,7 +673,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -680,7 +681,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); + auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -688,7 +689,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(60); - auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); + auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); tmp *= scaling_factor; std::get<60>(evals) += tmp; } @@ -696,7 +697,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(61); - auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); + auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); tmp *= scaling_factor; std::get<61>(evals) += tmp; } @@ -704,8 +705,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(62); - 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_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<62>(evals) += tmp; } @@ -713,7 +713,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(63); - 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_return * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<63>(evals) += tmp; } @@ -721,7 +722,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(64); - auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); tmp *= scaling_factor; std::get<64>(evals) += tmp; } @@ -729,7 +730,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(65); - auto tmp = (avm_main_sel_internal_return * avm_main_rwa); + auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<65>(evals) += tmp; } @@ -737,7 +738,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(66); - auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); + auto tmp = (avm_main_sel_internal_return * avm_main_rwa); tmp *= scaling_factor; std::get<66>(evals) += tmp; } @@ -745,6 +746,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(67); + auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); + tmp *= scaling_factor; + std::get<67>(evals) += tmp; + } + // Contribution 68 + { + Avm_DECLARE_VIEWS(68); + 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) + @@ -766,32 +775,24 @@ template class avm_mainImpl { avm_main_sel_op_transaction_fee))) * (avm_main_pc_shift - (avm_main_pc + FF(1)))); tmp *= scaling_factor; - std::get<67>(evals) += tmp; + std::get<68>(evals) += tmp; } - // Contribution 68 + // Contribution 69 { - Avm_DECLARE_VIEWS(68); + Avm_DECLARE_VIEWS(69); 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<68>(evals) += tmp; - } - // Contribution 69 - { - Avm_DECLARE_VIEWS(69); - - auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); - tmp *= scaling_factor; std::get<69>(evals) += tmp; } // Contribution 70 { Avm_DECLARE_VIEWS(70); - auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); + auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); tmp *= scaling_factor; std::get<70>(evals) += tmp; } @@ -799,7 +800,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(71); - 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_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<71>(evals) += tmp; } @@ -807,7 +808,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(72); - auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); + 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<72>(evals) += tmp; } @@ -815,7 +816,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(73); - auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); + auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); tmp *= scaling_factor; std::get<73>(evals) += tmp; } @@ -823,7 +824,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(74); - auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); + auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); tmp *= scaling_factor; std::get<74>(evals) += tmp; } @@ -831,7 +832,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(75); - 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_ib - avm_main_ic)); tmp *= scaling_factor; std::get<75>(evals) += tmp; } @@ -839,6 +840,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(76); + 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<76>(evals) += tmp; + } + // Contribution 77 + { + Avm_DECLARE_VIEWS(77); + 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_div) + @@ -852,11 +861,11 @@ template class avm_mainImpl { (-avm_main_tag_err + FF(1))) * (-avm_main_op_err + FF(1)))); tmp *= scaling_factor; - std::get<76>(evals) += tmp; + std::get<77>(evals) += tmp; } - // Contribution 77 + // Contribution 78 { - Avm_DECLARE_VIEWS(77); + Avm_DECLARE_VIEWS(78); auto tmp = ((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_div) + @@ -868,21 +877,13 @@ template class avm_mainImpl { avm_main_sel_op_shl) * (avm_main_alu_in_tag - avm_main_r_in_tag)); tmp *= scaling_factor; - std::get<77>(evals) += tmp; - } - // Contribution 78 - { - Avm_DECLARE_VIEWS(78); - - auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); - tmp *= scaling_factor; std::get<78>(evals) += tmp; } // Contribution 79 { Avm_DECLARE_VIEWS(79); - auto tmp = (avm_main_sel_op_sender * (avm_kernel_kernel_sel - FF(0))); + auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); tmp *= scaling_factor; std::get<79>(evals) += tmp; } @@ -890,7 +891,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(80); - auto tmp = (avm_main_sel_op_address * (avm_kernel_kernel_sel - FF(1))); + auto tmp = (avm_main_sel_op_sender * (avm_kernel_kernel_sel - FF(0))); tmp *= scaling_factor; std::get<80>(evals) += tmp; } @@ -898,7 +899,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(81); - auto tmp = (avm_main_sel_op_portal * (avm_kernel_kernel_sel - FF(2))); + auto tmp = (avm_main_sel_op_address * (avm_kernel_kernel_sel - FF(1))); tmp *= scaling_factor; std::get<81>(evals) += tmp; } @@ -906,7 +907,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(82); - auto tmp = (avm_main_sel_op_fee_per_da_gas * (avm_kernel_kernel_sel - FF(37))); + auto tmp = (avm_main_sel_op_portal * (avm_kernel_kernel_sel - FF(2))); tmp *= scaling_factor; std::get<82>(evals) += tmp; } @@ -914,7 +915,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(83); - auto tmp = (avm_main_sel_op_fee_per_l2_gas * (avm_kernel_kernel_sel - FF(38))); + auto tmp = (avm_main_sel_op_fee_per_da_gas * (avm_kernel_kernel_sel - FF(37))); tmp *= scaling_factor; std::get<83>(evals) += tmp; } @@ -922,7 +923,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(84); - auto tmp = (avm_main_sel_op_transaction_fee * (avm_kernel_kernel_sel - FF(39))); + auto tmp = (avm_main_sel_op_fee_per_l2_gas * (avm_kernel_kernel_sel - FF(38))); tmp *= scaling_factor; std::get<84>(evals) += tmp; } @@ -930,7 +931,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(85); - auto tmp = (avm_main_sel_op_chain_id * (avm_kernel_kernel_sel - FF(28))); + auto tmp = (avm_main_sel_op_transaction_fee * (avm_kernel_kernel_sel - FF(39))); tmp *= scaling_factor; std::get<85>(evals) += tmp; } @@ -938,7 +939,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(86); - auto tmp = (avm_main_sel_op_version * (avm_kernel_kernel_sel - FF(29))); + auto tmp = (avm_main_sel_op_chain_id * (avm_kernel_kernel_sel - FF(28))); tmp *= scaling_factor; std::get<86>(evals) += tmp; } @@ -946,7 +947,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(87); - auto tmp = (avm_main_sel_op_block_number * (avm_kernel_kernel_sel - FF(30))); + auto tmp = (avm_main_sel_op_version * (avm_kernel_kernel_sel - FF(29))); tmp *= scaling_factor; std::get<87>(evals) += tmp; } @@ -954,7 +955,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(88); - auto tmp = (avm_main_sel_op_coinbase * (avm_kernel_kernel_sel - FF(32))); + auto tmp = (avm_main_sel_op_block_number * (avm_kernel_kernel_sel - FF(30))); tmp *= scaling_factor; std::get<88>(evals) += tmp; } @@ -962,7 +963,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(89); - auto tmp = (avm_main_sel_op_timestamp * (avm_kernel_kernel_sel - FF(31))); + auto tmp = (avm_main_sel_op_coinbase * (avm_kernel_kernel_sel - FF(32))); tmp *= scaling_factor; std::get<89>(evals) += tmp; } @@ -970,7 +971,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(90); - auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); + auto tmp = (avm_main_sel_op_timestamp * (avm_kernel_kernel_sel - FF(31))); tmp *= scaling_factor; std::get<90>(evals) += tmp; } @@ -978,10 +979,18 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(91); - auto tmp = (avm_main_bin_sel - ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)); + auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); tmp *= scaling_factor; std::get<91>(evals) += tmp; } + // Contribution 92 + { + Avm_DECLARE_VIEWS(92); + + 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<92>(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 04ed0e23448..bdcee9c8c63 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -107,6 +107,11 @@ [[maybe_unused]] auto avm_byte_lookup_table_input_b = View(new_term.avm_byte_lookup_table_input_b); \ [[maybe_unused]] auto avm_byte_lookup_table_op_id = View(new_term.avm_byte_lookup_table_op_id); \ [[maybe_unused]] auto avm_byte_lookup_table_output = View(new_term.avm_byte_lookup_table_output); \ + [[maybe_unused]] auto avm_conversion_clk = View(new_term.avm_conversion_clk); \ + [[maybe_unused]] auto avm_conversion_input = View(new_term.avm_conversion_input); \ + [[maybe_unused]] auto avm_conversion_num_limbs = View(new_term.avm_conversion_num_limbs); \ + [[maybe_unused]] auto avm_conversion_radix = View(new_term.avm_conversion_radix); \ + [[maybe_unused]] auto avm_conversion_to_radix_le_sel = View(new_term.avm_conversion_to_radix_le_sel); \ [[maybe_unused]] auto avm_kernel_kernel_inputs__is_public = View(new_term.avm_kernel_kernel_inputs__is_public); \ [[maybe_unused]] auto avm_kernel_kernel_sel = View(new_term.avm_kernel_kernel_sel); \ [[maybe_unused]] auto avm_kernel_q_public_input_kernel_add_to_table = \ @@ -173,6 +178,7 @@ [[maybe_unused]] auto avm_main_sel_op_not = View(new_term.avm_main_sel_op_not); \ [[maybe_unused]] auto avm_main_sel_op_or = View(new_term.avm_main_sel_op_or); \ [[maybe_unused]] auto avm_main_sel_op_portal = View(new_term.avm_main_sel_op_portal); \ + [[maybe_unused]] auto avm_main_sel_op_radix_le = View(new_term.avm_main_sel_op_radix_le); \ [[maybe_unused]] auto avm_main_sel_op_sender = View(new_term.avm_main_sel_op_sender); \ [[maybe_unused]] auto avm_main_sel_op_shl = View(new_term.avm_main_sel_op_shl); \ [[maybe_unused]] auto avm_main_sel_op_shr = View(new_term.avm_main_sel_op_shr); \ @@ -216,6 +222,7 @@ [[maybe_unused]] auto avm_mem_w_in_tag = View(new_term.avm_mem_w_in_tag); \ [[maybe_unused]] auto perm_main_alu = View(new_term.perm_main_alu); \ [[maybe_unused]] auto perm_main_bin = View(new_term.perm_main_bin); \ + [[maybe_unused]] auto perm_main_conv = View(new_term.perm_main_conv); \ [[maybe_unused]] auto perm_main_mem_a = View(new_term.perm_main_mem_a); \ [[maybe_unused]] auto perm_main_mem_b = View(new_term.perm_main_mem_b); \ [[maybe_unused]] auto perm_main_mem_c = View(new_term.perm_main_mem_c); \ diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_conv.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_conv.hpp new file mode 100644 index 00000000000..2d7ac39f44e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_conv.hpp @@ -0,0 +1,102 @@ + + +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_main_conv_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 4; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.avm_main_sel_op_radix_le == 1 || in.avm_conversion_to_radix_le_sel == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_conv, + in.avm_main_sel_op_radix_le, + in.avm_main_sel_op_radix_le, + in.avm_conversion_to_radix_le_sel, + in.avm_main_clk, + in.avm_main_ia, + in.avm_main_ic, + in.avm_main_id, + in.avm_conversion_clk, + in.avm_conversion_input, + in.avm_conversion_radix, + in.avm_conversion_num_limbs); + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_conv, + in.avm_main_sel_op_radix_le, + in.avm_main_sel_op_radix_le, + in.avm_conversion_to_radix_le_sel, + in.avm_main_clk, + in.avm_main_ia, + in.avm_main_ic, + in.avm_main_id, + in.avm_conversion_clk, + in.avm_conversion_input, + in.avm_conversion_radix, + in.avm_conversion_num_limbs); + } +}; + +template +using perm_main_conv_relation = GenericPermutationRelation; +template using perm_main_conv = GenericPermutation; + +} // namespace bb 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 5ea81593782..3c2e8888411 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -53,6 +53,9 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, // Control Flow - Contract Calls { OpCode::RETURN, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + // Gadget - Conversion + { OpCode::TORADIXLE, + { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, }; const std::unordered_map OPERAND_TYPE_SIZE = { 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 0ebf977df75..f00c7305d7a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -68,6 +68,22 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) * @return The trace as a vector of Row. */ std::vector Execution::gen_trace(std::vector const& instructions, std::vector const& calldata) +{ + std::vector returndata{}; + return gen_trace(instructions, returndata, calldata); +} + +/** + * @brief Generate the execution trace pertaining to the supplied instructions returns the return data. + * + * @param instructions A vector of the instructions to be executed. + * @param calldata expressed as a vector of finite field elements. + * @return The trace as a vector of Row. + */ +std::vector Execution::gen_trace(std::vector const& instructions, + std::vector& returndata, + std::vector const& calldata) + { AvmTraceBuilder trace_builder; @@ -252,10 +268,19 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(4))); break; // Control Flow - Contract Calls - case OpCode::RETURN: - trace_builder.return_op(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + case OpCode::RETURN: { + auto ret = trace_builder.return_op(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); + returndata.insert(returndata.end(), ret.begin(), ret.end()); + break; + } + case OpCode::TORADIXLE: + trace_builder.op_to_radix_le(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4))); break; default: break; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp index 7f6aac52704..a6ca87d9272 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp @@ -14,6 +14,9 @@ class Execution { public: Execution() = default; + static std::vector gen_trace(std::vector const& instructions, + std::vector& returndata, + std::vector const& calldata = {}); static std::vector gen_trace(std::vector const& instructions, std::vector const& calldata = {}); static std::tuple prove(std::vector const& bytecode, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp index af36d8df5da..fe7d7308a84 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp @@ -411,4 +411,4 @@ void AvmMemTraceBuilder::write_into_memory(uint32_t const clk, store_in_mem_trace(clk, interm_reg, addr, val, r_in_tag, w_in_tag); } -} // namespace bb::avm_trace \ No newline at end of file +} // namespace bb::avm_trace 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 c82f2cbec74..86997f101bf 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -1686,6 +1686,154 @@ void AvmTraceBuilder::internal_return() internal_return_ptr--; } +// TODO(ilyas: #6383): Temporary way to bulk write slices +void write_slice_to_memory(AvmMemTraceBuilder& mem_trace, + std::vector& main_trace, + uint32_t clk, + uint32_t dst_offset, + AvmMemoryTag r_tag, + AvmMemoryTag w_tag, + FF internal_return_ptr, + std::vector const& slice) +{ + // We have 4 registers that we are able to use to write to memory within a single main trace row + auto register_order = std::array{ IntermRegister::IA, IntermRegister::IB, IntermRegister::IC, IntermRegister::ID }; + // If the slice size isnt a multiple of 4, we still need an extra row to write the remainder + uint32_t const num_main_rows = + static_cast(slice.size()) / 4 + static_cast(slice.size() % 4 != 0); + for (uint32_t i = 0; i < num_main_rows; i++) { + Row main_row{ + .avm_main_clk = clk + i, + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_r_in_tag = FF(static_cast(r_tag)), + .avm_main_w_in_tag = FF(static_cast(w_tag)), + }; + // Write 4 values to memory in each_row + for (uint32_t j = 0; j < 4; j++) { + auto offset = i * 4 + j; + // If we exceed the slice size, we break + if (offset >= slice.size()) { + break; + } + mem_trace.write_into_memory( + clk + i, register_order[j], dst_offset + offset, slice.at(offset), r_tag, w_tag); + // This looks a bit gross, but it is fine for now. + if (j == 0) { + main_row.avm_main_ia = slice.at(offset); + main_row.avm_main_mem_idx_a = FF(dst_offset + offset); + main_row.avm_main_mem_op_a = FF(1); + main_row.avm_main_rwa = FF(1); + } else if (j == 1) { + main_row.avm_main_ib = slice.at(offset); + main_row.avm_main_mem_idx_b = FF(dst_offset + offset); + main_row.avm_main_mem_op_b = FF(1); + main_row.avm_main_rwb = FF(1); + } else if (j == 2) { + main_row.avm_main_ic = slice.at(offset); + main_row.avm_main_mem_idx_c = FF(dst_offset + offset); + main_row.avm_main_mem_op_c = FF(1); + main_row.avm_main_rwc = FF(1); + } else { + main_row.avm_main_id = slice.at(offset); + main_row.avm_main_mem_idx_d = FF(dst_offset + offset); + main_row.avm_main_mem_op_d = FF(1); + main_row.avm_main_rwd = FF(1); + } + } + main_trace.emplace_back(main_row); + } +} + +/** + * @brief To_Radix_LE with direct or indirect memory access. + * + * @param indirect A byte encoding information about indirect/direct memory access. + * @param src_offset An index in memory pointing to the input of the To_Radix_LE conversion. + * @param dst_offset An index in memory pointing to the output of the To_Radix_LE conversion. + * @param radix A strict upper bound of each converted limb, i.e., 0 <= limb < radix. + * @param num_limbs The number of limbs to the value into. + */ +void AvmTraceBuilder::op_to_radix_le( + uint8_t indirect, uint32_t src_offset, uint32_t dst_offset, uint32_t radix, uint32_t num_limbs) +{ + auto clk = static_cast(main_trace.size()); + bool tag_match = true; + uint32_t direct_src_offset = src_offset; + uint32_t direct_dst_offset = dst_offset; + + bool indirect_src_flag = is_operand_indirect(indirect, 0); + bool indirect_dst_flag = is_operand_indirect(indirect, 1); + + if (indirect_src_flag) { + auto read_ind_src = + mem_trace_builder.indirect_read_and_load_from_memory(clk, IndirectRegister::IND_A, src_offset); + direct_src_offset = uint32_t(read_ind_src.val); + tag_match = tag_match && read_ind_src.tag_match; + } + + if (indirect_dst_flag) { + auto read_ind_dst = + mem_trace_builder.indirect_read_and_load_from_memory(clk, IndirectRegister::IND_B, dst_offset); + direct_dst_offset = uint32_t(read_ind_dst.val); + tag_match = tag_match && read_ind_dst.tag_match; + } + + auto read_src = mem_trace_builder.read_and_load_from_memory( + clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::FF, AvmMemoryTag::U8); + // Read in the memory address of where the first limb should be stored (the read_tag must be U32 and write tag U8) + auto read_dst = mem_trace_builder.read_and_load_from_memory( + clk, IntermRegister::IB, direct_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::U8); + + FF input = read_src.val; + FF dst_addr = read_dst.val; + + // In case of a memory tag error, we do not perform the computation. + // Therefore, we do not create any entry in gadget table and return a vector of 0 + std::vector res = tag_match ? conversion_trace_builder.op_to_radix_le(input, radix, num_limbs, clk) + : std::vector(num_limbs, 0); + + // This is the row that contains the selector to trigger the sel_op_radix_le + // In this row, we read the input value and the destination address into register A and B respectively + main_trace.push_back(Row{ + .avm_main_clk = clk, + .avm_main_ia = input, + .avm_main_ib = dst_addr, + .avm_main_ic = radix, + .avm_main_id = num_limbs, + .avm_main_ind_a = indirect_src_flag ? src_offset : 0, + .avm_main_ind_b = indirect_dst_flag ? dst_offset : 0, + .avm_main_ind_op_a = FF(static_cast(indirect_src_flag)), + .avm_main_ind_op_b = FF(static_cast(indirect_dst_flag)), + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_mem_idx_a = FF(direct_src_offset), + .avm_main_mem_idx_b = FF(direct_dst_offset), + .avm_main_mem_op_a = FF(1), + .avm_main_mem_op_b = FF(1), + .avm_main_pc = FF(pc++), + .avm_main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), + .avm_main_sel_op_radix_le = FF(1), + .avm_main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), + }); + // Increment the clock so we dont write at the same clock cycle + // Instead we temporarily encode the writes into the subsequent rows of the main trace + clk++; + + // MemTrace, write into memory value b from intermediate register ib. + std::vector ff_res = {}; + ff_res.reserve(res.size()); + for (auto const& limb : res) { + ff_res.emplace_back(limb); + } + write_slice_to_memory(mem_trace_builder, + main_trace, + clk, + direct_dst_offset, + AvmMemoryTag::FF, + AvmMemoryTag::U8, + FF(internal_return_ptr), + ff_res); +} + // Finalise Lookup Counts // // For log derivative lookups, we require a column that contains the number of times each lookup is consumed @@ -1714,10 +1862,12 @@ std::vector AvmTraceBuilder::finalize() bool const range_check_required = true; auto mem_trace = mem_trace_builder.finalize(); auto alu_trace = alu_trace_builder.finalize(); + auto conv_trace = conversion_trace_builder.finalize(); auto bin_trace = bin_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(); + size_t conv_trace_size = conv_trace.size(); size_t bin_trace_size = bin_trace.size(); // Get tag_err counts from the mem_trace_builder @@ -1728,12 +1878,12 @@ std::vector AvmTraceBuilder::finalize() std::unordered_map mem_rng_check_hi_counts; // Main Trace needs to be at least as big as the biggest subtrace. - // If the bin_trace_size has entries, we need the main_trace to be as big as our byte lookup table (3 * 2**16 - // long) + // If the bin_trace_size has entries, we need the main_trace to be as big as our byte lookup table (3 * + // 2**16 long) size_t const lookup_table_size = bin_trace_size > 0 ? 3 * (1 << 16) : 0; size_t const range_check_size = range_check_required ? UINT16_MAX + 1 : 0; - std::vector trace_sizes = { mem_trace_size, main_trace_size, alu_trace_size, - lookup_table_size, range_check_size, KERNEL_INPUTS_LENGTH }; + std::vector trace_sizes = { mem_trace_size, main_trace_size, alu_trace_size, lookup_table_size, + range_check_size, conv_trace_size, KERNEL_INPUTS_LENGTH }; auto trace_size = std::max_element(trace_sizes.begin(), trace_sizes.end()); // We only need to pad with zeroes to the size to the largest trace here, pow_2 padding is handled in the @@ -2045,6 +2195,17 @@ std::vector AvmTraceBuilder::finalize() } } + // Add Conversion Gadget table + for (size_t i = 0; i < conv_trace_size; i++) { + auto const& src = conv_trace.at(i); + auto& dest = main_trace.at(i); + dest.avm_conversion_to_radix_le_sel = FF(static_cast(src.to_radix_le_sel)); + dest.avm_conversion_clk = FF(src.conversion_clk); + dest.avm_conversion_input = src.input; + dest.avm_conversion_radix = FF(src.radix); + dest.avm_conversion_num_limbs = FF(src.num_limbs); + } + // Add Binary Trace table for (size_t i = 0; i < bin_trace_size; i++) { auto const& src = bin_trace.at(i); @@ -2096,7 +2257,8 @@ std::vector AvmTraceBuilder::finalize() // Generate ByteLength Lookup table of instruction tags to the number of bytes // {U8: 1, U16: 2, U32: 4, U64: 8, U128: 16} for (uint8_t avm_in_tag = 0; avm_in_tag < 5; avm_in_tag++) { - // The +1 here is because the instruction tags we care about (i.e excl U0 and FF) has the range [1,5] + // The +1 here is because the instruction tags we care about (i.e excl U0 and FF) has the range + // [1,5] main_trace.at(avm_in_tag).avm_byte_lookup_table_in_tags = avm_in_tag + 1; main_trace.at(avm_in_tag).avm_byte_lookup_table_byte_lengths = static_cast(pow(2, avm_in_tag)); main_trace.at(avm_in_tag).lookup_byte_lengths_counts = @@ -2129,4 +2291,4 @@ std::vector AvmTraceBuilder::finalize() return trace; } -} // namespace bb::avm_trace \ No newline at end of file +} // namespace bb::avm_trace 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 ebf8cbc5435..c4693fda067 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -8,6 +8,7 @@ #include "avm_instructions.hpp" #include "avm_mem_trace.hpp" #include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.hpp" #include "constants.hpp" #include "barretenberg/relations/generated/avm/avm_main.hpp" @@ -131,6 +132,11 @@ class AvmTraceBuilder { // indirect: return(M[M[ret_offset]:M[ret_offset]+ret_size]) std::vector return_op(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + // Gadgets + // --- Conversions + // To Radix LE conversion operation. + void op_to_radix_le(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset, uint32_t radix, uint32_t num_limbs); + private: // Used for the standard indirect address resolution of three operands opcode. struct IndirectThreeResolution { @@ -149,6 +155,7 @@ class AvmTraceBuilder { AvmAluTraceBuilder alu_trace_builder; AvmBinaryTraceBuilder bin_trace_builder; AvmKernelTraceBuilder kernel_trace_builder; + AvmConversionTraceBuilder conversion_trace_builder; Row create_kernel_lookup_opcode(uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag); void finalise_mem_trace_lookup_counts(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.cpp new file mode 100644 index 00000000000..9a6371824f5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.cpp @@ -0,0 +1,61 @@ + +#include "avm_conversion_trace.hpp" +#include "../avm_common.hpp" + +namespace bb::avm_trace { + +AvmConversionTraceBuilder::AvmConversionTraceBuilder() +{ + conversion_trace.reserve(AVM_TRACE_SIZE); +} + +std::vector AvmConversionTraceBuilder::finalize() +{ + return std::move(conversion_trace); +} + +void AvmConversionTraceBuilder::reset() +{ + conversion_trace.clear(); +} + +/** + * @brief Build conversion trace and compute the result of a TO_RADIX_LE operation. + * This operation is only valid for the FF instr_tag and always returns a byte array + * + * @param a First operand of the TO_RADIX_LE, the value to be converted + * @param radix The upper bound for each limbm 0 <= limb < radix + * @param num_limbs The number of limbs to the value into. + * @param in_tag Instruction tag defining the number of bits for the LT. + * @param clk Clock referring to the operation in the main trace. + * + * @return std::vector The LE converted values stored as bytes. + */ +std::vector AvmConversionTraceBuilder::op_to_radix_le(FF const& a, + uint32_t radix, + uint32_t num_limbs, + uint32_t clk) +{ + ASSERT(radix <= 256); + + auto a_uint256 = uint256_t(a); + auto radix_uint256 = uint256_t(radix); + + std::vector bytes{}; + for (uint32_t i = 0; i < num_limbs; i++) { + bytes.emplace_back(static_cast(a_uint256 % radix_uint256)); + a_uint256 /= radix_uint256; + } + + conversion_trace.emplace_back(ConversionTraceEntry{ + .conversion_clk = clk, + .to_radix_le_sel = true, + .input = a, + .radix = radix, + .num_limbs = num_limbs, + .limbs = bytes, + }); + + return bytes; +} +} // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.hpp new file mode 100644 index 00000000000..f646d7f7e61 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "../avm_common.hpp" +#include "barretenberg/numeric/uint128/uint128.hpp" +#include +#include + +namespace bb::avm_trace { +class AvmConversionTraceBuilder { + public: + struct ConversionTraceEntry { + uint32_t conversion_clk = 0; + bool to_radix_le_sel = false; + FF input{}; + uint32_t radix = 0; + uint32_t num_limbs = 0; + std::vector limbs; + }; + + AvmConversionTraceBuilder(); + void reset(); + // Finalize the trace + std::vector finalize(); + + std::vector op_to_radix_le(FF const& a, uint32_t radix, uint32_t num_limbs, uint32_t clk); + + private: + std::vector conversion_trace; +}; +} // namespace bb::avm_trace 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 fe495ae8c09..df4e7bea62c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -18,6 +18,7 @@ #include "barretenberg/relations/generated/avm/avm_alu.hpp" #include "barretenberg/relations/generated/avm/avm_binary.hpp" +#include "barretenberg/relations/generated/avm/avm_conversion.hpp" #include "barretenberg/relations/generated/avm/avm_main.hpp" #include "barretenberg/relations/generated/avm/avm_mem.hpp" #include "barretenberg/relations/generated/avm/incl_main_tag_err.hpp" @@ -56,6 +57,7 @@ #include "barretenberg/relations/generated/avm/lookup_u8_1.hpp" #include "barretenberg/relations/generated/avm/perm_main_alu.hpp" #include "barretenberg/relations/generated/avm/perm_main_bin.hpp" +#include "barretenberg/relations/generated/avm/perm_main_conv.hpp" #include "barretenberg/relations/generated/avm/perm_main_mem_a.hpp" #include "barretenberg/relations/generated/avm/perm_main_mem_b.hpp" #include "barretenberg/relations/generated/avm/perm_main_mem_c.hpp" @@ -174,6 +176,11 @@ template struct AvmFullRow { FF avm_byte_lookup_table_input_b{}; FF avm_byte_lookup_table_op_id{}; FF avm_byte_lookup_table_output{}; + FF avm_conversion_clk{}; + FF avm_conversion_input{}; + FF avm_conversion_num_limbs{}; + FF avm_conversion_radix{}; + FF avm_conversion_to_radix_le_sel{}; FF avm_kernel_kernel_inputs__is_public{}; FF avm_kernel_kernel_sel{}; FF avm_kernel_q_public_input_kernel_add_to_table{}; @@ -239,6 +246,7 @@ template struct AvmFullRow { FF avm_main_sel_op_not{}; FF avm_main_sel_op_or{}; FF avm_main_sel_op_portal{}; + FF avm_main_sel_op_radix_le{}; FF avm_main_sel_op_sender{}; FF avm_main_sel_op_shl{}; FF avm_main_sel_op_shr{}; @@ -282,6 +290,7 @@ template struct AvmFullRow { FF avm_mem_w_in_tag{}; FF perm_main_alu{}; FF perm_main_bin{}; + FF perm_main_conv{}; FF perm_main_mem_a{}; FF perm_main_mem_b{}; FF perm_main_mem_c{}; @@ -422,8 +431,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 341; - static constexpr size_t num_polys = 289; + static constexpr size_t num_fixed_columns = 348; + static constexpr size_t num_polys = 296; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -544,6 +553,11 @@ class AvmCircuitBuilder { polys.avm_byte_lookup_table_input_b[i] = rows[i].avm_byte_lookup_table_input_b; polys.avm_byte_lookup_table_op_id[i] = rows[i].avm_byte_lookup_table_op_id; polys.avm_byte_lookup_table_output[i] = rows[i].avm_byte_lookup_table_output; + polys.avm_conversion_clk[i] = rows[i].avm_conversion_clk; + polys.avm_conversion_input[i] = rows[i].avm_conversion_input; + polys.avm_conversion_num_limbs[i] = rows[i].avm_conversion_num_limbs; + polys.avm_conversion_radix[i] = rows[i].avm_conversion_radix; + polys.avm_conversion_to_radix_le_sel[i] = rows[i].avm_conversion_to_radix_le_sel; polys.avm_kernel_kernel_inputs__is_public[i] = rows[i].avm_kernel_kernel_inputs__is_public; polys.avm_kernel_kernel_sel[i] = rows[i].avm_kernel_kernel_sel; polys.avm_kernel_q_public_input_kernel_add_to_table[i] = @@ -610,6 +624,7 @@ class AvmCircuitBuilder { polys.avm_main_sel_op_not[i] = rows[i].avm_main_sel_op_not; polys.avm_main_sel_op_or[i] = rows[i].avm_main_sel_op_or; polys.avm_main_sel_op_portal[i] = rows[i].avm_main_sel_op_portal; + polys.avm_main_sel_op_radix_le[i] = rows[i].avm_main_sel_op_radix_le; polys.avm_main_sel_op_sender[i] = rows[i].avm_main_sel_op_sender; polys.avm_main_sel_op_shl[i] = rows[i].avm_main_sel_op_shl; polys.avm_main_sel_op_shr[i] = rows[i].avm_main_sel_op_shr; @@ -820,6 +835,11 @@ class AvmCircuitBuilder { Avm_vm::get_relation_label_avm_binary); }; + auto avm_conversion = [=]() { + return evaluate_relation.template operator()>( + "avm_conversion", Avm_vm::get_relation_label_avm_conversion); + }; + auto avm_main = [=]() { return evaluate_relation.template operator()>("avm_main", Avm_vm::get_relation_label_avm_main); @@ -838,6 +858,10 @@ class AvmCircuitBuilder { return evaluate_logderivative.template operator()>("PERM_MAIN_BIN"); }; + auto perm_main_conv = [=]() { + return evaluate_logderivative.template operator()>("PERM_MAIN_CONV"); + }; + auto perm_main_mem_a = [=]() { return evaluate_logderivative.template operator()>("PERM_MAIN_MEM_A"); }; @@ -1018,6 +1042,8 @@ class AvmCircuitBuilder { relation_futures.emplace_back(std::async(std::launch::async, avm_binary)); + relation_futures.emplace_back(std::async(std::launch::async, avm_conversion)); + relation_futures.emplace_back(std::async(std::launch::async, avm_main)); relation_futures.emplace_back(std::async(std::launch::async, avm_mem)); @@ -1026,6 +1052,8 @@ class AvmCircuitBuilder { relation_futures.emplace_back(std::async(std::launch::async, perm_main_bin)); + relation_futures.emplace_back(std::async(std::launch::async, perm_main_conv)); + relation_futures.emplace_back(std::async(std::launch::async, perm_main_mem_a)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_mem_b)); @@ -1123,6 +1151,8 @@ class AvmCircuitBuilder { avm_binary(); + avm_conversion(); + avm_main(); avm_mem(); @@ -1131,6 +1161,8 @@ class AvmCircuitBuilder { perm_main_bin(); + perm_main_conv(); + perm_main_mem_a(); perm_main_mem_b(); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index bf208bc727e..691cc506c76 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -15,6 +15,7 @@ #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/relations/generated/avm/avm_alu.hpp" #include "barretenberg/relations/generated/avm/avm_binary.hpp" +#include "barretenberg/relations/generated/avm/avm_conversion.hpp" #include "barretenberg/relations/generated/avm/avm_main.hpp" #include "barretenberg/relations/generated/avm/avm_mem.hpp" #include "barretenberg/relations/generated/avm/incl_main_tag_err.hpp" @@ -53,6 +54,7 @@ #include "barretenberg/relations/generated/avm/lookup_u8_1.hpp" #include "barretenberg/relations/generated/avm/perm_main_alu.hpp" #include "barretenberg/relations/generated/avm/perm_main_bin.hpp" +#include "barretenberg/relations/generated/avm/perm_main_conv.hpp" #include "barretenberg/relations/generated/avm/perm_main_mem_a.hpp" #include "barretenberg/relations/generated/avm/perm_main_mem_b.hpp" #include "barretenberg/relations/generated/avm/perm_main_mem_c.hpp" @@ -82,14 +84,15 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 287; + static constexpr size_t NUM_WITNESS_ENTITIES = 294; 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 = 341; + static constexpr size_t NUM_ALL_ENTITIES = 348; using GrandProductRelations = std::tuple, perm_main_bin_relation, + perm_main_conv_relation, perm_main_mem_a_relation, perm_main_mem_b_relation, perm_main_mem_c_relation, @@ -135,10 +138,12 @@ class AvmFlavor { using Relations = std::tuple, Avm_vm::avm_binary, + Avm_vm::avm_conversion, Avm_vm::avm_main, Avm_vm::avm_mem, perm_main_alu_relation, perm_main_bin_relation, + perm_main_conv_relation, perm_main_mem_a_relation, perm_main_mem_b_relation, perm_main_mem_c_relation, @@ -317,6 +322,11 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_conversion_clk, + avm_conversion_input, + avm_conversion_num_limbs, + avm_conversion_radix, + avm_conversion_to_radix_le_sel, avm_kernel_kernel_inputs__is_public, avm_kernel_kernel_sel, avm_kernel_q_public_input_kernel_add_to_table, @@ -382,6 +392,7 @@ class AvmFlavor { avm_main_sel_op_not, avm_main_sel_op_or, avm_main_sel_op_portal, + avm_main_sel_op_radix_le, avm_main_sel_op_sender, avm_main_sel_op_shl, avm_main_sel_op_shr, @@ -425,6 +436,7 @@ class AvmFlavor { avm_mem_w_in_tag, perm_main_alu, perm_main_bin, + perm_main_conv, perm_main_mem_a, perm_main_mem_b, perm_main_mem_c, @@ -607,6 +619,11 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_conversion_clk, + avm_conversion_input, + avm_conversion_num_limbs, + avm_conversion_radix, + avm_conversion_to_radix_le_sel, avm_kernel_kernel_inputs__is_public, avm_kernel_kernel_sel, avm_kernel_q_public_input_kernel_add_to_table, @@ -672,6 +689,7 @@ class AvmFlavor { avm_main_sel_op_not, avm_main_sel_op_or, avm_main_sel_op_portal, + avm_main_sel_op_radix_le, avm_main_sel_op_sender, avm_main_sel_op_shl, avm_main_sel_op_shr, @@ -715,6 +733,7 @@ class AvmFlavor { avm_mem_w_in_tag, perm_main_alu, perm_main_bin, + perm_main_conv, perm_main_mem_a, perm_main_mem_b, perm_main_mem_c, @@ -902,6 +921,11 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_conversion_clk, + avm_conversion_input, + avm_conversion_num_limbs, + avm_conversion_radix, + avm_conversion_to_radix_le_sel, avm_kernel_kernel_inputs__is_public, avm_kernel_kernel_sel, avm_kernel_q_public_input_kernel_add_to_table, @@ -967,6 +991,7 @@ class AvmFlavor { avm_main_sel_op_not, avm_main_sel_op_or, avm_main_sel_op_portal, + avm_main_sel_op_radix_le, avm_main_sel_op_sender, avm_main_sel_op_shl, avm_main_sel_op_shr, @@ -1010,6 +1035,7 @@ class AvmFlavor { avm_mem_w_in_tag, perm_main_alu, perm_main_bin, + perm_main_conv, perm_main_mem_a, perm_main_mem_b, perm_main_mem_c, @@ -1246,6 +1272,11 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_conversion_clk, + avm_conversion_input, + avm_conversion_num_limbs, + avm_conversion_radix, + avm_conversion_to_radix_le_sel, avm_kernel_kernel_inputs__is_public, avm_kernel_kernel_sel, avm_kernel_q_public_input_kernel_add_to_table, @@ -1311,6 +1342,7 @@ class AvmFlavor { avm_main_sel_op_not, avm_main_sel_op_or, avm_main_sel_op_portal, + avm_main_sel_op_radix_le, avm_main_sel_op_sender, avm_main_sel_op_shl, avm_main_sel_op_shr, @@ -1354,6 +1386,7 @@ class AvmFlavor { avm_mem_w_in_tag, perm_main_alu, perm_main_bin, + perm_main_conv, perm_main_mem_a, perm_main_mem_b, perm_main_mem_c, @@ -1590,6 +1623,11 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_conversion_clk, + avm_conversion_input, + avm_conversion_num_limbs, + avm_conversion_radix, + avm_conversion_to_radix_le_sel, avm_kernel_kernel_inputs__is_public, avm_kernel_kernel_sel, avm_kernel_q_public_input_kernel_add_to_table, @@ -1655,6 +1693,7 @@ class AvmFlavor { avm_main_sel_op_not, avm_main_sel_op_or, avm_main_sel_op_portal, + avm_main_sel_op_radix_le, avm_main_sel_op_sender, avm_main_sel_op_shl, avm_main_sel_op_shr, @@ -1698,6 +1737,7 @@ class AvmFlavor { avm_mem_w_in_tag, perm_main_alu, perm_main_bin, + perm_main_conv, perm_main_mem_a, perm_main_mem_b, perm_main_mem_c, @@ -1959,6 +1999,8 @@ class AvmFlavor { prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( prover_polynomials, relation_parameters, this->circuit_size); + bb::compute_logderivative_inverse>( + prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( @@ -2248,6 +2290,11 @@ class AvmFlavor { Base::avm_byte_lookup_table_input_b = "AVM_BYTE_LOOKUP_TABLE_INPUT_B"; Base::avm_byte_lookup_table_op_id = "AVM_BYTE_LOOKUP_TABLE_OP_ID"; Base::avm_byte_lookup_table_output = "AVM_BYTE_LOOKUP_TABLE_OUTPUT"; + Base::avm_conversion_clk = "AVM_CONVERSION_CLK"; + Base::avm_conversion_input = "AVM_CONVERSION_INPUT"; + Base::avm_conversion_num_limbs = "AVM_CONVERSION_NUM_LIMBS"; + Base::avm_conversion_radix = "AVM_CONVERSION_RADIX"; + Base::avm_conversion_to_radix_le_sel = "AVM_CONVERSION_TO_RADIX_LE_SEL"; Base::avm_kernel_kernel_inputs__is_public = "AVM_KERNEL_KERNEL_INPUTS__IS_PUBLIC"; Base::avm_kernel_kernel_sel = "AVM_KERNEL_KERNEL_SEL"; Base::avm_kernel_q_public_input_kernel_add_to_table = "AVM_KERNEL_Q_PUBLIC_INPUT_KERNEL_ADD_TO_TABLE"; @@ -2313,6 +2360,7 @@ class AvmFlavor { Base::avm_main_sel_op_not = "AVM_MAIN_SEL_OP_NOT"; Base::avm_main_sel_op_or = "AVM_MAIN_SEL_OP_OR"; Base::avm_main_sel_op_portal = "AVM_MAIN_SEL_OP_PORTAL"; + Base::avm_main_sel_op_radix_le = "AVM_MAIN_SEL_OP_RADIX_LE"; Base::avm_main_sel_op_sender = "AVM_MAIN_SEL_OP_SENDER"; Base::avm_main_sel_op_shl = "AVM_MAIN_SEL_OP_SHL"; Base::avm_main_sel_op_shr = "AVM_MAIN_SEL_OP_SHR"; @@ -2356,6 +2404,7 @@ class AvmFlavor { Base::avm_mem_w_in_tag = "AVM_MEM_W_IN_TAG"; Base::perm_main_alu = "PERM_MAIN_ALU"; Base::perm_main_bin = "PERM_MAIN_BIN"; + Base::perm_main_conv = "PERM_MAIN_CONV"; Base::perm_main_mem_a = "PERM_MAIN_MEM_A"; Base::perm_main_mem_b = "PERM_MAIN_MEM_B"; Base::perm_main_mem_c = "PERM_MAIN_MEM_C"; @@ -2554,6 +2603,11 @@ class AvmFlavor { Commitment avm_byte_lookup_table_input_b; Commitment avm_byte_lookup_table_op_id; Commitment avm_byte_lookup_table_output; + Commitment avm_conversion_clk; + Commitment avm_conversion_input; + Commitment avm_conversion_num_limbs; + Commitment avm_conversion_radix; + Commitment avm_conversion_to_radix_le_sel; Commitment avm_kernel_kernel_inputs__is_public; Commitment avm_kernel_kernel_sel; Commitment avm_kernel_q_public_input_kernel_add_to_table; @@ -2619,6 +2673,7 @@ class AvmFlavor { Commitment avm_main_sel_op_not; Commitment avm_main_sel_op_or; Commitment avm_main_sel_op_portal; + Commitment avm_main_sel_op_radix_le; Commitment avm_main_sel_op_sender; Commitment avm_main_sel_op_shl; Commitment avm_main_sel_op_shr; @@ -2662,6 +2717,7 @@ class AvmFlavor { Commitment avm_mem_w_in_tag; Commitment perm_main_alu; Commitment perm_main_bin; + Commitment perm_main_conv; Commitment perm_main_mem_a; Commitment perm_main_mem_b; Commitment perm_main_mem_c; @@ -2861,6 +2917,11 @@ class AvmFlavor { avm_byte_lookup_table_input_b = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_byte_lookup_table_op_id = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_byte_lookup_table_output = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_conversion_clk = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_conversion_input = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_conversion_num_limbs = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_conversion_radix = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_conversion_to_radix_le_sel = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_kernel_kernel_inputs__is_public = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_kernel_kernel_sel = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2928,6 +2989,7 @@ class AvmFlavor { avm_main_sel_op_not = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_or = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_portal = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_sel_op_radix_le = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_sender = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_shl = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_shr = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2971,6 +3033,7 @@ class AvmFlavor { avm_mem_w_in_tag = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_alu = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_bin = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + perm_main_conv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_mem_a = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_mem_b = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_mem_c = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3173,6 +3236,11 @@ class AvmFlavor { serialize_to_buffer(avm_byte_lookup_table_input_b, Transcript::proof_data); serialize_to_buffer(avm_byte_lookup_table_op_id, Transcript::proof_data); serialize_to_buffer(avm_byte_lookup_table_output, Transcript::proof_data); + serialize_to_buffer(avm_conversion_clk, Transcript::proof_data); + serialize_to_buffer(avm_conversion_input, Transcript::proof_data); + serialize_to_buffer(avm_conversion_num_limbs, Transcript::proof_data); + serialize_to_buffer(avm_conversion_radix, Transcript::proof_data); + serialize_to_buffer(avm_conversion_to_radix_le_sel, Transcript::proof_data); serialize_to_buffer(avm_kernel_kernel_inputs__is_public, Transcript::proof_data); serialize_to_buffer(avm_kernel_kernel_sel, Transcript::proof_data); serialize_to_buffer(avm_kernel_q_public_input_kernel_add_to_table, Transcript::proof_data); @@ -3238,6 +3306,7 @@ class AvmFlavor { serialize_to_buffer(avm_main_sel_op_not, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_or, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_portal, Transcript::proof_data); + serialize_to_buffer(avm_main_sel_op_radix_le, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_sender, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_shl, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_shr, Transcript::proof_data); @@ -3281,6 +3350,7 @@ class AvmFlavor { serialize_to_buffer(avm_mem_w_in_tag, Transcript::proof_data); serialize_to_buffer(perm_main_alu, Transcript::proof_data); serialize_to_buffer(perm_main_bin, Transcript::proof_data); + serialize_to_buffer(perm_main_conv, Transcript::proof_data); serialize_to_buffer(perm_main_mem_a, Transcript::proof_data); serialize_to_buffer(perm_main_mem_b, Transcript::proof_data); serialize_to_buffer(perm_main_mem_c, 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 6f5fd5a27fd..a88fac34e33 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -163,6 +163,11 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_byte_lookup_table_input_b = commitment_key->commit(key->avm_byte_lookup_table_input_b); witness_commitments.avm_byte_lookup_table_op_id = commitment_key->commit(key->avm_byte_lookup_table_op_id); witness_commitments.avm_byte_lookup_table_output = commitment_key->commit(key->avm_byte_lookup_table_output); + witness_commitments.avm_conversion_clk = commitment_key->commit(key->avm_conversion_clk); + witness_commitments.avm_conversion_input = commitment_key->commit(key->avm_conversion_input); + witness_commitments.avm_conversion_num_limbs = commitment_key->commit(key->avm_conversion_num_limbs); + witness_commitments.avm_conversion_radix = commitment_key->commit(key->avm_conversion_radix); + witness_commitments.avm_conversion_to_radix_le_sel = commitment_key->commit(key->avm_conversion_to_radix_le_sel); witness_commitments.avm_kernel_kernel_inputs__is_public = commitment_key->commit(key->avm_kernel_kernel_inputs__is_public); witness_commitments.avm_kernel_kernel_sel = commitment_key->commit(key->avm_kernel_kernel_sel); @@ -230,6 +235,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_main_sel_op_not = commitment_key->commit(key->avm_main_sel_op_not); witness_commitments.avm_main_sel_op_or = commitment_key->commit(key->avm_main_sel_op_or); witness_commitments.avm_main_sel_op_portal = commitment_key->commit(key->avm_main_sel_op_portal); + witness_commitments.avm_main_sel_op_radix_le = commitment_key->commit(key->avm_main_sel_op_radix_le); witness_commitments.avm_main_sel_op_sender = commitment_key->commit(key->avm_main_sel_op_sender); witness_commitments.avm_main_sel_op_shl = commitment_key->commit(key->avm_main_sel_op_shl); witness_commitments.avm_main_sel_op_shr = commitment_key->commit(key->avm_main_sel_op_shr); @@ -424,6 +430,13 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_byte_lookup_table_op_id); transcript->send_to_verifier(commitment_labels.avm_byte_lookup_table_output, witness_commitments.avm_byte_lookup_table_output); + transcript->send_to_verifier(commitment_labels.avm_conversion_clk, witness_commitments.avm_conversion_clk); + transcript->send_to_verifier(commitment_labels.avm_conversion_input, witness_commitments.avm_conversion_input); + transcript->send_to_verifier(commitment_labels.avm_conversion_num_limbs, + witness_commitments.avm_conversion_num_limbs); + transcript->send_to_verifier(commitment_labels.avm_conversion_radix, witness_commitments.avm_conversion_radix); + transcript->send_to_verifier(commitment_labels.avm_conversion_to_radix_le_sel, + witness_commitments.avm_conversion_to_radix_le_sel); transcript->send_to_verifier(commitment_labels.avm_kernel_kernel_inputs__is_public, witness_commitments.avm_kernel_kernel_inputs__is_public); transcript->send_to_verifier(commitment_labels.avm_kernel_kernel_sel, witness_commitments.avm_kernel_kernel_sel); @@ -501,6 +514,8 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.avm_main_sel_op_not, witness_commitments.avm_main_sel_op_not); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_or, witness_commitments.avm_main_sel_op_or); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_portal, witness_commitments.avm_main_sel_op_portal); + transcript->send_to_verifier(commitment_labels.avm_main_sel_op_radix_le, + witness_commitments.avm_main_sel_op_radix_le); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_sender, witness_commitments.avm_main_sel_op_sender); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_shl, witness_commitments.avm_main_sel_op_shl); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_shr, witness_commitments.avm_main_sel_op_shr); @@ -608,6 +623,7 @@ void AvmProver::execute_log_derivative_inverse_round() // Commit to all logderivative inverse polynomials witness_commitments.perm_main_alu = commitment_key->commit(key->perm_main_alu); witness_commitments.perm_main_bin = commitment_key->commit(key->perm_main_bin); + witness_commitments.perm_main_conv = commitment_key->commit(key->perm_main_conv); witness_commitments.perm_main_mem_a = commitment_key->commit(key->perm_main_mem_a); witness_commitments.perm_main_mem_b = commitment_key->commit(key->perm_main_mem_b); witness_commitments.perm_main_mem_c = commitment_key->commit(key->perm_main_mem_c); @@ -654,6 +670,7 @@ void AvmProver::execute_log_derivative_inverse_round() // Send all commitments to the verifier transcript->send_to_verifier(commitment_labels.perm_main_alu, witness_commitments.perm_main_alu); transcript->send_to_verifier(commitment_labels.perm_main_bin, witness_commitments.perm_main_bin); + transcript->send_to_verifier(commitment_labels.perm_main_conv, witness_commitments.perm_main_conv); transcript->send_to_verifier(commitment_labels.perm_main_mem_a, witness_commitments.perm_main_mem_a); transcript->send_to_verifier(commitment_labels.perm_main_mem_b, witness_commitments.perm_main_mem_b); transcript->send_to_verifier(commitment_labels.perm_main_mem_c, witness_commitments.perm_main_mem_c); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 75984868e88..9c203fc061b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -33,8 +33,8 @@ using FF = AvmFlavor::FF; std::vector challenges) { - // TODO: we pad the points to the circuit size in order to get the correct evaluation - // This is not efficient, and will not be valid in production + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6361): we pad the points to the circuit size in order + // to get the correct evaluation This is not efficient, and will not be valid in production std::vector new_points(circuit_size, 0); std::copy(points.begin(), points.end(), new_points.data()); @@ -238,6 +238,16 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector& pu transcript->template receive_from_prover(commitment_labels.avm_byte_lookup_table_op_id); commitments.avm_byte_lookup_table_output = transcript->template receive_from_prover(commitment_labels.avm_byte_lookup_table_output); + commitments.avm_conversion_clk = + transcript->template receive_from_prover(commitment_labels.avm_conversion_clk); + commitments.avm_conversion_input = + transcript->template receive_from_prover(commitment_labels.avm_conversion_input); + commitments.avm_conversion_num_limbs = + transcript->template receive_from_prover(commitment_labels.avm_conversion_num_limbs); + commitments.avm_conversion_radix = + transcript->template receive_from_prover(commitment_labels.avm_conversion_radix); + commitments.avm_conversion_to_radix_le_sel = + transcript->template receive_from_prover(commitment_labels.avm_conversion_to_radix_le_sel); commitments.avm_kernel_kernel_inputs__is_public = transcript->template receive_from_prover(commitment_labels.avm_kernel_kernel_inputs__is_public); commitments.avm_kernel_kernel_sel = @@ -353,6 +363,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector& pu transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_or); commitments.avm_main_sel_op_portal = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_portal); + commitments.avm_main_sel_op_radix_le = + transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_radix_le); commitments.avm_main_sel_op_sender = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_sender); commitments.avm_main_sel_op_shl = @@ -500,6 +512,7 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector& pu // Get commitments to inverses commitments.perm_main_alu = transcript->template receive_from_prover(commitment_labels.perm_main_alu); commitments.perm_main_bin = transcript->template receive_from_prover(commitment_labels.perm_main_bin); + commitments.perm_main_conv = transcript->template receive_from_prover(commitment_labels.perm_main_conv); commitments.perm_main_mem_a = transcript->template receive_from_prover(commitment_labels.perm_main_mem_a); commitments.perm_main_mem_b = 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 63b54ce4c72..77a4facddd3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -4,6 +4,7 @@ #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_deserialization.hpp" #include "barretenberg/vm/avm_trace/avm_opcode.hpp" +#include namespace tests_avm { @@ -621,6 +622,76 @@ TEST_F(AvmExecutionTests, setAndCastOpcodes) validate_trace(std::move(trace)); } +// Positive test with TO_RADIX_LE. +TEST_F(AvmExecutionTests, toRadixLeOpcode) +{ + std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY + "00" // Indirect flag + "00000000" // cd_offset + "00000001" // copy_size + "00000001" // dst_offset + + to_hex(OpCode::SET) + // opcode SET for indirect src + "00" // Indirect flag + "03" // U32 + "00000001" // value 1 (i.e. where the src from calldata is copied) + "00000011" // dst_offset 17 + + to_hex(OpCode::SET) + // opcode SET for indirect dst + "00" // Indirect flag + "03" // U32 + "00000005" // value 5 (i.e. where the dst will be written to) + "00000015" // dst_offset 21 + + to_hex(OpCode::TORADIXLE) + // opcode TO_RADIX_LE + "03" // Indirect flag + "00000011" // src_offset 17 (indirect) + "00000015" // dst_offset 21 (indirect) + "00000002" // radix: 2 (i.e. perform bitwise decomposition) + "00000100" // limbs: 256 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000005" // ret offset 0 + "00000100"; // ret size 0 + + auto bytecode = hex_to_bytes(bytecode_hex); + auto instructions = Deserialization::parse(bytecode); + + ASSERT_THAT(instructions, SizeIs(5)); + + // TORADIXLE + EXPECT_THAT(instructions.at(3), + AllOf(Field(&Instruction::op_code, OpCode::TORADIXLE), + Field(&Instruction::operands, + ElementsAre(VariantWith(3), + VariantWith(17), + VariantWith(21), + VariantWith(2), + VariantWith(256))))); + + // Assign a vector that we will mutate internally in gen_trace to store the return values; + std::vector returndata = std::vector(); + auto trace = Execution::gen_trace(instructions, returndata, std::vector{ FF::modulus - FF(1) }); + + // Find the first row enabling the TORADIXLE selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_radix_le == 1; }); + EXPECT_EQ(row->avm_main_ind_a, 17); + EXPECT_EQ(row->avm_main_ind_b, 21); + EXPECT_EQ(row->avm_main_mem_idx_a, 1); // Indirect(17) -> 1 + EXPECT_EQ(row->avm_main_mem_idx_b, 5); // Indirect(21) -> 5 + EXPECT_EQ(row->avm_main_ia, FF(FF::modulus - FF(1))); // Indirect(17) -> Direct(1) -> FF::modulus - FF(1) + EXPECT_EQ(row->avm_main_ib, 0); // Indirect(21) -> 5 -> Unintialized memory + EXPECT_EQ(row->avm_main_ic, 2); + EXPECT_EQ(row->avm_main_id, 256); + + // Expected output is bitwise decomposition of MODULUS - 1..could hardcode the result but it's a bit long + std::vector expected_output; + // Extract each bit. + for (size_t i = 0; i < 256; i++) { + FF expected_limb = (FF::modulus - 1) >> i & 1; + expected_output.emplace_back(expected_limb); + } + EXPECT_EQ(returndata, expected_output); + + validate_trace(std::move(trace)); +} // Negative test detecting an invalid opcode byte. TEST_F(AvmExecutionTests, invalidOpcode) {