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/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index f055af7abe12..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 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); + std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs, calldata); return verifier.verify_proof(raw_proof, public_inputs_columns); } @@ -309,7 +320,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 +447,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_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/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 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..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,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, diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 9a5753a68adc..7c97fcede72c 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -12,6 +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 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, @@ -276,10 +280,10 @@ export async function generateAvmProof( } // Paths for the inputs - const bytecodePath = join(workingDirectory, 'avm_bytecode.bin'); - const calldataPath = join(workingDirectory, 'avm_calldata.bin'); - 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;