From 34088b48acdfc40df3144509a3effd348167ee58 Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Thu, 30 May 2024 11:18:26 +0100 Subject: [PATCH] feat(avm): add temporary sha256 execution (#6604) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- barretenberg/cpp/pil/avm/avm_main.pil | 9 +- .../relations/generated/avm/declare_views.hpp | 1 - .../vm/avm_trace/avm_deserialization.cpp | 1 + .../vm/avm_trace/avm_execution.cpp | 7 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 142 ++++++++++++++++++ .../barretenberg/vm/avm_trace/avm_trace.hpp | 2 + .../vm/avm_trace/gadgets/avm_sha256.cpp | 7 + .../vm/avm_trace/gadgets/avm_sha256.hpp | 7 +- .../vm/generated/avm_circuit_builder.hpp | 14 +- .../barretenberg/vm/generated/avm_flavor.hpp | 18 +-- .../barretenberg/vm/generated/avm_prover.cpp | 2 - .../vm/generated/avm_verifier.cpp | 2 - .../vm/tests/avm_execution.test.cpp | 91 +++++++++++ 13 files changed, 262 insertions(+), 41 deletions(-) diff --git a/barretenberg/cpp/pil/avm/avm_main.pil b/barretenberg/cpp/pil/avm/avm_main.pil index aee693953da..9589f74b6f0 100644 --- a/barretenberg/cpp/pil/avm/avm_main.pil +++ b/barretenberg/cpp/pil/avm/avm_main.pil @@ -560,10 +560,11 @@ namespace avm_main(256); is avm_conversion.to_radix_le_sel {avm_conversion.clk, avm_conversion.input, avm_conversion.radix, avm_conversion.num_limbs}; - #[PERM_MAIN_SHA256] - sel_op_sha256 {clk, ia, ib, ic} - is - avm_sha256.sha256_compression_sel {avm_sha256.clk, avm_sha256.state, avm_sha256.input, avm_sha256.output}; + // This will be enabled when we migrate just to sha256Compression, as getting sha256 to work with it is tricky. + // #[PERM_MAIN_SHA256] + // sel_op_sha256 {clk, ia, ib, ic} + // is + // avm_sha256.sha256_compression_sel {avm_sha256.clk, avm_sha256.state, avm_sha256.input, avm_sha256.output}; #[PERM_MAIN_POS2_PERM] sel_op_poseidon2 {clk, ia, ib} 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 e2e377fdaef..3391da29168 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -279,7 +279,6 @@ [[maybe_unused]] auto perm_main_alu = View(new_term.perm_main_alu); \ [[maybe_unused]] auto perm_main_bin = View(new_term.perm_main_bin); \ [[maybe_unused]] auto perm_main_conv = View(new_term.perm_main_conv); \ - [[maybe_unused]] auto perm_main_sha256 = View(new_term.perm_main_sha256); \ [[maybe_unused]] auto perm_main_pos2_perm = View(new_term.perm_main_pos2_perm); \ [[maybe_unused]] auto perm_main_mem_a = View(new_term.perm_main_mem_a); \ [[maybe_unused]] auto perm_main_mem_b = View(new_term.perm_main_mem_b); \ 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 389da570169..91e8d30ec58 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -108,6 +108,7 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::TORADIXLE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, // Gadget - Hashing + { OpCode::SHA256, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::SHA256COMPRESSION, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::POSEIDON2, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, 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 dd732650dcb..c71fa8aa76e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -290,7 +290,12 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(1)), std::get(inst.operands.at(2)), std::get(inst.operands.at(3))); - + break; + case OpCode::SHA256: + trace_builder.op_sha256(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::POSEIDON2: trace_builder.op_poseidon2_permutation(std::get(inst.operands.at(0)), 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 ee34862d571..24be48a3b4a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -2203,6 +2203,148 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, call_ptr, clk, res.direct_c_offset, AvmMemoryTag::U32, AvmMemoryTag::U32, FF(internal_return_ptr), ff_result); } +/** + * @brief SHA256 Hash with direct or indirect memory access. + * This function is temporary until we have transitioned to sha256Compression + * @param indirect byte encoding information about indirect/direct memory access. + * @param output_offset An index in memory pointing to where the first U32 value of the output array should be stored. + * @param input_offset An index in memory pointing to the first U8 value of the state array to be used in the next + * instance of sha256. + * @param input_size_offset An index in memory pointing to the U32 value of the input size. + */ +void AvmTraceBuilder::op_sha256(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 sha256_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_sha256 = 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 sha256 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 = sha256_trace_builder.sha256(input, sha256_op_clk); + // 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); +} /** * @brief Poseidon2 Permutation with direct or indirect memory access. * 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 1b3ecc50fbb..494a0a0a459 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -159,6 +159,8 @@ class AvmTraceBuilder { 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); + // SHA256 operation - temporary while we transition to sha256_compression + void op_sha256(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. diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_sha256.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_sha256.cpp index 0db56894eef..515c356cd07 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_sha256.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_sha256.cpp @@ -121,4 +121,11 @@ std::array AvmSha256TraceBuilder::sha256_compression(const std::arr return output; } +std::array AvmSha256TraceBuilder::sha256(const std::vector& input, uint32_t clk) +{ + auto output = crypto::sha256(input); + // Cant push here since we are not using the same format as the sha256_compression + sha256_trace.push_back(Sha256TraceEntry{ clk, {}, {}, {} }); + return output; +} } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_sha256.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_sha256.hpp index 67338677709..056954aeace 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_sha256.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_sha256.hpp @@ -8,9 +8,9 @@ class AvmSha256TraceBuilder { public: struct Sha256TraceEntry { uint32_t clk = 0; - std::array state; - std::array input; - std::array output; + std::array state{}; + std::array input{}; + std::array output{}; }; AvmSha256TraceBuilder(); @@ -21,6 +21,7 @@ class AvmSha256TraceBuilder { std::array sha256_compression(const std::array& h_init, const std::array& input, uint32_t clk); + std::array sha256(const std::vector& input, uint32_t clk); private: std::vector sha256_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 9c6ea6d1cdc..e78e002424d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -73,7 +73,6 @@ #include "barretenberg/relations/generated/avm/perm_main_mem_ind_c.hpp" #include "barretenberg/relations/generated/avm/perm_main_mem_ind_d.hpp" #include "barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp" -#include "barretenberg/relations/generated/avm/perm_main_sha256.hpp" #include "barretenberg/vm/generated/avm_flavor.hpp" namespace bb { @@ -344,7 +343,6 @@ template struct AvmFullRow { FF perm_main_alu{}; FF perm_main_bin{}; FF perm_main_conv{}; - FF perm_main_sha256{}; FF perm_main_pos2_perm{}; FF perm_main_mem_a{}; FF perm_main_mem_b{}; @@ -500,8 +498,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 409; - static constexpr size_t num_polys = 347; + static constexpr size_t num_fixed_columns = 408; + static constexpr size_t num_polys = 346; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -1018,10 +1016,6 @@ class AvmCircuitBuilder { return evaluate_logderivative.template operator()>("PERM_MAIN_CONV"); }; - auto perm_main_sha256 = [=]() { - return evaluate_logderivative.template operator()>("PERM_MAIN_SHA256"); - }; - auto perm_main_pos2_perm = [=]() { return evaluate_logderivative.template operator()>("PERM_MAIN_POS2_PERM"); }; @@ -1236,8 +1230,6 @@ class AvmCircuitBuilder { relation_futures.emplace_back(std::async(std::launch::async, perm_main_conv)); - relation_futures.emplace_back(std::async(std::launch::async, perm_main_sha256)); - relation_futures.emplace_back(std::async(std::launch::async, perm_main_pos2_perm)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_mem_a)); @@ -1361,8 +1353,6 @@ class AvmCircuitBuilder { perm_main_conv(); - perm_main_sha256(); - perm_main_pos2_perm(); perm_main_mem_a(); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index a9b922fe7bc..339240d27f1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -70,7 +70,6 @@ #include "barretenberg/relations/generated/avm/perm_main_mem_ind_c.hpp" #include "barretenberg/relations/generated/avm/perm_main_mem_ind_d.hpp" #include "barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp" -#include "barretenberg/relations/generated/avm/perm_main_sha256.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb { @@ -92,16 +91,15 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 345; + static constexpr size_t NUM_WITNESS_ENTITIES = 344; 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 = 409; + static constexpr size_t NUM_ALL_ENTITIES = 408; using GrandProductRelations = std::tuple, perm_main_bin_relation, perm_main_conv_relation, - perm_main_sha256_relation, perm_main_pos2_perm_relation, perm_main_mem_a_relation, perm_main_mem_b_relation, @@ -160,7 +158,6 @@ class AvmFlavor { perm_main_alu_relation, perm_main_bin_relation, perm_main_conv_relation, - perm_main_sha256_relation, perm_main_pos2_perm_relation, perm_main_mem_a_relation, perm_main_mem_b_relation, @@ -502,7 +499,6 @@ class AvmFlavor { perm_main_alu, perm_main_bin, perm_main_conv, - perm_main_sha256, perm_main_pos2_perm, perm_main_mem_a, perm_main_mem_b, @@ -850,7 +846,6 @@ class AvmFlavor { perm_main_alu, perm_main_bin, perm_main_conv, - perm_main_sha256, perm_main_pos2_perm, perm_main_mem_a, perm_main_mem_b, @@ -1203,7 +1198,6 @@ class AvmFlavor { perm_main_alu, perm_main_bin, perm_main_conv, - perm_main_sha256, perm_main_pos2_perm, perm_main_mem_a, perm_main_mem_b, @@ -1615,7 +1609,6 @@ class AvmFlavor { perm_main_alu, perm_main_bin, perm_main_conv, - perm_main_sha256, perm_main_pos2_perm, perm_main_mem_a, perm_main_mem_b, @@ -2027,7 +2020,6 @@ class AvmFlavor { perm_main_alu, perm_main_bin, perm_main_conv, - perm_main_sha256, perm_main_pos2_perm, perm_main_mem_a, perm_main_mem_b, @@ -2326,8 +2318,6 @@ class AvmFlavor { prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( prover_polynomials, relation_parameters, this->circuit_size); - bb::compute_logderivative_inverse>( - prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( @@ -2780,7 +2770,6 @@ class AvmFlavor { Base::perm_main_alu = "PERM_MAIN_ALU"; Base::perm_main_bin = "PERM_MAIN_BIN"; Base::perm_main_conv = "PERM_MAIN_CONV"; - Base::perm_main_sha256 = "PERM_MAIN_SHA256"; Base::perm_main_pos2_perm = "PERM_MAIN_POS2_PERM"; Base::perm_main_mem_a = "PERM_MAIN_MEM_A"; Base::perm_main_mem_b = "PERM_MAIN_MEM_B"; @@ -3144,7 +3133,6 @@ class AvmFlavor { Commitment perm_main_alu; Commitment perm_main_bin; Commitment perm_main_conv; - Commitment perm_main_sha256; Commitment perm_main_pos2_perm; Commitment perm_main_mem_a; Commitment perm_main_mem_b; @@ -3528,7 +3516,6 @@ class AvmFlavor { perm_main_alu = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_bin = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_conv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - perm_main_sha256 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_pos2_perm = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_mem_a = deserialize_from_buffer(Transcript::proof_data, num_frs_read); perm_main_mem_b = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3896,7 +3883,6 @@ class AvmFlavor { serialize_to_buffer(perm_main_alu, Transcript::proof_data); serialize_to_buffer(perm_main_bin, Transcript::proof_data); serialize_to_buffer(perm_main_conv, Transcript::proof_data); - serialize_to_buffer(perm_main_sha256, Transcript::proof_data); serialize_to_buffer(perm_main_pos2_perm, Transcript::proof_data); serialize_to_buffer(perm_main_mem_a, Transcript::proof_data); serialize_to_buffer(perm_main_mem_b, 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 02f64feda97..de2540e2a4d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -765,7 +765,6 @@ void AvmProver::execute_log_derivative_inverse_round() witness_commitments.perm_main_alu = commitment_key->commit(key->perm_main_alu); witness_commitments.perm_main_bin = commitment_key->commit(key->perm_main_bin); witness_commitments.perm_main_conv = commitment_key->commit(key->perm_main_conv); - witness_commitments.perm_main_sha256 = commitment_key->commit(key->perm_main_sha256); witness_commitments.perm_main_pos2_perm = commitment_key->commit(key->perm_main_pos2_perm); witness_commitments.perm_main_mem_a = commitment_key->commit(key->perm_main_mem_a); witness_commitments.perm_main_mem_b = commitment_key->commit(key->perm_main_mem_b); @@ -816,7 +815,6 @@ void AvmProver::execute_log_derivative_inverse_round() transcript->send_to_verifier(commitment_labels.perm_main_alu, witness_commitments.perm_main_alu); transcript->send_to_verifier(commitment_labels.perm_main_bin, witness_commitments.perm_main_bin); transcript->send_to_verifier(commitment_labels.perm_main_conv, witness_commitments.perm_main_conv); - transcript->send_to_verifier(commitment_labels.perm_main_sha256, witness_commitments.perm_main_sha256); transcript->send_to_verifier(commitment_labels.perm_main_pos2_perm, witness_commitments.perm_main_pos2_perm); transcript->send_to_verifier(commitment_labels.perm_main_mem_a, witness_commitments.perm_main_mem_a); transcript->send_to_verifier(commitment_labels.perm_main_mem_b, witness_commitments.perm_main_mem_b); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 731d3b07211..ec5b401341b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -607,8 +607,6 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.perm_main_alu); commitments.perm_main_bin = transcript->template receive_from_prover(commitment_labels.perm_main_bin); commitments.perm_main_conv = transcript->template receive_from_prover(commitment_labels.perm_main_conv); - commitments.perm_main_sha256 = - transcript->template receive_from_prover(commitment_labels.perm_main_sha256); commitments.perm_main_pos2_perm = transcript->template receive_from_prover(commitment_labels.perm_main_pos2_perm); commitments.perm_main_mem_a = 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 6846c5f57b6..c798b258afd 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -787,6 +787,97 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) validate_trace(std::move(trace)); } +// Positive test with SHA256 +TEST_F(AvmExecutionTests, sha256Opcode) +{ + + // Test vectors taken from noir black_box_solver + // Uint8Array.from([0x61, 0x62, 0x63]), + // Uint8Array.from([ + // 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, + // 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad, + // ]), + std::vector expected_output = { + FF(0xba), FF(0x78), FF(0x16), FF(0xbf), FF(0x8f), FF(0x01), FF(0xcf), FF(0xea), FF(0x41), FF(0x41), FF(0x40), + FF(0xde), FF(0x5d), FF(0xae), FF(0x22), FF(0x23), FF(0xb0), FF(0x03), FF(0x61), FF(0xa3), FF(0x96), FF(0x17), + FF(0x7a), FF(0x9c), FF(0xb4), FF(0x10), FF(0xff), FF(0x61), FF(0xf2), FF(0x00), FF(0x15), FF(0xad), + }; + std::string bytecode_hex = to_hex(OpCode::SET) + // Initial SET operations to store state and input + "00" // Indirect Flag + "01" // U8 + "61" // val 97 + "00000001" // dst_offset 1 + + to_hex(OpCode::SET) + // opcode SET for indirect src (input) + "00" // Indirect flag + "01" // U8 + "62" // value 98 (i.e. where the src will be read from)A + "00000002" // input_offset 2 + + to_hex(OpCode::SET) + // opcode SET for indirect src (input) + "00" // Indirect flag + "01" // U32 + "63" // value 99 (i.e. where the src will be read from) + "00000003" // input_offset 36 + + 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 + "00000003" // value 3 (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::SHA256) + // opcode SHA256 + "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(8)); + // + // SHA256 + EXPECT_THAT(instructions.at(6), + AllOf(Field(&Instruction::op_code, OpCode::SHA256), + 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 sha256 selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_sha256 == 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, 97); + 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, 3); // Input length + + EXPECT_EQ(returndata, expected_output); + + validate_trace(std::move(trace)); +} // Positive test with POSEIDON2_PERM. TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) {