From 2ae9ad46f2d73a3d05050b680a62bdd56b06c49b Mon Sep 17 00:00:00 2001 From: jeanmon Date: Thu, 27 Jun 2024 10:13:05 +0000 Subject: [PATCH 1/4] 7211: Define a public column named calldata --- barretenberg/cpp/pil/avm/main.pil | 3 +++ .../relations/generated/avm/declare_views.hpp | 1 + .../vm/generated/avm_circuit_builder.cpp | 26 ++++++++++--------- .../vm/generated/avm_circuit_builder.hpp | 6 +++-- .../barretenberg/vm/generated/avm_flavor.hpp | 13 ++++++++-- .../barretenberg/vm/generated/avm_prover.cpp | 2 ++ .../vm/generated/avm_verifier.cpp | 6 +++++ 7 files changed, 41 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/pil/avm/main.pil b/barretenberg/cpp/pil/avm/main.pil index 19e445d62907..8ea4377a538d 100644 --- a/barretenberg/cpp/pil/avm/main.pil +++ b/barretenberg/cpp/pil/avm/main.pil @@ -17,6 +17,9 @@ namespace main(256); pol constant sel_first = [1] + [0]*; // Used mostly to toggle off the first row consisting // only in first element of shifted polynomials. + //===== PUBLIC COLUMNS========================================================= + pol public calldata; + //===== KERNEL INPUTS ========================================================= // Kernel lookup selector opcodes pol commit sel_q_kernel_lookup; 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 2cdb82e6d1e2..9fa9e19c6c43 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -8,6 +8,7 @@ [[maybe_unused]] auto kernel_kernel_value_out = View(new_term.kernel_kernel_value_out); \ [[maybe_unused]] auto kernel_kernel_side_effect_out = View(new_term.kernel_kernel_side_effect_out); \ [[maybe_unused]] auto kernel_kernel_metadata_out = View(new_term.kernel_kernel_metadata_out); \ + [[maybe_unused]] auto main_calldata = View(new_term.main_calldata); \ [[maybe_unused]] auto alu_a_hi = View(new_term.alu_a_hi); \ [[maybe_unused]] auto alu_a_lo = View(new_term.alu_a_lo); \ [[maybe_unused]] auto alu_b_hi = View(new_term.alu_b_hi); \ diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp index 448bf350a0e9..5ccb624b528b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp @@ -24,6 +24,7 @@ template std::vector AvmFullRow::names() "kernel_kernel_value_out", "kernel_kernel_side_effect_out", "kernel_kernel_metadata_out", + "main_calldata", "alu_a_hi", "alu_a_lo", "alu_b_hi", @@ -412,18 +413,19 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << field_to_string(row.main_clk) << "," << field_to_string(row.main_sel_first) << "," << field_to_string(row.kernel_kernel_inputs) << "," << field_to_string(row.kernel_kernel_value_out) << "," << field_to_string(row.kernel_kernel_side_effect_out) << "," - << field_to_string(row.kernel_kernel_metadata_out) << "," << field_to_string(row.alu_a_hi) << "," - << field_to_string(row.alu_a_lo) << "," << field_to_string(row.alu_b_hi) << "," - << field_to_string(row.alu_b_lo) << "," << field_to_string(row.alu_borrow) << "," - << field_to_string(row.alu_cf) << "," << field_to_string(row.alu_clk) << "," - << field_to_string(row.alu_cmp_rng_ctr) << "," << field_to_string(row.alu_div_u16_r0) << "," - << field_to_string(row.alu_div_u16_r1) << "," << field_to_string(row.alu_div_u16_r2) << "," - << field_to_string(row.alu_div_u16_r3) << "," << field_to_string(row.alu_div_u16_r4) << "," - << field_to_string(row.alu_div_u16_r5) << "," << field_to_string(row.alu_div_u16_r6) << "," - << field_to_string(row.alu_div_u16_r7) << "," << field_to_string(row.alu_divisor_hi) << "," - << field_to_string(row.alu_divisor_lo) << "," << field_to_string(row.alu_ff_tag) << "," - << field_to_string(row.alu_ia) << "," << field_to_string(row.alu_ib) << "," << field_to_string(row.alu_ic) - << "," << field_to_string(row.alu_in_tag) << "," << field_to_string(row.alu_op_add) << "," + << field_to_string(row.kernel_kernel_metadata_out) << "," << field_to_string(row.main_calldata) << "," + << field_to_string(row.alu_a_hi) << "," << field_to_string(row.alu_a_lo) << "," + << field_to_string(row.alu_b_hi) << "," << field_to_string(row.alu_b_lo) << "," + << field_to_string(row.alu_borrow) << "," << field_to_string(row.alu_cf) << "," + << field_to_string(row.alu_clk) << "," << field_to_string(row.alu_cmp_rng_ctr) << "," + << field_to_string(row.alu_div_u16_r0) << "," << field_to_string(row.alu_div_u16_r1) << "," + << field_to_string(row.alu_div_u16_r2) << "," << field_to_string(row.alu_div_u16_r3) << "," + << field_to_string(row.alu_div_u16_r4) << "," << field_to_string(row.alu_div_u16_r5) << "," + << field_to_string(row.alu_div_u16_r6) << "," << field_to_string(row.alu_div_u16_r7) << "," + << field_to_string(row.alu_divisor_hi) << "," << field_to_string(row.alu_divisor_lo) << "," + << field_to_string(row.alu_ff_tag) << "," << field_to_string(row.alu_ia) << "," + << field_to_string(row.alu_ib) << "," << field_to_string(row.alu_ic) << "," + << field_to_string(row.alu_in_tag) << "," << field_to_string(row.alu_op_add) << "," << field_to_string(row.alu_op_cast) << "," << field_to_string(row.alu_op_cast_prev) << "," << field_to_string(row.alu_op_div) << "," << field_to_string(row.alu_op_div_a_lt_b) << "," << field_to_string(row.alu_op_div_std) << "," << field_to_string(row.alu_op_eq) << "," 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 9bbe9334c855..b0acd7a8bace 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -93,6 +93,7 @@ template struct AvmFullRow { FF kernel_kernel_value_out{}; FF kernel_kernel_side_effect_out{}; FF kernel_kernel_metadata_out{}; + FF main_calldata{}; FF alu_a_hi{}; FF alu_a_lo{}; FF alu_b_hi{}; @@ -553,8 +554,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 450; - static constexpr size_t num_polys = 385; + static constexpr size_t num_fixed_columns = 451; + static constexpr size_t num_polys = 386; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -576,6 +577,7 @@ class AvmCircuitBuilder { polys.kernel_kernel_value_out[i] = rows[i].kernel_kernel_value_out; polys.kernel_kernel_side_effect_out[i] = rows[i].kernel_kernel_side_effect_out; polys.kernel_kernel_metadata_out[i] = rows[i].kernel_kernel_metadata_out; + polys.main_calldata[i] = rows[i].main_calldata; polys.alu_a_hi[i] = rows[i].alu_a_hi; polys.alu_a_lo[i] = rows[i].alu_a_lo; polys.alu_b_hi[i] = rows[i].alu_b_hi; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index e5729066c00e..0d33acf8c1d3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -100,11 +100,11 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 383; + static constexpr size_t NUM_WITNESS_ENTITIES = 384; 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 = 450; + static constexpr size_t NUM_ALL_ENTITIES = 451; using GrandProductRelations = std::tuple, perm_main_bin_relation, @@ -264,6 +264,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -650,6 +651,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1041,6 +1043,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1494,6 +1497,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1947,6 +1951,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -2756,6 +2761,7 @@ class AvmFlavor { Base::kernel_kernel_value_out = "KERNEL_KERNEL_VALUE_OUT"; Base::kernel_kernel_side_effect_out = "KERNEL_KERNEL_SIDE_EFFECT_OUT"; Base::kernel_kernel_metadata_out = "KERNEL_KERNEL_METADATA_OUT"; + Base::main_calldata = "MAIN_CALLDATA"; Base::alu_a_hi = "ALU_A_HI"; Base::alu_a_lo = "ALU_A_LO"; Base::alu_b_hi = "ALU_B_HI"; @@ -3158,6 +3164,7 @@ class AvmFlavor { Commitment kernel_kernel_value_out; Commitment kernel_kernel_side_effect_out; Commitment kernel_kernel_metadata_out; + Commitment main_calldata; Commitment alu_a_hi; Commitment alu_a_lo; Commitment alu_b_hi; @@ -3560,6 +3567,7 @@ class AvmFlavor { kernel_kernel_value_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_kernel_side_effect_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_kernel_metadata_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + main_calldata = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_a_hi = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_a_lo = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_b_hi = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3978,6 +3986,7 @@ class AvmFlavor { serialize_to_buffer(kernel_kernel_value_out, Transcript::proof_data); serialize_to_buffer(kernel_kernel_side_effect_out, Transcript::proof_data); serialize_to_buffer(kernel_kernel_metadata_out, Transcript::proof_data); + serialize_to_buffer(main_calldata, Transcript::proof_data); serialize_to_buffer(alu_a_hi, Transcript::proof_data); serialize_to_buffer(alu_a_lo, Transcript::proof_data); serialize_to_buffer(alu_b_hi, 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 a10bc668d027..b35428e51f1c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -62,6 +62,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.kernel_kernel_value_out = commitment_key->commit(key->kernel_kernel_value_out); witness_commitments.kernel_kernel_side_effect_out = commitment_key->commit(key->kernel_kernel_side_effect_out); witness_commitments.kernel_kernel_metadata_out = commitment_key->commit(key->kernel_kernel_metadata_out); + witness_commitments.main_calldata = commitment_key->commit(key->main_calldata); witness_commitments.alu_a_hi = commitment_key->commit(key->alu_a_hi); witness_commitments.alu_a_lo = commitment_key->commit(key->alu_a_lo); witness_commitments.alu_b_hi = commitment_key->commit(key->alu_b_hi); @@ -408,6 +409,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.kernel_kernel_side_effect_out); transcript->send_to_verifier(commitment_labels.kernel_kernel_metadata_out, witness_commitments.kernel_kernel_metadata_out); + transcript->send_to_verifier(commitment_labels.main_calldata, witness_commitments.main_calldata); transcript->send_to_verifier(commitment_labels.alu_a_hi, witness_commitments.alu_a_hi); transcript->send_to_verifier(commitment_labels.alu_a_lo, witness_commitments.alu_a_lo); transcript->send_to_verifier(commitment_labels.alu_b_hi, witness_commitments.alu_b_hi); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 0a863144aadb..49302f921bbc 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -79,6 +79,7 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.kernel_kernel_side_effect_out); commitments.kernel_kernel_metadata_out = transcript->template receive_from_prover(commitment_labels.kernel_kernel_metadata_out); + commitments.main_calldata = transcript->template receive_from_prover(commitment_labels.main_calldata); commitments.alu_a_hi = transcript->template receive_from_prover(commitment_labels.alu_a_hi); commitments.alu_a_lo = transcript->template receive_from_prover(commitment_labels.alu_a_lo); commitments.alu_b_hi = transcript->template receive_from_prover(commitment_labels.alu_b_hi); @@ -737,6 +738,11 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector Date: Thu, 27 Jun 2024 18:30:36 +0000 Subject: [PATCH 2/4] 7211: calldata passed through the verifier --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 11 +- .../vm/avm_trace/avm_execution.cpp | 9 +- .../vm/avm_trace/avm_execution.hpp | 2 +- .../barretenberg/vm/avm_trace/avm_helper.cpp | 6 +- .../barretenberg/vm/avm_trace/avm_helper.hpp | 3 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 51 +++++++-- .../barretenberg/vm/avm_trace/avm_trace.hpp | 11 +- .../vm/tests/avm_arithmetic.test.cpp | 103 +++++++++++++----- .../vm/tests/avm_bitwise.test.cpp | 2 +- .../barretenberg/vm/tests/avm_cast.test.cpp | 29 +++-- .../vm/tests/avm_comparison.test.cpp | 23 +++- .../vm/tests/avm_control_flow.test.cpp | 2 +- .../vm/tests/avm_execution.test.cpp | 30 ++--- .../vm/tests/avm_indirect_mem.test.cpp | 2 +- .../barretenberg/vm/tests/avm_kernel.test.cpp | 2 +- .../vm/tests/avm_mem_opcodes.test.cpp | 2 +- .../barretenberg/vm/tests/avm_memory.test.cpp | 17 +-- .../barretenberg/vm/tests/helpers.test.cpp | 12 +- .../barretenberg/vm/tests/helpers.test.hpp | 3 +- 19 files changed, 214 insertions(+), 106 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 114e2f0caf2f..93feb8cb3275 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -723,18 +723,22 @@ void avm_prove(const std::filesystem::path& bytecode_path, * * @param proof_path Path to the file containing the serialized proof * @param vk_path Path to the file containing the serialized verification key + * @param calldata_path Path to the file containing the serialised calldata (could be empty) * @return true If the proof is valid * @return false If the proof is invalid */ -bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::path& vk_path) +bool avm_verify(const std::filesystem::path& proof_path, + const std::filesystem::path& vk_path, + const std::filesystem::path& calldata_path) { std::vector const proof = many_from_buffer(read_file(proof_path)); + std::vector const calldata = many_from_buffer(read_file(calldata_path)); std::vector vk_bytes = read_file(vk_path); auto circuit_size = from_buffer(vk_bytes, 0); auto num_public_inputs = from_buffer(vk_bytes, sizeof(size_t)); auto vk = AvmFlavor::VerificationKey(circuit_size, num_public_inputs); - const bool verified = avm_trace::Execution::verify(vk, proof); + const bool verified = avm_trace::Execution::verify(vk, proof, calldata); vinfo("verified: ", verified); return verified; } @@ -1144,7 +1148,8 @@ int main(int argc, char* argv[]) avm_dump_trace_path = get_option(args, "--avm-dump-trace", ""); avm_prove(avm_bytecode_path, avm_calldata_path, avm_public_inputs_path, avm_hints_path, output_path); } else if (command == "avm_verify") { - return avm_verify(proof_path, vk_path) ? 0 : 1; + std::filesystem::path avm_calldata_path = get_option(args, "--avm-calldata", "./target/avm_calldata.bin"); + return avm_verify(proof_path, vk_path, avm_calldata_path) ? 0 : 1; #endif } else if (command == "prove_ultra_honk") { std::string output_path = get_option(args, "-o", "./proofs/proof"); 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 f055af7abe12..d69ce78abfab 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -251,7 +251,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in return public_inputs; } -bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) +bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof, std::vector const& calldata) { auto verification_key = std::make_shared(vk); AvmVerifier verifier(verification_key); @@ -268,7 +268,7 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) std::copy(proof.begin() + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, proof.end(), std::back_inserter(raw_proof)); VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); - std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs); + std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs, calldata); return verifier.verify_proof(raw_proof, public_inputs_columns); } @@ -309,7 +309,7 @@ std::vector Execution::gen_trace(std::vector const& instructio uint32_t start_side_effect_counter = !public_inputs_vec.empty() ? static_cast(public_inputs_vec[PCPI_START_SIDE_EFFECT_COUNTER_OFFSET]) : 0; - AvmTraceBuilder trace_builder(public_inputs, execution_hints, start_side_effect_counter); + AvmTraceBuilder trace_builder(public_inputs, execution_hints, start_side_effect_counter, calldata); // Copied version of pc maintained in trace builder. The value of pc is evolving based // on opcode logic and therefore is not maintained here. However, the next opcode in the execution @@ -436,8 +436,7 @@ std::vector Execution::gen_trace(std::vector const& instructio trace_builder.op_calldata_copy(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - calldata); + std::get(inst.operands.at(3))); break; // Machine State - Gas case OpCode::L2GASLEFT: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp index 2b6175febf18..371e96a6b2dc 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp @@ -38,7 +38,7 @@ class Execution { std::vector const& calldata = {}, std::vector const& public_inputs_vec = getDefaultPublicInputs(), ExecutionHints const& execution_hints = {}); - static bool verify(AvmFlavor::VerificationKey vk, HonkProof const& proof); + static bool verify(AvmFlavor::VerificationKey vk, HonkProof const& proof, std::vector const& calldata); }; } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp index 8a508442aa59..231b62278a9b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp @@ -136,7 +136,8 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx) return static_cast((ind_value & (1 << operand_idx)) >> operand_idx); } -std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs) +std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, + std::vector const& calldata) { // We convert to a vector as the pil generated verifier is generic and unaware of the KERNEL_INPUTS_LENGTH // For each of the public input vectors @@ -158,7 +159,8 @@ std::vector> copy_public_inputs_columns(VmPublicInputs const& pu return { std::move(public_inputs_kernel_inputs), std::move(public_inputs_kernel_value_outputs), std::move(public_inputs_kernel_side_effect_outputs), - std::move(public_inputs_kernel_metadata_outputs) }; + std::move(public_inputs_kernel_metadata_outputs), + calldata }; } } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp index 105e1c529f76..d982ee258a97 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp @@ -16,6 +16,7 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx); // There are 4 public input columns, one for inputs, and 3 for the kernel outputs {value, side effect counter, metadata} // The verifier is generic, and so accepts vectors of these values rather than the fixed length arrays that are used // during circuit building. This method copies each array into a vector to be used by the verifier. -std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs); +std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, + std::vector const& calldata); } // namespace bb::avm_trace \ No newline at end of file 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 b1f7109c6d54..477775e22b42 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -32,9 +32,11 @@ namespace bb::avm_trace { */ AvmTraceBuilder::AvmTraceBuilder(VmPublicInputs public_inputs, ExecutionHints execution_hints, - uint32_t side_effect_counter) + uint32_t side_effect_counter, + std::vector calldata) // NOTE: we initialise the environment builder here as it requires public inputs : kernel_trace_builder(std::move(public_inputs)) + , calldata(std::move(calldata)) , side_effect_counter(side_effect_counter) , initial_side_effect_counter(side_effect_counter) , execution_hints(std::move(execution_hints)) @@ -1886,10 +1888,8 @@ void AvmTraceBuilder::op_div( * @param cd_offset The starting index of the region in calldata to be copied. * @param copy_size The number of finite field elements to be copied into memory. * @param dst_offset The starting index of memory where calldata will be copied to. - * @param call_data_mem The vector containing calldata. */ -void AvmTraceBuilder::op_calldata_copy( - uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset, std::vector const& call_data_mem) +void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset) { // We parallelize storing memory operations in chunk of 3, i.e., 1 per intermediate register. // The variable pos is an index pointing to the first storing operation (pertaining to intermediate @@ -1912,7 +1912,7 @@ void AvmTraceBuilder::op_calldata_copy( uint32_t rwc(0); auto clk = static_cast(main_trace.size()) + 1; - FF ia = call_data_mem.at(cd_offset + pos); + FF ia = calldata.at(cd_offset + pos); uint32_t mem_op_a(1); uint32_t rwa = 1; @@ -1934,7 +1934,7 @@ void AvmTraceBuilder::op_calldata_copy( call_ptr, clk, IntermRegister::IA, mem_addr_a, ia, AvmMemoryTag::U0, AvmMemoryTag::FF); if (copy_size - pos > 1) { - ib = call_data_mem.at(cd_offset + pos + 1); + ib = calldata.at(cd_offset + pos + 1); mem_op_b = 1; mem_addr_b = direct_dst_offset + pos + 1; rwb = 1; @@ -1945,7 +1945,7 @@ void AvmTraceBuilder::op_calldata_copy( } if (copy_size - pos > 2) { - ic = call_data_mem.at(cd_offset + pos + 2); + ic = calldata.at(cd_offset + pos + 2); mem_op_c = 1; mem_addr_c = direct_dst_offset + pos + 2; rwc = 1; @@ -3762,7 +3762,9 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c main_trace.at(*trace_size - 1).main_sel_last = FF(1); - // Memory trace inclusion + /********************************************************************************************** + * MEMORY TRACE INCLUSION + **********************************************************************************************/ // We compute in the main loop the timestamp and global address for next row. // Perform initialization for index 0 outside of the loop provided that mem trace exists. @@ -3866,7 +3868,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } - // Alu trace inclusion + /********************************************************************************************** + * ALU TRACE INCLUSION + **********************************************************************************************/ + for (size_t i = 0; i < alu_trace_size; i++) { auto const& src = alu_trace.at(i); auto& dest = main_trace.at(i); @@ -4013,6 +4018,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } + /********************************************************************************************** + * GADGET TABLES INCLUSION + **********************************************************************************************/ + // Add Conversion Gadget table for (size_t i = 0; i < conv_trace_size; i++) { auto const& src = conv_trace.at(i); @@ -4067,6 +4076,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.pedersen_sel_pedersen = FF(1); } + /********************************************************************************************** + * BINARY TRACE INCLUSION + **********************************************************************************************/ + // Add Binary Trace table for (size_t i = 0; i < bin_trace_size; i++) { auto const& src = bin_trace.at(i); @@ -4132,7 +4145,9 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } - /////////// GAS ACCOUNTING ////////////////////////// + /********************************************************************************************** + * GAS TRACE INCLUSION + **********************************************************************************************/ // Add the gas cost table to the main trace // TODO: do i need a way to produce an interupt that will stop the execution of the trace when the gas left @@ -4222,11 +4237,14 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.main_da_gas_remaining = current_da_gas_remaining; } - /////////// END OF GAS ACCOUNTING ////////////////////////// - // Adding extra row for the shifted values at the top of the execution trace. Row first_row = Row{ .main_sel_first = FF(1), .mem_lastAccess = FF(1) }; main_trace.insert(main_trace.begin(), first_row); + + /********************************************************************************************** + * RANGE CHECKS AND SELECTORS INCLUSION + **********************************************************************************************/ + auto const old_trace_size = main_trace.size(); auto new_trace_size = range_check_required ? old_trace_size @@ -4316,6 +4334,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } + /********************************************************************************************** + * KERNEL TRACE INCLUSION + **********************************************************************************************/ + // Write the kernel trace into the main trace // 1. The write offsets are constrained to be non changing over the entire trace, so we fill in the values // until we @@ -4494,6 +4516,11 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c std::get(kernel_trace_builder.public_inputs).at(i); } + // calldata column inclusion + for (size_t i = 0; i < calldata.size(); i++) { + main_trace.at(i).main_calldata = calldata.at(i); + } + // Get tag_err counts from the mem_trace_builder if (range_check_required) { finalise_mem_trace_lookup_counts(); 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 951dd1eb6d8e..3baf3ce50d25 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -39,7 +39,8 @@ class AvmTraceBuilder { public: AvmTraceBuilder(VmPublicInputs public_inputs = {}, ExecutionHints execution_hints = {}, - uint32_t side_effect_counter = 0); + uint32_t side_effect_counter = 0, + std::vector calldata = {}); std::vector finalize(uint32_t min_trace_size = 0, bool range_check_required = ENABLE_PROVING); void reset(); @@ -158,11 +159,7 @@ class AvmTraceBuilder { // CALLDATACOPY opcode with direct/indirect memory access, i.e., // direct: M[dst_offset:dst_offset+copy_size] = calldata[cd_offset:cd_offset+copy_size] // indirect: M[M[dst_offset]:M[dst_offset]+copy_size] = calldata[cd_offset:cd_offset+copy_size] - void op_calldata_copy(uint8_t indirect, - uint32_t cd_offset, - uint32_t copy_size, - uint32_t dst_offset, - std::vector const& call_data_mem); + void op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset); // REVERT Opcode (that just call return under the hood for now) std::vector op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); @@ -241,6 +238,8 @@ class AvmTraceBuilder { AvmPedersenTraceBuilder pedersen_trace_builder; AvmEccTraceBuilder ecc_trace_builder; + std::vector calldata{}; + /** * @brief Create a kernel lookup opcode object * diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp index 314c723aca6c..a320b2d7245d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp @@ -215,6 +215,11 @@ class AvmArithmeticTests : public ::testing::Test { VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; + void gen_trace_builder(std::vector const& calldata) + { + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + } + // Generate a trace with an EQ opcode operation. std::vector gen_trace_eq(uint128_t const& a, uint128_t const& b, @@ -368,9 +373,11 @@ std::vector> positive_op_div_test_values = { { // Test on basic addition over finite field type. TEST_F(AvmArithmeticTestsFF, addition) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 37, 4, 11 }); + std::vector const calldata = { 37, 4, 11 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); - // Memory layout: [37,4,11,0,0,0,....] + // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] trace_builder.op_return(0, 0, 5); auto trace = trace_builder.finalize(); @@ -381,13 +388,15 @@ TEST_F(AvmArithmeticTestsFF, addition) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Test on basic subtraction over finite field type. TEST_F(AvmArithmeticTestsFF, subtraction) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 8, 4, 17 }); + std::vector const calldata = { 8, 4, 17 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] @@ -400,13 +409,15 @@ TEST_F(AvmArithmeticTestsFF, subtraction) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on basic multiplication over finite field type. TEST_F(AvmArithmeticTestsFF, multiplication) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 5, 0, 20 }); + std::vector const calldata = { 5, 0, 20 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] @@ -420,13 +431,15 @@ TEST_F(AvmArithmeticTestsFF, multiplication) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on multiplication by zero over finite field type. TEST_F(AvmArithmeticTestsFF, multiplicationByZero) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 127 }); + std::vector const calldata = { 127 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [127,0,0,0,0,0,....] trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::FF); // [127,0,0,0,0,0....] @@ -440,13 +453,15 @@ TEST_F(AvmArithmeticTestsFF, multiplicationByZero) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on basic division over finite field type. TEST_F(AvmArithmeticTestsFF, fDivision) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] @@ -463,13 +478,15 @@ TEST_F(AvmArithmeticTestsFF, fDivision) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division with zero numerator over finite field type. TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 0); // [0,0,0,0,0,0....] @@ -486,14 +503,16 @@ TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division by zero over finite field type. // We check that the operator error flag is raised. TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] @@ -511,7 +530,7 @@ TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) EXPECT_EQ(row->main_rwc, FF(1)); EXPECT_EQ(row->main_op_err, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division of zero by zero over finite field type. @@ -543,7 +562,9 @@ TEST_F(AvmArithmeticTestsFF, fDivisionZeroByZeroError) // No check on the evaluation is performed here. TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) { - trace_builder.op_calldata_copy(0, 0, 3, 2, std::vector{ 45, 23, 12 }); + std::vector const calldata = { 45, 23, 12 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 2); // Memory layout: [0,0,45,23,12,0,0,0,....] trace_builder.op_add(0, 2, 3, 4, AvmMemoryTag::FF); // [0,0,45,23,68,0,0,0,....] @@ -558,7 +579,7 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) trace_builder.halt(); auto trace = trace_builder.finalize(); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Test of equality on FF elements @@ -566,7 +587,9 @@ TEST_F(AvmArithmeticTestsFF, equality) { // Pick a field-sized number FF elem = FF::modulus - FF(1); - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ elem, elem, 1 }); + std::vector const calldata = { elem, elem, 1 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q -1, 1,0..] trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); @@ -576,14 +599,16 @@ TEST_F(AvmArithmeticTestsFF, equality) EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_op_eq_diff_inv, FF(0)); // Expect 0 as inv of (q-1) - (q-1) - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test correct non-equality of FF elements TEST_F(AvmArithmeticTestsFF, nonEquality) { FF elem = FF::modulus - FF(1); - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ elem, elem + FF(1), 0 }); + std::vector const calldata = { elem, elem + FF(1), 0 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q, 1,0..] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -593,7 +618,7 @@ TEST_F(AvmArithmeticTestsFF, nonEquality) EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_op_eq_diff_inv, FF(-1).invert()); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } TEST_P(AvmArithmeticTestsDiv, division) @@ -1758,7 +1783,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, multiplication) // Test on basic incorrect division over finite field type. TEST_F(AvmArithmeticNegativeTestsFF, fDivision) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] @@ -1775,7 +1802,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivision) // in the trace. TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] @@ -1801,7 +1830,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) // Test with finite field division by zero occurs and no error is raised (remove error flag) TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] @@ -1837,7 +1868,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) // Test with finite field division using a wrong read instruction tag TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 18, 6 }); + std::vector const calldata = { 18, 6 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] trace_builder.halt(); @@ -1855,7 +1888,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) // Test with finite field division using a wrong write instruction tag TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 18, 6 }); + std::vector const calldata = { 18, 6 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] trace_builder.halt(); @@ -1874,7 +1909,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) // the addition, subtraction, multiplication. TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 37, 4, 11 }); + std::vector const calldata = { 37, 4, 11 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] @@ -1893,7 +1930,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 8, 4, 17 }); + std::vector const calldata = { 8, 4, 17 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] @@ -1911,7 +1950,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag3) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 5, 0, 20 }); + std::vector const calldata = { 5, 0, 20 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] @@ -1954,7 +1995,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, nonBooleanEq) TEST_F(AvmArithmeticNegativeTestsFF, eqOutputWrongTag) { FF elem = FF::modulus - FF(15); - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ elem, elem }); + std::vector const calldata = { elem, elem }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [elem, elem, 1, 0..] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index 387da11f11b4..e70b50106af9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -492,7 +492,7 @@ TEST_P(AvmBitwiseTestsAnd, AllAndTest) auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 0, a, b, output, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, AvmBitwiseTestsAnd, diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp index 80629cd9e576..42ea23cc974d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp @@ -23,6 +23,7 @@ class AvmCastTests : public ::testing::Test { VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; + std::vector calldata{}; std::vector trace; size_t main_addr; @@ -113,9 +114,9 @@ class AvmCastTests : public ::testing::Test { // We still want the ability to enable proving through the environment variable and therefore we do not pass // the boolean variable force_proof to validate_trace second argument. if (force_proof) { - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } else { - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } } }; @@ -171,7 +172,9 @@ TEST_F(AvmCastTests, noTruncationFFToU32) TEST_F(AvmCastTests, truncationFFToU16ModMinus1) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus - 1) }); + calldata = { FF::modulus - 1 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -182,7 +185,9 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus1) TEST_F(AvmCastTests, truncationFFToU16ModMinus2) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two) }); + calldata = { FF::modulus_minus_two }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -291,7 +296,9 @@ TEST_F(AvmCastNegativeTests, wrongOutputAluIc) TEST_F(AvmCastNegativeTests, wrongLimbDecompositionInput) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two) }); + calldata = { FF::modulus_minus_two }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -314,7 +321,9 @@ TEST_F(AvmCastNegativeTests, wrongPSubALo) TEST_F(AvmCastNegativeTests, wrongPSubAHi) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 987) }); + calldata = { FF::modulus_minus_two - 987 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -352,7 +361,9 @@ TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionLo) TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionHi) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 987) }); + calldata = { FF::modulus_minus_two - 987 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -396,7 +407,9 @@ TEST_F(AvmCastNegativeTests, wrongCopySubLoForRangeCheck) TEST_F(AvmCastNegativeTests, wrongCopySubHiForRangeCheck) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 972836) }); + std::vector const calldata = { FF::modulus_minus_two - 972836 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U128); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp index 0ed161a8afd7..c3e65de12425 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp @@ -106,8 +106,12 @@ TEST_P(AvmCmpTestsLT, ParamTest) { const auto [params, mem_tag] = GetParam(); const auto [a, b, c] = params; + std::vector calldata{}; + if (mem_tag == AvmMemoryTag::FF) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ a, b }); + calldata = { a, b }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); } else { trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); @@ -128,7 +132,7 @@ TEST_P(AvmCmpTestsLT, ParamTest) ASSERT_TRUE(alu_row != trace.end()); common_validate_cmp(*row, *alu_row, a, b, c, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } INSTANTIATE_TEST_SUITE_P(AvmCmpTests, AvmCmpTestsLT, @@ -138,8 +142,12 @@ TEST_P(AvmCmpTestsLTE, ParamTest) { const auto [params, mem_tag] = GetParam(); const auto [a, b, c] = params; + std::vector calldata{}; + if (mem_tag == AvmMemoryTag::FF) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ a, b }); + calldata = { a, b }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); } else { trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); @@ -157,7 +165,7 @@ TEST_P(AvmCmpTestsLTE, ParamTest) ASSERT_TRUE(row != trace.end()); ASSERT_TRUE(alu_row != trace.end()); common_validate_cmp(*row, *alu_row, a, b, c, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } INSTANTIATE_TEST_SUITE_P(AvmCmpTests, AvmCmpTestsLTE, @@ -309,7 +317,9 @@ TEST_P(AvmCmpNegativeTestsLT, ParamTest) const auto [failure, params] = GetParam(); const auto [failure_string, failure_mode] = failure; const auto [a, b, output] = params; - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ a, b, output }); + + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ a, b, output }); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lt(0, 0, 1, 2, AvmMemoryTag::FF); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -327,7 +337,8 @@ TEST_P(AvmCmpNegativeTestsLTE, ParamTest) const auto [failure, params] = GetParam(); const auto [failure_string, failure_mode] = failure; const auto [a, b, output] = params; - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ a, b, output }); + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ a, b, output }); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lte(0, 0, 1, 2, AvmMemoryTag::FF); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp index 31d4facca5e9..f961e542cb47 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp @@ -87,7 +87,7 @@ TEST_F(AvmControlFlowTests, simpleCall) EXPECT_EQ(halt_row->main_pc, FF(CALL_PC)); EXPECT_EQ(halt_row->main_internal_return_ptr, FF(1)); } - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } TEST_F(AvmControlFlowTests, simpleJump) 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 c7af3789b56d..6e9d749e6d45 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -100,7 +100,7 @@ TEST_F(AvmExecutionTests, basicAddReturn) ElementsAre(VariantWith(0), VariantWith(0), VariantWith(0))))); auto trace = gen_trace_from_instr(instructions); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Positive test for SET and SUB opcodes @@ -165,7 +165,7 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) // Find the first row enabling the subtraction selector auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sub == 1; }); EXPECT_EQ(row->main_ic, 10000); // 47123 - 37123 = 10000 - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Positive test for multiple MUL opcodes @@ -467,7 +467,7 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) // It must have failed as subtraction was "jumped over". EXPECT_EQ(row, trace.end()); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, { 13, 156 }); } // Positive test for JUMPI. @@ -561,8 +561,8 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) EXPECT_EQ(row->main_ic, 1600); // 800 = (20 + 20) * (20 + 20) // traces validation - validate_trace(std::move(trace_jump), public_inputs); - validate_trace(std::move(trace_no_jump), public_inputs); + validate_trace(std::move(trace_jump), public_inputs, { 9873123 }); + validate_trace(std::move(trace_no_jump), public_inputs, { 0 }); } // Positive test with MOV. @@ -805,7 +805,7 @@ TEST_F(AvmExecutionTests, toRadixLeOpcode) } EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, { FF::modulus - FF(1) }); } // // Positive test with SHA256COMPRESSION. @@ -873,7 +873,7 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with SHA256 @@ -992,7 +992,7 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with Keccakf1600. @@ -1177,7 +1177,7 @@ TEST_F(AvmExecutionTests, pedersenHashOpCode) EXPECT_EQ(returndata[0], expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // // Positive test with EmbeddedCurveAdd @@ -1239,7 +1239,7 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with MSM @@ -1316,7 +1316,7 @@ TEST_F(AvmExecutionTests, msmOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test for Kernel Input opcodes @@ -1899,7 +1899,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) EXPECT_EQ(metadata_out, 9); // slot feed_output(sstore_out_offset, value_out, side_effect_out, metadata_out); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // SSTORE @@ -1961,7 +1961,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeComplex) feed_output(sstore_out_offset, 42, 0, 9); feed_output(sstore_out_offset + 1, 123, 1, 10); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // SLOAD and SSTORE @@ -2217,7 +2217,7 @@ TEST_F(AvmExecutionTests, opCallOpcodes) auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 9, 8, 1 })); // The 1 represents the success - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) @@ -2256,7 +2256,7 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 1, 2, 3, 4, 5, 6 })); // The first one represents true - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Negative test detecting an invalid opcode byte. TEST_F(AvmExecutionTests, invalidOpcode) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp index ccead55c438a..47e82b751023 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp @@ -68,7 +68,7 @@ TEST_F(AvmIndirectMemTests, allIndirectAdd) EXPECT_EQ(row->main_sel_mem_op_b, FF(1)); EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Testing a subtraction operation with direct input operands a, b, and an indirect diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp index f4076677049f..dcfb3ab71a19 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp @@ -581,7 +581,7 @@ void negative_test_incorrect_ia_kernel_lookup(OpcodesFunc apply_opcodes, check_trace(/*indirect*/ false, trace); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace), public_inputs), expected_message); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), expected_message); } TEST_F(AvmKernelNegativeTests, incorrectIaSender) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp index 7114919ee69a..94157443a75f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp @@ -402,7 +402,7 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) MEM_ROW_FIELD_EQ(r_in_tag, static_cast(AvmMemoryTag::U32)), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1))); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } /****************************************************************************** diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp index 4d3b6fd18a9c..05a02bb3862f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp @@ -36,7 +36,9 @@ class AvmMemoryTests : public ::testing::Test { // The proof must pass and we check that the AVM error is raised. TEST_F(AvmMemoryTests, mismatchedTagAddOperation) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 98, 12 }); + std::vector const calldata = { 98, 12 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::U8); trace_builder.halt(); @@ -75,7 +77,7 @@ TEST_F(AvmMemoryTests, mismatchedTagAddOperation) EXPECT_EQ(row->mem_r_in_tag, FF(static_cast(AvmMemoryTag::U8))); EXPECT_EQ(row->mem_tag, FF(static_cast(AvmMemoryTag::FF))); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Testing an equality operation with a mismatched memory tag. @@ -228,7 +230,8 @@ TEST_F(AvmMemoryTests, readUninitializedMemoryViolation) // must raise a VM error. TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 98, 12 }); + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, { 98, 12 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_sub(0, 0, 1, 4, AvmMemoryTag::U8); trace_builder.halt(); @@ -262,8 +265,8 @@ TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) // must not set a VM error. TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ 84, 7 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -288,8 +291,8 @@ TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) // Testing violation that a write operation must not set a VM error. TEST_F(AvmMemoryTests, noErrorTagWriteViolation) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, { 84, 7 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp index 1657ba8ce0db..d84f11226dec 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp @@ -23,9 +23,9 @@ std::vector gen_three_op_params(std::vector opera * * @param trace The execution trace */ -void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs public_inputs) +void validate_trace_check_circuit(std::vector&& trace) { - validate_trace(std::move(trace), public_inputs, false); + validate_trace(std::move(trace), {}, {}, false); }; /** @@ -34,7 +34,10 @@ void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs publi * * @param trace The execution trace */ -void validate_trace(std::vector&& trace, VmPublicInputs const& public_inputs, bool with_proof) +void validate_trace(std::vector&& trace, + VmPublicInputs const& public_inputs, + std::vector const& calldata, + bool with_proof) { auto circuit_builder = AvmCircuitBuilder(); circuit_builder.set_trace(std::move(trace)); @@ -47,7 +50,8 @@ void validate_trace(std::vector&& trace, VmPublicInputs const& public_input AvmVerifier verifier = composer.create_verifier(circuit_builder); - std::vector> public_inputs_as_vec = bb::avm_trace::copy_public_inputs_columns(public_inputs); + std::vector> public_inputs_as_vec = + bb::avm_trace::copy_public_inputs_columns(public_inputs, calldata); bool verified = verifier.verify_proof(proof, { public_inputs_as_vec }); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp index 0dcf63815024..0640121b319d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp @@ -28,9 +28,10 @@ using VmPublicInputs = bb::avm_trace::VmPublicInputs; // If the test is expecting a relation to fail, then use validate_trace_check_circuit. // Otherwise, use validate_trace with a single argument. If the proving needs to be // enabled all the time in a given test, use validate_trace with setting with_proof = true. -void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs public_inputs = {}); +void validate_trace_check_circuit(std::vector&& trace); void validate_trace(std::vector&& trace, VmPublicInputs const& public_inputs = {}, + std::vector const& calldata = {}, bool with_proof = bb::avm_trace::ENABLE_PROVING); void mutate_ic_in_trace(std::vector& trace, std::function&& selectRow, From 1367f04081cbb3e69c452c30f8b683128bccca63 Mon Sep 17 00:00:00 2001 From: jeanmon Date: Fri, 28 Jun 2024 09:38:57 +0000 Subject: [PATCH 3/4] 7211: TS changes to support calldata file --- yarn-project/bb-prover/src/avm_proving.test.ts | 3 ++- yarn-project/bb-prover/src/bb/execute.ts | 12 ++++++++++-- yarn-project/bb-prover/src/prover/bb_prover.ts | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index 6f465bf4d958..65ce1604ee08 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -278,7 +278,8 @@ const proveAndVerifyAvmTestContract = async ( // Then we verify. const rawVkPath = path.join(succeededRes.vkPath!, 'vk'); - const verificationRes = await verifyAvmProof(bbPath, succeededRes.proofPath!, rawVkPath, logger); + const calldataPath = path.join(bbWorkingDirectory, 'avm_calldata.bin'); + const verificationRes = await verifyAvmProof(bbPath, succeededRes.proofPath!, rawVkPath, logger, calldataPath); expect(verificationRes.status).toBe(BB_RESULT.SUCCESS); }; diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 9a5753a68adc..3ff7c58d2204 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -12,6 +12,7 @@ export const VK_FILENAME = 'vk'; export const VK_FIELDS_FILENAME = 'vk_fields.json'; export const PROOF_FILENAME = 'proof'; export const PROOF_FIELDS_FILENAME = 'proof_fields.json'; +export const CALLDATA_FILENAME = 'avm_calldata.bin'; export enum BB_RESULT { SUCCESS, @@ -277,7 +278,7 @@ export async function generateAvmProof( // Paths for the inputs const bytecodePath = join(workingDirectory, 'avm_bytecode.bin'); - const calldataPath = join(workingDirectory, 'avm_calldata.bin'); + const calldataPath = join(workingDirectory, CALLDATA_FILENAME); const publicInputsPath = join(workingDirectory, 'avm_public_inputs.bin'); const avmHintsPath = join(workingDirectory, 'avm_hints.bin'); @@ -385,6 +386,7 @@ export async function verifyProof( * @param pathToBB - The full path to the bb binary * @param proofFullPath - The full path to the proof to be verified * @param verificationKeyPath - The full path to the circuit verification key + * @param calldataPath - The full path to calldata * @param log - A logging function * @returns An object containing a result indication and duration taken */ @@ -393,8 +395,9 @@ export async function verifyAvmProof( proofFullPath: string, verificationKeyPath: string, log: LogFn, + calldataPath?: string, ): Promise { - return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', log); + return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', log, calldataPath); } /** @@ -404,6 +407,7 @@ export async function verifyAvmProof( * @param verificationKeyPath - The full path to the circuit verification key * @param command - The BB command to execute (verify/avm_verify) * @param log - A logging function + * @param calldataPath - The full path to calldata (only relevant for avm_verify) * @returns An object containing a result indication and duration taken */ async function verifyProofInternal( @@ -412,6 +416,7 @@ async function verifyProofInternal( verificationKeyPath: string, command: 'verify' | 'avm_verify', log: LogFn, + calldataPath?: string, ): Promise { const binaryPresent = await fs .access(pathToBB, fs.constants.R_OK) @@ -423,6 +428,9 @@ async function verifyProofInternal( try { const args = ['-p', proofFullPath, '-k', verificationKeyPath]; + if (calldataPath !== undefined) { + args.push('--avm-calldata', calldataPath); + } const timer = new Timer(); const result = await executeBB(pathToBB, command, args, log); const duration = timer.ms(); diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 00c9d0e8b8a7..092854b7fc9f 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -67,6 +67,7 @@ import * as path from 'path'; import { type BBSuccess, BB_RESULT, + CALLDATA_FILENAME, PROOF_FIELDS_FILENAME, PROOF_FILENAME, VK_FILENAME, @@ -640,6 +641,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { proofFileName, verificationKeyPath!, logFunction, + verificationFunction instanceof verifyAvmProof ? path.join(bbWorkingDirectory, CALLDATA_FILENAME) : undefined, ); if (result.status === BB_RESULT.FAILURE) { From e77f2106c1c7bdb945c2e8cec8b05b2bfb4bdd38 Mon Sep 17 00:00:00 2001 From: jeanmon Date: Fri, 28 Jun 2024 14:08:11 +0000 Subject: [PATCH 4/4] 7211: review comments addressed --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 11 +++------ .../vm/avm_trace/avm_execution.cpp | 23 ++++++++++++++----- .../vm/avm_trace/avm_execution.hpp | 2 +- .../barretenberg/vm/tests/avm_cast.test.cpp | 2 +- .../bb-prover/src/avm_proving.test.ts | 3 +-- yarn-project/bb-prover/src/bb/execute.ts | 22 ++++++++---------- .../bb-prover/src/prover/bb_prover.ts | 2 -- 7 files changed, 32 insertions(+), 33 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 93feb8cb3275..114e2f0caf2f 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -723,22 +723,18 @@ void avm_prove(const std::filesystem::path& bytecode_path, * * @param proof_path Path to the file containing the serialized proof * @param vk_path Path to the file containing the serialized verification key - * @param calldata_path Path to the file containing the serialised calldata (could be empty) * @return true If the proof is valid * @return false If the proof is invalid */ -bool avm_verify(const std::filesystem::path& proof_path, - const std::filesystem::path& vk_path, - const std::filesystem::path& calldata_path) +bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::path& vk_path) { std::vector const proof = many_from_buffer(read_file(proof_path)); - std::vector const calldata = many_from_buffer(read_file(calldata_path)); std::vector vk_bytes = read_file(vk_path); auto circuit_size = from_buffer(vk_bytes, 0); auto num_public_inputs = from_buffer(vk_bytes, sizeof(size_t)); auto vk = AvmFlavor::VerificationKey(circuit_size, num_public_inputs); - const bool verified = avm_trace::Execution::verify(vk, proof, calldata); + const bool verified = avm_trace::Execution::verify(vk, proof); vinfo("verified: ", verified); return verified; } @@ -1148,8 +1144,7 @@ int main(int argc, char* argv[]) avm_dump_trace_path = get_option(args, "--avm-dump-trace", ""); avm_prove(avm_bytecode_path, avm_calldata_path, avm_public_inputs_path, avm_hints_path, output_path); } else if (command == "avm_verify") { - std::filesystem::path avm_calldata_path = get_option(args, "--avm-calldata", "./target/avm_calldata.bin"); - return avm_verify(proof_path, vk_path, avm_calldata_path) ? 0 : 1; + return avm_verify(proof_path, vk_path) ? 0 : 1; #endif } else if (command == "prove_ultra_honk") { std::string output_path = get_option(args, "-o", "./proofs/proof"); 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 d69ce78abfab..79bc084ac060 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -1,6 +1,7 @@ #include "barretenberg/vm/avm_trace/avm_execution.hpp" #include "barretenberg/bb/log.hpp" #include "barretenberg/common/serialize.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_deserialization.hpp" #include "barretenberg/vm/avm_trace/avm_helper.hpp" @@ -78,10 +79,11 @@ std::tuple Execution::prove(std::vector const& public_in return public_inputs; } -bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof, std::vector const& calldata) +bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) { auto verification_key = std::make_shared(vk); AvmVerifier verifier(verification_key); @@ -261,11 +263,20 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof, st // crs_factory_); // output_state.pcs_verification_key = std::move(pcs_verification_key); + // Proof structure: public_inputs | calldata_size | calldata | raw proof std::vector public_inputs_vec; + std::vector calldata; std::vector raw_proof; - std::copy( - proof.begin(), proof.begin() + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, std::back_inserter(public_inputs_vec)); - std::copy(proof.begin() + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, proof.end(), std::back_inserter(raw_proof)); + + // This can be made nicer using BB's serialize::read, probably. + const auto public_inputs_offset = proof.begin(); + const auto calldata_size_offset = public_inputs_offset + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH; + const auto calldata_offset = calldata_size_offset + 1; + const auto raw_proof_offset = calldata_offset + static_cast(uint64_t(*calldata_size_offset)); + + std::copy(public_inputs_offset, calldata_size_offset, std::back_inserter(public_inputs_vec)); + std::copy(calldata_offset, raw_proof_offset, std::back_inserter(calldata)); + std::copy(raw_proof_offset, proof.end(), std::back_inserter(raw_proof)); VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs, calldata); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp index 371e96a6b2dc..2b6175febf18 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.hpp @@ -38,7 +38,7 @@ class Execution { std::vector const& calldata = {}, std::vector const& public_inputs_vec = getDefaultPublicInputs(), ExecutionHints const& execution_hints = {}); - static bool verify(AvmFlavor::VerificationKey vk, HonkProof const& proof, std::vector const& calldata); + static bool verify(AvmFlavor::VerificationKey vk, HonkProof const& proof); }; } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp index 42ea23cc974d..11d9768300df 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp @@ -23,7 +23,7 @@ class AvmCastTests : public ::testing::Test { VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; - std::vector calldata{}; + std::vector calldata; std::vector trace; size_t main_addr; diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index 65ce1604ee08..6f465bf4d958 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -278,8 +278,7 @@ const proveAndVerifyAvmTestContract = async ( // Then we verify. const rawVkPath = path.join(succeededRes.vkPath!, 'vk'); - const calldataPath = path.join(bbWorkingDirectory, 'avm_calldata.bin'); - const verificationRes = await verifyAvmProof(bbPath, succeededRes.proofPath!, rawVkPath, logger, calldataPath); + const verificationRes = await verifyAvmProof(bbPath, succeededRes.proofPath!, rawVkPath, logger); expect(verificationRes.status).toBe(BB_RESULT.SUCCESS); }; diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 3ff7c58d2204..7c97fcede72c 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -12,7 +12,10 @@ export const VK_FILENAME = 'vk'; export const VK_FIELDS_FILENAME = 'vk_fields.json'; export const PROOF_FILENAME = 'proof'; export const PROOF_FIELDS_FILENAME = 'proof_fields.json'; -export const CALLDATA_FILENAME = 'avm_calldata.bin'; +export const AVM_BYTECODE_FILENAME = 'avm_bytecode.bin'; +export const AVM_CALLDATA_FILENAME = 'avm_calldata.bin'; +export const AVM_PUBLIC_INPUTS_FILENAME = 'avm_public_inputs.bin'; +export const AVM_HINTS_FILENAME = 'avm_hints.bin'; export enum BB_RESULT { SUCCESS, @@ -277,10 +280,10 @@ export async function generateAvmProof( } // Paths for the inputs - const bytecodePath = join(workingDirectory, 'avm_bytecode.bin'); - const calldataPath = join(workingDirectory, CALLDATA_FILENAME); - const publicInputsPath = join(workingDirectory, 'avm_public_inputs.bin'); - const avmHintsPath = join(workingDirectory, 'avm_hints.bin'); + const bytecodePath = join(workingDirectory, AVM_BYTECODE_FILENAME); + const calldataPath = join(workingDirectory, AVM_CALLDATA_FILENAME); + const publicInputsPath = join(workingDirectory, AVM_PUBLIC_INPUTS_FILENAME); + const avmHintsPath = join(workingDirectory, AVM_HINTS_FILENAME); // The proof is written to e.g. /workingDirectory/proof const outputPath = workingDirectory; @@ -386,7 +389,6 @@ export async function verifyProof( * @param pathToBB - The full path to the bb binary * @param proofFullPath - The full path to the proof to be verified * @param verificationKeyPath - The full path to the circuit verification key - * @param calldataPath - The full path to calldata * @param log - A logging function * @returns An object containing a result indication and duration taken */ @@ -395,9 +397,8 @@ export async function verifyAvmProof( proofFullPath: string, verificationKeyPath: string, log: LogFn, - calldataPath?: string, ): Promise { - return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', log, calldataPath); + return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', log); } /** @@ -407,7 +408,6 @@ export async function verifyAvmProof( * @param verificationKeyPath - The full path to the circuit verification key * @param command - The BB command to execute (verify/avm_verify) * @param log - A logging function - * @param calldataPath - The full path to calldata (only relevant for avm_verify) * @returns An object containing a result indication and duration taken */ async function verifyProofInternal( @@ -416,7 +416,6 @@ async function verifyProofInternal( verificationKeyPath: string, command: 'verify' | 'avm_verify', log: LogFn, - calldataPath?: string, ): Promise { const binaryPresent = await fs .access(pathToBB, fs.constants.R_OK) @@ -428,9 +427,6 @@ async function verifyProofInternal( try { const args = ['-p', proofFullPath, '-k', verificationKeyPath]; - if (calldataPath !== undefined) { - args.push('--avm-calldata', calldataPath); - } const timer = new Timer(); const result = await executeBB(pathToBB, command, args, log); const duration = timer.ms(); diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 092854b7fc9f..00c9d0e8b8a7 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -67,7 +67,6 @@ import * as path from 'path'; import { type BBSuccess, BB_RESULT, - CALLDATA_FILENAME, PROOF_FIELDS_FILENAME, PROOF_FILENAME, VK_FILENAME, @@ -641,7 +640,6 @@ export class BBNativeRollupProver implements ServerCircuitProver { proofFileName, verificationKeyPath!, logFunction, - verificationFunction instanceof verifyAvmProof ? path.join(bbWorkingDirectory, CALLDATA_FILENAME) : undefined, ); if (result.status === BB_RESULT.FAILURE) {