From 71c6c5b77165fac960af10a418ee508de665ffca Mon Sep 17 00:00:00 2001 From: jeanmon Date: Fri, 27 Sep 2024 11:54:38 +0000 Subject: [PATCH] 8714: review comments addressed --- .../barretenberg/polynomials/CMakeLists.txt | 2 +- .../polynomials/legacy_polynomial.cpp | 7 - .../barretenberg/polynomials/polynomial.cpp | 100 --------- .../barretenberg/polynomials/polynomial.hpp | 97 ++++++++- .../recursion/avm_recursive_verifier.test.cpp | 2 +- .../src/barretenberg/vm/avm/trace/helper.cpp | 202 +----------------- .../src/barretenberg/vm/avm/trace/helper.hpp | 181 +++++++++++++++- .../bb-pil-backend/templates/verifier.cpp.hbs | 2 +- 8 files changed, 271 insertions(+), 322 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/polynomials/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/polynomials/CMakeLists.txt index 93d9513b8d73..596e1916afaa 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/polynomials/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(polynomials numeric ecc crypto_sha256 stdlib_primitives) \ No newline at end of file +barretenberg_module(polynomials numeric ecc crypto_sha256) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.cpp b/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.cpp index 717a10e44eb8..0f6701193118 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.cpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.cpp @@ -15,13 +15,6 @@ namespace bb { -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) -template std::shared_ptr _allocate_aligned_memory(const size_t n_elements) -{ - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) - return std::static_pointer_cast(get_mem_slab(sizeof(Fr) * n_elements)); -} - template void LegacyPolynomial::allocate_backing_memory(size_t n_elements) { size_ = n_elements; diff --git a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp index 31b3d2ac713f..292cf11bbd7a 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp @@ -4,10 +4,7 @@ #include "barretenberg/common/thread.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/numeric/bitop/pow.hpp" -#include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" #include "barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp" -#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp" -#include "barretenberg/stdlib/primitives/field/field.hpp" #include "polynomial_arithmetic.hpp" #include #include @@ -21,13 +18,6 @@ namespace bb { -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) -template std::shared_ptr _allocate_aligned_memory(size_t n_elements) -{ - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) - return std::static_pointer_cast(get_mem_slab(sizeof(Fr) * n_elements)); -} - // Note: This function is pretty gnarly, but we try to make it the only function that deals // with copying polynomials. It should be scrutinized thusly. template @@ -188,76 +178,6 @@ template Fr Polynomial::evaluate(const Fr& z) const return polynomial_arithmetic::evaluate(data(), z, size()); } -/** - * @brief Internal implementation to support both native and stdlib circuit field types. - * @details Instantiation with circuit field type is always called with shift == false - */ -template -Fr_ _evaluate_mle(std::span evaluation_points, - SharedShiftedVirtualZeroesArray const& coefficients, - bool shift) -{ - constexpr bool is_native = IsAnyOf; - // shift ==> native - ASSERT(!shift || is_native); - - if (coefficients.size() == 0) { - return Fr_(0); - } - - const size_t n = evaluation_points.size(); - const size_t dim = numeric::get_msb(coefficients.end_ - 1) + 1; // Round up to next power of 2 - - // To simplify handling of edge cases, we assume that the index space is always a power of 2 - ASSERT(coefficients.virtual_size() == static_cast(1 << n)); - - // We first fold over dim rounds l = 0,...,dim-1. - // in round l, n_l is the size of the buffer containing the Polynomial partially evaluated - // at u₀,..., u_l. - // In round 0, this is half the size of dim - size_t n_l = 1 << (dim - 1); - - // temporary buffer of half the size of the Polynomial - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1096): Make this a Polynomial with DontZeroMemory::FLAG - auto tmp_ptr = _allocate_aligned_memory(sizeof(Fr_) * n_l); - auto tmp = tmp_ptr.get(); - - size_t offset = 0; - if constexpr (is_native) { - if (shift) { - ASSERT(coefficients.get(0) == Fr_::zero()); - offset++; - } - } - - Fr_ u_l = evaluation_points[0]; - for (size_t i = 0; i < n_l; ++i) { - // curr[i] = (Fr(1) - u_l) * prev[i * 2] + u_l * prev[(i * 2) + 1]; - // Note: i * 2 + 1 + offset might equal virtual_size. This used to subtlely be handled by extra capacity padding - // (and there used to be no assert time checks, which this constant helps with). - const size_t ALLOW_ONE_PAST_READ = 1; - tmp[i] = coefficients.get(i * 2 + offset) + - u_l * (coefficients.get(i * 2 + 1 + offset, ALLOW_ONE_PAST_READ) - coefficients.get(i * 2 + offset)); - } - - // partially evaluate the dim-1 remaining points - for (size_t l = 1; l < dim; ++l) { - n_l = 1 << (dim - l - 1); - u_l = evaluation_points[l]; - for (size_t i = 0; i < n_l; ++i) { - tmp[i] = tmp[i * 2] + u_l * (tmp[(i * 2) + 1] - tmp[i * 2]); - } - } - auto result = tmp[0]; - - // We handle the "trivial" dimensions which are full of zeros. - for (size_t i = dim; i < n; i++) { - result *= (Fr_(1) - evaluation_points[i]); - } - - return result; -} - template Fr Polynomial::evaluate_mle(std::span evaluation_points, bool shift) const { return _evaluate_mle(evaluation_points, coefficients_, shift); @@ -404,26 +324,6 @@ template Polynomial Polynomial::shifted() const return result; } -template -Fr_ generic_evaluate_mle(std::span evaluation_points, - SharedShiftedVirtualZeroesArray const& coefficients) -{ - return _evaluate_mle(evaluation_points, coefficients, false); -} - template class Polynomial; template class Polynomial; -template bb::fr generic_evaluate_mle(std::span evaluation_points, - SharedShiftedVirtualZeroesArray const& coefficients); -template bb::fr _evaluate_mle(std::span evaluation_points, - const SharedShiftedVirtualZeroesArray& coefficients, - bool shift); - -using field_ct = stdlib::field_t; -template field_ct generic_evaluate_mle(std::span evaluation_points, - SharedShiftedVirtualZeroesArray const& coefficients); -template field_ct _evaluate_mle(std::span evaluation_points, - const SharedShiftedVirtualZeroesArray& coefficients, - bool shift); - } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp index 3ff4aae68cbd..ca025cb84a53 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp @@ -3,13 +3,13 @@ #include "barretenberg/common/zip_view.hpp" #include "barretenberg/crypto/sha256/sha256.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" #include "barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp" #include "evaluation_domain.hpp" #include "polynomial_arithmetic.hpp" #include #include #include - namespace bb { /* Span class with a start index offset. @@ -363,6 +363,93 @@ template class Polynomial { SharedShiftedVirtualZeroesArray coefficients_; }; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) +template std::shared_ptr _allocate_aligned_memory(size_t n_elements) +{ + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) + return std::static_pointer_cast(get_mem_slab(sizeof(Fr) * n_elements)); +} + +/** + * @brief Internal implementation to support both native and stdlib circuit field types. + * @details Instantiation with circuit field type is always called with shift == false + */ +template +Fr_ _evaluate_mle(std::span evaluation_points, + SharedShiftedVirtualZeroesArray const& coefficients, + bool shift) +{ + constexpr bool is_native = IsAnyOf; + // shift ==> native + ASSERT(!shift || is_native); + + if (coefficients.size() == 0) { + return Fr_(0); + } + + const size_t n = evaluation_points.size(); + const size_t dim = numeric::get_msb(coefficients.end_ - 1) + 1; // Round up to next power of 2 + + // To simplify handling of edge cases, we assume that the index space is always a power of 2 + ASSERT(coefficients.virtual_size() == static_cast(1 << n)); + + // We first fold over dim rounds l = 0,...,dim-1. + // in round l, n_l is the size of the buffer containing the Polynomial partially evaluated + // at u₀,..., u_l. + // In round 0, this is half the size of dim + size_t n_l = 1 << (dim - 1); + + // temporary buffer of half the size of the Polynomial + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1096): Make this a Polynomial with DontZeroMemory::FLAG + auto tmp_ptr = _allocate_aligned_memory(sizeof(Fr_) * n_l); + auto tmp = tmp_ptr.get(); + + size_t offset = 0; + if constexpr (is_native) { + if (shift) { + ASSERT(coefficients.get(0) == Fr_::zero()); + offset++; + } + } + + Fr_ u_l = evaluation_points[0]; + for (size_t i = 0; i < n_l; ++i) { + // curr[i] = (Fr(1) - u_l) * prev[i * 2] + u_l * prev[(i * 2) + 1]; + // Note: i * 2 + 1 + offset might equal virtual_size. This used to subtlely be handled by extra capacity padding + // (and there used to be no assert time checks, which this constant helps with). + const size_t ALLOW_ONE_PAST_READ = 1; + tmp[i] = coefficients.get(i * 2 + offset) + + u_l * (coefficients.get(i * 2 + 1 + offset, ALLOW_ONE_PAST_READ) - coefficients.get(i * 2 + offset)); + } + + // partially evaluate the dim-1 remaining points + for (size_t l = 1; l < dim; ++l) { + n_l = 1 << (dim - l - 1); + u_l = evaluation_points[l]; + for (size_t i = 0; i < n_l; ++i) { + tmp[i] = tmp[i * 2] + u_l * (tmp[(i * 2) + 1] - tmp[i * 2]); + } + } + auto result = tmp[0]; + + // We handle the "trivial" dimensions which are full of zeros. + for (size_t i = dim; i < n; i++) { + result *= (Fr_(1) - evaluation_points[i]); + } + + return result; +} + +/** + * @brief Static exposed implementation to support both native and stdlib circuit field types. + */ +template +Fr_ generic_evaluate_mle(std::span evaluation_points, + SharedShiftedVirtualZeroesArray const& coefficients) +{ + return _evaluate_mle(evaluation_points, coefficients, false); +} + template inline std::ostream& operator<<(std::ostream& os, Polynomial const& p) { if (p.size() == 0) { @@ -387,12 +474,4 @@ template auto zip_polys(Poly&& poly, Polys&&. ASSERT((poly.start_index() == polys.start_index() && poly.end_index() == polys.end_index()) && ...); return zip_view(poly.indices(), poly.coeffs(), polys.coeffs()...); } - -/** - * @brief Static exposed implementation to support both native and stdlib circuit field types. - */ -template -Fr_ generic_evaluate_mle(std::span evaluation_points, - SharedShiftedVirtualZeroesArray const& coefficients); - } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.test.cpp index 058cf9981a61..5280e49e6161 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.test.cpp @@ -63,7 +63,7 @@ class AvmRecursiveTests : public ::testing::Test { TEST_F(AvmRecursiveTests, recursion) { - auto const public_inputs = generate_base_public_inputs(); + const auto public_inputs = generate_base_public_inputs(); AvmCircuitBuilder circuit_builder = generate_avm_circuit(public_inputs); AvmComposer composer = AvmComposer(); InnerProver prover = composer.create_prover(circuit_builder); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp index 252e51bbb97e..fb4f575a4d66 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp @@ -1,12 +1,8 @@ #include "barretenberg/vm/avm/trace/helper.hpp" - +#include "barretenberg/vm/avm/trace/mem_trace.hpp" #include #include -#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp" -#include "barretenberg/stdlib/primitives/field/field.hpp" -#include "barretenberg/vm/avm/trace/mem_trace.hpp" - namespace bb::avm_trace { template std::string field_to_string(const FF& ff) @@ -74,205 +70,9 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx) return (ind_value & (1 << operand_idx)) != 0; } -/** - * @brief Convert Public Inputs - * - * **Transitional** - * Converts public inputs from the public inputs vec (PublicCircuitPublicInputs) into it's respective public input - * columns Which are represented by the `VmPublicInputs` object. - * - * @param public_inputs_vec - * @return VmPublicInputs - */ -template VmPublicInputs convert_public_inputs(std::vector const& public_inputs_vec) -{ - VmPublicInputs public_inputs; - - // Case where we pass in empty public inputs - this will be used in tests where they are not required - if (public_inputs_vec.empty()) { - return public_inputs; - } - - // Convert the public inputs into the VmPublicInputs object, the public inputs vec must be the correct length - else - // we throw an exception - if (public_inputs_vec.size() != PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH) { - throw_or_abort("Public inputs vector is not of PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH"); - } - - std::array& kernel_inputs = std::get(public_inputs); - - // Copy items from PublicCircuitPublicInputs vector to public input columns - // PublicCircuitPublicInputs - CallContext - kernel_inputs[SENDER_SELECTOR] = public_inputs_vec[SENDER_SELECTOR]; // Sender - // NOTE: address has same position as storage address (they are the same for now...) - // kernel_inputs[ADDRESS_SELECTOR] = public_inputs_vec[ADDRESS_SELECTOR]; // Address - kernel_inputs[STORAGE_ADDRESS_SELECTOR] = public_inputs_vec[STORAGE_ADDRESS_SELECTOR]; // Storage Address - kernel_inputs[FUNCTION_SELECTOR_SELECTOR] = public_inputs_vec[FUNCTION_SELECTOR_SELECTOR]; - kernel_inputs[IS_STATIC_CALL_SELECTOR] = public_inputs_vec[IS_STATIC_CALL_SELECTOR]; - - // PublicCircuitPublicInputs - GlobalVariables - kernel_inputs[CHAIN_ID_SELECTOR] = public_inputs_vec[CHAIN_ID_OFFSET]; // Chain ID - kernel_inputs[VERSION_SELECTOR] = public_inputs_vec[VERSION_OFFSET]; // Version - kernel_inputs[BLOCK_NUMBER_SELECTOR] = public_inputs_vec[BLOCK_NUMBER_OFFSET]; // Block Number - kernel_inputs[TIMESTAMP_SELECTOR] = public_inputs_vec[TIMESTAMP_OFFSET]; // Timestamp - // PublicCircuitPublicInputs - GlobalVariables - GasFees - kernel_inputs[FEE_PER_DA_GAS_SELECTOR] = public_inputs_vec[FEE_PER_DA_GAS_OFFSET]; - kernel_inputs[FEE_PER_L2_GAS_SELECTOR] = public_inputs_vec[FEE_PER_L2_GAS_OFFSET]; - - // Transaction fee - kernel_inputs[TRANSACTION_FEE_SELECTOR] = public_inputs_vec[TRANSACTION_FEE_OFFSET]; - - kernel_inputs[DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET] = public_inputs_vec[DA_START_GAS_LEFT_PCPI_OFFSET]; - kernel_inputs[L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET] = public_inputs_vec[L2_START_GAS_LEFT_PCPI_OFFSET]; - - // Copy the output columns - std::array& ko_values = std::get(public_inputs); - std::array& ko_side_effect = - std::get(public_inputs); - std::array& ko_metadata = std::get(public_inputs); - - // We copy each type of the kernel outputs into their respective columns, each has differeing lengths / data - // For NOTEHASHEXISTS - for (size_t i = 0; i < MAX_NOTE_HASH_READ_REQUESTS_PER_CALL; i++) { - size_t dest_offset = START_NOTE_HASH_EXISTS_WRITE_OFFSET + i; - size_t pcpi_offset = PCPI_NOTE_HASH_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); - - ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - } - // For NULLIFIEREXISTS - for (size_t i = 0; i < MAX_NULLIFIER_READ_REQUESTS_PER_CALL; i++) { - size_t dest_offset = START_NULLIFIER_EXISTS_OFFSET + i; - size_t pcpi_offset = PCPI_NULLIFIER_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); - - ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - ko_metadata[dest_offset] = FF(1); - } - // For NULLIFIEREXISTS - non existent - for (size_t i = 0; i < MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL; i++) { - size_t dest_offset = START_NULLIFIER_NON_EXISTS_OFFSET + i; - size_t pcpi_offset = PCPI_NULLIFIER_NON_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); - - ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - ko_metadata[dest_offset] = FF(0); - } - // For L1TOL2MSGEXISTS - for (size_t i = 0; i < MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL; i++) { - size_t dest_offset = START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + i; - size_t pcpi_offset = PCPI_L1_TO_L2_MSG_READ_REQUESTS_OFFSET + (i * READ_REQUEST_LENGTH); - - ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - } - // For SSTORE - for (size_t i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) { - size_t dest_offset = START_SSTORE_WRITE_OFFSET + i; - size_t pcpi_offset = PCPI_PUBLIC_DATA_UPDATE_OFFSET + (i * CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH); - - // slot, value, side effect - ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_values[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2]; - } - // For SLOAD - for (size_t i = 0; i < MAX_PUBLIC_DATA_READS_PER_CALL; i++) { - size_t dest_offset = START_SLOAD_WRITE_OFFSET + i; - size_t pcpi_offset = PCPI_PUBLIC_DATA_READ_OFFSET + (i * CONTRACT_STORAGE_READ_LENGTH); - - // slot, value, side effect - ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_values[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2]; - } - // For EMITNOTEHASH - for (size_t i = 0; i < MAX_NOTE_HASHES_PER_CALL; i++) { - size_t dest_offset = START_EMIT_NOTE_HASH_WRITE_OFFSET + i; - size_t pcpi_offset = PCPI_NEW_NOTE_HASHES_OFFSET + (i * NOTE_HASH_LENGTH); - - ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - } - // For EMITNULLIFIER - for (size_t i = 0; i < MAX_NULLIFIERS_PER_CALL; i++) { - size_t dest_offset = START_EMIT_NULLIFIER_WRITE_OFFSET + i; - size_t pcpi_offset = PCPI_NEW_NULLIFIERS_OFFSET + (i * NULLIFIER_LENGTH); - - ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - } - // For EMITL2TOL1MSG - for (size_t i = 0; i < MAX_L2_TO_L1_MSGS_PER_CALL; i++) { - size_t dest_offset = START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET + i; - size_t pcpi_offset = PCPI_NEW_L2_TO_L1_MSGS_OFFSET + (i * L2_TO_L1_MESSAGE_LENGTH); - - // Note: unorthadox order - ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_values[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2]; - } - // For EMITUNENCRYPTEDLOG - for (size_t i = 0; i < MAX_UNENCRYPTED_LOGS_PER_CALL; i++) { - size_t dest_offset = START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET + i; - size_t pcpi_offset = - PCPI_NEW_UNENCRYPTED_LOGS_OFFSET + (i * 3); // 3 because we have metadata, this is the window size - - ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; - ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; - ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset + 2]; - } - - return public_inputs; -} - -template -std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, - std::vector const& calldata, - std::vector const& returndata) -{ - // 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 - std::vector public_inputs_kernel_inputs(std::get(public_inputs).begin(), - std::get(public_inputs).end()); - std::vector public_inputs_kernel_value_outputs(std::get(public_inputs).begin(), - std::get(public_inputs).end()); - std::vector public_inputs_kernel_side_effect_outputs( - std::get(public_inputs).begin(), - std::get(public_inputs).end()); - std::vector public_inputs_kernel_metadata_outputs(std::get(public_inputs).begin(), - std::get(public_inputs).end()); - - assert(public_inputs_kernel_inputs.size() == KERNEL_INPUTS_LENGTH); - assert(public_inputs_kernel_value_outputs.size() == KERNEL_OUTPUTS_LENGTH); - assert(public_inputs_kernel_side_effect_outputs.size() == KERNEL_OUTPUTS_LENGTH); - assert(public_inputs_kernel_metadata_outputs.size() == KERNEL_OUTPUTS_LENGTH); - - 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), - calldata, - returndata, - }; -} - std::string to_hex(bb::avm_trace::AvmMemoryTag tag) { return to_hex(static_cast(tag)); } -using field_ct = stdlib::field_t; - -template VmPublicInputs convert_public_inputs(std::vector const& public_inputs_vec); -template VmPublicInputs convert_public_inputs(std::vector const& public_inputs_vec); - -template std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, - std::vector const& calldata, - std::vector const& returndata); -template std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, - std::vector const& calldata, - std::vector const& returndata); - } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp index 20d5ee606db4..3b64afe14889 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp @@ -12,7 +12,157 @@ void dump_trace_as_csv(const std::vector& trace, const std::filesystem::pat bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx); -template VmPublicInputs convert_public_inputs(std::vector const& public_inputs_vec); +/** + * @brief Convert Public Inputs + * + * **Transitional** + * Converts public inputs from the public inputs vec (PublicCircuitPublicInputs) into it's respective public input + * columns Which are represented by the `VmPublicInputs` object. + * + * @param public_inputs_vec + * @return VmPublicInputs + */ +template VmPublicInputs convert_public_inputs(std::vector const& public_inputs_vec) +{ + VmPublicInputs public_inputs; + + // Case where we pass in empty public inputs - this will be used in tests where they are not required + if (public_inputs_vec.empty()) { + return public_inputs; + } + + // Convert the public inputs into the VmPublicInputs object, the public inputs vec must be the correct length - else + // we throw an exception + if (public_inputs_vec.size() != PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH) { + throw_or_abort("Public inputs vector is not of PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH"); + } + + std::array& kernel_inputs = std::get(public_inputs); + + // Copy items from PublicCircuitPublicInputs vector to public input columns + // PublicCircuitPublicInputs - CallContext + kernel_inputs[SENDER_SELECTOR] = public_inputs_vec[SENDER_SELECTOR]; // Sender + // NOTE: address has same position as storage address (they are the same for now...) + // kernel_inputs[ADDRESS_SELECTOR] = public_inputs_vec[ADDRESS_SELECTOR]; // Address + kernel_inputs[STORAGE_ADDRESS_SELECTOR] = public_inputs_vec[STORAGE_ADDRESS_SELECTOR]; // Storage Address + kernel_inputs[FUNCTION_SELECTOR_SELECTOR] = public_inputs_vec[FUNCTION_SELECTOR_SELECTOR]; + kernel_inputs[IS_STATIC_CALL_SELECTOR] = public_inputs_vec[IS_STATIC_CALL_SELECTOR]; + + // PublicCircuitPublicInputs - GlobalVariables + kernel_inputs[CHAIN_ID_SELECTOR] = public_inputs_vec[CHAIN_ID_OFFSET]; // Chain ID + kernel_inputs[VERSION_SELECTOR] = public_inputs_vec[VERSION_OFFSET]; // Version + kernel_inputs[BLOCK_NUMBER_SELECTOR] = public_inputs_vec[BLOCK_NUMBER_OFFSET]; // Block Number + kernel_inputs[TIMESTAMP_SELECTOR] = public_inputs_vec[TIMESTAMP_OFFSET]; // Timestamp + // PublicCircuitPublicInputs - GlobalVariables - GasFees + kernel_inputs[FEE_PER_DA_GAS_SELECTOR] = public_inputs_vec[FEE_PER_DA_GAS_OFFSET]; + kernel_inputs[FEE_PER_L2_GAS_SELECTOR] = public_inputs_vec[FEE_PER_L2_GAS_OFFSET]; + + // Transaction fee + kernel_inputs[TRANSACTION_FEE_SELECTOR] = public_inputs_vec[TRANSACTION_FEE_OFFSET]; + + kernel_inputs[DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET] = public_inputs_vec[DA_START_GAS_LEFT_PCPI_OFFSET]; + kernel_inputs[L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET] = public_inputs_vec[L2_START_GAS_LEFT_PCPI_OFFSET]; + + // Copy the output columns + std::array& ko_values = std::get(public_inputs); + std::array& ko_side_effect = + std::get(public_inputs); + std::array& ko_metadata = std::get(public_inputs); + + // We copy each type of the kernel outputs into their respective columns, each has differeing lengths / data + // For NOTEHASHEXISTS + for (size_t i = 0; i < MAX_NOTE_HASH_READ_REQUESTS_PER_CALL; i++) { + size_t dest_offset = START_NOTE_HASH_EXISTS_WRITE_OFFSET + i; + size_t pcpi_offset = PCPI_NOTE_HASH_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); + + ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + } + // For NULLIFIEREXISTS + for (size_t i = 0; i < MAX_NULLIFIER_READ_REQUESTS_PER_CALL; i++) { + size_t dest_offset = START_NULLIFIER_EXISTS_OFFSET + i; + size_t pcpi_offset = PCPI_NULLIFIER_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); + + ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + ko_metadata[dest_offset] = FF(1); + } + // For NULLIFIEREXISTS - non existent + for (size_t i = 0; i < MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL; i++) { + size_t dest_offset = START_NULLIFIER_NON_EXISTS_OFFSET + i; + size_t pcpi_offset = PCPI_NULLIFIER_NON_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); + + ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + ko_metadata[dest_offset] = FF(0); + } + // For L1TOL2MSGEXISTS + for (size_t i = 0; i < MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL; i++) { + size_t dest_offset = START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + i; + size_t pcpi_offset = PCPI_L1_TO_L2_MSG_READ_REQUESTS_OFFSET + (i * READ_REQUEST_LENGTH); + + ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + } + // For SSTORE + for (size_t i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) { + size_t dest_offset = START_SSTORE_WRITE_OFFSET + i; + size_t pcpi_offset = PCPI_PUBLIC_DATA_UPDATE_OFFSET + (i * CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH); + + // slot, value, side effect + ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_values[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2]; + } + // For SLOAD + for (size_t i = 0; i < MAX_PUBLIC_DATA_READS_PER_CALL; i++) { + size_t dest_offset = START_SLOAD_WRITE_OFFSET + i; + size_t pcpi_offset = PCPI_PUBLIC_DATA_READ_OFFSET + (i * CONTRACT_STORAGE_READ_LENGTH); + + // slot, value, side effect + ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_values[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2]; + } + // For EMITNOTEHASH + for (size_t i = 0; i < MAX_NOTE_HASHES_PER_CALL; i++) { + size_t dest_offset = START_EMIT_NOTE_HASH_WRITE_OFFSET + i; + size_t pcpi_offset = PCPI_NEW_NOTE_HASHES_OFFSET + (i * NOTE_HASH_LENGTH); + + ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + } + // For EMITNULLIFIER + for (size_t i = 0; i < MAX_NULLIFIERS_PER_CALL; i++) { + size_t dest_offset = START_EMIT_NULLIFIER_WRITE_OFFSET + i; + size_t pcpi_offset = PCPI_NEW_NULLIFIERS_OFFSET + (i * NULLIFIER_LENGTH); + + ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + } + // For EMITL2TOL1MSG + for (size_t i = 0; i < MAX_L2_TO_L1_MSGS_PER_CALL; i++) { + size_t dest_offset = START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET + i; + size_t pcpi_offset = PCPI_NEW_L2_TO_L1_MSGS_OFFSET + (i * L2_TO_L1_MESSAGE_LENGTH); + + // Note: unorthadox order + ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_values[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2]; + } + // For EMITUNENCRYPTEDLOG + for (size_t i = 0; i < MAX_UNENCRYPTED_LOGS_PER_CALL; i++) { + size_t dest_offset = START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET + i; + size_t pcpi_offset = + PCPI_NEW_UNENCRYPTED_LOGS_OFFSET + (i * 3); // 3 because we have metadata, this is the window size + + ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; + ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; + ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset + 2]; + } + + return public_inputs; +} // Copy Public Input Columns // There are 5 public input columns, one for inputs, one for returndata and 3 for the kernel outputs @@ -22,7 +172,34 @@ template VmPublicInputs convert_public_inputs(std::vector std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, std::vector const& calldata, - std::vector const& returndata); + std::vector const& returndata) +{ + // 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 + std::vector public_inputs_kernel_inputs(std::get(public_inputs).begin(), + std::get(public_inputs).end()); + std::vector public_inputs_kernel_value_outputs(std::get(public_inputs).begin(), + std::get(public_inputs).end()); + std::vector public_inputs_kernel_side_effect_outputs( + std::get(public_inputs).begin(), + std::get(public_inputs).end()); + std::vector public_inputs_kernel_metadata_outputs(std::get(public_inputs).begin(), + std::get(public_inputs).end()); + + assert(public_inputs_kernel_inputs.size() == KERNEL_INPUTS_LENGTH); + assert(public_inputs_kernel_value_outputs.size() == KERNEL_OUTPUTS_LENGTH); + assert(public_inputs_kernel_side_effect_outputs.size() == KERNEL_OUTPUTS_LENGTH); + assert(public_inputs_kernel_metadata_outputs.size() == KERNEL_OUTPUTS_LENGTH); + + 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), + calldata, + returndata, + }; +} template requires(std::unsigned_integral) diff --git a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs index b6a101ff1fd9..2b7bcfc07f47 100644 --- a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs @@ -38,7 +38,7 @@ inline FF AvmVerifier::evaluate_public_input_column(const std::vector& point * @brief This function verifies an {{name}} Honk proof for given program settings. * */ -bool {{name}}Verifier::verify_proof(const HonkProof& proof, [[maybe_unused]] const std::vector>& public_inputs) +bool {{name}}Verifier::verify_proof(const HonkProof& proof, const std::vector>& public_inputs) { using Flavor = {{name}}Flavor; using FF = Flavor::FF;