diff --git a/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp index ded7acc08f1..80d3e326144 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp @@ -20,7 +20,6 @@ namespace { class ClientIVCBench : public benchmark::Fixture { public: using Builder = GoblinUltraCircuitBuilder; - using VerifierFoldData = GoblinMockCircuits::VerifierFoldData; // Number of function circuits to accumulate(based on Zacs target numbers) static constexpr size_t NUM_ITERATIONS_MEDIUM_COMPLEXITY = 6; @@ -31,6 +30,36 @@ class ClientIVCBench : public benchmark::Fixture { bb::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); } + /** + * @brief Compute verification key for each circuit in the IVC based on the number of desired function circuits + * @details Assumes the following circuit ordering: one initial function circuit followed by pairs of {function, + * kernel} until the desired number of function circuits has been reached. + * + * @param ivc + * @param num_function_circuits + */ + static auto precompute_verification_keys(ClientIVC& ivc, const size_t num_function_circuits) + { + // Populate the set of mock function and kernel circuits to be accumulated in the IVC + std::vector circuits; + Builder function_circuit{ ivc.goblin.op_queue }; + GoblinMockCircuits::construct_mock_function_circuit(function_circuit); + circuits.emplace_back(function_circuit); + + for (size_t idx = 1; idx < num_function_circuits; ++idx) { + Builder function_circuit{ ivc.goblin.op_queue }; + GoblinMockCircuits::construct_mock_function_circuit(function_circuit); + circuits.emplace_back(function_circuit); + + Builder kernel_circuit{ ivc.goblin.op_queue }; + GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit); + circuits.emplace_back(kernel_circuit); + } + + // Compute and return the verfication keys corresponding to this set of circuits + return ivc.precompute_folding_verification_keys(circuits); + } + /** * @brief Perform a specified number of function circuit accumulation rounds * @details Each round "accumulates" a mock function circuit and a mock kernel circuit. Each round thus consists of @@ -40,9 +69,13 @@ class ClientIVCBench : public benchmark::Fixture { * we set the size of the function circuit to be 2^17. The first one should be 2^19 but we can't currently support * folding circuits of unequal size. * + * @param NUM_CIRCUITS Number of function circuits to accumulate */ - static void perform_ivc_accumulation_rounds(State& state, ClientIVC& ivc) + static void perform_ivc_accumulation_rounds(size_t NUM_CIRCUITS, ClientIVC& ivc, auto& precomputed_vks) { + size_t TOTAL_NUM_CIRCUITS = NUM_CIRCUITS * 2 - 1; // need one less kernel than number of function circuits + ASSERT(precomputed_vks.size() == TOTAL_NUM_CIRCUITS); // ensure presence of a precomputed VK for each circuit + const size_t size_hint = 1 << 17; // Size hint for reserving wires/selector vector memory in builders std::vector initial_function_circuits(2); @@ -57,31 +90,21 @@ class ClientIVCBench : public benchmark::Fixture { // Prepend queue to the first circuit initial_function_circuits[0].op_queue->prepend_previous_queue(*ivc.goblin.op_queue); // Initialize ivc - ivc.initialize(initial_function_circuits[0]); + ivc.accumulate(initial_function_circuits[0], precomputed_vks[0]); // Retrieve the queue std::swap(*ivc.goblin.op_queue, *initial_function_circuits[0].op_queue); // Prepend queue to the second circuit initial_function_circuits[1].op_queue->prepend_previous_queue(*ivc.goblin.op_queue); // Accumulate another function circuit - auto function_fold_proof = ivc.accumulate(initial_function_circuits[1]); + ivc.accumulate(initial_function_circuits[1], precomputed_vks[1]); // Retrieve the queue std::swap(*ivc.goblin.op_queue, *initial_function_circuits[1].op_queue); - VerifierFoldData function_fold_output = { function_fold_proof, ivc.vks.func_vk }; // Free memory initial_function_circuits.clear(); - auto NUM_CIRCUITS = static_cast(state.range(0)); - // Subtract two to account for the "initialization" round above i.e. we have already folded two function - // circuits - NUM_CIRCUITS -= 2; - - // The accumulator for kernel uses the function accumulation verification key - auto kernel_verifier_accumulator = std::make_shared(ivc.vks.first_func_vk); - - VerifierFoldData kernel_fold_output; - for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { + for (size_t circuit_idx = 2; circuit_idx < TOTAL_NUM_CIRCUITS - 1; circuit_idx += 2) { Builder kernel_circuit{ size_hint, ivc.goblin.op_queue }; Builder function_circuit{ size_hint }; // Construct function and kernel circuits in parallel @@ -90,18 +113,7 @@ class ClientIVCBench : public benchmark::Fixture { parallel_for(2, [&](size_t workload_idx) { // workload index is 0 for kernel and 1 for function if (workload_idx == 0) { - if (circuit_idx == 0) { - - // Create the first folding kernel which only verifies the accumulation of a - // function circuit - kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, function_fold_output, {}, kernel_verifier_accumulator); - } else { - // Create kernel circuit containing the recursive folding verification of a function circuit - // and a kernel circuit - kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, function_fold_output, kernel_fold_output, kernel_verifier_accumulator); - } + GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit); } else { GoblinMockCircuits::construct_mock_function_circuit(function_circuit); } @@ -110,48 +122,25 @@ class ClientIVCBench : public benchmark::Fixture { // No need to prepend queue, it's the same after last swap // Accumulate kernel circuit - auto kernel_fold_proof = ivc.accumulate(kernel_circuit); - - // First iteration and the following ones differ - if (circuit_idx == 0) { - kernel_fold_output = { kernel_fold_proof, ivc.vks.first_kernel_vk }; - } else { - kernel_fold_output = { kernel_fold_proof, ivc.vks.kernel_vk }; - } + ivc.accumulate(kernel_circuit, precomputed_vks[circuit_idx]); // Prepend queue to function circuit function_circuit.op_queue->prepend_previous_queue(*ivc.goblin.op_queue); // Accumulate function circuit - auto function_fold_proof = ivc.accumulate(function_circuit); - function_fold_output = { function_fold_proof, ivc.vks.func_vk }; + ivc.accumulate(function_circuit, precomputed_vks[circuit_idx + 1]); // Retrieve queue std::swap(*ivc.goblin.op_queue, *function_circuit.op_queue); } - // If we haven't entered the cycle, the kernel proof accumulates just function proofs - if (NUM_CIRCUITS == 0) { - // Create and accumulate the first folding kernel which only verifies the accumulation of a function circuit - Builder kernel_circuit{ size_hint, ivc.goblin.op_queue }; - auto kernel_verifier_accumulator = std::make_shared(ivc.vks.first_func_vk); - { - BB_OP_COUNT_TIME_NAME("construct_circuits"); - kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, function_fold_output, {}, kernel_verifier_accumulator); - } - auto kernel_fold_proof = ivc.accumulate(kernel_circuit); - kernel_fold_output = { kernel_fold_proof, ivc.vks.first_kernel_vk }; - } else { - Builder kernel_circuit{ size_hint, ivc.goblin.op_queue }; - { - BB_OP_COUNT_TIME_NAME("construct_circuits"); - kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, function_fold_output, kernel_fold_output, kernel_verifier_accumulator); - } - auto kernel_fold_proof = ivc.accumulate(kernel_circuit); - kernel_fold_output = { kernel_fold_proof, ivc.vks.kernel_vk }; + // Final kernel + Builder kernel_circuit{ size_hint, ivc.goblin.op_queue }; + { + BB_OP_COUNT_TIME_NAME("construct_circuits"); + GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit); } + ivc.accumulate(kernel_circuit, precomputed_vks.back()); } }; @@ -162,11 +151,14 @@ class ClientIVCBench : public benchmark::Fixture { BENCHMARK_DEFINE_F(ClientIVCBench, Full)(benchmark::State& state) { ClientIVC ivc; - ivc.precompute_folding_verification_keys(); + + auto num_circuits = static_cast(state.range(0)); + auto precomputed_vks = precompute_verification_keys(ivc, num_circuits); + for (auto _ : state) { BB_REPORT_OP_COUNT_IN_BENCH(state); // Perform a specified number of iterations of function/kernel accumulation - perform_ivc_accumulation_rounds(state, ivc); + perform_ivc_accumulation_rounds(num_circuits, ivc, precomputed_vks); // Construct IVC scheme proof (fold, decider, merge, eccvm, translator) ivc.prove(); @@ -181,11 +173,14 @@ BENCHMARK_DEFINE_F(ClientIVCBench, FullStructured)(benchmark::State& state) { ClientIVC ivc; ivc.structured_flag = true; - ivc.precompute_folding_verification_keys(); + + auto num_circuits = static_cast(state.range(0)); + auto precomputed_vks = precompute_verification_keys(ivc, num_circuits); + for (auto _ : state) { BB_REPORT_OP_COUNT_IN_BENCH(state); // Perform a specified number of iterations of function/kernel accumulation - perform_ivc_accumulation_rounds(state, ivc); + perform_ivc_accumulation_rounds(num_circuits, ivc, precomputed_vks); // Construct IVC scheme proof (fold, decider, merge, eccvm, translator) ivc.prove(); @@ -199,11 +194,14 @@ BENCHMARK_DEFINE_F(ClientIVCBench, FullStructured)(benchmark::State& state) BENCHMARK_DEFINE_F(ClientIVCBench, Accumulate)(benchmark::State& state) { ClientIVC ivc; - ivc.precompute_folding_verification_keys(); + + auto num_circuits = static_cast(state.range(0)); + auto precomputed_vks = precompute_verification_keys(ivc, num_circuits); + // Perform a specified number of iterations of function/kernel accumulation for (auto _ : state) { BB_REPORT_OP_COUNT_IN_BENCH(state); - perform_ivc_accumulation_rounds(state, ivc); + perform_ivc_accumulation_rounds(num_circuits, ivc, precomputed_vks); } } @@ -214,8 +212,12 @@ BENCHMARK_DEFINE_F(ClientIVCBench, Accumulate)(benchmark::State& state) BENCHMARK_DEFINE_F(ClientIVCBench, Decide)(benchmark::State& state) { ClientIVC ivc; + + auto num_circuits = static_cast(state.range(0)); + auto precomputed_vks = precompute_verification_keys(ivc, num_circuits); + // Perform a specified number of iterations of function/kernel accumulation - perform_ivc_accumulation_rounds(state, ivc); + perform_ivc_accumulation_rounds(num_circuits, ivc, precomputed_vks); // Construct eccvm proof, measure only translator proof construction for (auto _ : state) { @@ -232,8 +234,11 @@ BENCHMARK_DEFINE_F(ClientIVCBench, ECCVM)(benchmark::State& state) { ClientIVC ivc; + auto num_circuits = static_cast(state.range(0)); + auto precomputed_vks = precompute_verification_keys(ivc, num_circuits); + // Perform a specified number of iterations of function/kernel accumulation - perform_ivc_accumulation_rounds(state, ivc); + perform_ivc_accumulation_rounds(num_circuits, ivc, precomputed_vks); // Construct and measure eccvm only for (auto _ : state) { @@ -249,10 +254,15 @@ BENCHMARK_DEFINE_F(ClientIVCBench, ECCVM)(benchmark::State& state) BENCHMARK_DEFINE_F(ClientIVCBench, Translator)(benchmark::State& state) { ClientIVC ivc; - ivc.precompute_folding_verification_keys(); + auto num_circuits = static_cast(state.range(0)); + auto precomputed_vks = precompute_verification_keys(ivc, num_circuits); + + // Perform a specified number of iterations of function/kernel accumulation + perform_ivc_accumulation_rounds(num_circuits, ivc, precomputed_vks); + BB_REPORT_OP_COUNT_IN_BENCH(state); // Perform a specified number of iterations of function/kernel accumulation - perform_ivc_accumulation_rounds(state, ivc); + perform_ivc_accumulation_rounds(num_circuits, ivc, precomputed_vks); // Construct eccvm proof, measure only translator proof construction ivc.goblin.prove_eccvm(); diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 758a313658b..71b2ef0f9dd 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -2,32 +2,48 @@ namespace bb { -/** - * @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 - prover_fold_output.accumulator = std::make_shared(circuit, structured_flag); -} - /** * @brief Accumulate a circuit into the IVC scheme - * @details Performs goblin merge, generates circuit instance, folds into accumulator and constructs a folding proof + * @details If this is the first circuit being accumulated, initialize the prover and verifier accumulators. Otherwise, + * fold the instance for the provided circuit into the accumulator. If a previous fold proof exists, a recursive folding + * verification is appended to the provided circuit prior to its accumulation. Similarly, if a merge proof exists, a + * recursive merge verifier is appended. * * @param circuit Circuit to be accumulated/folded - * @return FoldProof + * @param precomputed_vk Optional precomputed VK (otherwise will be computed herein) */ -ClientIVC::FoldProof ClientIVC::accumulate(ClientCircuit& circuit) +void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr& precomputed_vk) { - goblin.merge(circuit); // Add recursive merge verifier and construct new merge proof + // If a previous fold proof exists, add a recursive folding verification to the circuit + if (!fold_output.proof.empty()) { + BB_OP_COUNT_TIME_NAME("construct_circuits"); + FoldingRecursiveVerifier verifier{ &circuit, verifier_accumulator, { instance_vk } }; + auto verifier_accum = verifier.verify_folding_proof(fold_output.proof); + verifier_accumulator = std::make_shared(verifier_accum->get_value()); + } + + // Construct a merge proof (and add a recursive merge verifier to the circuit if a previous merge proof exists) + goblin.merge(circuit); + + // Construct the prover instance for circuit prover_instance = std::make_shared(circuit, structured_flag); - FoldingProver folding_prover({ prover_fold_output.accumulator, prover_instance }); - prover_fold_output = folding_prover.fold_instances(); - return prover_fold_output.folding_data; + + // Set the instance verification key from precomputed if available, else compute it + if (precomputed_vk) { + instance_vk = precomputed_vk; + } else { + instance_vk = std::make_shared(prover_instance->proving_key); + } + + // If the IVC is uninitialized, simply initialize the prover and verifier accumulator instances + if (!initialized) { + fold_output.accumulator = prover_instance; + verifier_accumulator = std::make_shared(instance_vk); + initialized = true; + } else { // Otherwise, fold the new instance into the accumulator + FoldingProver folding_prover({ fold_output.accumulator, prover_instance }); + fold_output = folding_prover.fold_instances(); + } } /** @@ -37,7 +53,7 @@ ClientIVC::FoldProof ClientIVC::accumulate(ClientCircuit& circuit) */ ClientIVC::Proof ClientIVC::prove() { - return { prover_fold_output.folding_data, decider_prove(), goblin.prove() }; + return { fold_output.proof, decider_prove(), goblin.prove() }; } /** @@ -46,7 +62,7 @@ ClientIVC::Proof ClientIVC::prove() * @param proof * @return bool */ -bool ClientIVC::verify(Proof& proof, const std::vector& verifier_instances) +bool ClientIVC::verify(Proof& proof, const std::vector>& verifier_instances) { // Goblin verification (merge, eccvm, translator) bool goblin_verified = goblin.verify(proof.goblin_proof); @@ -67,63 +83,38 @@ bool ClientIVC::verify(Proof& proof, const std::vector& ver */ HonkProof ClientIVC::decider_prove() const { - GoblinUltraDeciderProver decider_prover(prover_fold_output.accumulator); + GoblinUltraDeciderProver decider_prover(fold_output.accumulator); return decider_prover.construct_proof(); } /** - * @brief Precompute the array of verification keys by simulating folding. There will be 4 different verification keys: - * initial function verification key (without recursive merge verifier), subsequent function verification key (with - * recursive merge verifier), initial kernel verification key (with recursive merge verifier appended, no previous - * kernel to fold), "full" kernel verification key( two recursive folding verifiers and merge verifier). + * @brief Given a set of circuits, compute the verification keys that will be required by the IVC scheme + * @details The verification keys computed here are in general not the same as the verification keys for the + * raw input circuits because recursive verifier circuits (merge and/or folding) may be appended to the incoming + * circuits as part accumulation. + * @note This method exists for convenience and is not not meant to be used in practice for IVC. Given a set of + * circuits, it could be run once and for all to compute then save the required VKs. It also provides a convenient + * (albeit innefficient) way of separating out the cost of computing VKs from a benchmark. * - * TODO(https://github.com/AztecProtocol/barretenberg/issues/904): This function should ultimately be moved outside of - * this class since it's used only for testing and benchmarking purposes and it requires us to clear state afterwards. - * (e.g. in the Goblin object) + * @param circuits A copy of the circuits to be accumulated (passing by reference would alter the original circuits) + * @return std::vector> */ -void ClientIVC::precompute_folding_verification_keys() +std::vector> ClientIVC::precompute_folding_verification_keys( + std::vector circuits) { - using VerifierInstance = VerifierInstance_; - using VerificationKey = Flavor::VerificationKey; - - ClientCircuit initial_function_circuit{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(initial_function_circuit); - - // Initialise both the first prover and verifier accumulator from the inital function circuit - initialize(initial_function_circuit); - vks.first_func_vk = std::make_shared(prover_fold_output.accumulator->proving_key); - auto initial_verifier_acc = std::make_shared(vks.first_func_vk); - - // Accumulate the next function circuit - ClientCircuit function_circuit{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(function_circuit); - auto function_fold_proof = accumulate(function_circuit); - - // Create its verification key (we have called accumulate so it includes the recursive merge verifier) - vks.func_vk = std::make_shared(prover_instance->proving_key); - - // Create the initial kernel iteration and precompute its verification key - ClientCircuit kernel_circuit{ goblin.op_queue }; - auto kernel_acc = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, { function_fold_proof, vks.func_vk }, {}, initial_verifier_acc); - auto kernel_fold_proof = accumulate(kernel_circuit); - vks.first_kernel_vk = std::make_shared(prover_instance->proving_key); - - // Create another mock function circuit to run the full kernel - function_circuit = ClientCircuit{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(function_circuit); - function_fold_proof = accumulate(function_circuit); - - // Create the full kernel circuit and compute verification key - kernel_circuit = GoblinUltraCircuitBuilder{ goblin.op_queue }; - kernel_acc = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, { function_fold_proof, vks.func_vk }, { kernel_fold_proof, vks.first_kernel_vk }, kernel_acc); - kernel_fold_proof = accumulate(kernel_circuit); - - vks.kernel_vk = std::make_shared(prover_instance->proving_key); - - // Clean the Goblin state (reinitialise op_queue with mocking and clear merge proofs) - goblin = Goblin(); + std::vector> vkeys; + + for (auto& circuit : circuits) { + accumulate(circuit); + vkeys.emplace_back(instance_vk); + } + + // Reset the scheme so it can be reused for actual accumulation, maintaining the structured trace flag as is + bool structured = structured_flag; + *this = ClientIVC(); + this->structured_flag = structured; + + return vkeys; } } // 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 index eafc0f72aef..d44b02f6740 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -23,8 +23,6 @@ class ClientIVC { using VerificationKey = Flavor::VerificationKey; using FF = Flavor::FF; using FoldProof = std::vector; - using ProverAccumulator = std::shared_ptr>; - using VerifierAccumulator = std::shared_ptr>; using ProverInstance = ProverInstance_; using VerifierInstance = VerifierInstance_; using ClientCircuit = GoblinUltraCircuitBuilder; // can only be GoblinUltra @@ -35,6 +33,11 @@ class ClientIVC { using VerifierInstances = VerifierInstances_; using FoldingVerifier = ProtoGalaxyVerifier_; + using GURecursiveFlavor = GoblinUltraRecursiveFlavor_; + using RecursiveVerifierInstances = bb::stdlib::recursion::honk::RecursiveVerifierInstances_; + using FoldingRecursiveVerifier = + bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_; + // A full proof for the IVC scheme struct Proof { FoldProof folding_proof; // final fold proof @@ -57,13 +60,6 @@ class ClientIVC { } }; - struct PrecomputedVerificationKeys { - std::shared_ptr first_func_vk; - std::shared_ptr func_vk; - std::shared_ptr first_kernel_vk; - std::shared_ptr kernel_vk; - }; - private: using ProverFoldOutput = FoldingResult; // Note: We need to save the last instance that was folded in order to compute its verification key, this will not @@ -71,28 +67,28 @@ class ClientIVC { public: Goblin goblin; - ProverFoldOutput prover_fold_output; - ProverAccumulator prover_accumulator; - PrecomputedVerificationKeys vks; + ProverFoldOutput fold_output; + std::shared_ptr prover_accumulator; + std::shared_ptr verifier_accumulator; // Note: We need to save the last instance that was folded in order to compute its verification key, this will not // be needed in the real IVC as they are provided as inputs std::shared_ptr prover_instance; + std::shared_ptr instance_vk; // A flag indicating whether or not to construct a structured trace in the ProverInstance bool structured_flag = false; - void initialize(ClientCircuit& circuit); + // A flag indicating whether the IVC has been initialized with an initial instance + bool initialized = false; - FoldProof accumulate(ClientCircuit& circuit); + void accumulate(ClientCircuit& circuit, const std::shared_ptr& precomputed_vk = nullptr); Proof prove(); - bool verify(Proof& proof, const std::vector& verifier_instances); + bool verify(Proof& proof, const std::vector>& verifier_instances); HonkProof decider_prove() const; - void decider_prove_and_verify(const VerifierAccumulator&) const; - - void precompute_folding_verification_keys(); + std::vector> precompute_folding_verification_keys(std::vector); }; } // 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 index 0dd189112b8..6a1676c4883 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -17,18 +17,11 @@ class ClientIVCTests : public ::testing::Test { using Flavor = ClientIVC::Flavor; using FF = typename Flavor::FF; + using VerificationKey = Flavor::VerificationKey; using Builder = ClientIVC::ClientCircuit; - using ProverAccumulator = ClientIVC::ProverAccumulator; - using VerifierAccumulator = ClientIVC::VerifierAccumulator; + using ProverInstance = ClientIVC::ProverInstance; using VerifierInstance = ClientIVC::VerifierInstance; using FoldProof = ClientIVC::FoldProof; - using VerifierFoldData = GoblinMockCircuits::VerifierFoldData; - using GURecursiveFlavor = GoblinUltraRecursiveFlavor_; - using RecursiveVerifierInstance = ::bb::stdlib::recursion::honk::RecursiveVerifierInstance_; - using RecursiveVerifierAccumulator = std::shared_ptr; - using RecursiveVerifierInstances = ::bb::stdlib::recursion::honk::RecursiveVerifierInstances_; - using FoldingRecursiveVerifier = - bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_; using DeciderProver = ClientIVC::DeciderProver; using DeciderVerifier = ClientIVC::DeciderVerifier; using ProverInstances = ProverInstances_; @@ -36,6 +29,20 @@ class ClientIVCTests : public ::testing::Test { using VerifierInstances = VerifierInstances_; using FoldingVerifier = ProtoGalaxyVerifier_; + /** + * @brief Prove and verify the IVC scheme + * @details Constructs four proofs: merge, eccvm, translator, decider; Verifies these four plus the final folding + * proof constructed on the last accumulation round + * + */ + static bool prove_and_verify(ClientIVC& ivc) + { + auto proof = ivc.prove(); + + auto verifier_inst = std::make_shared(ivc.instance_vk); + return ivc.verify(proof, { ivc.verifier_accumulator, verifier_inst }); + } + /** * @brief Construct mock circuit with arithmetic gates and goblin ops * @details Currently default sized to 2^16 to match kernel. (Note: dummy op gates added to avoid non-zero @@ -55,111 +62,153 @@ class ClientIVCTests : public ::testing::Test { MockCircuits::construct_goblin_ecc_op_circuit(circuit); return circuit; } +}; - /** - * @brief Construct mock kernel consisting of two recursive folding verifiers to verify the folding of the previous - * function circuit and kernel circuit. - * - * @param builder - * @param func_accum contains the folding proof for the function circuit and the corresponsing function - * verifier instance - * @param kernel_accum contains the folding proof for the kernel circuit and the corresponding kernel verifier - * instance - * @returns the updated verifier accumulator - */ - static VerifierAccumulator construct_mock_folding_kernel(Builder& builder, - VerifierFoldData& func_accum, - VerifierFoldData& kernel_accum, - VerifierAccumulator& prev_kernel_accum) - { +/** + * @brief A simple-as-possible test demonstrating IVC for two mock circuits + * + */ +TEST_F(ClientIVCTests, Basic) +{ + ClientIVC ivc; + + // Initialize the IVC with an arbitrary circuit + Builder circuit_0 = create_mock_circuit(ivc); + ivc.accumulate(circuit_0); - FoldingRecursiveVerifier verifier_1{ &builder, prev_kernel_accum, { func_accum.inst_vk } }; - auto fctn_verifier_accum = verifier_1.verify_folding_proof(func_accum.fold_proof); - auto native_acc = std::make_shared(fctn_verifier_accum->get_value()); - FoldingRecursiveVerifier verifier_2{ &builder, native_acc, { kernel_accum.inst_vk } }; - auto kernel_verifier_accum = verifier_2.verify_folding_proof(kernel_accum.fold_proof); - return std::make_shared(kernel_verifier_accum->get_value()); + // Create another circuit and accumulate + Builder circuit_1 = create_mock_circuit(ivc); + ivc.accumulate(circuit_1); + + EXPECT_TRUE(prove_and_verify(ivc)); +}; + +/** + * @brief Check that the IVC fails to verify if an intermediate fold proof is invalid + * + */ +TEST_F(ClientIVCTests, BasicFailure) +{ + ClientIVC ivc; + + // Initialize the IVC with an arbitrary circuit + Builder circuit_0 = create_mock_circuit(ivc); + ivc.accumulate(circuit_0); + + // Create another circuit and accumulate + Builder circuit_1 = create_mock_circuit(ivc); + ivc.accumulate(circuit_1); + + // Tamper with the fold proof just created in the last accumulation step + for (auto& val : ivc.fold_output.proof) { + if (val > 0) { // tamper by finding the first non-zero value and incrementing it by 1 + val += 1; + break; + } } - /** - * @brief Perform native fold verification and run decider prover/verifier - * - */ - static VerifierAccumulator update_accumulator_and_decide_native( - const ProverAccumulator& prover_accumulator, - const FoldProof& fold_proof, - const VerifierAccumulator& prev_verifier_accumulator, - const std::shared_ptr& verifier_inst_vk) - { - // Verify fold proof - auto new_verifier_inst = std::make_shared(verifier_inst_vk); - FoldingVerifier folding_verifier({ prev_verifier_accumulator, new_verifier_inst }); - auto verifier_accumulator = folding_verifier.verify_folding_proof(fold_proof); - - // Run decider - DeciderProver decider_prover(prover_accumulator); - DeciderVerifier decider_verifier(verifier_accumulator); - auto decider_proof = decider_prover.construct_proof(); - bool decision = decider_verifier.verify_proof(decider_proof); - EXPECT_TRUE(decision); - - return verifier_accumulator; + // Accumulate another circuit; this involves recursive folding verification of the bad proof + Builder circuit_2 = create_mock_circuit(ivc); + ivc.accumulate(circuit_2); + + // The bad fold proof should result in an invalid witness in the final circuit and the IVC should fail to verify + EXPECT_FALSE(prove_and_verify(ivc)); +}; + +/** + * @brief Prove and verify accumulation of an arbitrary set of circuits + * + */ +TEST_F(ClientIVCTests, BasicLarge) +{ + ClientIVC ivc; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 5; + std::vector circuits; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + circuits.emplace_back(create_mock_circuit(ivc)); + } + + // Accumulate each circuit + for (auto& circuit : circuits) { + ivc.accumulate(circuit); } + + EXPECT_TRUE(prove_and_verify(ivc)); }; /** - * @brief A full Goblin test using PG that mimicks the basic aztec client architecture + * @brief Using a structured trace allows for the accumulation of circuits of varying size * */ -// TODO fix with https://github.com/AztecProtocol/barretenberg/issues/930 -// intermittent failures, presumably due to uninitialized memory -TEST_F(ClientIVCTests, DISABLED_Full) +TEST_F(ClientIVCTests, BasicStructured) { - using VerificationKey = Flavor::VerificationKey; + ClientIVC ivc; + ivc.structured_flag = true; + + // Construct some circuits of varying size + Builder circuit_0 = create_mock_circuit(ivc, /*log2_num_gates=*/5); + Builder circuit_1 = create_mock_circuit(ivc, /*log2_num_gates=*/10); + Builder circuit_2 = create_mock_circuit(ivc, /*log2_num_gates=*/15); + + // The circuits can be accumulated as normal due to the structured trace + ivc.accumulate(circuit_0); + ivc.accumulate(circuit_1); + ivc.accumulate(circuit_2); + + EXPECT_TRUE(prove_and_verify(ivc)); +}; +/** + * @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys + * + */ +TEST_F(ClientIVCTests, PrecomputedVerificationKeys) +{ ClientIVC ivc; - // Initialize IVC with function circuit - Builder function_circuit = create_mock_circuit(ivc); - ivc.initialize(function_circuit); - - auto function_vk = std::make_shared(ivc.prover_fold_output.accumulator->proving_key); - auto foo_verifier_instance = std::make_shared(function_vk); - // 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); - // This will have a different verification key because we added the recursive merge verification to the circuit - auto function_vk_with_merge = std::make_shared(ivc.prover_instance->proving_key); - auto kernel_vk = function_vk_with_merge; - auto intermediary_acc = update_accumulator_and_decide_native( - ivc.prover_fold_output.accumulator, kernel_fold_proof, foo_verifier_instance, kernel_vk); - - VerifierFoldData kernel_fold_output = { kernel_fold_proof, function_vk_with_merge }; - 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); - - intermediary_acc = update_accumulator_and_decide_native( - ivc.prover_fold_output.accumulator, function_fold_proof, intermediary_acc, function_vk_with_merge); - - VerifierFoldData function_fold_output = { function_fold_proof, function_vk_with_merge }; - // Accumulate kernel circuit - Builder kernel_circuit{ ivc.goblin.op_queue }; - foo_verifier_instance = construct_mock_folding_kernel( - kernel_circuit, kernel_fold_output, function_fold_output, foo_verifier_instance); - FoldProof kernel_fold_proof = ivc.accumulate(kernel_circuit); - kernel_vk = std::make_shared(ivc.prover_instance->proving_key); - - intermediary_acc = update_accumulator_and_decide_native( - ivc.prover_fold_output.accumulator, kernel_fold_proof, intermediary_acc, kernel_vk); - - VerifierFoldData kernel_fold_output = { kernel_fold_proof, kernel_vk }; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 3; + std::vector circuits; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + circuits.emplace_back(create_mock_circuit(ivc)); + } + + // Precompute the verification keys that will be needed for the IVC + auto precomputed_vkeys = ivc.precompute_folding_verification_keys(circuits); + + // Accumulate each circuit using the precomputed VKs + for (auto [circuit, precomputed_vk] : zip_view(circuits, precomputed_vkeys)) { + ivc.accumulate(circuit, precomputed_vk); + } + + EXPECT_TRUE(prove_and_verify(ivc)); +}; + +/** + * @brief Perform accumulation with a structured trace and precomputed verification keys + * + */ +TEST_F(ClientIVCTests, StructuredPrecomputedVKs) +{ + ClientIVC ivc; + ivc.structured_flag = true; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 3; + std::vector circuits; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + circuits.emplace_back(create_mock_circuit(ivc)); } - // Constuct four proofs: merge, eccvm, translator, decider - auto proof = ivc.prove(); - auto inst = std::make_shared(kernel_vk); - // Verify all four proofs - EXPECT_TRUE(ivc.verify(proof, { foo_verifier_instance, inst })); -}; \ No newline at end of file + // Precompute the (structured) verification keys that will be needed for the IVC + auto precomputed_vkeys = ivc.precompute_folding_verification_keys(circuits); + + // Accumulate each circuit + for (auto [circuit, precomputed_vk] : zip_view(circuits, precomputed_vkeys)) { + ivc.accumulate(circuit, precomputed_vk); + } + + EXPECT_TRUE(prove_and_verify(ivc)); +}; diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp index d4d06758e2f..bb11e2cc670 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp @@ -12,6 +12,9 @@ using namespace bb; * */ class MockKernelTest : public ::testing::Test { + public: + using Builder = GoblinUltraCircuitBuilder; + protected: static void SetUpTestSuite() { srs::init_crs_factory("../srs_db/ignition"); } }; @@ -19,38 +22,20 @@ class MockKernelTest : public ::testing::Test { TEST_F(MockKernelTest, PinFoldingKernelSizes) { ClientIVC ivc; - ivc.precompute_folding_verification_keys(); - // Accumulate three circuits to generate two folding proofs for input to folding kernel - GoblinUltraCircuitBuilder circuit_1{ ivc.goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(circuit_1); - ivc.initialize(circuit_1); - auto kernel_acc = std::make_shared(ivc.vks.first_func_vk); - kernel_acc->verification_key = ivc.vks.first_func_vk; - EXPECT_EQ(ivc.prover_instance->proving_key.log_circuit_size, 17); - GoblinUltraCircuitBuilder circuit_2{ ivc.goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(circuit_2); - auto func_fold_proof = ivc.accumulate(circuit_2); - EXPECT_EQ(ivc.prover_instance->proving_key.log_circuit_size, 17); + // Construct two function circuits and a kernel circuit + Builder circuit_1{ ivc.goblin.op_queue }; + Builder circuit_2{ ivc.goblin.op_queue }; + Builder kernel_circuit{ ivc.goblin.op_queue }; - // Construct kernel circuit - GoblinUltraCircuitBuilder kernel_circuit{ ivc.goblin.op_queue }; - kernel_acc = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, { func_fold_proof, ivc.vks.func_vk }, {}, kernel_acc); + GoblinMockCircuits::construct_mock_function_circuit(circuit_1); + GoblinMockCircuits::construct_mock_function_circuit(circuit_2); + GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit); - auto kernel_fold_proof = ivc.accumulate(kernel_circuit); - EXPECT_EQ(ivc.prover_instance->proving_key.log_circuit_size, 17); + // Accumulate all three; The kernel will contain a single recursive folding verifier + ivc.accumulate(circuit_1); + ivc.accumulate(circuit_2); + ivc.accumulate(kernel_circuit); - GoblinUltraCircuitBuilder circuit_3{ ivc.goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(circuit_3); - func_fold_proof = ivc.accumulate(circuit_3); EXPECT_EQ(ivc.prover_instance->proving_key.log_circuit_size, 17); - - kernel_circuit = GoblinUltraCircuitBuilder{ ivc.goblin.op_queue }; - kernel_acc = GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit, - { kernel_fold_proof, ivc.vks.first_kernel_vk }, - { func_fold_proof, ivc.vks.func_vk }, - kernel_acc); - auto instance = std::make_shared(kernel_circuit); - EXPECT_EQ(instance->proving_key.log_circuit_size, 17); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 46586ff58da..a3234dbc984 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -41,15 +41,6 @@ class GoblinMockCircuits { std::shared_ptr verification_key; }; - /** - * @brief Information required by the verifier to verify a folding round besides the previous accumulator. - */ - struct VerifierFoldData { - std::vector fold_proof; // folding proof - std::shared_ptr - inst_vk; // Verification key of the instance to be folded (note: this would be a vector if k > 1 ) - }; - /** * @brief Populate a builder with some arbitrary but nontrivial constraints * @details Although the details of the circuit constructed here are arbitrary, the intent is to mock something a @@ -64,12 +55,16 @@ class GoblinMockCircuits { // Determine number of times to execute the below operations that constitute the mock circuit logic. Note that // the circuit size does not scale linearly with number of iterations due to e.g. amortization of lookup costs const size_t NUM_ITERATIONS_LARGE = 12; // results in circuit size 2^19 (502238 gates) - const size_t NUM_ITERATIONS_MEDIUM = 3; // results in circuit size 2^17 (124843 gates) - const size_t NUM_ITERATIONS = large ? NUM_ITERATIONS_LARGE : NUM_ITERATIONS_MEDIUM; - stdlib::generate_sha256_test_circuit(builder, NUM_ITERATIONS); // min gates: ~39k - stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ITERATIONS); // min gates: ~41k - stdlib::generate_merkle_membership_test_circuit(builder, NUM_ITERATIONS); // min gates: ~29k + if (large) { + stdlib::generate_sha256_test_circuit(builder, NUM_ITERATIONS_LARGE); + stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ITERATIONS_LARGE); + stdlib::generate_merkle_membership_test_circuit(builder, NUM_ITERATIONS_LARGE); + } else { // Results in circuit size 2^17 when accumulated via ClientIvc + stdlib::generate_sha256_test_circuit(builder, 5); + stdlib::generate_ecdsa_verification_test_circuit(builder, 2); + stdlib::generate_merkle_membership_test_circuit(builder, 10); + } // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): We require goblin ops to be added to the // function circuit because we cannot support zero commtiments. While the builder handles this at @@ -177,50 +172,24 @@ class GoblinMockCircuits { } /** - * @brief Construct a mock kernel circuit based on folding - * @details This circuit contains (1) some arbitrary operations representing general kernel logic, (2) recursive - * folding verification of a function circuit folding proof, and (3) recursive folding verification of a previous - * kernel circuit folding proof. The arbitrary kernel logic is structured to bring the final dyadic circuit size of - * the kernel to 2^17. + * @brief Construct a mock kernel circuit + * @details Construct an arbitrary circuit meant to represent the aztec private function execution kernel. Recursive + * folding verification is handled internally by ClientIvc, not in the kernel. * * @param builder * @param function_fold_proof * @param kernel_fold_proof */ - static std::shared_ptr construct_mock_folding_kernel( - GoblinUltraBuilder& builder, - const VerifierFoldData& func, - const VerifierFoldData& kernel, - std::shared_ptr& prev_kernel_accum) + static void construct_mock_folding_kernel(GoblinUltraBuilder& builder) { - using GURecursiveFlavor = GoblinUltraRecursiveFlavor_; - using RecursiveVerifierInstances = - bb::stdlib::recursion::honk::RecursiveVerifierInstances_; - using FoldingRecursiveVerifier = - bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_; - // Add operations representing general kernel logic e.g. state updates. Note: these are structured to make - // the kernel "full" within the dyadic size 2^17 (130914 gates) - const size_t NUM_MERKLE_CHECKS = 25; - const size_t NUM_ECDSA_VERIFICATIONS = 1; + // the kernel "full" within the dyadic size 2^17 + const size_t NUM_MERKLE_CHECKS = 20; + const size_t NUM_ECDSA_VERIFICATIONS = 2; const size_t NUM_SHA_HASHES = 1; stdlib::generate_merkle_membership_test_circuit(builder, NUM_MERKLE_CHECKS); stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ECDSA_VERIFICATIONS); stdlib::generate_sha256_test_circuit(builder, NUM_SHA_HASHES); - - // Initial kernel iteration does not have a previous kernel to fold - if (kernel.fold_proof.empty()) { - FoldingRecursiveVerifier verifier_1{ &builder, prev_kernel_accum, { func.inst_vk } }; - auto fctn_verifier_accum = verifier_1.verify_folding_proof(func.fold_proof); - return std::make_shared(fctn_verifier_accum->get_value()); - } - - FoldingRecursiveVerifier verifier_2{ &builder, prev_kernel_accum, { kernel.inst_vk } }; - auto kernel_verifier_accum = verifier_2.verify_folding_proof(kernel.fold_proof); - auto native_acc = std::make_shared(kernel_verifier_accum->get_value()); - FoldingRecursiveVerifier verifier_1{ &builder, native_acc, { func.inst_vk } }; - auto fctn_verifier_accum = verifier_1.verify_folding_proof(func.fold_proof); - return std::make_shared(fctn_verifier_accum->get_value()); } /** diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp index 4bf3eb88fff..61d6fdf3dd3 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp @@ -13,6 +13,6 @@ template struct FoldingResult { public: std::shared_ptr> accumulator; // TODO(https://github.com/AztecProtocol/barretenberg/issues/656): turn folding data into a struct - std::vector folding_data; + std::vector proof; }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index 6d67ab10576..e003418a524 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -192,7 +192,7 @@ template void ProtoGalaxyProver_::accum FF combiner_challenge = transcript->template get_challenge("combiner_quotient_challenge"); std::shared_ptr next_accumulator = compute_next_accumulator(instances, state.combiner_quotient, combiner_challenge, state.compressed_perturbator); - state.result.folding_data = transcript->proof_data; + state.result.proof = transcript->proof_data; state.result.accumulator = next_accumulator; }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.test.cpp index 673d7234df9..786d75545fc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.test.cpp @@ -195,14 +195,14 @@ template class ProtoGalaxyRecursiveTests : public tes OuterBuilder folding_circuit; auto verifier = FoldingRecursiveVerifier(&folding_circuit, verifier_instance_1, { verifier_instance_2->verification_key }); - verifier.verify_folding_proof(folding_proof.folding_data); + verifier.verify_folding_proof(folding_proof.proof); info("Folding Recursive Verifier: num gates = ", folding_circuit.num_gates); EXPECT_EQ(folding_circuit.failed(), false) << folding_circuit.err(); // Perform native folding verification and ensure it returns the same result (either true or false) as // calling check_circuit on the recursive folding verifier InnerFoldingVerifier native_folding_verifier({ verifier_instance_1, verifier_instance_2 }); - native_folding_verifier.verify_folding_proof(folding_proof.folding_data); + native_folding_verifier.verify_folding_proof(folding_proof.proof); // Ensure that the underlying native and recursive folding verification algorithms agree by ensuring the // manifestsproduced by each agree. @@ -259,7 +259,7 @@ template class ProtoGalaxyRecursiveTests : public tes OuterBuilder folding_circuit; auto verifier = FoldingRecursiveVerifier(&folding_circuit, verifier_instance_1, { verifier_instance_2->verification_key }); - auto recursive_verifier_accumulator = verifier.verify_folding_proof(folding_proof.folding_data); + auto recursive_verifier_accumulator = verifier.verify_folding_proof(folding_proof.proof); auto native_verifier_acc = std::make_shared(recursive_verifier_accumulator->get_value()); info("Folding Recursive Verifier: num gates = ", folding_circuit.num_gates); @@ -269,7 +269,7 @@ template class ProtoGalaxyRecursiveTests : public tes // Perform native folding verification and ensure it returns the same result (either true or false) as // calling check_circuit on the recursive folding verifier InnerFoldingVerifier native_folding_verifier({ verifier_instance_1, verifier_instance_2 }); - auto verifier_accumulator = native_folding_verifier.verify_folding_proof(folding_proof.folding_data); + auto verifier_accumulator = native_folding_verifier.verify_folding_proof(folding_proof.proof); // Ensure that the underlying native and recursive folding verification algorithms agree by ensuring the // manifestsproduced by each agree. @@ -359,7 +359,7 @@ template class ProtoGalaxyRecursiveTests : public tes FoldingRecursiveVerifier verifier{ &folding_circuit, verifier_accumulator, { verifier_inst->verification_key } }; - auto recursive_verifier_acc = verifier.verify_folding_proof(folding_proof.folding_data); + auto recursive_verifier_acc = verifier.verify_folding_proof(folding_proof.proof); // Validate that the target sum between prover and verifier is now different EXPECT_FALSE(folding_proof.accumulator->target_sum == recursive_verifier_acc->target_sum.get_value()); };