From 295cd5564048ca27316c508766a2dcfc3cc1bf7e Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Wed, 7 Feb 2024 12:52:48 -0700 Subject: [PATCH] feat: PG + Goblin (#4399) Implements a new `ClientIvc` class that serves as the interface for doing IVC with PG + Goblin. Adds a PoC for the architecture in new test file. This test (and an updated one for Goblin + vanilla recursion) use a new goblin method `merge` which is similar to the `accumulate` method but with the IVC prover related work stripped out. This allows goblin to be completely agnostic to the IVC scheme (recursion/folding) that it's being used with. --------- Co-authored-by: codygunton --- barretenberg/barretenberg.code-workspace | 3 +- barretenberg/cpp/scripts/bb-tests.sh | 1 + barretenberg/cpp/src/CMakeLists.txt | 1 + .../barretenberg/client_ivc/CMakeLists.txt | 1 + .../barretenberg/client_ivc/client_ivc.cpp | 79 ++++++++++++ .../barretenberg/client_ivc/client_ivc.hpp | 50 ++++++++ .../client_ivc/client_ivc.test.cpp | 120 ++++++++++++++++++ .../goblin/full_goblin_recursion.test.cpp | 62 --------- .../cpp/src/barretenberg/goblin/goblin.hpp | 25 ++++ .../goblin/goblin_recursion.test.cpp | 75 +++++++++++ .../src/barretenberg/goblin/mock_circuits.hpp | 21 ++- .../protogalaxy/protogalaxy_prover.cpp | 7 +- .../protogalaxy/protogalaxy_verifier.cpp | 7 +- .../ultra_honk/protogalaxy.test.cpp | 2 +- 14 files changed, 384 insertions(+), 70 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/client_ivc/CMakeLists.txt create mode 100644 barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp create mode 100644 barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp create mode 100644 barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/goblin/full_goblin_recursion.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/goblin/goblin_recursion.test.cpp diff --git a/barretenberg/barretenberg.code-workspace b/barretenberg/barretenberg.code-workspace index 24c8a186612..362ddc1783c 100644 --- a/barretenberg/barretenberg.code-workspace +++ b/barretenberg/barretenberg.code-workspace @@ -152,8 +152,7 @@ }, "cmake.configureArgs": [ "--preset clang16", - "-G Ninja", - "-g" + "-G Ninja" ], "cmake.useCMakePresets": "auto", "editor.inlayHints.enabled": "offUnlessPressed", diff --git a/barretenberg/cpp/scripts/bb-tests.sh b/barretenberg/cpp/scripts/bb-tests.sh index a4ba5b39417..0c0d27ed922 100755 --- a/barretenberg/cpp/scripts/bb-tests.sh +++ b/barretenberg/cpp/scripts/bb-tests.sh @@ -11,6 +11,7 @@ IMAGE_URI=$(calculate_image_uri $REPOSITORY) retry docker pull $IMAGE_URI TESTS=( + client_ivc_tests commitment_schemes_tests crypto_aes128_tests crypto_blake2s_tests diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index 65176f7c421..3c996c513dc 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -49,6 +49,7 @@ else() endif() add_subdirectory(barretenberg/bb) +add_subdirectory(barretenberg/client_ivc) add_subdirectory(barretenberg/commitment_schemes) add_subdirectory(barretenberg/common) add_subdirectory(barretenberg/crypto) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/client_ivc/CMakeLists.txt new file mode 100644 index 00000000000..e4f75e5e984 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/client_ivc/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(client_ivc goblin) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp new file mode 100644 index 00000000000..3affe72d550 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -0,0 +1,79 @@ +#include "barretenberg/client_ivc/client_ivc.hpp" + +namespace bb { + +ClientIVC::ClientIVC() +{ + // TODO(https://github.com/AztecProtocol/barretenberg/issues/723): + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue); +} + +/** + * @brief Initialize the IVC with a first circuit + * @details Initializes the accumulator and performs the initial goblin merge + * + * @param circuit + */ +void ClientIVC::initialize(ClientCircuit& circuit) +{ + goblin.merge(circuit); // Construct new merge proof + Composer composer; + fold_output.accumulator = composer.create_instance(circuit); +} + +/** + * @brief Accumulate a circuit into the IVC scheme + * @details Performs goblin merge, generates circuit instance, folds into accumulator and constructs a folding proof + * + * @param circuit Circuit to be accumulated/folded + * @return FoldProof + */ +ClientIVC::FoldProof ClientIVC::accumulate(ClientCircuit& circuit) +{ + goblin.merge(circuit); // Add recursive merge verifier and construct new merge proof + Composer composer; + auto instance = composer.create_instance(circuit); + std::vector> instances{ fold_output.accumulator, instance }; + auto folding_prover = composer.create_folding_prover(instances); + fold_output = folding_prover.fold_instances(); + return fold_output.folding_data; +} + +/** + * @brief Construct a proof for the IVC, which, if verified, fully establishes its correctness + * + * @return Proof + */ +ClientIVC::Proof ClientIVC::prove() +{ + // Construct Goblin proof (merge, eccvm, translator) + auto goblin_proof = goblin.prove(); + + // Construct decider proof for the final accumulator + Composer composer; + auto decider_prover = composer.create_decider_prover(fold_output.accumulator); + auto decider_proof = decider_prover.construct_proof(); + return { goblin_proof, fold_output.folding_data, decider_proof }; +} + +/** + * @brief Verify a full proof of the IVC + * + * @param proof + * @return bool + */ +bool ClientIVC::verify(Proof& proof) +{ + // Goblin verification (merge, eccvm, translator) + bool goblin_verified = goblin.verify(proof.goblin_proof); + + // Decider verification + Composer composer; + auto folding_verifier = composer.create_folding_verifier(); + bool folding_verified = folding_verifier.verify_folding_proof(proof.fold_proof); + // NOTE: Use of member accumulator here will go away with removal of vkey from ProverInstance + auto decider_verifier = composer.create_decider_verifier(fold_output.accumulator); + bool decision = decider_verifier.verify_proof(proof.decider_proof); + return goblin_verified && folding_verified && decision; +} +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp new file mode 100644 index 00000000000..6f065bd452f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" + +namespace bb { + +/** + * @brief The IVC interface to be used by the aztec client for private function execution + * @details Combines Protogalaxy with Goblin to accumulate one circuit instance at a time with efficient EC group + * operations + * + */ +class ClientIVC { + + public: + using Flavor = GoblinUltraFlavor; + using FF = Flavor::FF; + using FoldProof = std::vector; + using Accumulator = std::shared_ptr>; + using ClientCircuit = GoblinUltraCircuitBuilder; // can only be GoblinUltra + + // A full proof for the IVC scheme + struct Proof { + Goblin::Proof goblin_proof; + FoldProof fold_proof; // final fold proof + HonkProof decider_proof; + }; + + private: + using FoldingOutput = FoldingResult; + using Instance = ProverInstance_; + using Composer = GoblinUltraComposer; + + public: + Goblin goblin; + FoldingOutput fold_output; + + ClientIVC(); + + void initialize(ClientCircuit& circuit); + + FoldProof accumulate(ClientCircuit& circuit); + + Proof prove(); + + bool verify(Proof& proof); +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp new file mode 100644 index 00000000000..52aed2f2987 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -0,0 +1,120 @@ +#include "barretenberg/client_ivc/client_ivc.hpp" +#include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/stdlib/recursion/honk/verifier/protogalaxy_recursive_verifier.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" + +#include +using namespace bb; + +class ClientIVCTests : public ::testing::Test { + protected: + static void SetUpTestSuite() + { + srs::init_crs_factory("../srs_db/ignition"); + srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } + + using Flavor = ClientIVC::Flavor; + using FF = typename Flavor::FF; + using Builder = ClientIVC::ClientCircuit; + using Composer = GoblinUltraComposer; + using Accumulator = ClientIVC::Accumulator; + using FoldProof = ClientIVC::FoldProof; + + using GURecursiveFlavor = GoblinUltraRecursiveFlavor_; + using RecursiveVerifierInstances = ::bb::VerifierInstances_; + using FoldingRecursiveVerifier = + bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_; + + /** + * @brief Construct mock circuit with arithmetic gates and goblin ops + * @details Currently default sized to 2^16 to match kernel. (Note: op gates will bump size to next power of 2) + * + */ + static Builder create_mock_circuit(ClientIVC& ivc, size_t num_gates = 1 << 15) + { + Builder circuit{ ivc.goblin.op_queue }; + GoblinMockCircuits::construct_arithmetic_circuit(circuit, num_gates); + GoblinMockCircuits::construct_goblin_ecc_op_circuit(circuit); + return circuit; + } + + /** + * @brief Construct mock kernel consisting of two recursive folding verifiers + * + * @param builder + * @param fctn_fold_proof + * @param kernel_fold_proof + */ + static void construct_mock_folding_kernel(Builder& builder, + FoldProof& fctn_fold_proof, + FoldProof& kernel_fold_proof) + { + FoldingRecursiveVerifier verifier_1{ &builder }; + verifier_1.verify_folding_proof(fctn_fold_proof); + + FoldingRecursiveVerifier verifier_2{ &builder }; + verifier_2.verify_folding_proof(kernel_fold_proof); + } + + /** + * @brief Perform native fold verification and run decider prover/verifier + * + */ + static void EXPECT_FOLDING_AND_DECIDING_VERIFIED(const Accumulator& accumulator, const FoldProof& fold_proof) + { + // Verify fold proof + Composer composer; + auto folding_verifier = composer.create_folding_verifier(); + bool folding_verified = folding_verifier.verify_folding_proof(fold_proof); + EXPECT_TRUE(folding_verified); + + // Run decider + auto decider_prover = composer.create_decider_prover(accumulator); + auto decider_verifier = composer.create_decider_verifier(accumulator); + auto decider_proof = decider_prover.construct_proof(); + bool decision = decider_verifier.verify_proof(decider_proof); + EXPECT_TRUE(decision); + } +}; + +/** + * @brief A full Goblin test using PG that mimicks the basic aztec client architecture + * + */ +TEST_F(ClientIVCTests, Full) +{ + ClientIVC ivc; + + // Initialize IVC with function circuit + Builder function_circuit = create_mock_circuit(ivc); + ivc.initialize(function_circuit); + + // Accumulate kernel circuit (first kernel mocked as simple circuit since no folding proofs yet) + Builder kernel_circuit = create_mock_circuit(ivc); + FoldProof kernel_fold_proof = ivc.accumulate(kernel_circuit); + EXPECT_FOLDING_AND_DECIDING_VERIFIED(ivc.fold_output.accumulator, kernel_fold_proof); + + size_t NUM_CIRCUITS = 1; + for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { + // Accumulate function circuit + Builder function_circuit = create_mock_circuit(ivc); + FoldProof function_fold_proof = ivc.accumulate(function_circuit); + EXPECT_FOLDING_AND_DECIDING_VERIFIED(ivc.fold_output.accumulator, function_fold_proof); + + // Accumulate kernel circuit + Builder kernel_circuit{ ivc.goblin.op_queue }; + construct_mock_folding_kernel(kernel_circuit, function_fold_proof, kernel_fold_proof); + FoldProof kernel_fold_proof = ivc.accumulate(kernel_circuit); + EXPECT_FOLDING_AND_DECIDING_VERIFIED(ivc.fold_output.accumulator, kernel_fold_proof); + } + + // Constuct four proofs: merge, eccvm, translator, decider + auto proof = ivc.prove(); + + // Verify all four proofs + EXPECT_TRUE(ivc.verify(proof)); +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_recursion.test.cpp deleted file mode 100644 index dcc1323d781..00000000000 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_recursion.test.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "barretenberg/eccvm/eccvm_composer.hpp" -#include "barretenberg/goblin/goblin.hpp" -#include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/goblin/translation_evaluations.hpp" -#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" -#include "barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp" -#include "barretenberg/translator_vm/goblin_translator_composer.hpp" -#include "barretenberg/ultra_honk/ultra_composer.hpp" - -#include - -using namespace bb; - -class GoblinRecursionTests : public ::testing::Test { - protected: - static void SetUpTestSuite() - { - srs::init_crs_factory("../srs_db/ignition"); - srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } - - using Curve = curve::BN254; - using FF = Curve::ScalarField; - using GoblinUltraBuilder = GoblinUltraCircuitBuilder; - using KernelInput = Goblin::AccumulationOutput; -}; - -/** * @brief A full Goblin test that mimicks the basic aztec client architecture - * - */ -TEST_F(GoblinRecursionTests, Pseudo) -{ - Goblin goblin; - - // Construct an initial circuit; its proof will be recursively verified by the first kernel - GoblinUltraBuilder initial_circuit{ goblin.op_queue }; - GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit); - KernelInput kernel_input = goblin.accumulate(initial_circuit); - - // Construct a series of simple Goblin circuits; generate and verify their proofs - size_t NUM_CIRCUITS = 2; - for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - // Construct a circuit with logic resembling that of the "kernel circuit" - GoblinUltraBuilder circuit_builder{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input, kernel_input); - - // Construct proof of the current kernel circuit to be recursively verified by the next one - kernel_input = goblin.accumulate(circuit_builder); - } - - Goblin::Proof proof = goblin.prove(); - // Verify the final ultra proof - GoblinUltraVerifier ultra_verifier{ kernel_input.verification_key }; - bool ultra_verified = ultra_verifier.verify_proof(kernel_input.proof); - // Verify the goblin proof (eccvm, translator, merge) - bool verified = goblin.verify(proof); - EXPECT_TRUE(ultra_verified && verified); -} - -// TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 3b028be637e..9f108389eda 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -120,6 +120,31 @@ class Goblin { return { ultra_proof, instance->verification_key }; }; + /** + * @brief Add a recursive merge verifier to input circuit and construct a merge proof for the updated op queue + * @details When this method is used, the "prover" functionality of the IVC scheme must be performed explicitly, but + * this method has to be called first so that the recursive merge verifier can be "appended" to the circuit being + * accumulated + * + * @param circuit_builder + */ + void merge(GoblinUltraCircuitBuilder& circuit_builder) + { + // Complete the circuit logic by recursively verifying previous merge proof if it exists + if (merge_proof_exists) { + RecursiveMergeVerifier merge_verifier{ &circuit_builder }; + [[maybe_unused]] auto pairing_points = merge_verifier.verify_proof(merge_proof); + } + + // Construct and store the merge proof to be recursively verified on the next call to accumulate + MergeProver merge_prover{ op_queue }; + merge_proof = merge_prover.construct_proof(); + + if (!merge_proof_exists) { + merge_proof_exists = true; + } + }; + /** * @brief Construct an ECCVM proof and the translation polynomial evaluations * diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin_recursion.test.cpp new file mode 100644 index 00000000000..dc0facdb60a --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin_recursion.test.cpp @@ -0,0 +1,75 @@ +#include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" + +#include + +using namespace bb; + +class GoblinRecursionTests : public ::testing::Test { + protected: + static void SetUpTestSuite() + { + srs::init_crs_factory("../srs_db/ignition"); + srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } + + using Curve = curve::BN254; + using FF = Curve::ScalarField; + using GoblinUltraBuilder = GoblinUltraCircuitBuilder; + using KernelInput = Goblin::AccumulationOutput; + + static Goblin::AccumulationOutput construct_accumulator(GoblinUltraBuilder& builder) + { + GoblinUltraComposer composer; + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); + auto ultra_proof = prover.construct_proof(); + return { ultra_proof, instance->verification_key }; + } +}; + +/** + * @brief A full Goblin test that mimicks the basic aztec client architecture + * @details + */ +TEST_F(GoblinRecursionTests, Vanilla) +{ + Goblin goblin; + + Goblin::AccumulationOutput kernel_accum; + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/723): + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue); + + size_t NUM_CIRCUITS = 2; + for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { + + // Construct and accumulate a mock function circuit + GoblinUltraCircuitBuilder function_circuit{ goblin.op_queue }; + GoblinMockCircuits::construct_arithmetic_circuit(function_circuit, 1 << 8); + GoblinMockCircuits::construct_goblin_ecc_op_circuit(function_circuit); + info("function merge"); + goblin.merge(function_circuit); + auto function_accum = construct_accumulator(function_circuit); + + // Construct and accumulate the mock kernel circuit (no kernel accum in first round) + GoblinUltraCircuitBuilder kernel_circuit{ goblin.op_queue }; + GoblinMockCircuits::construct_mock_kernel_small(kernel_circuit, function_accum, kernel_accum); + info("kernel accum"); + goblin.merge(kernel_circuit); + kernel_accum = construct_accumulator(kernel_circuit); + } + + Goblin::Proof proof = goblin.prove(); + // Verify the final ultra proof + GoblinUltraVerifier ultra_verifier{ kernel_accum.verification_key }; + bool ultra_verified = ultra_verifier.verify_proof(kernel_accum.proof); + // Verify the goblin proof (eccvm, translator, merge) + bool verified = goblin.verify(proof); + EXPECT_TRUE(ultra_verified && verified); +} + +// TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 576fc798ae0..d2a75f243f7 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -164,7 +164,7 @@ class GoblinMockCircuits { } /** - * @brief Construct a mock kernel circuit + * @brief Construct a size 2^17 mock kernel circuit for benchmarking * @details This circuit contains (1) some arbitrary operations representing general kernel logic, (2) recursive * verification of a function circuit proof, and optionally (3) recursive verification of a previous kernel circuit * proof. The arbitrary kernel logic is structured to bring the final dyadic circuit size of the kernel to 2^17. @@ -197,5 +197,24 @@ class GoblinMockCircuits { verifier2.verify_proof(prev_kernel_accum.proof); } } + + /** + * @brief A minimal version of the mock kernel (recursive verifiers only) for faster testing + * + */ + static void construct_mock_kernel_small(GoblinUltraBuilder& builder, + const KernelInput& function_accum, + const KernelInput& prev_kernel_accum) + { + // Execute recursive aggregation of function proof + RecursiveVerifier verifier1{ &builder, function_accum.verification_key }; + verifier1.verify_proof(function_accum.proof); + + // Execute recursive aggregation of previous kernel proof if one exists + if (!prev_kernel_accum.proof.empty()) { + RecursiveVerifier verifier2{ &builder, prev_kernel_accum.verification_key }; + verifier2.verify_proof(prev_kernel_accum.proof); + } + } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index c0efde0a3d8..48bbcd86e8b 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -246,8 +246,11 @@ std::shared_ptr ProtoGalaxyProver_public_inputs) { size_t inst = 0; for (auto& instance : instances) { - el += instance->public_inputs[el_idx] * lagranges[inst]; - inst++; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/830) + if (instance->public_inputs.size() >= next_accumulator->public_inputs.size()) { + el += instance->public_inputs[el_idx] * lagranges[inst]; + inst++; + }; } transcript->send_to_verifier("next_public_input_" + std::to_string(el_idx), el); el_idx++; diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index bee65a68010..3aeeda75779 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -247,8 +247,11 @@ bool ProtoGalaxyVerifier_::verify_folding_proof(const std::ve for (auto& expected_el : folded_public_inputs) { size_t inst = 0; for (auto& instance : instances) { - expected_el += instance->public_inputs[el_idx] * lagranges[inst]; - inst++; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/830) + if (instance->public_inputs.size() >= folded_public_inputs.size()) { + expected_el += instance->public_inputs[el_idx] * lagranges[inst]; + inst++; + }; } auto el = transcript->template receive_from_prover("next_public_input" + std::to_string(el_idx)); verified = verified & (el == expected_el); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/protogalaxy.test.cpp index f0237d439f1..42f5757c1e3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/protogalaxy.test.cpp @@ -320,7 +320,7 @@ template class ProtoGalaxyTests : public testing::Test { auto second_accumulator = fold_and_verify(instances, composer, true); check_accumulator_target_sum_manual(second_accumulator, true); - decide_and_verify(first_accumulator, composer, true); + decide_and_verify(second_accumulator, composer, true); } /**