diff --git a/barretenberg/cpp/pil/avm/avm_main.pil b/barretenberg/cpp/pil/avm/avm_main.pil index dcfafd1aafed..aee693953dab 100644 --- a/barretenberg/cpp/pil/avm/avm_main.pil +++ b/barretenberg/cpp/pil/avm/avm_main.pil @@ -7,6 +7,7 @@ include "avm_kernel.pil"; include "gadgets/avm_conversion.pil"; include "gadgets/avm_sha256.pil"; include "gadgets/avm_poseidon2.pil"; +include "gadgets/avm_keccakf1600.pil"; namespace avm_main(256); //===== CONSTANT POLYNOMIALS ================================================== @@ -52,6 +53,7 @@ namespace avm_main(256); pol commit sel_op_radix_le; pol commit sel_op_sha256; pol commit sel_op_poseidon2; + pol commit sel_op_keccak; //===== Fix Range Checks Selectors============================================= // We re-use the clk column for the lookup values of 8-bit resp. 16-bit range check. @@ -208,6 +210,7 @@ namespace avm_main(256); sel_op_radix_le * (1 - sel_op_radix_le) = 0; sel_op_sha256 * (1 - sel_op_sha256) = 0; sel_op_poseidon2 * (1 - sel_op_poseidon2) = 0; + sel_op_keccak * (1 - sel_op_keccak) = 0; sel_op_add * (1 - sel_op_add) = 0; sel_op_sub * (1 - sel_op_sub) = 0; @@ -361,7 +364,7 @@ namespace avm_main(256); //===== CONTROL_FLOW_CONSISTENCY ============================================ pol INTERNAL_CALL_STACK_SELECTORS = (first + sel_internal_call + sel_internal_return + sel_halt); pol ALL_BINARY_SEL = sel_op_and + sel_op_or + sel_op_xor; - pol ALL_GADGET_SEL = sel_op_radix_le + sel_op_sha256 + sel_op_poseidon2; + pol ALL_GADGET_SEL = sel_op_radix_le + sel_op_sha256 + sel_op_poseidon2 + sel_op_keccak; pol ALL_MEMORY_SEL = sel_cmov + sel_mov; pol OPCODE_SELECTORS = ALU_ALL_SEL + ALL_BINARY_SEL + ALL_MEMORY_SEL + ALL_GADGET_SEL + KERNEL_INPUT_SELECTORS + KERNEL_OUTPUT_SELECTORS; @@ -567,6 +570,12 @@ namespace avm_main(256); is avm_poseidon2.poseidon_perm_sel {avm_poseidon2.clk, avm_poseidon2.input, avm_poseidon2.output}; + // This will be enabled when we migrate just to keccakf1600, as getting keccak to work with it is tricky. + // #[PERM_MAIN_KECCAK] + // sel_op_keccak {clk, ia, ic} + // is + // avm_keccakf1600.keccakf1600_sel {avm_keccakf1600.clk, avm_keccakf1600.input, avm_keccakf1600.output}; + #[PERM_MAIN_MEM_A] mem_op_a {clk, space_id, 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_keccakf1600.pil b/barretenberg/cpp/pil/avm/gadgets/avm_keccakf1600.pil new file mode 100644 index 000000000000..acc9a54f277c --- /dev/null +++ b/barretenberg/cpp/pil/avm/gadgets/avm_keccakf1600.pil @@ -0,0 +1,13 @@ +include "../avm_main.pil"; + +namespace avm_keccakf1600(256); + + pol commit clk; + + // Selector for Keccak Permutation Operation + pol commit keccakf1600_sel; + keccakf1600_sel * (1 - keccakf1600_sel) = 0; + + // These will all be arrays, but we just store the first element for permutation to the main trace for now + pol commit input; + pol commit output; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_keccakf1600.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_keccakf1600.hpp new file mode 100644 index 000000000000..b5df59d290b3 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_keccakf1600.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_keccakf1600Row { + FF avm_keccakf1600_keccakf1600_sel{}; +}; + +inline std::string get_relation_label_avm_keccakf1600(int index) +{ + switch (index) {} + return std::to_string(index); +} + +template class avm_keccakf1600Impl { + 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_keccakf1600_keccakf1600_sel * (-avm_keccakf1600_keccakf1600_sel + FF(1))); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + } +}; + +template using avm_keccakf1600 = 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 059eb9d61b95..3970a9eaf17d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp @@ -78,6 +78,7 @@ template struct Avm_mainRow { FF avm_main_sel_op_fdiv{}; FF avm_main_sel_op_fee_per_da_gas{}; FF avm_main_sel_op_fee_per_l2_gas{}; + FF avm_main_sel_op_keccak{}; FF avm_main_sel_op_l1_to_l2_msg_exists{}; FF avm_main_sel_op_lt{}; FF avm_main_sel_op_lte{}; @@ -107,127 +108,127 @@ template struct Avm_mainRow { inline std::string get_relation_label_avm_main(int index) { switch (index) { - case 58: + case 59: return "OUTPUT_U8"; - case 59: + case 60: return "SUBOP_FDIV"; - case 60: + case 61: return "SUBOP_FDIV_ZERO_ERR1"; - case 61: + case 62: return "SUBOP_FDIV_ZERO_ERR2"; - case 62: + case 63: return "SUBOP_FDIV_R_IN_TAG_FF"; - case 63: + case 64: return "SUBOP_FDIV_W_IN_TAG_FF"; - case 64: + case 65: return "SUBOP_ERROR_RELEVANT_OP"; - case 65: + case 66: return "KERNEL_INPUT_ACTIVE_CHECK"; - case 66: + case 67: return "KERNEL_OUTPUT_ACTIVE_CHECK"; - case 68: + case 69: return "RETURN_POINTER_INCREMENT"; - case 74: + case 75: return "RETURN_POINTER_DECREMENT"; - case 79: + case 80: return "PC_INCREMENT"; - case 80: + case 81: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 81: + case 82: return "SPACE_ID_INTERNAL"; - case 82: + case 83: return "SPACE_ID_STANDARD_OPCODES"; - case 83: + case 84: return "CMOV_CONDITION_RES_1"; - case 84: + case 85: return "CMOV_CONDITION_RES_2"; - case 87: + case 88: return "MOV_SAME_VALUE_A"; - case 88: + case 89: return "MOV_SAME_VALUE_B"; - case 89: + case 90: return "MOV_MAIN_SAME_TAG"; - case 93: + case 94: return "SENDER_KERNEL"; - case 94: + case 95: return "ADDRESS_KERNEL"; - case 95: + case 96: return "FEE_DA_GAS_KERNEL"; - case 96: + case 97: return "FEE_L2_GAS_KERNEL"; - case 97: + case 98: return "FEE_TRANSACTION_FEE_KERNEL"; - case 98: + case 99: return "CHAIN_ID_KERNEL"; - case 99: + case 100: return "VERSION_KERNEL"; - case 100: + case 101: return "BLOCK_NUMBER_KERNEL"; - case 101: + case 102: return "COINBASE_KERNEL"; - case 102: + case 103: return "TIMESTAMP_KERNEL"; - case 103: + case 104: return "NOTE_HASH_KERNEL_OUTPUT"; - case 105: + case 106: return "EMIT_NOTE_HASH_KERNEL_OUTPUT"; - case 107: + case 108: return "NULLIFIER_EXISTS_KERNEL_OUTPUT"; - case 109: + case 110: return "EMIT_NULLIFIER_KERNEL_OUTPUT"; - case 111: + case 112: return "L1_TO_L2_MSG_EXISTS_KERNEL_OUTPUT"; - case 113: + case 114: return "EMIT_UNENCRYPTED_LOG_KERNEL_OUTPUT"; - case 115: + case 116: return "EMIT_L2_TO_L1_MSGS_KERNEL_OUTPUT"; - case 117: + case 118: return "SLOAD_KERNEL_OUTPUT"; - case 119: + case 120: return "SSTORE_KERNEL_OUTPUT"; - case 122: + case 123: return "BIN_SEL_1"; - case 123: + case 124: return "BIN_SEL_2"; } return std::to_string(index); @@ -237,11 +238,11 @@ 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, 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, 3, 5, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 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, 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, 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, 3, 5, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 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, 2, }; template @@ -431,7 +432,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (avm_main_sel_op_add * (-avm_main_sel_op_add + FF(1))); + auto tmp = (avm_main_sel_op_keccak * (-avm_main_sel_op_keccak + FF(1))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -439,7 +440,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(23); - 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<23>(evals) += tmp; } @@ -447,7 +448,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(24); - 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<24>(evals) += tmp; } @@ -455,7 +456,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(25); - 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<25>(evals) += tmp; } @@ -463,7 +464,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(26); - 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<26>(evals) += tmp; } @@ -471,7 +472,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(27); - 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<27>(evals) += tmp; } @@ -479,7 +480,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(28); - 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<28>(evals) += tmp; } @@ -487,7 +488,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(29); - 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<29>(evals) += tmp; } @@ -495,7 +496,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(30); - 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<30>(evals) += tmp; } @@ -503,7 +504,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(31); - 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<31>(evals) += tmp; } @@ -511,7 +512,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(32); - 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<32>(evals) += tmp; } @@ -519,7 +520,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(33); - 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<33>(evals) += tmp; } @@ -527,7 +528,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(34); - 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<34>(evals) += tmp; } @@ -535,7 +536,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(35); - 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<35>(evals) += tmp; } @@ -543,7 +544,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(36); - 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<36>(evals) += tmp; } @@ -551,7 +552,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(37); - 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<37>(evals) += tmp; } @@ -559,7 +560,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(38); - 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<38>(evals) += tmp; } @@ -567,7 +568,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(39); - 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<39>(evals) += tmp; } @@ -575,7 +576,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(40); - 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<40>(evals) += tmp; } @@ -583,7 +584,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(41); - 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<41>(evals) += tmp; } @@ -591,7 +592,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(42); - 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<42>(evals) += tmp; } @@ -599,7 +600,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(43); - 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<43>(evals) += tmp; } @@ -607,7 +608,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(44); - 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<44>(evals) += tmp; } @@ -615,7 +616,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(45); - 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<45>(evals) += tmp; } @@ -623,7 +624,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(46); - 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<46>(evals) += tmp; } @@ -631,7 +632,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(47); - 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<47>(evals) += tmp; } @@ -639,7 +640,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(48); - 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<48>(evals) += tmp; } @@ -647,7 +648,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(49); - 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<49>(evals) += tmp; } @@ -655,7 +656,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(50); - 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<50>(evals) += tmp; } @@ -663,7 +664,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(51); - 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<51>(evals) += tmp; } @@ -671,7 +672,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(52); - 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<52>(evals) += tmp; } @@ -679,7 +680,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(53); - 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<53>(evals) += tmp; } @@ -687,7 +688,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(54); - 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<54>(evals) += tmp; } @@ -695,7 +696,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(55); - 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<55>(evals) += tmp; } @@ -703,7 +704,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(56); - 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<56>(evals) += tmp; } @@ -711,7 +712,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(57); - 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<57>(evals) += tmp; } @@ -719,8 +720,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(58); - 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<58>(evals) += tmp; } @@ -729,7 +729,7 @@ template class avm_mainImpl { Avm_DECLARE_VIEWS(59); 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<59>(evals) += tmp; } @@ -737,8 +737,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(60); - 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<60>(evals) += tmp; } @@ -746,7 +746,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(61); - 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<61>(evals) += tmp; } @@ -754,7 +755,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(62); - 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<62>(evals) += tmp; } @@ -762,7 +763,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(63); - 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<63>(evals) += tmp; } @@ -770,7 +771,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(64); - 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<64>(evals) += tmp; } @@ -778,6 +779,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(65); + auto tmp = (avm_main_op_err * ((avm_main_sel_op_fdiv + avm_main_sel_op_div) - FF(1))); + tmp *= scaling_factor; + std::get<65>(evals) += tmp; + } + // Contribution 66 + { + Avm_DECLARE_VIEWS(66); + auto tmp = ((((((((((avm_main_sel_op_sender + avm_main_sel_op_address) + avm_main_sel_op_chain_id) + avm_main_sel_op_version) + avm_main_sel_op_block_number) + @@ -788,11 +797,11 @@ template class avm_mainImpl { avm_main_sel_op_transaction_fee) * (-avm_main_q_kernel_lookup + FF(1))); tmp *= scaling_factor; - std::get<65>(evals) += tmp; + std::get<66>(evals) += tmp; } - // Contribution 66 + // Contribution 67 { - Avm_DECLARE_VIEWS(66); + Avm_DECLARE_VIEWS(67); auto tmp = (((((((((avm_main_sel_op_note_hash_exists + avm_main_sel_op_emit_note_hash) + avm_main_sel_op_nullifier_exists) + @@ -804,22 +813,13 @@ template class avm_mainImpl { avm_main_sel_op_sstore) * (-avm_main_q_kernel_output_lookup + FF(1))); tmp *= scaling_factor; - std::get<66>(evals) += tmp; - } - // Contribution 67 - { - Avm_DECLARE_VIEWS(67); - - auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); - tmp *= scaling_factor; std::get<67>(evals) += tmp; } // Contribution 68 { Avm_DECLARE_VIEWS(68); - 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<68>(evals) += tmp; } @@ -827,7 +827,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(69); - 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<69>(evals) += tmp; } @@ -835,7 +836,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(70); - 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<70>(evals) += tmp; } @@ -843,7 +844,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(71); - 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<71>(evals) += tmp; } @@ -851,7 +852,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(72); - 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<72>(evals) += tmp; } @@ -859,7 +860,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(73); - 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<73>(evals) += tmp; } @@ -867,8 +868,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(74); - 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<74>(evals) += tmp; } @@ -876,7 +876,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(75); - 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<75>(evals) += tmp; } @@ -884,7 +885,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(76); - 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<76>(evals) += tmp; } @@ -892,7 +893,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(77); - 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<77>(evals) += tmp; } @@ -900,7 +901,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(78); - 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<78>(evals) += tmp; } @@ -908,6 +909,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(79); + auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); + tmp *= scaling_factor; + std::get<79>(evals) += tmp; + } + // Contribution 80 + { + Avm_DECLARE_VIEWS(80); + 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_mul) + avm_main_sel_op_div) + @@ -920,7 +929,8 @@ template class avm_mainImpl { avm_main_sel_op_cast) + ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)) + (avm_main_sel_cmov + avm_main_sel_mov)) + - ((avm_main_sel_op_radix_le + avm_main_sel_op_sha256) + avm_main_sel_op_poseidon2)) + + (((avm_main_sel_op_radix_le + avm_main_sel_op_sha256) + avm_main_sel_op_poseidon2) + + avm_main_sel_op_keccak)) + (((((((((avm_main_sel_op_sender + avm_main_sel_op_address) + avm_main_sel_op_chain_id) + avm_main_sel_op_version) + avm_main_sel_op_block_number) + @@ -939,30 +949,30 @@ template class avm_mainImpl { avm_main_sel_op_sstore))) * (avm_main_pc_shift - (avm_main_pc + FF(1)))); tmp *= scaling_factor; - std::get<79>(evals) += tmp; + std::get<80>(evals) += tmp; } - // Contribution 80 + // Contribution 81 { - Avm_DECLARE_VIEWS(80); + Avm_DECLARE_VIEWS(81); 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<80>(evals) += tmp; + std::get<81>(evals) += tmp; } - // Contribution 81 + // Contribution 82 { - Avm_DECLARE_VIEWS(81); + Avm_DECLARE_VIEWS(82); auto tmp = ((avm_main_sel_internal_call + avm_main_sel_internal_return) * (avm_main_space_id - FF(255))); tmp *= scaling_factor; - std::get<81>(evals) += tmp; + std::get<82>(evals) += tmp; } - // Contribution 82 + // Contribution 83 { - Avm_DECLARE_VIEWS(82); + Avm_DECLARE_VIEWS(83); auto tmp = ((((((((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_div) + @@ -975,7 +985,8 @@ template class avm_mainImpl { avm_main_sel_op_cast) + ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)) + (avm_main_sel_cmov + avm_main_sel_mov)) + - ((avm_main_sel_op_radix_le + avm_main_sel_op_sha256) + avm_main_sel_op_poseidon2)) + + (((avm_main_sel_op_radix_le + avm_main_sel_op_sha256) + avm_main_sel_op_poseidon2) + + avm_main_sel_op_keccak)) + (((((((((avm_main_sel_op_sender + avm_main_sel_op_address) + avm_main_sel_op_chain_id) + avm_main_sel_op_version) + avm_main_sel_op_block_number) + @@ -994,21 +1005,13 @@ template class avm_mainImpl { avm_main_sel_op_sstore)) * (avm_main_call_ptr - avm_main_space_id)); tmp *= scaling_factor; - std::get<82>(evals) += tmp; - } - // Contribution 83 - { - Avm_DECLARE_VIEWS(83); - - auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); - tmp *= scaling_factor; std::get<83>(evals) += tmp; } // Contribution 84 { Avm_DECLARE_VIEWS(84); - 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<84>(evals) += tmp; } @@ -1016,7 +1019,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(85); - 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<85>(evals) += tmp; } @@ -1024,7 +1027,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(86); - 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<86>(evals) += tmp; } @@ -1032,7 +1035,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(87); - 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<87>(evals) += tmp; } @@ -1040,7 +1043,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(88); - 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<88>(evals) += tmp; } @@ -1048,7 +1051,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(89); - 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<89>(evals) += tmp; } @@ -1056,6 +1059,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(90); + 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<90>(evals) += tmp; + } + // Contribution 91 + { + Avm_DECLARE_VIEWS(91); + 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) + @@ -1069,11 +1080,11 @@ template class avm_mainImpl { (-avm_main_tag_err + FF(1))) * (-avm_main_op_err + FF(1)))); tmp *= scaling_factor; - std::get<90>(evals) += tmp; + std::get<91>(evals) += tmp; } - // Contribution 91 + // Contribution 92 { - Avm_DECLARE_VIEWS(91); + Avm_DECLARE_VIEWS(92); auto tmp = ((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_div) + @@ -1085,21 +1096,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<91>(evals) += tmp; - } - // Contribution 92 - { - Avm_DECLARE_VIEWS(92); - - auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); - tmp *= scaling_factor; std::get<92>(evals) += tmp; } // Contribution 93 { Avm_DECLARE_VIEWS(93); - auto tmp = (avm_main_sel_op_sender * (avm_kernel_kernel_in_offset - FF(0))); + auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); tmp *= scaling_factor; std::get<93>(evals) += tmp; } @@ -1107,7 +1110,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(94); - auto tmp = (avm_main_sel_op_address * (avm_kernel_kernel_in_offset - FF(1))); + auto tmp = (avm_main_sel_op_sender * (avm_kernel_kernel_in_offset - FF(0))); tmp *= scaling_factor; std::get<94>(evals) += tmp; } @@ -1115,7 +1118,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(95); - auto tmp = (avm_main_sel_op_fee_per_da_gas * (avm_kernel_kernel_in_offset - FF(38))); + auto tmp = (avm_main_sel_op_address * (avm_kernel_kernel_in_offset - FF(1))); tmp *= scaling_factor; std::get<95>(evals) += tmp; } @@ -1123,7 +1126,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(96); - auto tmp = (avm_main_sel_op_fee_per_l2_gas * (avm_kernel_kernel_in_offset - FF(39))); + auto tmp = (avm_main_sel_op_fee_per_da_gas * (avm_kernel_kernel_in_offset - FF(38))); tmp *= scaling_factor; std::get<96>(evals) += tmp; } @@ -1131,7 +1134,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(97); - auto tmp = (avm_main_sel_op_transaction_fee * (avm_kernel_kernel_in_offset - FF(40))); + auto tmp = (avm_main_sel_op_fee_per_l2_gas * (avm_kernel_kernel_in_offset - FF(39))); tmp *= scaling_factor; std::get<97>(evals) += tmp; } @@ -1139,7 +1142,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(98); - auto tmp = (avm_main_sel_op_chain_id * (avm_kernel_kernel_in_offset - FF(29))); + auto tmp = (avm_main_sel_op_transaction_fee * (avm_kernel_kernel_in_offset - FF(40))); tmp *= scaling_factor; std::get<98>(evals) += tmp; } @@ -1147,7 +1150,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(99); - auto tmp = (avm_main_sel_op_version * (avm_kernel_kernel_in_offset - FF(30))); + auto tmp = (avm_main_sel_op_chain_id * (avm_kernel_kernel_in_offset - FF(29))); tmp *= scaling_factor; std::get<99>(evals) += tmp; } @@ -1155,7 +1158,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(100); - auto tmp = (avm_main_sel_op_block_number * (avm_kernel_kernel_in_offset - FF(31))); + auto tmp = (avm_main_sel_op_version * (avm_kernel_kernel_in_offset - FF(30))); tmp *= scaling_factor; std::get<100>(evals) += tmp; } @@ -1163,7 +1166,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(101); - auto tmp = (avm_main_sel_op_coinbase * (avm_kernel_kernel_in_offset - FF(33))); + auto tmp = (avm_main_sel_op_block_number * (avm_kernel_kernel_in_offset - FF(31))); tmp *= scaling_factor; std::get<101>(evals) += tmp; } @@ -1171,7 +1174,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(102); - auto tmp = (avm_main_sel_op_timestamp * (avm_kernel_kernel_in_offset - FF(32))); + auto tmp = (avm_main_sel_op_coinbase * (avm_kernel_kernel_in_offset - FF(33))); tmp *= scaling_factor; std::get<102>(evals) += tmp; } @@ -1179,8 +1182,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(103); - auto tmp = (avm_main_sel_op_note_hash_exists * - (avm_kernel_kernel_out_offset - (avm_kernel_note_hash_exist_write_offset + FF(0)))); + auto tmp = (avm_main_sel_op_timestamp * (avm_kernel_kernel_in_offset - FF(32))); tmp *= scaling_factor; std::get<103>(evals) += tmp; } @@ -1188,7 +1190,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(104); - auto tmp = (avm_main_first * avm_kernel_note_hash_exist_write_offset); + auto tmp = (avm_main_sel_op_note_hash_exists * + (avm_kernel_kernel_out_offset - (avm_kernel_note_hash_exist_write_offset + FF(0)))); tmp *= scaling_factor; std::get<104>(evals) += tmp; } @@ -1196,8 +1199,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(105); - auto tmp = (avm_main_sel_op_emit_note_hash * - (avm_kernel_kernel_out_offset - (avm_kernel_emit_note_hash_write_offset + FF(4)))); + auto tmp = (avm_main_first * avm_kernel_note_hash_exist_write_offset); tmp *= scaling_factor; std::get<105>(evals) += tmp; } @@ -1205,7 +1207,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(106); - auto tmp = (avm_main_first * avm_kernel_emit_note_hash_write_offset); + auto tmp = (avm_main_sel_op_emit_note_hash * + (avm_kernel_kernel_out_offset - (avm_kernel_emit_note_hash_write_offset + FF(4)))); tmp *= scaling_factor; std::get<106>(evals) += tmp; } @@ -1213,8 +1216,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(107); - auto tmp = (avm_main_sel_op_nullifier_exists * - (avm_kernel_kernel_out_offset - (avm_kernel_nullifier_exists_write_offset + FF(8)))); + auto tmp = (avm_main_first * avm_kernel_emit_note_hash_write_offset); tmp *= scaling_factor; std::get<107>(evals) += tmp; } @@ -1222,7 +1224,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(108); - auto tmp = (avm_main_first * avm_kernel_nullifier_exists_write_offset); + auto tmp = (avm_main_sel_op_nullifier_exists * + (avm_kernel_kernel_out_offset - (avm_kernel_nullifier_exists_write_offset + FF(8)))); tmp *= scaling_factor; std::get<108>(evals) += tmp; } @@ -1230,8 +1233,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(109); - auto tmp = (avm_main_sel_op_emit_nullifier * - (avm_kernel_kernel_out_offset - (avm_kernel_emit_nullifier_write_offset + FF(12)))); + auto tmp = (avm_main_first * avm_kernel_nullifier_exists_write_offset); tmp *= scaling_factor; std::get<109>(evals) += tmp; } @@ -1239,7 +1241,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(110); - auto tmp = (avm_main_first * avm_kernel_emit_nullifier_write_offset); + auto tmp = (avm_main_sel_op_emit_nullifier * + (avm_kernel_kernel_out_offset - (avm_kernel_emit_nullifier_write_offset + FF(12)))); tmp *= scaling_factor; std::get<110>(evals) += tmp; } @@ -1247,8 +1250,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(111); - auto tmp = (avm_main_sel_op_l1_to_l2_msg_exists * - (avm_kernel_kernel_out_offset - (avm_kernel_l1_to_l2_msg_exists_write_offset + FF(16)))); + auto tmp = (avm_main_first * avm_kernel_emit_nullifier_write_offset); tmp *= scaling_factor; std::get<111>(evals) += tmp; } @@ -1256,7 +1258,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(112); - auto tmp = (avm_main_first * avm_kernel_l1_to_l2_msg_exists_write_offset); + auto tmp = (avm_main_sel_op_l1_to_l2_msg_exists * + (avm_kernel_kernel_out_offset - (avm_kernel_l1_to_l2_msg_exists_write_offset + FF(16)))); tmp *= scaling_factor; std::get<112>(evals) += tmp; } @@ -1264,8 +1267,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(113); - auto tmp = (avm_main_sel_op_emit_unencrypted_log * - (avm_kernel_kernel_out_offset - (avm_kernel_emit_unencrypted_log_write_offset + FF(20)))); + auto tmp = (avm_main_first * avm_kernel_l1_to_l2_msg_exists_write_offset); tmp *= scaling_factor; std::get<113>(evals) += tmp; } @@ -1273,7 +1275,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(114); - auto tmp = (avm_main_first * avm_kernel_emit_unencrypted_log_write_offset); + auto tmp = (avm_main_sel_op_emit_unencrypted_log * + (avm_kernel_kernel_out_offset - (avm_kernel_emit_unencrypted_log_write_offset + FF(20)))); tmp *= scaling_factor; std::get<114>(evals) += tmp; } @@ -1281,8 +1284,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(115); - auto tmp = (avm_main_sel_op_emit_l2_to_l1_msg * - (avm_kernel_kernel_out_offset - (avm_kernel_emit_l2_to_l1_msg_write_offset + FF(24)))); + auto tmp = (avm_main_first * avm_kernel_emit_unencrypted_log_write_offset); tmp *= scaling_factor; std::get<115>(evals) += tmp; } @@ -1290,7 +1292,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(116); - auto tmp = (avm_main_first * avm_kernel_emit_l2_to_l1_msg_write_offset); + auto tmp = (avm_main_sel_op_emit_l2_to_l1_msg * + (avm_kernel_kernel_out_offset - (avm_kernel_emit_l2_to_l1_msg_write_offset + FF(24)))); tmp *= scaling_factor; std::get<116>(evals) += tmp; } @@ -1298,8 +1301,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(117); - auto tmp = - (avm_main_sel_op_sload * (avm_kernel_kernel_out_offset - (avm_kernel_sload_write_offset + FF(28)))); + auto tmp = (avm_main_first * avm_kernel_emit_l2_to_l1_msg_write_offset); tmp *= scaling_factor; std::get<117>(evals) += tmp; } @@ -1307,7 +1309,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(118); - auto tmp = (avm_main_first * avm_kernel_sload_write_offset); + auto tmp = + (avm_main_sel_op_sload * (avm_kernel_kernel_out_offset - (avm_kernel_sload_write_offset + FF(28)))); tmp *= scaling_factor; std::get<118>(evals) += tmp; } @@ -1315,8 +1318,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(119); - auto tmp = - (avm_main_sel_op_sstore * (avm_kernel_kernel_out_offset - (avm_kernel_sstore_write_offset + FF(32)))); + auto tmp = (avm_main_first * avm_kernel_sload_write_offset); tmp *= scaling_factor; std::get<119>(evals) += tmp; } @@ -1324,7 +1326,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(120); - auto tmp = (avm_main_first * avm_kernel_sstore_write_offset); + auto tmp = + (avm_main_sel_op_sstore * (avm_kernel_kernel_out_offset - (avm_kernel_sstore_write_offset + FF(32)))); tmp *= scaling_factor; std::get<120>(evals) += tmp; } @@ -1332,6 +1335,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(121); + auto tmp = (avm_main_first * avm_kernel_sstore_write_offset); + tmp *= scaling_factor; + std::get<121>(evals) += tmp; + } + // Contribution 122 + { + Avm_DECLARE_VIEWS(122); + auto tmp = (((((((((avm_main_sel_op_note_hash_exists + avm_main_sel_op_emit_note_hash) + avm_main_sel_op_nullifier_exists) + avm_main_sel_op_emit_nullifier) + @@ -1342,23 +1353,23 @@ template class avm_mainImpl { avm_main_sel_op_sstore) * (avm_kernel_side_effect_counter_shift - (avm_kernel_side_effect_counter + FF(1)))); tmp *= scaling_factor; - std::get<121>(evals) += tmp; + std::get<122>(evals) += tmp; } - // Contribution 122 + // Contribution 123 { - Avm_DECLARE_VIEWS(122); + Avm_DECLARE_VIEWS(123); auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); tmp *= scaling_factor; - std::get<122>(evals) += tmp; + std::get<123>(evals) += tmp; } - // Contribution 123 + // Contribution 124 { - Avm_DECLARE_VIEWS(123); + Avm_DECLARE_VIEWS(124); 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<123>(evals) += tmp; + std::get<124>(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 798cf989d1c1..e2e377fdaef4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -112,6 +112,10 @@ [[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_keccakf1600_clk = View(new_term.avm_keccakf1600_clk); \ + [[maybe_unused]] auto avm_keccakf1600_input = View(new_term.avm_keccakf1600_input); \ + [[maybe_unused]] auto avm_keccakf1600_keccakf1600_sel = View(new_term.avm_keccakf1600_keccakf1600_sel); \ + [[maybe_unused]] auto avm_keccakf1600_output = View(new_term.avm_keccakf1600_output); \ [[maybe_unused]] auto avm_kernel_emit_l2_to_l1_msg_write_offset = \ View(new_term.avm_kernel_emit_l2_to_l1_msg_write_offset); \ [[maybe_unused]] auto avm_kernel_emit_note_hash_write_offset = \ @@ -204,6 +208,7 @@ [[maybe_unused]] auto avm_main_sel_op_fdiv = View(new_term.avm_main_sel_op_fdiv); \ [[maybe_unused]] auto avm_main_sel_op_fee_per_da_gas = View(new_term.avm_main_sel_op_fee_per_da_gas); \ [[maybe_unused]] auto avm_main_sel_op_fee_per_l2_gas = View(new_term.avm_main_sel_op_fee_per_l2_gas); \ + [[maybe_unused]] auto avm_main_sel_op_keccak = View(new_term.avm_main_sel_op_keccak); \ [[maybe_unused]] auto avm_main_sel_op_l1_to_l2_msg_exists = View(new_term.avm_main_sel_op_l1_to_l2_msg_exists); \ [[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); \ 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 b9459320d401..389da5701692 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -111,6 +111,8 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::SHA256COMPRESSION, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::POSEIDON2, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::KECCAK, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::KECCAKF1600, { OperandType::INDIRECT, 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 da3634e9d550..dd732650dcb1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -297,6 +297,20 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(1)), std::get(inst.operands.at(2))); + break; + case OpCode::KECCAK: + trace_builder.op_keccak(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; + case OpCode::KECCAKF1600: + trace_builder.op_keccakf1600(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; default: throw_or_abort("Don't know how to execute opcode " + to_hex(inst.op_code) + " at pc " + std::to_string(pc) + diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp index 046934a99c2d..cc7cdd2b431e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp @@ -1,5 +1,7 @@ #pragma once +#include "barretenberg/common/log.hpp" +#include "barretenberg/common/serialize.hpp" #include #include #include @@ -107,6 +109,7 @@ enum class OpCode : uint8_t { TORADIXLE, // Future Gadgets -- pending changes in noir SHA256COMPRESSION, + KECCAKF1600, // Here for when we eventually support this // Sentinel LAST_OPCODE_SENTINEL, @@ -124,7 +127,7 @@ std::string to_hex(T value) { std::ostringstream stream; auto num_bytes = static_cast(sizeof(T)); - uint64_t mask = (static_cast(1) << (num_bytes * 8)) - 1; + auto mask = static_cast((static_cast(1) << (num_bytes * 8)) - 1); auto padding = static_cast(num_bytes * 2); stream << std::setfill('0') << std::setw(padding) << std::hex << (value & mask); return stream.str(); 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 79aca60e186a..ee34862d571a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -1999,18 +1999,22 @@ void AvmTraceBuilder::read_slice_to_memory(uint8_t space_id, main_row.avm_main_ia = slice.at(offset); main_row.avm_main_mem_idx_a = FF(src_offset + offset); main_row.avm_main_mem_op_a = FF(1); + main_row.avm_main_tag_err = FF(static_cast(!mem_read.tag_match)); } else if (j == 1) { main_row.avm_main_ib = slice.at(offset); main_row.avm_main_mem_idx_b = FF(src_offset + offset); main_row.avm_main_mem_op_b = FF(1); + main_row.avm_main_tag_err = FF(static_cast(!mem_read.tag_match)); } else if (j == 2) { main_row.avm_main_ic = slice.at(offset); main_row.avm_main_mem_idx_c = FF(src_offset + offset); main_row.avm_main_mem_op_c = FF(1); + main_row.avm_main_tag_err = FF(static_cast(!mem_read.tag_match)); } else { main_row.avm_main_id = slice.at(offset); main_row.avm_main_mem_idx_d = FF(src_offset + offset); main_row.avm_main_mem_op_d = FF(1); + main_row.avm_main_tag_err = FF(static_cast(!mem_read.tag_match)); } } main_trace.emplace_back(main_row); @@ -2282,6 +2286,255 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ call_ptr, clk, direct_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, FF(internal_return_ptr), ff_result); } +/** + * @brief Keccakf1600 with direct or indirect memory access. + * This function temporarily has the same interface as the kecccak opcode for compatibility, when the keccak migration + * is complete (to keccakf1600) We will update this function call as we will not likely need input_size_offset + * @param indirect byte encoding information about indirect/direct memory access. + * @param output_offset An index in memory pointing to where the first u64 value of the output array should be stored. + * @param input_offset An index in memory pointing to the first u64 value of the input array to be used in the next + * instance of poseidon2 permutation. + * @param input_size offset An index in memory pointing to the size of the input array. Temporary while we maintain the + * same interface as keccak (this is fixed to 25) + */ +void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, + uint32_t output_offset, + uint32_t input_offset, + uint32_t input_size_offset) +{ + // What happens if the input_size_offset is > 25 when the state is more that that? + auto clk = static_cast(main_trace.size()); + // bool tag_match = res.tag_match; + bool tag_match = true; + uint32_t direct_src_offset = input_offset; + uint32_t direct_dst_offset = output_offset; + + bool indirect_src_flag = is_operand_indirect(indirect, 1); + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + + if (indirect_src_flag) { + auto read_ind_src = + mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, input_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(call_ptr, clk, IndirectRegister::IND_C, output_offset); + direct_dst_offset = uint32_t(read_ind_dst.val); + tag_match = tag_match && read_ind_dst.tag_match; + } + + auto input_read = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::U64, AvmMemoryTag::U64); + auto output_read = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk, IntermRegister::IC, direct_dst_offset, AvmMemoryTag::U64, AvmMemoryTag::U64); + + main_trace.push_back(Row{ + .avm_main_clk = clk, + .avm_main_ia = input_read.val, // First element of input + .avm_main_ic = output_read.val, // First element of output + .avm_main_ind_a = indirect_src_flag ? FF(input_offset) : FF(0), + .avm_main_ind_c = indirect_dst_flag ? FF(output_offset) : FF(0), + .avm_main_ind_op_a = FF(static_cast(indirect_src_flag)), + .avm_main_ind_op_c = FF(static_cast(indirect_dst_flag)), + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_mem_idx_a = FF(direct_src_offset), // input + .avm_main_mem_idx_c = FF(direct_dst_offset), // output + .avm_main_mem_op_a = FF(1), + .avm_main_mem_op_c = FF(1), + .avm_main_pc = FF(pc++), + .avm_main_r_in_tag = FF(static_cast(AvmMemoryTag::U64)), + .avm_main_sel_op_keccak = FF(1), + .avm_main_w_in_tag = FF(static_cast(AvmMemoryTag::U64)), + }); + // We store the current clk this main trace row occurred so that we can line up the keccak gadget operation + // at the same clk later. + auto keccak_op_clk = clk; + // We need to increment the clk + clk++; + auto input_length_read = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk, IntermRegister::IB, input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); + main_trace.push_back(Row{ + .avm_main_clk = clk, + .avm_main_ib = input_length_read.val, // Message Length + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_mem_idx_b = FF(input_size_offset), // length + .avm_main_mem_op_b = FF(1), + .avm_main_pc = FF(pc), + .avm_main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), + .avm_main_w_in_tag = FF(static_cast(AvmMemoryTag::U32)), + }); + clk++; + // Array input is fixed to 1600 bits + std::array input; + // Check if the input size is greater than 25 + ASSERT(input.size() <= 25); + // Read results are written to input array + read_slice_to_memory( + call_ptr, clk, direct_src_offset, AvmMemoryTag::U64, AvmMemoryTag::U64, FF(internal_return_ptr), input); + + // Increment the clock by 7 since (25 reads / 4 reads per row = 7) + clk += 7; + + // Now that we have read all the values, we can perform the operation to get the resulting witness. + // Note: We use the keccak_op_clk to ensure that the keccakf1600 operation is performed at the same clock cycle as + // the main trace that has the selector + std::array result = keccak_trace_builder.keccakf1600(keccak_op_clk, input); + // We convert the results to field elements here + std::vector ff_result; + for (uint32_t i = 0; i < 25; i++) { + ff_result.emplace_back(result[i]); + } + + // Write the result to memory after + write_slice_to_memory( + call_ptr, clk, direct_dst_offset, AvmMemoryTag::U64, AvmMemoryTag::U64, FF(internal_return_ptr), ff_result); +} + +/** + * @brief Keccak with direct or indirect memory access. + * Keccak is TEMPORARY while we wait for the transition to keccakf1600, so we do the minimal to store the result + * @param indirect byte encoding information about indirect/direct memory access. + * @param output_offset An index in memory pointing to where the first u8 value of the output array should be stored. + * @param input_offset An index in memory pointing to the first u8 value of the input array to be used in the next + * instance of poseidon2 permutation. + * @param input_size offset An index in memory pointing to the size of the input array. + */ +void AvmTraceBuilder::op_keccak(uint8_t indirect, + uint32_t output_offset, + uint32_t input_offset, + uint32_t input_size_offset) +{ + auto clk = static_cast(main_trace.size()); + bool tag_match = true; + uint32_t direct_src_offset = input_offset; + uint32_t direct_dst_offset = output_offset; + + bool indirect_src_flag = is_operand_indirect(indirect, 1); + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + + if (indirect_src_flag) { + auto read_ind_src = + mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, input_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(call_ptr, clk, IndirectRegister::IND_C, output_offset); + direct_dst_offset = uint32_t(read_ind_dst.val); + tag_match = tag_match && read_ind_dst.tag_match; + } + // Note we load the input and output onto one line in the main trace and the length on the next line + // We do this so we can load two different AvmMemoryTags (u8 for the I/O and u32 for the length) + auto input_read = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::U8, AvmMemoryTag::U8); + auto output_read = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk, IntermRegister::IC, direct_dst_offset, AvmMemoryTag::U8, AvmMemoryTag::U8); + + // Store the clock time that we will use to line up the gadget later + auto keccak_op_clk = clk; + main_trace.push_back(Row{ + .avm_main_clk = clk, + .avm_main_ia = input_read.val, // First element of input + .avm_main_ic = output_read.val, // First element of output + .avm_main_ind_a = indirect_src_flag ? FF(input_offset) : FF(0), + .avm_main_ind_c = indirect_dst_flag ? FF(output_offset) : FF(0), + .avm_main_ind_op_a = FF(static_cast(indirect_src_flag)), + .avm_main_ind_op_c = FF(static_cast(indirect_dst_flag)), + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_mem_idx_a = FF(direct_src_offset), // input + .avm_main_mem_idx_c = FF(direct_dst_offset), // output + .avm_main_mem_op_a = FF(1), + .avm_main_mem_op_c = FF(1), + .avm_main_pc = FF(pc++), + .avm_main_r_in_tag = FF(static_cast(AvmMemoryTag::U8)), + .avm_main_sel_op_keccak = FF(1), + .avm_main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), + }); + clk++; + auto input_length_read = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk, IntermRegister::IB, input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); + main_trace.push_back(Row{ + .avm_main_clk = clk, + .avm_main_ib = input_length_read.val, // Message Length + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_mem_idx_b = FF(input_size_offset), // length + .avm_main_mem_op_b = FF(1), + .avm_main_pc = FF(pc), + .avm_main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), + .avm_main_w_in_tag = FF(static_cast(AvmMemoryTag::U32)), + }); + clk++; + + std::vector input; + input.reserve(uint32_t(input_length_read.val)); + + // We unroll this loop because the function typically expects arrays and for this temporary keccak function we have + // a dynamic amount of input so we will use a vector. + 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(input_length_read.val) / 4 + + static_cast(uint32_t(input_length_read.val) % 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_pc = FF(pc), + .avm_main_r_in_tag = FF(static_cast(AvmMemoryTag::U8)), + .avm_main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), + }; + // 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 >= uint32_t(input_length_read.val)) { + break; + } + auto mem_read = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk + i, register_order[j], direct_src_offset + offset, AvmMemoryTag::U8, AvmMemoryTag::U8); + input.emplace_back(uint8_t(mem_read.val)); + // This looks a bit gross, but it is fine for now. + if (j == 0) { + main_row.avm_main_ia = input.at(offset); + main_row.avm_main_mem_idx_a = FF(direct_src_offset + offset); + main_row.avm_main_mem_op_a = FF(1); + main_row.avm_main_tag_err = FF(static_cast(!mem_read.tag_match)); + } else if (j == 1) { + main_row.avm_main_ib = input.at(offset); + main_row.avm_main_mem_idx_b = FF(direct_src_offset + offset); + main_row.avm_main_mem_op_b = FF(1); + main_row.avm_main_tag_err = FF(static_cast(!mem_read.tag_match)); + } else if (j == 2) { + main_row.avm_main_ic = input.at(offset); + main_row.avm_main_mem_idx_c = FF(direct_src_offset + offset); + main_row.avm_main_mem_op_c = FF(1); + main_row.avm_main_tag_err = FF(static_cast(!mem_read.tag_match)); + } else { + main_row.avm_main_id = input.at(offset); + main_row.avm_main_mem_idx_d = FF(direct_src_offset + offset); + main_row.avm_main_mem_op_d = FF(1); + main_row.avm_main_tag_err = FF(static_cast(!mem_read.tag_match)); + } + } + main_trace.emplace_back(main_row); + } + + clk += num_main_rows; + + std::array result = keccak_trace_builder.keccak(keccak_op_clk, input, uint32_t(input_length_read.val)); + // We convert the results to field elements here + std::vector ff_result; + for (uint32_t i = 0; i < 32; i++) { + ff_result.emplace_back(result[i]); + } + // Write the result to memory after + write_slice_to_memory( + call_ptr, clk, direct_dst_offset, AvmMemoryTag::U8, AvmMemoryTag::U8, FF(internal_return_ptr), ff_result); +} // Finalise Lookup Counts // // For log derivative lookups, we require a column that contains the number of times each lookup is consumed @@ -2407,6 +2660,7 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c auto conv_trace = conversion_trace_builder.finalize(); auto sha256_trace = sha256_trace_builder.finalize(); auto poseidon2_trace = poseidon2_trace_builder.finalize(); + auto keccak_trace = keccak_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(); @@ -2414,6 +2668,7 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c size_t conv_trace_size = conv_trace.size(); size_t sha256_trace_size = sha256_trace.size(); size_t poseidon2_trace_size = poseidon2_trace.size(); + size_t keccak_trace_size = keccak_trace.size(); size_t bin_trace_size = bin_trace.size(); // Get tag_err counts from the mem_trace_builder @@ -2790,7 +3045,7 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.avm_sha256_sha256_compression_sel = FF(1); dest.avm_sha256_state = src.state[0]; } - // + // Add Poseidon2 Gadget table for (size_t i = 0; i < poseidon2_trace_size; i++) { auto const& src = poseidon2_trace.at(i); @@ -2802,6 +3057,17 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.avm_poseidon2_poseidon_perm_sel = FF(1); } + // Add KeccakF1600 Gadget table + for (size_t i = 0; i < keccak_trace_size; i++) { + auto const& src = keccak_trace.at(i); + auto& dest = main_trace.at(i); + dest.avm_keccakf1600_clk = FF(src.clk); + dest.avm_keccakf1600_input = FF(src.input[0]); + // TODO: This will need to be enabled later + // dest.avm_keccakf1600_output = src.output[0]; + dest.avm_keccakf1600_keccakf1600_sel = FF(1); + } + // Add Binary Trace table for (size_t i = 0; i < bin_trace_size; i++) { auto const& src = bin_trace.at(i); 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 40c5fe64a0d2..1b3ecc50fbbd 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -8,14 +8,14 @@ #include "avm_instructions.hpp" #include "avm_mem_trace.hpp" #include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/relations/generated/avm/avm_main.hpp" +#include "barretenberg/vm/avm_trace/avm_kernel_trace.hpp" #include "barretenberg/vm/avm_trace/gadgets/avm_conversion_trace.hpp" +#include "barretenberg/vm/avm_trace/gadgets/avm_keccak.hpp" #include "barretenberg/vm/avm_trace/gadgets/avm_poseidon2.hpp" #include "barretenberg/vm/avm_trace/gadgets/avm_sha256.hpp" #include "constants.hpp" -#include "barretenberg/relations/generated/avm/avm_main.hpp" -#include "barretenberg/vm/avm_trace/avm_kernel_trace.hpp" - namespace bb::avm_trace { // This is the internal context that we keep along the lifecycle of bytecode execution @@ -155,6 +155,10 @@ class AvmTraceBuilder { void op_sha256_compression(uint8_t indirect, uint32_t output_offset, uint32_t h_init_offset, uint32_t input_offset); // Poseidon2 Permutation operation void op_poseidon2_permutation(uint8_t indirect, uint32_t input_offset, uint32_t output_offset); + // Keccakf1600 operation - interface will likely change (e..g no input size offset) + void op_keccakf1600(uint8_t indirect, uint32_t output_offset, uint32_t input_offset, uint32_t input_size_offset); + // Keccak operation - temporary while we transition to keccakf1600 + void op_keccak(uint8_t indirect, uint32_t output_offset, uint32_t input_offset, uint32_t input_size_offset); private: // Used for the standard indirect address resolution of three operands opcode. @@ -177,6 +181,7 @@ class AvmTraceBuilder { AvmConversionTraceBuilder conversion_trace_builder; AvmSha256TraceBuilder sha256_trace_builder; AvmPoseidon2TraceBuilder poseidon2_trace_builder; + AvmKeccakTraceBuilder keccak_trace_builder; /** * @brief Create a kernel lookup opcode object diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_keccak.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_keccak.cpp new file mode 100644 index 000000000000..9f3e9e2b0fd6 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_keccak.cpp @@ -0,0 +1,83 @@ + + +#include "barretenberg/vm/avm_trace/gadgets/avm_keccak.hpp" +#include "barretenberg/crypto/hashers/hashers.hpp" +#include "barretenberg/crypto/keccak/keccak.hpp" +#include +#include +namespace bb::avm_trace { + +AvmKeccakTraceBuilder::AvmKeccakTraceBuilder() +{ + keccak_trace.reserve(AVM_TRACE_SIZE); +} + +std::vector AvmKeccakTraceBuilder::finalize() +{ + return std::move(keccak_trace); +} + +void AvmKeccakTraceBuilder::reset() +{ + keccak_trace.clear(); +} + +std::array AvmKeccakTraceBuilder::keccakf1600(uint32_t clk, std::array input) +{ + // BB's Eth hash function uses C-style arrays, while we like to use std::array + // We do a few conversions for here but maybe we will update later. + uint64_t state[25] = {}; + std::copy(input.begin(), input.end(), state); + std::vector input_vector(input.begin(), input.end()); + // This function mutates state + ethash_keccakf1600(state); + std::array output = {}; + for (size_t i = 0; i < 25; i++) { + output[i] = state[i]; + } + std::vector output_vector(output.begin(), output.end()); + keccak_trace.push_back(KeccakTraceEntry{ + .clk = clk, + .input = input_vector, + .output = output_vector, + .input_size = 25, + .output_size = 25, + }); + return output; +} + +std::array AvmKeccakTraceBuilder::keccak(uint32_t clk, std::vector input, uint32_t size) +{ + // We treat the input vector as an array of 64-bit integers for the avm (even though keccak takes in bytes). + std::vector vector_input; + for (size_t i = 0; i < input.size(); i += 4) { + auto uint64 = from_buffer(input, i); + vector_input.push_back(uint64); + } + auto result = ethash_keccak256(&input[0], size); + std::vector output_vector = {}; + std::array output_bytes = {}; + // The result encodes each limb in LE, we need to swap them to BE + // If we had C++23 we could use std::byteswap, but instead we write our own + for (size_t i = 0; i < 4; i++) { + std::vector le_bytes = to_buffer(result.word64s[i]); + // Reverse the bytes + std::ranges::reverse(le_bytes); + // Convert the bytes back to a uint64_t + auto be_u64 = from_buffer(le_bytes); + output_vector.push_back(be_u64); + // Copy the bytes to the output + for (size_t j = 0; j < 8; j++) { + output_bytes[i * 8 + j] = le_bytes[j]; + } + } + keccak_trace.push_back(KeccakTraceEntry{ + .clk = clk, + .input = vector_input, + .output = output_vector, + .input_size = size, + .output_size = 4, + }); + return output_bytes; +} +} // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_keccak.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_keccak.hpp new file mode 100644 index 000000000000..dc8456b8505a --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_keccak.hpp @@ -0,0 +1,29 @@ + +#pragma once + +#include "../avm_common.hpp" +#include + +namespace bb::avm_trace { +class AvmKeccakTraceBuilder { + public: + struct KeccakTraceEntry { + uint32_t clk = 0; + std::vector input; + std::vector output; + uint32_t input_size = 0; + uint32_t output_size = 0; + }; + + AvmKeccakTraceBuilder(); + void reset(); + // Finalize the trace + std::vector finalize(); + + std::array keccakf1600(uint32_t clk, std::array input); + std::array keccak(uint32_t clk, std::vector input, uint32_t size); + + private: + std::vector keccak_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 4d39496065fa..9c6ea6d1cdc4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -19,6 +19,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_keccakf1600.hpp" #include "barretenberg/relations/generated/avm/avm_kernel.hpp" #include "barretenberg/relations/generated/avm/avm_main.hpp" #include "barretenberg/relations/generated/avm/avm_mem.hpp" @@ -188,6 +189,10 @@ template struct AvmFullRow { FF avm_conversion_num_limbs{}; FF avm_conversion_radix{}; FF avm_conversion_to_radix_le_sel{}; + FF avm_keccakf1600_clk{}; + FF avm_keccakf1600_input{}; + FF avm_keccakf1600_keccakf1600_sel{}; + FF avm_keccakf1600_output{}; FF avm_kernel_emit_l2_to_l1_msg_write_offset{}; FF avm_kernel_emit_note_hash_write_offset{}; FF avm_kernel_emit_nullifier_write_offset{}; @@ -268,6 +273,7 @@ template struct AvmFullRow { FF avm_main_sel_op_fdiv{}; FF avm_main_sel_op_fee_per_da_gas{}; FF avm_main_sel_op_fee_per_l2_gas{}; + FF avm_main_sel_op_keccak{}; FF avm_main_sel_op_l1_to_l2_msg_exists{}; FF avm_main_sel_op_lt{}; FF avm_main_sel_op_lte{}; @@ -494,8 +500,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 404; - static constexpr size_t num_polys = 342; + static constexpr size_t num_fixed_columns = 409; + static constexpr size_t num_polys = 347; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -621,6 +627,10 @@ class AvmCircuitBuilder { 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_keccakf1600_clk[i] = rows[i].avm_keccakf1600_clk; + polys.avm_keccakf1600_input[i] = rows[i].avm_keccakf1600_input; + polys.avm_keccakf1600_keccakf1600_sel[i] = rows[i].avm_keccakf1600_keccakf1600_sel; + polys.avm_keccakf1600_output[i] = rows[i].avm_keccakf1600_output; polys.avm_kernel_emit_l2_to_l1_msg_write_offset[i] = rows[i].avm_kernel_emit_l2_to_l1_msg_write_offset; polys.avm_kernel_emit_note_hash_write_offset[i] = rows[i].avm_kernel_emit_note_hash_write_offset; polys.avm_kernel_emit_nullifier_write_offset[i] = rows[i].avm_kernel_emit_nullifier_write_offset; @@ -705,6 +715,7 @@ class AvmCircuitBuilder { polys.avm_main_sel_op_fdiv[i] = rows[i].avm_main_sel_op_fdiv; polys.avm_main_sel_op_fee_per_da_gas[i] = rows[i].avm_main_sel_op_fee_per_da_gas; polys.avm_main_sel_op_fee_per_l2_gas[i] = rows[i].avm_main_sel_op_fee_per_l2_gas; + polys.avm_main_sel_op_keccak[i] = rows[i].avm_main_sel_op_keccak; polys.avm_main_sel_op_l1_to_l2_msg_exists[i] = rows[i].avm_main_sel_op_l1_to_l2_msg_exists; 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; @@ -965,6 +976,11 @@ class AvmCircuitBuilder { "avm_conversion", Avm_vm::get_relation_label_avm_conversion); }; + auto avm_keccakf1600 = [=]() { + return evaluate_relation.template operator()>( + "avm_keccakf1600", Avm_vm::get_relation_label_avm_keccakf1600); + }; + auto avm_kernel = [=]() { return evaluate_relation.template operator()>("avm_kernel", Avm_vm::get_relation_label_avm_kernel); @@ -1202,6 +1218,8 @@ class AvmCircuitBuilder { relation_futures.emplace_back(std::async(std::launch::async, avm_conversion)); + relation_futures.emplace_back(std::async(std::launch::async, avm_keccakf1600)); + relation_futures.emplace_back(std::async(std::launch::async, avm_kernel)); relation_futures.emplace_back(std::async(std::launch::async, avm_main)); @@ -1325,6 +1343,8 @@ class AvmCircuitBuilder { avm_conversion(); + avm_keccakf1600(); + avm_kernel(); avm_main(); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index 86f6cdbbdaf6..a9b922fe7bc1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -16,6 +16,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_keccakf1600.hpp" #include "barretenberg/relations/generated/avm/avm_kernel.hpp" #include "barretenberg/relations/generated/avm/avm_main.hpp" #include "barretenberg/relations/generated/avm/avm_mem.hpp" @@ -91,11 +92,11 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 340; + static constexpr size_t NUM_WITNESS_ENTITIES = 345; 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 = 404; + static constexpr size_t NUM_ALL_ENTITIES = 409; using GrandProductRelations = std::tuple, perm_main_bin_relation, @@ -150,6 +151,7 @@ class AvmFlavor { using Relations = std::tuple, Avm_vm::avm_binary, Avm_vm::avm_conversion, + Avm_vm::avm_keccakf1600, Avm_vm::avm_kernel, Avm_vm::avm_main, Avm_vm::avm_mem, @@ -345,6 +347,10 @@ class AvmFlavor { avm_conversion_num_limbs, avm_conversion_radix, avm_conversion_to_radix_le_sel, + avm_keccakf1600_clk, + avm_keccakf1600_input, + avm_keccakf1600_keccakf1600_sel, + avm_keccakf1600_output, avm_kernel_emit_l2_to_l1_msg_write_offset, avm_kernel_emit_note_hash_write_offset, avm_kernel_emit_nullifier_write_offset, @@ -425,6 +431,7 @@ class AvmFlavor { avm_main_sel_op_fdiv, avm_main_sel_op_fee_per_da_gas, avm_main_sel_op_fee_per_l2_gas, + avm_main_sel_op_keccak, avm_main_sel_op_l1_to_l2_msg_exists, avm_main_sel_op_lt, avm_main_sel_op_lte, @@ -688,6 +695,10 @@ class AvmFlavor { avm_conversion_num_limbs, avm_conversion_radix, avm_conversion_to_radix_le_sel, + avm_keccakf1600_clk, + avm_keccakf1600_input, + avm_keccakf1600_keccakf1600_sel, + avm_keccakf1600_output, avm_kernel_emit_l2_to_l1_msg_write_offset, avm_kernel_emit_note_hash_write_offset, avm_kernel_emit_nullifier_write_offset, @@ -768,6 +779,7 @@ class AvmFlavor { avm_main_sel_op_fdiv, avm_main_sel_op_fee_per_da_gas, avm_main_sel_op_fee_per_l2_gas, + avm_main_sel_op_keccak, avm_main_sel_op_l1_to_l2_msg_exists, avm_main_sel_op_lt, avm_main_sel_op_lte, @@ -1036,6 +1048,10 @@ class AvmFlavor { avm_conversion_num_limbs, avm_conversion_radix, avm_conversion_to_radix_le_sel, + avm_keccakf1600_clk, + avm_keccakf1600_input, + avm_keccakf1600_keccakf1600_sel, + avm_keccakf1600_output, avm_kernel_emit_l2_to_l1_msg_write_offset, avm_kernel_emit_note_hash_write_offset, avm_kernel_emit_nullifier_write_offset, @@ -1116,6 +1132,7 @@ class AvmFlavor { avm_main_sel_op_fdiv, avm_main_sel_op_fee_per_da_gas, avm_main_sel_op_fee_per_l2_gas, + avm_main_sel_op_keccak, avm_main_sel_op_l1_to_l2_msg_exists, avm_main_sel_op_lt, avm_main_sel_op_lte, @@ -1443,6 +1460,10 @@ class AvmFlavor { avm_conversion_num_limbs, avm_conversion_radix, avm_conversion_to_radix_le_sel, + avm_keccakf1600_clk, + avm_keccakf1600_input, + avm_keccakf1600_keccakf1600_sel, + avm_keccakf1600_output, avm_kernel_emit_l2_to_l1_msg_write_offset, avm_kernel_emit_note_hash_write_offset, avm_kernel_emit_nullifier_write_offset, @@ -1523,6 +1544,7 @@ class AvmFlavor { avm_main_sel_op_fdiv, avm_main_sel_op_fee_per_da_gas, avm_main_sel_op_fee_per_l2_gas, + avm_main_sel_op_keccak, avm_main_sel_op_l1_to_l2_msg_exists, avm_main_sel_op_lt, avm_main_sel_op_lte, @@ -1850,6 +1872,10 @@ class AvmFlavor { avm_conversion_num_limbs, avm_conversion_radix, avm_conversion_to_radix_le_sel, + avm_keccakf1600_clk, + avm_keccakf1600_input, + avm_keccakf1600_keccakf1600_sel, + avm_keccakf1600_output, avm_kernel_emit_l2_to_l1_msg_write_offset, avm_kernel_emit_note_hash_write_offset, avm_kernel_emit_nullifier_write_offset, @@ -1930,6 +1956,7 @@ class AvmFlavor { avm_main_sel_op_fdiv, avm_main_sel_op_fee_per_da_gas, avm_main_sel_op_fee_per_l2_gas, + avm_main_sel_op_keccak, avm_main_sel_op_l1_to_l2_msg_exists, avm_main_sel_op_lt, avm_main_sel_op_lte, @@ -2597,6 +2624,10 @@ class AvmFlavor { 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_keccakf1600_clk = "AVM_KECCAKF1600_CLK"; + Base::avm_keccakf1600_input = "AVM_KECCAKF1600_INPUT"; + Base::avm_keccakf1600_keccakf1600_sel = "AVM_KECCAKF1600_KECCAKF1600_SEL"; + Base::avm_keccakf1600_output = "AVM_KECCAKF1600_OUTPUT"; Base::avm_kernel_emit_l2_to_l1_msg_write_offset = "AVM_KERNEL_EMIT_L2_TO_L1_MSG_WRITE_OFFSET"; Base::avm_kernel_emit_note_hash_write_offset = "AVM_KERNEL_EMIT_NOTE_HASH_WRITE_OFFSET"; Base::avm_kernel_emit_nullifier_write_offset = "AVM_KERNEL_EMIT_NULLIFIER_WRITE_OFFSET"; @@ -2678,6 +2709,7 @@ class AvmFlavor { Base::avm_main_sel_op_fdiv = "AVM_MAIN_SEL_OP_FDIV"; Base::avm_main_sel_op_fee_per_da_gas = "AVM_MAIN_SEL_OP_FEE_PER_DA_GAS"; Base::avm_main_sel_op_fee_per_l2_gas = "AVM_MAIN_SEL_OP_FEE_PER_L2_GAS"; + Base::avm_main_sel_op_keccak = "AVM_MAIN_SEL_OP_KECCAK"; Base::avm_main_sel_op_l1_to_l2_msg_exists = "AVM_MAIN_SEL_OP_L1_TO_L2_MSG_EXISTS"; Base::avm_main_sel_op_lt = "AVM_MAIN_SEL_OP_LT"; Base::avm_main_sel_op_lte = "AVM_MAIN_SEL_OP_LTE"; @@ -2957,6 +2989,10 @@ class AvmFlavor { Commitment avm_conversion_num_limbs; Commitment avm_conversion_radix; Commitment avm_conversion_to_radix_le_sel; + Commitment avm_keccakf1600_clk; + Commitment avm_keccakf1600_input; + Commitment avm_keccakf1600_keccakf1600_sel; + Commitment avm_keccakf1600_output; Commitment avm_kernel_emit_l2_to_l1_msg_write_offset; Commitment avm_kernel_emit_note_hash_write_offset; Commitment avm_kernel_emit_nullifier_write_offset; @@ -3037,6 +3073,7 @@ class AvmFlavor { Commitment avm_main_sel_op_fdiv; Commitment avm_main_sel_op_fee_per_da_gas; Commitment avm_main_sel_op_fee_per_l2_gas; + Commitment avm_main_sel_op_keccak; Commitment avm_main_sel_op_l1_to_l2_msg_exists; Commitment avm_main_sel_op_lt; Commitment avm_main_sel_op_lte; @@ -3317,6 +3354,10 @@ class AvmFlavor { 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_keccakf1600_clk = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_keccakf1600_input = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_keccakf1600_keccakf1600_sel = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_keccakf1600_output = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_kernel_emit_l2_to_l1_msg_write_offset = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_kernel_emit_note_hash_write_offset = @@ -3412,6 +3453,7 @@ class AvmFlavor { avm_main_sel_op_fdiv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_fee_per_da_gas = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_fee_per_l2_gas = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_sel_op_keccak = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_l1_to_l2_msg_exists = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_lt = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3699,6 +3741,10 @@ class AvmFlavor { 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_keccakf1600_clk, Transcript::proof_data); + serialize_to_buffer(avm_keccakf1600_input, Transcript::proof_data); + serialize_to_buffer(avm_keccakf1600_keccakf1600_sel, Transcript::proof_data); + serialize_to_buffer(avm_keccakf1600_output, Transcript::proof_data); serialize_to_buffer(avm_kernel_emit_l2_to_l1_msg_write_offset, Transcript::proof_data); serialize_to_buffer(avm_kernel_emit_note_hash_write_offset, Transcript::proof_data); serialize_to_buffer(avm_kernel_emit_nullifier_write_offset, Transcript::proof_data); @@ -3779,6 +3825,7 @@ class AvmFlavor { serialize_to_buffer(avm_main_sel_op_fdiv, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_fee_per_da_gas, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_fee_per_l2_gas, Transcript::proof_data); + serialize_to_buffer(avm_main_sel_op_keccak, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_l1_to_l2_msg_exists, 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); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index 94f54d5b6735..02f64feda97f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -168,6 +168,10 @@ void AvmProver::execute_wire_commitments_round() 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_keccakf1600_clk = commitment_key->commit(key->avm_keccakf1600_clk); + witness_commitments.avm_keccakf1600_input = commitment_key->commit(key->avm_keccakf1600_input); + witness_commitments.avm_keccakf1600_keccakf1600_sel = commitment_key->commit(key->avm_keccakf1600_keccakf1600_sel); + witness_commitments.avm_keccakf1600_output = commitment_key->commit(key->avm_keccakf1600_output); witness_commitments.avm_kernel_emit_l2_to_l1_msg_write_offset = commitment_key->commit(key->avm_kernel_emit_l2_to_l1_msg_write_offset); witness_commitments.avm_kernel_emit_note_hash_write_offset = @@ -263,6 +267,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_main_sel_op_fdiv = commitment_key->commit(key->avm_main_sel_op_fdiv); witness_commitments.avm_main_sel_op_fee_per_da_gas = commitment_key->commit(key->avm_main_sel_op_fee_per_da_gas); witness_commitments.avm_main_sel_op_fee_per_l2_gas = commitment_key->commit(key->avm_main_sel_op_fee_per_l2_gas); + witness_commitments.avm_main_sel_op_keccak = commitment_key->commit(key->avm_main_sel_op_keccak); witness_commitments.avm_main_sel_op_l1_to_l2_msg_exists = commitment_key->commit(key->avm_main_sel_op_l1_to_l2_msg_exists); witness_commitments.avm_main_sel_op_lt = commitment_key->commit(key->avm_main_sel_op_lt); @@ -496,6 +501,11 @@ void AvmProver::execute_wire_commitments_round() 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_keccakf1600_clk, witness_commitments.avm_keccakf1600_clk); + transcript->send_to_verifier(commitment_labels.avm_keccakf1600_input, witness_commitments.avm_keccakf1600_input); + transcript->send_to_verifier(commitment_labels.avm_keccakf1600_keccakf1600_sel, + witness_commitments.avm_keccakf1600_keccakf1600_sel); + transcript->send_to_verifier(commitment_labels.avm_keccakf1600_output, witness_commitments.avm_keccakf1600_output); transcript->send_to_verifier(commitment_labels.avm_kernel_emit_l2_to_l1_msg_write_offset, witness_commitments.avm_kernel_emit_l2_to_l1_msg_write_offset); transcript->send_to_verifier(commitment_labels.avm_kernel_emit_note_hash_write_offset, @@ -609,6 +619,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_main_sel_op_fee_per_da_gas); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_fee_per_l2_gas, witness_commitments.avm_main_sel_op_fee_per_l2_gas); + transcript->send_to_verifier(commitment_labels.avm_main_sel_op_keccak, witness_commitments.avm_main_sel_op_keccak); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_l1_to_l2_msg_exists, witness_commitments.avm_main_sel_op_l1_to_l2_msg_exists); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_lt, witness_commitments.avm_main_sel_op_lt); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index a4f5c6ec78d9..731d3b072112 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -248,6 +248,14 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate 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_keccakf1600_clk = + transcript->template receive_from_prover(commitment_labels.avm_keccakf1600_clk); + commitments.avm_keccakf1600_input = + transcript->template receive_from_prover(commitment_labels.avm_keccakf1600_input); + commitments.avm_keccakf1600_keccakf1600_sel = + transcript->template receive_from_prover(commitment_labels.avm_keccakf1600_keccakf1600_sel); + commitments.avm_keccakf1600_output = + transcript->template receive_from_prover(commitment_labels.avm_keccakf1600_output); commitments.avm_kernel_emit_l2_to_l1_msg_write_offset = transcript->template receive_from_prover( commitment_labels.avm_kernel_emit_l2_to_l1_msg_write_offset); commitments.avm_kernel_emit_note_hash_write_offset = @@ -394,6 +402,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.avm_main_sel_op_fee_per_da_gas); commitments.avm_main_sel_op_fee_per_l2_gas = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_fee_per_l2_gas); + commitments.avm_main_sel_op_keccak = + transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_keccak); commitments.avm_main_sel_op_l1_to_l2_msg_exists = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_l1_to_l2_msg_exists); commitments.avm_main_sel_op_lt = 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 035e9138b0b0..6846c5f57b6d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -1,10 +1,13 @@ #include "barretenberg/vm/avm_trace/avm_execution.hpp" #include "avm_common.test.hpp" +#include "barretenberg/common/serialize.hpp" #include "barretenberg/common/utils.hpp" #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 #include +#include namespace tests_avm { using namespace bb; @@ -706,8 +709,6 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) "03" + // U32 to_hex(i) + // val i to_hex(i); // val i - // to_hex(i) + // val i - // to_hex(i); // dst offset } // Set operations for sha256 input // Test vectors taken from noir black_box_solver @@ -718,8 +719,6 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) "03" + // U32 to_hex(i) + // val i to_hex(i + 8); // val i - // to_hex(i) + // val i - // to_hex(i + 8); // dst offset } std::string bytecode_hex = bytecode_preamble // Initial SET operations to store state and input + to_hex(OpCode::SET) + // opcode SET for indirect dst (output) @@ -798,7 +797,6 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) FF(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")), FF(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")) }; - // We use calldatacopy twice because we need to set up 4 inputs std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALL DATA COPY "00" // Indirect Flag "00000000" // cd_offset @@ -865,6 +863,187 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) validate_trace(std::move(trace)); } + +// Positive test with Keccakf1600. +TEST_F(AvmExecutionTests, keccakf1600OpCode) +{ + + // Test vectors taken noir/noir-repo/acvm-repo/blackbox_solver/src/hash.rs + std::vector state = { + 0xF1258F7940E1DDE7LLU, 0x84D5CCF933C0478ALLU, 0xD598261EA65AA9EELLU, 0xBD1547306F80494DLLU, + 0x8B284E056253D057LLU, 0xFF97A42D7F8E6FD4LLU, 0x90FEE5A0A44647C4LLU, 0x8C5BDA0CD6192E76LLU, + 0xAD30A6F71B19059CLLU, 0x30935AB7D08FFC64LLU, 0xEB5AA93F2317D635LLU, 0xA9A6E6260D712103LLU, + 0x81A57C16DBCF555FLLU, 0x43B831CD0347C826LLU, 0x01F22F1A11A5569FLLU, 0x05E5635A21D9AE61LLU, + 0x64BEFEF28CC970F2LLU, 0x613670957BC46611LLU, 0xB87C5A554FD00ECBLLU, 0x8C3EE88A1CCF32C8LLU, + 0x940C7922AE3A2614LLU, 0x1841F924A2C509E4LLU, 0x16F53526E70465C2LLU, 0x75F644E97F30A13BLLU, + 0xEAF1FF7B5CECA249LLU, + }; + std::vector expected_output = { + FF(0x2D5C954DF96ECB3CLLU), FF(0x6A332CD07057B56DLLU), FF(0x093D8D1270D76B6CLLU), FF(0x8A20D9B25569D094LLU), + FF(0x4F9C4F99E5E7F156LLU), FF(0xF957B9A2DA65FB38LLU), FF(0x85773DAE1275AF0DLLU), FF(0xFAF4F247C3D810F7LLU), + FF(0x1F1B9EE6F79A8759LLU), FF(0xE4FECC0FEE98B425LLU), FF(0x68CE61B6B9CE68A1LLU), FF(0xDEEA66C4BA8F974FLLU), + FF(0x33C43D836EAFB1F5LLU), FF(0xE00654042719DBD9LLU), FF(0x7CF8A9F009831265LLU), FF(0xFD5449A6BF174743LLU), + FF(0x97DDAD33D8994B40LLU), FF(0x48EAD5FC5D0BE774LLU), FF(0xE3B8C8EE55B7B03CLLU), FF(0x91A0226E649E42E9LLU), + FF(0x900E3129E7BADD7BLLU), FF(0x202A9EC5FAA3CCE8LLU), FF(0x5B3402464E1C3DB6LLU), FF(0x609F4E62A44C1059LLU), + FF(0x20D06CD26A8FBF5CLLU), + }; + + std::string bytecode_preamble; + // Set operations for keccak state + for (uint32_t i = 0; i < 25; i++) { + bytecode_preamble += to_hex(OpCode::SET) + // opcode SET + "00" // Indirect flag + "04" + // U64 + to_hex(state[i]) + // val i + to_hex(i + 1); // dst offset + } + + // We use calldatacopy twice because we need to set up 4 inputs + std::string bytecode_hex = bytecode_preamble + // Initial SET operations to store state and input + to_hex(OpCode::SET) + // opcode SET for indirect src (input) + "00" // Indirect flag + "03" // U32 + "00000001" // value 1 (i.e. where the src will be read from) + "00000024" // input_offset 36 + + to_hex(OpCode::SET) + // + "00" // Indirect flag + "03" // U32 + "00000019" // value 25 (i.e. where the length parameter is stored) + "00000025" // input_offset 37 + + to_hex(OpCode::SET) + // opcode SET for indirect dst (output) + "00" // Indirect flag + "03" // U32 + "00000100" // value 256 (i.e. where the ouput will be written to) + "00000023" // dst_offset 35 + + to_hex(OpCode::KECCAKF1600) + // opcode KECCAKF1600 + "03" // Indirect flag (first 2 operands indirect) + "00000023" // output offset (indirect 35) + "00000024" // input offset (indirect 36) + "00000025" // length offset 37 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000100" // ret offset 256 + "00000019"; // ret size 25 + + auto bytecode = hex_to_bytes(bytecode_hex); + auto instructions = Deserialization::parse(bytecode); + + // 25 SET for input + 2 SET for setting up indirects + 1 KECCAK + 1 RETURN + ASSERT_THAT(instructions, SizeIs(30)); + // + // KECCAKF1600 + EXPECT_THAT(instructions.at(28), + AllOf(Field(&Instruction::op_code, OpCode::KECCAKF1600), + Field(&Instruction::operands, + ElementsAre(VariantWith(3), + VariantWith(35), + VariantWith(36), + VariantWith(37))))); + // + // 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); + + // Find the first row enabling the keccak selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_keccak == 1; }); + EXPECT_EQ(row->avm_main_ind_a, 36); // Register A is indirect + EXPECT_EQ(row->avm_main_ind_c, 35); // Register C is indirect + EXPECT_EQ(row->avm_main_mem_idx_a, 1); // Indirect(36) -> 1 + EXPECT_EQ(row->avm_main_mem_idx_c, 256); // Indirect(35) -> 256 + EXPECT_EQ(row->avm_main_ia, (0xF1258F7940E1DDE7LLU)); + EXPECT_EQ(row->avm_main_ic, 0); + + std::advance(row, 1); + EXPECT_EQ(row->avm_main_ind_b, 0); // Register B is not + EXPECT_EQ(row->avm_main_mem_idx_b, 37); // Load(37) -> input length + EXPECT_EQ(row->avm_main_ib, 25); // Input length + EXPECT_EQ(returndata, expected_output); + + validate_trace(std::move(trace)); +} + +// Positive test with Keccak. +TEST_F(AvmExecutionTests, keccakOpCode) +{ + + // Test vectors from keccak256_test_cases in noir/noir-repo/acvm-repo/blackbox_solver/ + // Input: Uint8Array.from([0xbd]), + // Output: Uint8Array.from([ + // 0x5a, 0x50, 0x2f, 0x9f, 0xca, 0x46, 0x7b, 0x26, 0x6d, 0x5b, 0x78, 0x33, 0x65, 0x19, 0x37, 0xe8, 0x05, 0x27, + // 0x0c, 0xa3, 0xf3, 0xaf, 0x1c, 0x0d, 0xd2, 0x46, 0x2d, 0xca, 0x4b, 0x3b, 0x1a, 0xbf, + // ]), + std::vector expected_output = { + FF(0x5a), FF(0x50), FF(0x2f), FF(0x9f), FF(0xca), FF(0x46), FF(0x7b), FF(0x26), FF(0x6d), FF(0x5b), FF(0x78), + FF(0x33), FF(0x65), FF(0x19), FF(0x37), FF(0xe8), FF(0x05), FF(0x27), FF(0x0c), FF(0xa3), FF(0xf3), FF(0xaf), + FF(0x1c), FF(0x0d), FF(0xd2), FF(0x46), FF(0x2d), FF(0xca), FF(0x4b), FF(0x3b), FF(0x1a), FF(0xbf) + }; + std::string bytecode_hex = to_hex(OpCode::SET) + // Initial SET operations to store state and input + "00" // Indirect Flag + "01" // U8 + "BD" // val 189 + "00000001" // dst_offset 1 + + to_hex(OpCode::SET) + // opcode SET for indirect src (input) + "00" // Indirect flag + "03" // U32 + "00000001" // value 1 (i.e. where the src will be read from) + "00000024" // input_offset 36 + + to_hex(OpCode::SET) + // + "00" // Indirect flag + "03" // U8 + "00000001" // value 1 (i.e. where the length parameter is stored) + "00000025" // input_offset 37 + + to_hex(OpCode::SET) + // opcode SET for indirect dst (output) + "00" // Indirect flag + "03" // U32 + "00000100" // value 256 (i.e. where the ouput will be written to) + "00000023" // dst_offset 35 + + to_hex(OpCode::KECCAK) + // opcode KECCAK + "03" // Indirect flag (first 2 operands indirect) + "00000023" // output offset (indirect 35) + "00000024" // input offset (indirect 36) + "00000025" // length offset 37 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000100" // ret offset 256 + "00000020"; // ret size 32 + + auto bytecode = hex_to_bytes(bytecode_hex); + auto instructions = Deserialization::parse(bytecode); + + ASSERT_THAT(instructions, SizeIs(6)); + // + // KECCAK + EXPECT_THAT(instructions.at(4), + AllOf(Field(&Instruction::op_code, OpCode::KECCAK), + Field(&Instruction::operands, + ElementsAre(VariantWith(3), + VariantWith(35), + VariantWith(36), + VariantWith(37))))); + + // 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); + + // Find the first row enabling the keccak selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_keccak == 1; }); + EXPECT_EQ(row->avm_main_ind_a, 36); // Register A is indirect + EXPECT_EQ(row->avm_main_ind_c, 35); // Register C is indirect + EXPECT_EQ(row->avm_main_mem_idx_a, 1); // Indirect(36) -> 1 + EXPECT_EQ(row->avm_main_mem_idx_c, 256); // Indirect(35) -> 256 + EXPECT_EQ(row->avm_main_ia, 189); + EXPECT_EQ(row->avm_main_ic, 0); + // Register b checks are done in the next row due to the difference in the memory tag + std::advance(row, 1); + EXPECT_EQ(row->avm_main_ind_b, 0); // Register B is not + EXPECT_EQ(row->avm_main_mem_idx_b, 37); // Load(37) -> input length + EXPECT_EQ(row->avm_main_ib, 1); // Input length + + EXPECT_EQ(returndata, expected_output); + + validate_trace(std::move(trace)); +} + // Negative test detecting an invalid opcode byte. TEST_F(AvmExecutionTests, invalidOpcode) {