diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.cpp index 68dcd61424b..f6224f8b398 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.cpp @@ -8,6 +8,8 @@ #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" #include "barretenberg/vm/avm/recursion/avm_recursive_flavor.hpp" #include "barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp" +#include "barretenberg/vm/avm/trace/common.hpp" +#include "barretenberg/vm/avm/trace/helper.hpp" #include "barretenberg/vm/aztec_constants.hpp" #include "proof_surgeon.hpp" #include @@ -168,13 +170,28 @@ AggregationObjectIndices create_avm_recursion_constraints(Builder& builder, // proof with public inputs reinserted std::vector proof_indices = // ProofSurgeon::create_indices_for_reconstructed_proof(input.proof, input.public_inputs); - std::vector proof_fields; - proof_fields.reserve(input.proof.size()); - - for (const auto& idx : input.proof) { - auto field = field_ct::from_witness_index(&builder, idx); - proof_fields.emplace_back(field); - } + auto fields_from_witnesses = [&](std::vector const& input) { + std::vector result; + result.reserve(input.size()); + for (const auto& idx : input) { + auto field = field_ct::from_witness_index(&builder, idx); + result.emplace_back(field); + } + return result; + }; + + const auto proof_fields = fields_from_witnesses(input.proof); + const auto public_inputs_flattened = fields_from_witnesses(input.public_inputs); + + auto it = public_inputs_flattened.begin(); + avm_trace::VmPublicInputs vm_public_inputs = + avm_trace::convert_public_inputs(std::vector(it, it + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH)); + it += PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH; + std::vector calldata(it, it + AVM_PUBLIC_COLUMN_MAX_SIZE); + it += AVM_PUBLIC_COLUMN_MAX_SIZE; + std::vector return_data(it, it + AVM_PUBLIC_COLUMN_MAX_SIZE); + + auto public_inputs_vectors = avm_trace::copy_public_inputs_columns(vm_public_inputs, calldata, return_data); // Populate the key fields and proof fields with dummy values to prevent issues (e.g. points must be on curve). if (!has_valid_witness_assignments) { @@ -186,7 +203,7 @@ AggregationObjectIndices create_avm_recursion_constraints(Builder& builder, RecursiveVerifier verifier(&builder, vkey); aggregation_state_ct input_agg_obj = bb::stdlib::recursion::convert_witness_indices_to_agg_obj( builder, input_aggregation_object_indices); - aggregation_state_ct output_agg_object = verifier.verify_proof(proof_fields, input_agg_obj); + aggregation_state_ct output_agg_object = verifier.verify_proof(proof_fields, public_inputs_vectors, input_agg_obj); // TODO(https://github.com/AztecProtocol/barretenberg/issues/996): investigate whether assert_equal on public // inputs is important, like what the plonk recursion constraint does. diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp index 619a9810aa4..963e9e47d29 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp @@ -13,7 +13,10 @@ #include "barretenberg/vm/avm/generated/prover.hpp" #include "barretenberg/vm/avm/generated/verifier.hpp" #include "barretenberg/vm/avm/tests/helpers.test.hpp" +#include "barretenberg/vm/avm/trace/helper.hpp" #include "barretenberg/vm/avm/trace/trace.hpp" +#include "barretenberg/vm/aztec_constants.hpp" +#include "barretenberg/vm/constants.hpp" #include "proof_surgeon.hpp" #include #include @@ -39,14 +42,9 @@ class AcirAvmRecursionConstraint : public ::testing::Test { static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } - static InnerBuilder create_inner_circuit() + static InnerBuilder create_inner_circuit(const std::vector& kernel_public_inputs_vec) { - VmPublicInputs public_inputs; - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = 1000000; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = 1000000; - std::get<0>(public_inputs) = kernel_inputs; - + auto public_inputs = convert_public_inputs(kernel_public_inputs_vec); AvmTraceBuilder trace_builder(public_inputs); InnerBuilder builder; @@ -66,7 +64,8 @@ class AcirAvmRecursionConstraint : public ::testing::Test { /** * @brief Create a circuit that recursively verifies one or more inner avm circuits */ - static OuterBuilder create_outer_circuit(std::vector& inner_avm_circuits) + static OuterBuilder create_outer_circuit(std::vector& inner_avm_circuits, + const std::vector& kernel_public_inputs_vec) { std::vector avm_recursion_constraints; @@ -80,6 +79,9 @@ class AcirAvmRecursionConstraint : public ::testing::Test { std::vector key_witnesses = verifier.key->to_field_elements(); std::vector proof_witnesses = prover.construct_proof(); + std::vector public_inputs_vec(kernel_public_inputs_vec); + public_inputs_vec.resize(AVM_PUBLIC_INPUTS_FLATTENED_SIZE); + // Helper to append some values to the witness vector and return their corresponding indices auto add_to_witness_and_track_indices = [&witness](const std::vector& input) -> std::vector { @@ -96,7 +98,7 @@ class AcirAvmRecursionConstraint : public ::testing::Test { RecursionConstraint avm_recursion_constraint{ .key = add_to_witness_and_track_indices(key_witnesses), .proof = add_to_witness_and_track_indices(proof_witnesses), - .public_inputs = {}, + .public_inputs = add_to_witness_and_track_indices(public_inputs_vec), .key_hash = 0, // not used .proof_type = AVM, }; @@ -121,9 +123,14 @@ class AcirAvmRecursionConstraint : public ::testing::Test { TEST_F(AcirAvmRecursionConstraint, TestBasicSingleAvmRecursionConstraint) { + std::vector public_inputs_vec; + public_inputs_vec.resize(PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH); + public_inputs_vec.at(L2_START_GAS_LEFT_PCPI_OFFSET) = FF(1000000); + public_inputs_vec.at(DA_START_GAS_LEFT_PCPI_OFFSET) = FF(1000000); + std::vector layer_1_circuits; - layer_1_circuits.push_back(create_inner_circuit()); - auto layer_2_circuit = create_outer_circuit(layer_1_circuits); + layer_1_circuits.push_back(create_inner_circuit(public_inputs_vec)); + auto layer_2_circuit = create_outer_circuit(layer_1_circuits, public_inputs_vec); info("circuit gates = ", layer_2_circuit.get_num_gates()); diff --git a/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.cpp b/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.cpp index 717a10e44eb..0f670119311 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 986f54ec086..292cf11bbd7 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp @@ -18,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 @@ -187,58 +180,7 @@ template Fr Polynomial::evaluate(const Fr& z) const template Fr Polynomial::evaluate_mle(std::span evaluation_points, bool shift) const { - if (size() == 0) { - return Fr(0); - } - - const size_t n = evaluation_points.size(); - const size_t dim = numeric::get_msb(end_index() - 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(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 (shift) { - ASSERT((*this)[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] = get(i * 2 + offset) + u_l * (get(i * 2 + 1 + offset, ALLOW_ONE_PAST_READ) - 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; + return _evaluate_mle(evaluation_points, coefficients_, shift); } template Polynomial Polynomial::partial_evaluate_mle(std::span evaluation_points) const @@ -384,5 +326,4 @@ template Polynomial Polynomial::shifted() const template class Polynomial; template class Polynomial; - } // 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 86a6e138d96..ec9c14d4084 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,7 +363,95 @@ template class Polynomial { SharedShiftedVirtualZeroesArray coefficients_; }; -template inline std::ostream& operator<<(std::ostream& os, Polynomial const& p) +// 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, + const SharedShiftedVirtualZeroesArray& 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]; + + // Note below: 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; + for (size_t i = 0; i < n_l; ++i) { + // curr[i] = (Fr(1) - u_l) * prev[i * 2] + u_l * prev[(i * 2) + 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, + const SharedShiftedVirtualZeroesArray& coefficients) +{ + return _evaluate_mle(evaluation_points, coefficients, false); +} + +template inline std::ostream& operator<<(std::ostream& os, const Polynomial& p) { if (p.size() == 0) { return os << "[]"; @@ -387,5 +475,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()...); } - } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.cpp index 49a0ba108b2..a7bd04b59a6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.cpp @@ -438,12 +438,6 @@ template bool_t bool_t::implies(const bool_ return (!(*this) || other); // P => Q is equiv. to !P || Q (not(P) or Q). } -/** - * (P => Q) && (P => R) - * <=> (!P || Q) && (!P || R) - * <=> !P || (Q && R) [by distributivity of propositional logic] - * <=> P => (Q && R) [a.k.a. distribution of implication over conjunction] - */ template void bool_t::must_imply(const bool_t& other, std::string const& msg) const { (this->implies(other)).assert_equal(true, msg); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp index 9f974702495..49bc491c708 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp @@ -38,8 +38,7 @@ inline FF AvmVerifier::evaluate_public_input_column(const std::vector& point * @brief This function verifies an Avm Honk proof for given program settings. * */ -bool AvmVerifier::verify_proof(const HonkProof& proof, - [[maybe_unused]] const std::vector>& public_inputs) +bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector>& public_inputs) { using Flavor = AvmFlavor; using FF = Flavor::FF; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.cpp index 9148e568668..562b630e715 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.cpp @@ -1,7 +1,14 @@ #include "barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp" #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" #include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp" +#include "barretenberg/stdlib/primitives/field/field.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/vm/aztec_constants.hpp" +#include +#include +#include namespace bb { @@ -18,18 +25,51 @@ AvmRecursiveVerifier_::AvmRecursiveVerifier_(Builder* builder, const std , builder(builder) {} +// Evaluate the given public input column over the multivariate challenge points template -AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_::verify_proof(const HonkProof& proof, - AggregationObject agg_obj) +Flavor::FF AvmRecursiveVerifier_::evaluate_public_input_column(const std::vector& points, + const std::vector& challenges) +{ + auto coefficients = SharedShiftedVirtualZeroesArray{ + .start_ = 0, + .end_ = points.size(), + .virtual_size_ = key->circuit_size, // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) + .backing_memory_ = std::static_pointer_cast(get_mem_slab(sizeof(FF) * points.size())), + }; + + memcpy( + static_cast(coefficients.data()), static_cast(points.data()), sizeof(FF) * points.size()); + + return generic_evaluate_mle(challenges, coefficients); +} + +template +AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_::verify_proof( + const HonkProof& proof, const std::vector>& public_inputs_vec_nt, AggregationObject agg_obj) { StdlibProof stdlib_proof = bb::convert_proof_to_witness(builder, proof); - return verify_proof(stdlib_proof, agg_obj); + + std::vector> public_inputs_ct; + public_inputs_ct.reserve(public_inputs_vec_nt.size()); + + for (const auto& vec : public_inputs_vec_nt) { + std::vector vec_ct; + vec_ct.reserve(vec.size()); + for (const auto& el : vec) { + vec_ct.push_back(bb::stdlib::witness_t(builder, el)); + } + public_inputs_ct.push_back(vec_ct); + } + + return verify_proof(stdlib_proof, public_inputs_ct, agg_obj); } // TODO(#991): (see https://github.com/AztecProtocol/barretenberg/issues/991) template AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_::verify_proof( - const StdlibProof& stdlib_proof, AggregationObject agg_obj) + const StdlibProof& stdlib_proof, + const std::vector>& public_inputs, + AggregationObject agg_obj) { using Curve = typename Flavor::Curve; using Zeromorph = ZeroMorphVerifier_; @@ -82,6 +122,32 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: vinfo("verified sumcheck: ", (sumcheck_verified.has_value() && sumcheck_verified.value())); + // Public columns evaluation checks + std::vector mle_challenge(multivariate_challenge.begin(), + multivariate_challenge.begin() + static_cast(log_circuit_size)); + + FF main_kernel_inputs_evaluation = evaluate_public_input_column(public_inputs[0], mle_challenge); + main_kernel_inputs_evaluation.assert_equal(claimed_evaluations.main_kernel_inputs, + "main_kernel_inputs_evaluation failed"); + + FF main_kernel_value_out_evaluation = evaluate_public_input_column(public_inputs[1], mle_challenge); + main_kernel_value_out_evaluation.assert_equal(claimed_evaluations.main_kernel_value_out, + "main_kernel_value_out_evaluation failed"); + + FF main_kernel_side_effect_out_evaluation = evaluate_public_input_column(public_inputs[2], mle_challenge); + main_kernel_side_effect_out_evaluation.assert_equal(claimed_evaluations.main_kernel_side_effect_out, + "main_kernel_side_effect_out_evaluation failed"); + + FF main_kernel_metadata_out_evaluation = evaluate_public_input_column(public_inputs[3], mle_challenge); + main_kernel_metadata_out_evaluation.assert_equal(claimed_evaluations.main_kernel_metadata_out, + "main_kernel_metadata_out_evaluation failed"); + + FF main_calldata_evaluation = evaluate_public_input_column(public_inputs[4], mle_challenge); + main_calldata_evaluation.assert_equal(claimed_evaluations.main_calldata, "main_calldata_evaluation failed"); + + FF main_returndata_evaluation = evaluate_public_input_column(public_inputs[5], mle_challenge); + main_returndata_evaluation.assert_equal(claimed_evaluations.main_returndata, "main_returndata_evaluation failed"); + auto opening_claim = Zeromorph::verify(circuit_size, commitments.get_unshifted(), commitments.get_to_be_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp index 15ddd48f56d..38584040419 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp @@ -24,11 +24,18 @@ template class AvmRecursiveVerifier_ { const std::shared_ptr& native_verification_key); explicit AvmRecursiveVerifier_(Builder* builder, const std::shared_ptr& vkey); - AggregationObject verify_proof(const HonkProof& proof, AggregationObject agg_obj); - AggregationObject verify_proof(const StdlibProof& stdlib_proof, AggregationObject agg_obj); + AggregationObject verify_proof(const HonkProof& proof, + const std::vector>& public_inputs_vec_nt, + AggregationObject agg_obj); + AggregationObject verify_proof(const StdlibProof& stdlib_proof, + const std::vector>& public_inputs, + AggregationObject agg_obj); std::shared_ptr key; Builder* builder; std::shared_ptr transcript; + + private: + FF evaluate_public_input_column(const std::vector& points, const std::vector& challenges); }; } // 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 946cd2e15fb..5280e49e616 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 @@ -42,9 +42,9 @@ class AvmRecursiveTests : public ::testing::Test { static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } // Generate an extremely simple avm trace - static AvmCircuitBuilder generate_avm_circuit() + static AvmCircuitBuilder generate_avm_circuit(VmPublicInputsNT public_inputs) { - AvmTraceBuilder trace_builder(generate_base_public_inputs()); + AvmTraceBuilder trace_builder(public_inputs); AvmCircuitBuilder builder; trace_builder.op_set(0, 1, 1, AvmMemoryTag::U8); @@ -63,14 +63,14 @@ class AvmRecursiveTests : public ::testing::Test { TEST_F(AvmRecursiveTests, recursion) { - AvmCircuitBuilder circuit_builder = generate_avm_circuit(); + 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); InnerVerifier verifier = composer.create_verifier(circuit_builder); HonkProof proof = prover.construct_proof(); - auto public_inputs = generate_base_public_inputs(); std::vector> public_inputs_vec = bb::avm_trace::copy_public_inputs_columns(public_inputs, {}, {}); @@ -85,7 +85,7 @@ TEST_F(AvmRecursiveTests, recursion) auto agg_object = stdlib::recursion::init_default_aggregation_state(outer_circuit); - auto agg_output = recursive_verifier.verify_proof(proof, agg_object); + auto agg_output = recursive_verifier.verify_proof(proof, public_inputs_vec, agg_object); bool agg_output_valid = verification_key->pcs_verification_key->pairing_check(agg_output.P0.get_value(), agg_output.P1.get_value()); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp index aae3a07fd72..f2ffca82aa6 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp @@ -211,7 +211,7 @@ class AvmArithmeticTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; void gen_trace_builder(std::vector const& calldata) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp index 3debc937021..a6de859dddb 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp @@ -356,7 +356,7 @@ class AvmBitwiseTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; std::vector gen_mutated_trace_not(FF const& a, FF const& c_mutated, avm_trace::AvmMemoryTag tag) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp index d93abc2872d..e88fdbd36f3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp @@ -23,7 +23,7 @@ class AvmCastTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; std::vector calldata; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp index 463a281f600..758d5fcd205 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp @@ -93,7 +93,7 @@ class AvmCmpTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp index 51120ff94c8..160bccf7800 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp @@ -46,7 +46,7 @@ class AvmControlFlowTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index 7a8c3cb6a36..d4cd303294f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -27,12 +27,12 @@ using bb::utils::hex_to_bytes; class AvmExecutionTests : public ::testing::Test { public: std::vector public_inputs_vec; - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmExecutionTests() : public_inputs_vec(PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH) { - Execution::set_trace_builder_constructor([](VmPublicInputs public_inputs, + Execution::set_trace_builder_constructor([](VmPublicInputsNT public_inputs, ExecutionHints execution_hints, uint32_t side_effect_counter, std::vector calldata) { @@ -52,7 +52,7 @@ class AvmExecutionTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); public_inputs_vec.at(DA_START_GAS_LEFT_PCPI_OFFSET) = DEFAULT_INITIAL_DA_GAS; public_inputs_vec.at(L2_START_GAS_LEFT_PCPI_OFFSET) = DEFAULT_INITIAL_L2_GAS; - public_inputs = Execution::convert_public_inputs(public_inputs_vec); + public_inputs = convert_public_inputs(public_inputs_vec); }; /** @@ -1723,7 +1723,7 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_is_static_call == 1; }); EXPECT_EQ(is_static_call_row->main_ia, is_static_call); - validate_trace(std::move(trace), Execution::convert_public_inputs(public_inputs_vec), calldata, returndata); + validate_trace(std::move(trace), convert_public_inputs(public_inputs_vec), calldata, returndata); } // Positive test for L2GASLEFT opcode diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp index 6e5525fce18..c88bc8683fd 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp @@ -36,7 +36,7 @@ void test_gas(StartGas startGas, OpcodesFunc apply_opcodes, CheckFunc check_trac kernel_inputs[L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET] = FF(startGas.l2_gas); kernel_inputs[DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET] = FF(startGas.da_gas); - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; std::get<0>(public_inputs) = kernel_inputs; auto trace_builder = AvmTraceBuilder(public_inputs).set_full_precomputed_tables(false).set_range_check_required(false); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/helpers.test.cpp index 90951a0e163..a1c7317d47d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/helpers.test.cpp @@ -36,7 +36,7 @@ void validate_trace_check_circuit(std::vector&& trace) * @param trace The execution trace */ void validate_trace(std::vector&& trace, - VmPublicInputs const& public_inputs, + VmPublicInputsNT const& public_inputs, std::vector const& calldata, std::vector const& returndata, bool with_proof, @@ -118,9 +118,9 @@ void mutate_ic_in_trace(std::vector& trace, std::function&& sele mem_row->mem_val = newValue; }; -VmPublicInputs generate_base_public_inputs() +VmPublicInputsNT generate_base_public_inputs() { - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; std::array kernel_inputs{}; kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/helpers.test.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/helpers.test.hpp index 6eba2649c7d..b881588de1d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/helpers.test.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/helpers.test.hpp @@ -25,14 +25,14 @@ using FF = bb::AvmFlavorSettings::FF; using Row = bb::AvmFullRow; using ThreeOpParam = std::array; using ThreeOpParamRow = std::tuple; -using VmPublicInputs = bb::avm_trace::VmPublicInputs; +using VmPublicInputsNT = 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); void validate_trace(std::vector&& trace, - VmPublicInputs const& public_inputs = {}, + VmPublicInputsNT const& public_inputs = {}, std::vector const& calldata = {}, std::vector const& returndata = {}, bool with_proof = false, @@ -46,6 +46,6 @@ void update_slice_registers(Row& row, uint256_t a); std::vector gen_three_op_params(std::vector> operands, std::vector mem_tags); -VmPublicInputs generate_base_public_inputs(); +VmPublicInputsNT generate_base_public_inputs(); } // namespace tests_avm diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp index 63ee094e9ab..eb9ddd455c3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp @@ -15,7 +15,7 @@ class AvmIndirectMemTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp index 4edde8f1296..f2e9c17967e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp @@ -21,7 +21,7 @@ class AvmInterTableTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp index 611e08dc34c..1ef1d921c3d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp @@ -30,9 +30,9 @@ class AvmKernelNegativeTests : public AvmKernelTests { using KernelInputs = std::array; const size_t INITIAL_GAS = 10000; -VmPublicInputs get_base_public_inputs() +VmPublicInputsNT get_base_public_inputs() { - VmPublicInputs public_inputs = {}; + VmPublicInputsNT public_inputs = {}; std::array kernel_inputs; for (size_t i = 0; i < KERNEL_INPUTS_LENGTH; i++) { @@ -49,9 +49,9 @@ VmPublicInputs get_base_public_inputs() return public_inputs; } -VmPublicInputs get_public_inputs_with_output(uint32_t output_offset, FF value, FF side_effect_counter, FF metadata) +VmPublicInputsNT get_public_inputs_with_output(uint32_t output_offset, FF value, FF side_effect_counter, FF metadata) { - VmPublicInputs public_inputs = get_base_public_inputs(); + VmPublicInputsNT public_inputs = get_base_public_inputs(); std::get(public_inputs)[output_offset] = value; std::get(public_inputs)[output_offset] = side_effect_counter; @@ -66,7 +66,7 @@ using CheckFunc = std::function&)>; void test_kernel_lookup(bool indirect, OpcodesFunc apply_opcodes, CheckFunc check_trace, - VmPublicInputs public_inputs = get_base_public_inputs(), + VmPublicInputsNT public_inputs = get_base_public_inputs(), ExecutionHints execution_hints = {}) { auto trace_builder = AvmTraceBuilder(public_inputs, std::move(execution_hints)) @@ -608,7 +608,7 @@ void negative_test_incorrect_ia_kernel_lookup(OpcodesFunc apply_opcodes, FF incorrect_ia, auto expected_message) { - VmPublicInputs public_inputs = get_base_public_inputs(); + VmPublicInputsNT public_inputs = get_base_public_inputs(); auto trace_builder = AvmTraceBuilder(public_inputs).set_full_precomputed_tables(false).set_range_check_required(false); @@ -956,7 +956,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNoteHash) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, /*metadata=*/0); }; - VmPublicInputs public_inputs = + VmPublicInputsNT public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, /*metadata*/ 0); test_kernel_lookup(false, direct_apply_opcodes, checks, public_inputs); test_kernel_lookup(true, indirect_apply_opcodes, checks, public_inputs); @@ -1000,7 +1000,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNullifier) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, /*metadata=*/0); }; - VmPublicInputs public_inputs = + VmPublicInputsNT public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, /*metadata*/ 0); test_kernel_lookup(false, direct_apply_opcodes, checks, public_inputs); test_kernel_lookup(true, indirect_apply_opcodes, checks, public_inputs); @@ -1051,7 +1051,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitL2ToL1Msg) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, /*metadata=*/recipient); }; - VmPublicInputs public_inputs = + VmPublicInputsNT public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, recipient); test_kernel_lookup(false, direct_apply_opcodes, checks, std::move(public_inputs)); test_kernel_lookup(true, indirect_apply_opcodes, checks, std::move(public_inputs)); @@ -1093,7 +1093,8 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitUnencryptedLog) check_kernel_outputs(trace.at(output_offset), value, 0, slot); }; - VmPublicInputs public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, slot); + VmPublicInputsNT public_inputs = + get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, slot); test_kernel_lookup(false, direct_apply_opcodes, checks, public_inputs); test_kernel_lookup(true, indirect_apply_opcodes, checks, public_inputs); } @@ -1137,7 +1138,8 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSload) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, slot); }; - VmPublicInputs public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, slot); + VmPublicInputsNT public_inputs = + get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, slot); test_kernel_lookup(false, apply_opcodes, checks, std::move(public_inputs), execution_hints); } @@ -1179,7 +1181,8 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSstore) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, slot); }; - VmPublicInputs public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, slot); + VmPublicInputsNT public_inputs = + get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, slot); test_kernel_lookup(false, apply_opcodes, checks, std::move(public_inputs)); } @@ -1228,7 +1231,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNoteHashExists) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists); }; - VmPublicInputs public_inputs = + VmPublicInputsNT public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, exists); test_kernel_lookup(false, direct_apply_opcodes, checks, public_inputs, execution_hints); test_kernel_lookup(true, indirect_apply_opcodes, checks, public_inputs, execution_hints); @@ -1268,7 +1271,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierExists) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists); }; - VmPublicInputs public_inputs = + VmPublicInputsNT public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, exists); test_kernel_lookup(false, apply_opcodes, checks, std::move(public_inputs), execution_hints); } @@ -1307,7 +1310,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierNonExists) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists); }; - VmPublicInputs public_inputs = + VmPublicInputsNT public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, exists); test_kernel_lookup(false, apply_opcodes, checks, std::move(public_inputs), execution_hints); } @@ -1348,7 +1351,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelL1ToL2MsgExists) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists); }; - VmPublicInputs public_inputs = + VmPublicInputsNT public_inputs = get_public_inputs_with_output(output_offset, value, /*side_effect_counter=*/0, exists); test_kernel_lookup(false, apply_opcodes, checks, std::move(public_inputs), execution_hints); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp index 74f3b934559..631c09d1cd4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp @@ -23,7 +23,7 @@ class AvmMemOpcodeTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; protected: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp index 245077021ef..67196ff92c2 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp @@ -16,7 +16,7 @@ class AvmMemoryTests : public ::testing::Test { srs::init_crs_factory("../srs_db/ignition"); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp index 300b1ca935b..6150290123d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp @@ -115,7 +115,7 @@ class AvmSliceTests : public ::testing::Test { validate_trace(std::move(trace), public_inputs, calldata); } - VmPublicInputs public_inputs; + VmPublicInputsNT public_inputs; AvmTraceBuilder trace_builder; std::vector calldata; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/common.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/common.hpp index 1f5df25e342..6f838cf9557 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/common.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/common.hpp @@ -14,10 +14,11 @@ namespace bb::avm_trace { using FF = AvmFlavorSettings::FF; // There are 4 public input columns, 1 for context inputs, and 3 for emitting side effects -using VmPublicInputs = std::tuple, // Input: Kernel context inputs - std::array, // Output: Kernel outputs data - std::array, // Output: Kernel outputs side effects - std::array>; // Output: Kernel outputs metadata +template +using VmPublicInputs = std::tuple, // Input: Kernel context inputs + std::array, // Output: Kernel outputs data + std::array, // Output: Kernel outputs side effects + std::array>; // Output: Kernel outputs metadata // Constants for indexing into the tuple above static const size_t KERNEL_INPUTS = 0; static const size_t KERNEL_OUTPUTS_VALUE = 1; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index ea713ac51be..74d5d4797b2 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -146,7 +146,7 @@ void show_trace_info(const auto& trace) } // namespace // Needed for dependency injection in tests. -Execution::TraceBuilderConstructor Execution::trace_builder_constructor = [](VmPublicInputs public_inputs, +Execution::TraceBuilderConstructor Execution::trace_builder_constructor = [](VmPublicInputs public_inputs, ExecutionHints execution_hints, uint32_t side_effect_counter, std::vector calldata) { @@ -229,157 +229,6 @@ std::tuple Execution::prove(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; -} - bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) { AvmVerifier verifier(std::make_shared(vk)); @@ -403,7 +252,7 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) std::copy(returndata_offset, raw_proof_offset, std::back_inserter(returndata)); std::copy(raw_proof_offset, proof.end(), std::back_inserter(raw_proof)); - VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); + VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs, calldata, returndata); return verifier.verify_proof(raw_proof, public_inputs_columns); @@ -442,7 +291,7 @@ std::vector Execution::gen_trace(std::vector const& instructio vinfo("------- GENERATING TRACE -------"); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6718): construction of the public input columns // should be done in the kernel - this is stubbed and underconstrained - VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); + VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); uint32_t start_side_effect_counter = !public_inputs_vec.empty() ? static_cast(public_inputs_vec[PCPI_START_SIDE_EFFECT_COUNTER_OFFSET]) : 0; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.hpp index ae6863589d0..7c7c0ddf4ec 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.hpp @@ -15,7 +15,7 @@ namespace bb::avm_trace { class Execution { public: static constexpr size_t SRS_SIZE = 1 << 22; - using TraceBuilderConstructor = std::function public_inputs, ExecutionHints execution_hints, uint32_t side_effect_counter, std::vector calldata)>; @@ -24,8 +24,6 @@ class Execution { static std::vector getDefaultPublicInputs(); - static VmPublicInputs convert_public_inputs(std::vector const& public_inputs_vec); - // TODO: Clean these overloaded functions. We probably need less and confusing overloading. static std::vector gen_trace(std::vector const& instructions, std::vector& returndata, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp index 588e750a10b..fb4f575a4d6 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp @@ -1,10 +1,8 @@ #include "barretenberg/vm/avm/trace/helper.hpp" - +#include "barretenberg/vm/avm/trace/mem_trace.hpp" #include #include -#include "barretenberg/vm/avm/trace/mem_trace.hpp" - namespace bb::avm_trace { template std::string field_to_string(const FF& ff) @@ -72,37 +70,6 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx) return (ind_value & (1 << operand_idx)) != 0; } -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)); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp index 91979bd4499..3b64afe1488 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp @@ -12,14 +12,194 @@ 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); +/** + * @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 // {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 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) +{ + // 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/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.hpp index 49979bca3cd..95f2815597b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.hpp @@ -57,7 +57,7 @@ class AvmKernelTraceBuilder { // optimise this to just hardcode the counter to be the same as the lookup selector value!!! std::unordered_map kernel_output_selector_counter; - AvmKernelTraceBuilder(uint32_t initial_side_effect_counter, VmPublicInputs public_inputs, ExecutionHints hints) + AvmKernelTraceBuilder(uint32_t initial_side_effect_counter, VmPublicInputs public_inputs, ExecutionHints hints) : public_inputs(std::move(public_inputs)) , initial_side_effect_counter(initial_side_effect_counter) , hints(std::move(hints)) @@ -98,7 +98,7 @@ class AvmKernelTraceBuilder { void op_emit_l2_to_l1_msg(uint32_t clk, uint32_t side_effect_counter, const FF& l2_to_l1_msg, const FF& recipient); // This is temporarily made public so we can access PIs - VmPublicInputs public_inputs; + VmPublicInputs public_inputs; private: std::vector kernel_trace; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index a1e563ed638..f4b82918975 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -276,7 +276,7 @@ void AvmTraceBuilder::finalise_mem_trace_lookup_counts() * @brief Constructor of a trace builder of AVM. Only serves to set the capacity of the * underlying traces and initialize gas values. */ -AvmTraceBuilder::AvmTraceBuilder(VmPublicInputs public_inputs, +AvmTraceBuilder::AvmTraceBuilder(VmPublicInputs public_inputs, ExecutionHints execution_hints_, uint32_t side_effect_counter, std::vector calldata) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index a9a1ee74476..29167b16a00 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -52,7 +52,7 @@ struct AddressWithMode { class AvmTraceBuilder { public: - AvmTraceBuilder(VmPublicInputs public_inputs = {}, + AvmTraceBuilder(VmPublicInputs public_inputs = {}, ExecutionHints execution_hints = {}, uint32_t side_effect_counter = 0, std::vector calldata = {}); diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index 8c6c05e4dc6..684319d2f13 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -35,7 +35,8 @@ #define PUBLIC_CONTEXT_INPUTS_LENGTH 42 #define AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS 66 #define AVM_PROOF_LENGTH_IN_FIELDS 3822 -#define AVM_PUBLIC_COLUMN_MAX_SIZE_LOG2 8 +#define AVM_PUBLIC_COLUMN_MAX_SIZE 1024 +#define AVM_PUBLIC_INPUTS_FLATTENED_SIZE 2739 #define MEM_TAG_U1 1 #define MEM_TAG_U8 2 #define MEM_TAG_U16 3 diff --git a/barretenberg/cpp/src/barretenberg/vm/constants.hpp b/barretenberg/cpp/src/barretenberg/vm/constants.hpp index aedd9cb3215..d8ee8a30dd8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/constants.hpp @@ -16,6 +16,14 @@ inline const std::size_t KERNEL_OUTPUTS_LENGTH = MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_READS_PER_CALL + MAX_NOTE_HASHES_PER_CALL + MAX_NULLIFIERS_PER_CALL + MAX_L2_TO_L1_MSGS_PER_CALL + MAX_UNENCRYPTED_LOGS_PER_CALL; +static_assert(KERNEL_INPUTS_LENGTH < AVM_PUBLIC_COLUMN_MAX_SIZE, + "The kernel inputs length cannot exceed the max size of a public column. This is a requirement for the " + "avm recursive verifier."); + +static_assert(KERNEL_OUTPUTS_LENGTH < AVM_PUBLIC_COLUMN_MAX_SIZE, + "The kernel outputs length cannot exceed the max size of a public column. This is a requirement for the " + "avm recursive verifier."); + // START INDEXES in the PUBLIC_CIRCUIT_PUBLIC_INPUTS // These line up with indexes found in // https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts diff --git a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs index b6a101ff1fd..2b7bcfc07f4 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; diff --git a/noir-projects/mock-protocol-circuits/crates/mock-public-kernel/src/main.nr b/noir-projects/mock-protocol-circuits/crates/mock-public-kernel/src/main.nr index b66b27da567..5f99389e499 100644 --- a/noir-projects/mock-protocol-circuits/crates/mock-public-kernel/src/main.nr +++ b/noir-projects/mock-protocol-circuits/crates/mock-public-kernel/src/main.nr @@ -1,9 +1,13 @@ -use dep::types::constants::{AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, AVM_PROOF_LENGTH_IN_FIELDS, PROOF_TYPE_AVM}; +use dep::types::constants::{ + AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, AVM_PROOF_LENGTH_IN_FIELDS, AVM_PUBLIC_INPUTS_FLATTENED_SIZE, + PROOF_TYPE_AVM +}; fn main( verification_key: [Field; AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS], - proof: [Field; AVM_PROOF_LENGTH_IN_FIELDS] + proof: [Field; AVM_PROOF_LENGTH_IN_FIELDS], + pub_cols_flattened: [Field; AVM_PUBLIC_INPUTS_FLATTENED_SIZE] ) -> pub u8 { - std::verify_proof_with_type(verification_key, proof, [], 0, PROOF_TYPE_AVM); + std::verify_proof_with_type(verification_key, proof, pub_cols_flattened, 0, PROOF_TYPE_AVM); 1 // Dummy value to return for the mock kernel as void function creates some pain. } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index c791b813df7..9dc189b2062 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -328,7 +328,8 @@ global AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = 2 + 16 * 4; // To determine latest value, hover `COMPUTED_AVM_PROOF_LENGTH_IN_FIELDS` // in barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp global AVM_PROOF_LENGTH_IN_FIELDS: u32 = 3822; -global AVM_PUBLIC_COLUMN_MAX_SIZE_LOG2 = 8; +global AVM_PUBLIC_COLUMN_MAX_SIZE : u32 = 1024; +global AVM_PUBLIC_INPUTS_FLATTENED_SIZE : u32 = 2 * AVM_PUBLIC_COLUMN_MAX_SIZE + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH; /** * Enumerate the hash_indices which are used for pedersen hashing. * We start from 1 to avoid the default generators. The generator indices are listed diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 5e60d76ff69..800b5a52b78 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -216,7 +216,8 @@ export const TUBE_PROOF_LENGTH = 439; export const VERIFICATION_KEY_LENGTH_IN_FIELDS = 128; export const AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS = 66; export const AVM_PROOF_LENGTH_IN_FIELDS = 3822; -export const AVM_PUBLIC_COLUMN_MAX_SIZE_LOG2 = 8; +export const AVM_PUBLIC_COLUMN_MAX_SIZE = 1024; +export const AVM_PUBLIC_INPUTS_FLATTENED_SIZE = 2739; export const MEM_TAG_U1 = 1; export const MEM_TAG_U8 = 2; export const MEM_TAG_U16 = 3; diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index bf922fa24fa..8580b48e8ba 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -269,7 +269,7 @@ function generateSolidityConstants({ constants }: ParsedContent, targetPath: str const resultSolidity: string = `// GENERATED FILE - DO NOT EDIT, RUN yarn remake-constants in circuits.js // SPDX-License-Identifier: Apache-2.0 // Copyright 2023 Aztec Labs. -pragma solidity >=0.8.18; +pragma solidity >=0.8.27; /** * @title Constants Library diff --git a/yarn-project/ivc-integration/src/avm_integration.test.ts b/yarn-project/ivc-integration/src/avm_integration.test.ts index c2bb09e3675..0811ca4c6bf 100644 --- a/yarn-project/ivc-integration/src/avm_integration.test.ts +++ b/yarn-project/ivc-integration/src/avm_integration.test.ts @@ -9,6 +9,8 @@ import { import { AvmCircuitInputs, FunctionSelector, Gas, GlobalVariables } from '@aztec/circuits.js'; import { AVM_PROOF_LENGTH_IN_FIELDS, + AVM_PUBLIC_COLUMN_MAX_SIZE, + AVM_PUBLIC_INPUTS_FLATTENED_SIZE, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, } from '@aztec/circuits.js/constants'; @@ -16,7 +18,7 @@ import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { BufferReader } from '@aztec/foundation/serialize'; import { type FixedLengthArray } from '@aztec/noir-protocol-circuits-types/types'; -import { AvmSimulator, type PublicContractsDB, PublicSideEffectTrace, type WorldStateDB } from '@aztec/simulator'; +import { AvmSimulator, PublicSideEffectTrace, type WorldStateDB } from '@aztec/simulator'; import { getAvmTestContractBytecode, initContext, @@ -72,7 +74,10 @@ describe('AVM Integration', () => { } it('Should generate and verify an ultra honk proof from an AVM verification', async () => { - const bbSuccess = await proveAvmTestContract('new_note_hash', [new Fr(1)]); + const bbSuccess = await proveAvmTestContract( + 'bulk_testing', + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x)), + ); const avmProofPath = bbSuccess.proofPath; const avmVkPath = bbSuccess.vkPath; @@ -82,11 +87,19 @@ describe('AVM Integration', () => { // Read the binary proof const avmProofBuffer = await fs.readFile(avmProofPath!); const reader = BufferReader.asReader(avmProofBuffer); - reader.readArray(PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, Fr); + const kernel_public_inputs = reader.readArray(PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, Fr); const calldataSize = Fr.fromBuffer(reader).toNumber(); - reader.readArray(calldataSize, Fr); + const calldata = reader.readArray(calldataSize, Fr); const returnDataSize = Fr.fromBuffer(reader).toNumber(); - reader.readArray(returnDataSize, Fr); + const returnData = reader.readArray(returnDataSize, Fr); + + const public_cols_flattened = kernel_public_inputs + .concat(calldata) + .concat(Array(AVM_PUBLIC_COLUMN_MAX_SIZE - calldata.length).fill(new Fr(0))) + .concat(returnData) + .concat(Array(AVM_PUBLIC_COLUMN_MAX_SIZE - returnData.length).fill(new Fr(0))); + + expect(public_cols_flattened.length).toBe(AVM_PUBLIC_INPUTS_FLATTENED_SIZE); const proof: Fr[] = []; while (!reader.isEmpty()) { @@ -106,6 +119,10 @@ describe('AVM Integration', () => { typeof AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS >, proof: proof.map(x => x.toString()) as FixedLengthArray, + pub_cols_flattened: public_cols_flattened.map(x => x.toString()) as FixedLengthArray< + string, + typeof AVM_PUBLIC_INPUTS_FLATTENED_SIZE + >, }); await createHonkProof(witGenResult.witness, MockPublicKernelCircuit.bytecode); @@ -134,7 +151,7 @@ const proveAvmTestContract = async ( const globals = GlobalVariables.empty(); const environment = initExecutionEnvironment({ functionSelector, calldata, globals }); - const contractsDb = mock(); + const worldStateDB = mock(); const contractInstance = new SerializableContractInstance({ version: 1, salt: new Fr(0x123), @@ -143,9 +160,8 @@ const proveAvmTestContract = async ( initializationHash: new Fr(0x101112), publicKeysHash: new Fr(0x161718), }).withAddress(environment.address); - contractsDb.getContractInstance.mockResolvedValue(await Promise.resolve(contractInstance)); + worldStateDB.getContractInstance.mockResolvedValue(await Promise.resolve(contractInstance)); - const worldStateDB = mock(); const storageValue = new Fr(5); worldStateDB.storageRead.mockResolvedValue(await Promise.resolve(storageValue));