From b1d8b978871948fbba639476465f4de6fb471292 Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Thu, 12 Dec 2024 08:34:34 -0700 Subject: [PATCH] feat: remove auto verify mode from ClientIVC (#10599) Removes auto verify mode from `ClientIVC`. Auto verify mode was a temporary feature designed to append kernel logic (recursive verifications etc.) to kernel circuits generated from noir kernel programs before the `verify_proof()` calls were integrated into those programs. Now that these calls are present in the kernels (mock and genuine), the kernel logic is automatically constructed via ivc_recursion_constraints via the normal `create_circuit()` pathway. If in the future there is need for a backend which automatically appends recursive verification logic, it should be implemented in an entirely separate class. Note: This change means we can no longer generate an IVC proof from the noir `fold_*` programs since they do not contain explicit recursive verifiers. All such tests/flows have been removed. Closes https://github.com/AztecProtocol/barretenberg/issues/1116 (remove manual setting of is_kernel) Closes https://github.com/AztecProtocol/barretenberg/issues/1101 (remove auto-verify) --- barretenberg/Earthfile | 10 +- .../flows/fold_and_verify_program.sh | 8 - .../flows/prove_then_verify_tube.sh | 2 +- barretenberg/cpp/src/barretenberg/bb/api.hpp | 4 +- .../src/barretenberg/bb/api_client_ivc.hpp | 68 ++++-- barretenberg/cpp/src/barretenberg/bb/main.cpp | 15 +- .../barretenberg/client_ivc/client_ivc.cpp | 6 - .../barretenberg/client_ivc/client_ivc.hpp | 14 +- .../client_ivc_auto_verify.test.cpp | 199 ------------------ .../dsl/acir_format/acir_integration.test.cpp | 32 --- .../barretenberg/dsl/acir_proofs/c_bind.cpp | 50 +---- .../client_ivc_recursive_verifier.cpp | 6 +- .../client_ivc_recursive_verifier.hpp | 7 +- .../client_ivc_recursive_verifier.test.cpp | 43 ++-- yarn-project/bb-prover/src/bb/execute.ts | 5 +- .../src/prover/bb_private_kernel_prover.ts | 1 - .../src/native_client_ivc_integration.test.ts | 1 - 17 files changed, 99 insertions(+), 372 deletions(-) delete mode 100755 barretenberg/acir_tests/flows/fold_and_verify_program.sh delete mode 100644 barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_auto_verify.test.cpp diff --git a/barretenberg/Earthfile b/barretenberg/Earthfile index a1bac58650e..34e966723f5 100644 --- a/barretenberg/Earthfile +++ b/barretenberg/Earthfile @@ -26,12 +26,8 @@ barretenberg-acir-tests-bb: ENV TEST_SRC /usr/src/acir_artifacts ENV VERBOSE=1 - # Fold and verify an ACIR program stack using ClientIvc - RUN INPUT_TYPE=compiletime_stack FLOW=prove_and_verify_client_ivc ./run_acir_tests.sh fold_basic - # Fold and verify an ACIR program stack using ClientIvc, then natively verify the ClientIVC proof. - RUN INPUT_TYPE=compiletime_stack FLOW=prove_then_verify_client_ivc ./run_acir_tests.sh fold_basic # Fold and verify an ACIR program stack using ClientIvc, recursively verify as part of the Tube circuit and produce and verify a Honk proof - RUN FLOW=prove_then_verify_tube ./run_acir_tests.sh fold_basic + RUN FLOW=prove_then_verify_tube ./run_acir_tests.sh 6_array # Run 1_mul through native bb build, all_cmds flow, to test all cli args. RUN FLOW=all_cmds ./run_acir_tests.sh 1_mul @@ -95,7 +91,7 @@ barretenberg-acir-tests-bb-client-ivc: # Construct and verify a ClientIVC proof for a single arbitrary program RUN FLOW=prove_and_verify_client_ivc ./run_acir_tests.sh 6_array # Construct and separately verify a ClientIVC proof for all acir programs - RUN FLOW=prove_then_verify_client_ivc CLIENT_IVC_SKIPS=true ./run_acir_tests.sh + RUN FLOW=prove_then_verify_client_ivc ./run_acir_tests.sh 6_array databus databus_two_calldata barretenberg-acir-tests-sol: FROM ../build-images/+from-registry @@ -174,7 +170,5 @@ barretenberg-acir-tests-bb.js: RUN BIN=../ts/dest/node/main.js FLOW=prove_then_verify_ultra_honk ./run_acir_tests.sh 6_array assert_statement # Run a single arbitrary test not involving recursion through bb.js for MegaHonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_mega_honk ./run_acir_tests.sh 6_array - # Run fold_basic test through bb.js which runs ClientIVC on fold basic - RUN BIN=../ts/dest/node/main.js FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # Run 1_mul through bb.js build, all_cmds flow, to test all cli args. RUN BIN=../ts/dest/node/main.js FLOW=all_cmds ./run_acir_tests.sh 1_mul \ No newline at end of file diff --git a/barretenberg/acir_tests/flows/fold_and_verify_program.sh b/barretenberg/acir_tests/flows/fold_and_verify_program.sh deleted file mode 100755 index 1157e802bc0..00000000000 --- a/barretenberg/acir_tests/flows/fold_and_verify_program.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -set -eu - -# this flow is deprecated. currently it is bb.js only. for bb is is replaced by: -# prove_and_verify --scheme client_ivc --input-type compiletime_stack -VFLAG=${VERBOSE:+-v} - -$BIN fold_and_verify_program $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/flows/prove_then_verify_tube.sh b/barretenberg/acir_tests/flows/prove_then_verify_tube.sh index dfc298ccd5b..79685bfc286 100755 --- a/barretenberg/acir_tests/flows/prove_then_verify_tube.sh +++ b/barretenberg/acir_tests/flows/prove_then_verify_tube.sh @@ -5,7 +5,7 @@ mkdir -p ./proofs VFLAG=${VERBOSE:+-v} -$BIN prove --scheme client_ivc --input_type compiletime_stack $VFLAG -c $CRS_PATH -b ./target/program.json +$BIN write_arbitrary_valid_proof_and_vk_to_file --scheme client_ivc $VFLAG -c $CRS_PATH $BIN prove_tube -k vk -p proof -c $CRS_PATH $VFLAG $BIN verify_tube -k vk -p proof -c $CRS_PATH $VFLAG diff --git a/barretenberg/cpp/src/barretenberg/bb/api.hpp b/barretenberg/cpp/src/barretenberg/bb/api.hpp index ab1a3628a4f..5c83275543f 100644 --- a/barretenberg/cpp/src/barretenberg/bb/api.hpp +++ b/barretenberg/cpp/src/barretenberg/bb/api.hpp @@ -8,7 +8,6 @@ class API { struct Flags { std::optional output_type; // bytes, fields, bytes_and_fields, fields_msgpack std::optional input_type; // compiletime_stack, runtime_stack - bool no_auto_verify; // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): remove }; virtual void prove(const Flags& flags, @@ -36,5 +35,8 @@ class API { const std::filesystem::path& proof_path, const std::filesystem::path& vk_path, const std::filesystem::path& output_path) = 0; + + virtual void write_arbitrary_valid_proof_and_vk_to_file(const API::Flags& flags, + const std::filesystem::path& output_dir) = 0; }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp index 8d0705b91c0..cbdfae92198 100644 --- a/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp @@ -3,6 +3,7 @@ #include "barretenberg/bb/acir_format_getters.hpp" #include "barretenberg/bb/api.hpp" #include "barretenberg/bb/init_srs.hpp" +#include "barretenberg/client_ivc/mock_circuit_producer.hpp" #include "barretenberg/common/throw_or_abort.hpp" #include "libdeflate.h" @@ -125,35 +126,22 @@ class ClientIVCAPI : public API { return folding_stack; }; - static std::shared_ptr _accumulate(std::vector& folding_stack, - bool auto_verify = false) + static std::shared_ptr _accumulate(std::vector& folding_stack) { using Builder = MegaCircuitBuilder; using Program = acir_format::AcirProgram; using namespace acir_format; - vinfo("performing accumulation with auto-verify = ", auto_verify); - TraceSettings trace_settings{ E2E_FULL_TEST_STRUCTURE }; - auto ivc = std::make_shared(trace_settings, auto_verify); + auto ivc = std::make_shared(trace_settings); const ProgramMetadata metadata{ ivc }; // Accumulate the entire program stack into the IVC - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1116): remove manual setting of is_kernel - bool is_kernel = false; for (Program& program : folding_stack) { // Construct a bberg circuit from the acir representation then accumulate it into the IVC Builder circuit = acir_format::create_circuit(program, metadata); - // Set the internal is_kernel flag based on the local mechanism only if it has not already been set to true - if (ivc->auto_verify_mode) { - if (!circuit.databus_propagation_data.is_kernel) { - circuit.databus_propagation_data.is_kernel = is_kernel; - } - is_kernel = !is_kernel; - } - // Do one step of ivc accumulator or, if there is only one circuit in the stack, prove that circuit. In this // case, no work is added to the Goblin opqueue, but VM proofs for trivials inputs are produced. ivc->accumulate(circuit, /*one_circuit=*/folding_stack.size() == 1); @@ -183,8 +171,7 @@ class ClientIVCAPI : public API { std::vector folding_stack = _build_folding_stack(*flags.input_type, bytecode_path, witness_path); - bool auto_verify = !flags.no_auto_verify; - std::shared_ptr ivc = _accumulate(folding_stack, auto_verify); + std::shared_ptr ivc = _accumulate(folding_stack); ClientIVC::Proof proof = ivc->prove(); // Write the proof and verification keys into the working directory in 'binary' format (in practice it seems @@ -246,11 +233,56 @@ class ClientIVCAPI : public API { std::vector folding_stack = _build_folding_stack(*flags.input_type, bytecode_path, witness_path); - std::shared_ptr ivc = _accumulate(folding_stack, /*auto_verify=*/true); + std::shared_ptr ivc = _accumulate(folding_stack); const bool verified = ivc->prove_and_verify(); return verified; }; + /** + * @brief Write an arbitrary but valid ClientIVC proof and VK to files + * @details used to test the prove_tube flow + * + * @param flags + * @param output_dir + */ + void write_arbitrary_valid_proof_and_vk_to_file(const API::Flags& flags, + const std::filesystem::path& output_dir) override + { + if (!flags.output_type || *flags.output_type != "fields_msgpack") { + throw_or_abort("No output_type or output_type not supported"); + } + + if (!flags.input_type || !(*flags.input_type == "compiletime_stack" || *flags.input_type == "runtime_stack")) { + throw_or_abort("No input_type or input_type not supported"); + } + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1163) set these dynamically + init_bn254_crs(1 << 20); + init_grumpkin_crs(1 << 15); + + ClientIVC ivc{ { CLIENT_IVC_BENCH_STRUCTURE } }; + + // Construct and accumulate a series of mocked private function execution circuits + PrivateFunctionExecutionMockCircuitProducer circuit_producer; + size_t NUM_CIRCUITS = 2; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + auto circuit = circuit_producer.create_next_circuit(ivc); + ivc.accumulate(circuit); + } + + ClientIVC::Proof proof = ivc.prove(); + + // Write the proof and verification keys into the working directory in 'binary' format + vinfo("writing ClientIVC proof and vk..."); + write_file(output_dir / "client_ivc_proof", to_buffer(proof)); + + auto eccvm_vk = std::make_shared(ivc.goblin.get_eccvm_proving_key()); + auto translator_vk = + std::make_shared(ivc.goblin.get_translator_proving_key()); + write_file(output_dir / "client_ivc_vk", + to_buffer(ClientIVC::VerificationKey{ ivc.honk_vk, eccvm_vk, translator_vk })); + }; + void gates([[maybe_unused]] const API::Flags& flags, [[maybe_unused]] const std::filesystem::path& bytecode_path, [[maybe_unused]] const std::filesystem::path& witness_path) override diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index eb1200e7f8e..f4fcba969fb 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -190,8 +190,6 @@ void prove_tube(const std::string& output_path) { using namespace stdlib::recursion::honk; - using GoblinVerifierInput = ClientIVCRecursiveVerifier::GoblinVerifierInput; - using VerifierInput = ClientIVCRecursiveVerifier::VerifierInput; using Builder = UltraCircuitBuilder; using GrumpkinVk = bb::VerifierCommitmentKey; @@ -211,8 +209,6 @@ void prove_tube(const std::string& output_path) // TODO(https://github.com/AztecProtocol/barretenberg/issues/1025) vk.eccvm->pcs_verification_key = std::make_shared(vk.eccvm->circuit_size + 1); - GoblinVerifierInput goblin_verifier_input{ vk.eccvm, vk.translator }; - VerifierInput input{ vk.mega, goblin_verifier_input }; auto builder = std::make_shared(); // Preserve the public inputs that should be passed to the base rollup by making them public inputs to the tube @@ -226,7 +222,7 @@ void prove_tube(const std::string& output_path) auto offset = bb::HONK_PROOF_PUBLIC_INPUT_OFFSET; builder->add_public_variable(proof.mega_proof[i + offset]); } - ClientIVCRecursiveVerifier verifier{ builder, input }; + ClientIVCRecursiveVerifier verifier{ builder, vk }; ClientIVCRecursiveVerifier::Output client_ivc_rec_verifier_output = verifier.verify(proof); @@ -1119,8 +1115,7 @@ int main(int argc, char* argv[]) const API::Flags flags = [&args]() { return API::Flags{ .output_type = get_option(args, "--output_type", "fields_msgpack"), - .input_type = get_option(args, "--input_type", "compiletime_stack"), - .no_auto_verify = flag_present(args, "--no_auto_verify") }; + .input_type = get_option(args, "--input_type", "compiletime_stack") }; }(); const std::string command = args[0]; @@ -1158,6 +1153,12 @@ int main(int argc, char* argv[]) return api.prove_and_verify(flags, bytecode_path, witness_path) ? 0 : 1; } + if (command == "write_arbitrary_valid_proof_and_vk_to_file") { + const std::filesystem::path output_dir = get_option(args, "-o", "./target"); + api.write_arbitrary_valid_proof_and_vk_to_file(flags, output_dir); + return 1; + } + throw_or_abort("Invalid command passed to execute_command in bb"); return 1; }; diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 4ba9ae098c7..df64300f75b 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -161,10 +161,6 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr& precomputed_vk, const bool mock_vk) { - if (auto_verify_mode && circuit.databus_propagation_data.is_kernel) { - complete_kernel_circuit_logic(circuit); - } - // Construct merge proof for the present circuit and add to merge verification queue MergeProof merge_proof = goblin.prove_merge(circuit); merge_verification_queue.emplace_back(merge_proof); @@ -407,10 +403,8 @@ std::vector> ClientIVC::precompute_ // Reset the scheme so it can be reused for actual accumulation, maintaining the trace structure setting as is TraceSettings settings = trace_settings; - bool auto_verify = auto_verify_mode; *this = ClientIVC(); this->trace_settings = settings; - this->auto_verify_mode = auto_verify; return vkeys; } diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp index 12ec8cdc041..eb28477637b 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -126,10 +126,6 @@ class ClientIVC { // Settings related to the use of fixed block sizes for each gate in the execution trace TraceSettings trace_settings; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): eventually do away with this. - // Setting auto_verify_mode = true will cause kernel completion logic to be added to kernels automatically - bool auto_verify_mode; - std::shared_ptr bn254_commitment_key; GoblinProver goblin; @@ -140,10 +136,9 @@ class ClientIVC { bool initialized = false; // Is the IVC accumulator initialized - ClientIVC(TraceSettings trace_settings = {}, bool auto_verify_mode = false) + ClientIVC(TraceSettings trace_settings = {}) : trace_usage_tracker(trace_settings) , trace_settings(trace_settings) - , auto_verify_mode(auto_verify_mode) , bn254_commitment_key(trace_settings.structure.has_value() ? std::make_shared>(trace_settings.dyadic_size()) : nullptr) @@ -191,5 +186,12 @@ class ClientIVC { std::vector> precompute_folding_verification_keys( std::vector circuits); + + VerificationKey get_vk() const + { + return { honk_vk, + std::make_shared(goblin.get_eccvm_proving_key()), + std::make_shared(goblin.get_translator_proving_key()) }; + } }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_auto_verify.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_auto_verify.test.cpp deleted file mode 100644 index f4dafde3803..00000000000 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_auto_verify.test.cpp +++ /dev/null @@ -1,199 +0,0 @@ -#include "barretenberg/client_ivc/client_ivc.hpp" -#include "barretenberg/goblin/goblin.hpp" -#include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" - -#include - -using namespace bb; - -// TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): These tests are for the auto_verify_mode version of -// ClientIVC and can be removed altogether when that functionality is removed. -class ClientIVCAutoVerifyTests : 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 VerificationKey = Flavor::VerificationKey; - using Builder = ClientIVC::ClientCircuit; - using DeciderProvingKey = ClientIVC::DeciderProvingKey; - using DeciderVerificationKey = ClientIVC::DeciderVerificationKey; - using FoldProof = ClientIVC::FoldProof; - using DeciderProver = ClientIVC::DeciderProver; - using DeciderVerifier = ClientIVC::DeciderVerifier; - using DeciderProvingKeys = DeciderProvingKeys_; - using FoldingProver = ProtogalaxyProver_; - using DeciderVerificationKeys = DeciderVerificationKeys_; - using FoldingVerifier = ProtogalaxyVerifier_; - - /** - * @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 - * polynomials will bump size to next power of 2) - * - */ - static Builder create_mock_circuit(ClientIVC& ivc, bool is_kernel, size_t log2_num_gates = 16) - { - Builder circuit{ ivc.goblin.op_queue }; - MockCircuits::construct_arithmetic_circuit(circuit, log2_num_gates); - - // 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 - // finalisation stage via the add_gates_to_ensure_all_polys_are_non_zero function for other MegaHonk - // circuits (where we don't explicitly need to add goblin ops), in ClientIVC merge proving happens prior to - // folding where the absense of goblin ecc ops will result in zero commitments. - MockCircuits::construct_goblin_ecc_op_circuit(circuit); - - circuit.databus_propagation_data.is_kernel = is_kernel; - return circuit; - } -}; - -/** - * @brief A simple-as-possible test demonstrating IVC for two mock circuits - * - */ -TEST_F(ClientIVCAutoVerifyTests, Basic) -{ - ClientIVC ivc{ {}, /*auto_verify_mode=*/true }; - - // Initialize the IVC with an arbitrary circuit - Builder circuit_0 = create_mock_circuit(ivc, /*is_kernel=*/false); - ivc.accumulate(circuit_0); - - // Create another circuit and accumulate - Builder circuit_1 = create_mock_circuit(ivc, /*is_kernel=*/true); - ivc.accumulate(circuit_1); - - EXPECT_TRUE(ivc.prove_and_verify()); -}; - -/** - * @brief The number of circuits processed can be odd as long as the last one is a kernel - * - */ -TEST_F(ClientIVCAutoVerifyTests, BasicOdd) -{ - ClientIVC ivc{ {}, /*auto_verify_mode=*/true }; - - // Initialize the IVC with an arbitrary circuit - Builder circuit_0 = create_mock_circuit(ivc, /*is_kernel=*/false); - ivc.accumulate(circuit_0); - - // Create another circuit and accumulate - Builder circuit_1 = create_mock_circuit(ivc, /*is_kernel=*/true); - ivc.accumulate(circuit_1); - - // Create another circuit and accumulate - Builder circuit_2 = create_mock_circuit(ivc, /*is_kernel=*/true); - ivc.accumulate(circuit_2); - - EXPECT_TRUE(ivc.prove_and_verify()); -}; - -/** - * @brief Prove and verify accumulation of an arbitrary set of circuits - * - */ -TEST_F(ClientIVCAutoVerifyTests, BasicLarge) -{ - ClientIVC ivc{ {}, /*auto_verify_mode=*/true }; - - // Construct a set of arbitrary circuits - size_t NUM_CIRCUITS = 6; - std::vector circuits; - for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { - bool is_kernel = (idx % 2 == 1); // every second circuit is a kernel - circuits.emplace_back(create_mock_circuit(ivc, is_kernel)); - } - - // Accumulate each circuit - for (auto& circuit : circuits) { - ivc.accumulate(circuit); - } - - EXPECT_TRUE(ivc.prove_and_verify()); -}; - -/** - * @brief Using a structured trace allows for the accumulation of circuits of varying size - * - */ -TEST_F(ClientIVCAutoVerifyTests, BasicStructured) -{ - ClientIVC ivc{ { SMALL_TEST_STRUCTURE }, /*auto_verify_mode=*/true }; - - // Construct some circuits of varying size - Builder circuit_0 = create_mock_circuit(ivc, /*is_kernel=*/false, /*log2_num_gates=*/5); - Builder circuit_1 = create_mock_circuit(ivc, /*is_kernel=*/true, /*log2_num_gates=*/8); - Builder circuit_2 = create_mock_circuit(ivc, /*is_kernel=*/false, /*log2_num_gates=*/11); - Builder circuit_3 = create_mock_circuit(ivc, /*is_kernel=*/true, /*log2_num_gates=*/11); - - // The circuits can be accumulated as normal due to the structured trace - ivc.accumulate(circuit_0); - ivc.accumulate(circuit_1); - ivc.accumulate(circuit_2); - ivc.accumulate(circuit_3); - - EXPECT_TRUE(ivc.prove_and_verify()); -}; - -/** - * @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys - * - */ -TEST_F(ClientIVCAutoVerifyTests, PrecomputedVerificationKeys) -{ - ClientIVC ivc{ {}, /*auto_verify_mode=*/true }; - - // Construct a set of arbitrary circuits - size_t NUM_CIRCUITS = 4; - std::vector circuits; - for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { - bool is_kernel = (idx % 2 == 1); // every second circuit is a kernel - circuits.emplace_back(create_mock_circuit(ivc, is_kernel)); - } - - // 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, /*one_circuit=*/false, precomputed_vk); - } - - EXPECT_TRUE(ivc.prove_and_verify()); -}; - -/** - * @brief Perform accumulation with a structured trace and precomputed verification keys - * - */ -TEST_F(ClientIVCAutoVerifyTests, StructuredPrecomputedVKs) -{ - ClientIVC ivc{ { SMALL_TEST_STRUCTURE }, /*auto_verify_mode=*/true }; - - // Construct a set of arbitrary circuits - size_t NUM_CIRCUITS = 4; - std::vector circuits; - for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { - bool is_kernel = (idx % 2 == 1); // every second circuit is a kernel - circuits.emplace_back(create_mock_circuit(ivc, is_kernel, /*log2_num_gates=*/5)); - } - - // 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, /*one_circuit=*/false, precomputed_vk); - } - - EXPECT_TRUE(ivc.prove_and_verify()); -}; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 3ed1f1df1c8..1a0d7b5b823 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -388,38 +388,6 @@ TEST_P(AcirIntegrationFoldingTest, DISABLED_ProveAndVerifyProgramStack) } } -TEST_P(AcirIntegrationFoldingTest, DISABLED_FoldAndVerifyProgramStack) -{ - using Flavor = MegaFlavor; - using Builder = Flavor::CircuitBuilder; - - std::string test_name = GetParam(); - auto program_stack = get_program_stack_data_from_test_file( - test_name, /*honk_recursion=*/false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): - // Assumes Flavor is not UltraHonk - - TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; - auto ivc = std::make_shared(trace_settings, /*auto_verify_mode=*/true); - - const acir_format::ProgramMetadata metadata{ ivc }; - - while (!program_stack.empty()) { - auto program = program_stack.back(); - - // Construct a bberg circuit from the acir representation - auto circuit = acir_format::create_circuit(program, metadata); - - ivc->accumulate(circuit); - - CircuitChecker::check(circuit); - // EXPECT_TRUE(prove_and_verify_honk(circuit)); - - program_stack.pop_back(); - } - - EXPECT_TRUE(ivc->prove_and_verify()); -} - INSTANTIATE_TEST_SUITE_P(AcirTests, AcirIntegrationFoldingTest, testing::Values("fold_basic", "fold_basic_nested_call")); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index d4045e636e6..a645a39649f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -86,43 +86,6 @@ WASM_EXPORT void acir_prove_and_verify_ultra_honk(uint8_t const* acir_vec, info("verified: ", *result); } -WASM_EXPORT void acir_fold_and_verify_program_stack(uint8_t const* acir_vec, - bool const* recursive, - uint8_t const* witness_vec, - bool* result) -{ - using ProgramStack = acir_format::AcirProgramStack; - using Builder = MegaCircuitBuilder; - - auto constraint_systems = - acir_format::program_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/false); - auto witness_stack = acir_format::witness_buf_to_witness_stack(from_buffer>(witness_vec)); - - ProgramStack program_stack{ constraint_systems, witness_stack }; - - TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; - auto ivc = std::make_shared(trace_settings, /*auto_verify_mode=*/true); - - const acir_format::ProgramMetadata metadata{ ivc, *recursive }; - - bool is_kernel = false; - while (!program_stack.empty()) { - auto program = program_stack.back(); - - // Construct a bberg circuit from the acir representation - auto builder = acir_format::create_circuit(program, metadata); - - builder.databus_propagation_data.is_kernel = is_kernel; - is_kernel = !is_kernel; // toggle on/off so every second circuit is intepreted as a kernel - - ivc->accumulate(builder); - - program_stack.pop_back(); - } - *result = ivc->prove_and_verify(); - info("acir_fold_and_verify_program_stack result: ", *result); -} - WASM_EXPORT void acir_prove_and_verify_mega_honk(uint8_t const* acir_vec, bool const* recursive, uint8_t const* witness_vec, @@ -238,9 +201,8 @@ WASM_EXPORT void acir_prove_and_verify_aztec_client(uint8_t const* acir_stack, folding_stack.push_back(Program{ constraints, witness }); } // TODO(#7371) dedupe this with the rest of the similar code - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): remove use of auto_verify_mode TraceSettings trace_settings{ E2E_FULL_TEST_STRUCTURE }; - auto ivc = std::make_shared(trace_settings, /*auto_verify_mode=*/true); + auto ivc = std::make_shared(trace_settings); const acir_format::ProgramMetadata metadata{ ivc }; @@ -296,28 +258,18 @@ WASM_EXPORT void acir_prove_aztec_client(uint8_t const* acir_stack, acir_format::circuit_buf_to_acir_format(bincode, /*honk_recursion=*/false); folding_stack.push_back(Program{ constraints, witness }); } - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): remove use of auto_verify_mode TraceSettings trace_settings{ E2E_FULL_TEST_STRUCTURE }; auto ivc = std::make_shared(trace_settings); const acir_format::ProgramMetadata metadata{ ivc }; // Accumulate the entire program stack into the IVC - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1116): remove manual setting of is_kernel once databus - // has been integrated into noir kernel programs - bool is_kernel = false; auto start = std::chrono::steady_clock::now(); for (Program& program : folding_stack) { // Construct a bberg circuit from the acir representation then accumulate it into the IVC vinfo("constructing circuit..."); auto circuit = acir_format::create_circuit(program, metadata); - // Set the internal is_kernel flag based on the local mechanism only if it has not already been set to true - if (!circuit.databus_propagation_data.is_kernel) { - circuit.databus_propagation_data.is_kernel = is_kernel; - } - is_kernel = !is_kernel; - vinfo("done constructing circuit. calling ivc.accumulate..."); ivc->accumulate(circuit); vinfo("done accumulating."); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.cpp index 90a7df0e894..ca351429ab0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.cpp @@ -11,8 +11,7 @@ namespace bb::stdlib::recursion::honk { ClientIVCRecursiveVerifier::Output ClientIVCRecursiveVerifier::verify(const ClientIVC::Proof& proof) { // Construct stdlib Mega verification key - auto stdlib_mega_vk = - std::make_shared(builder.get(), verifier_input.mega_verification_key); + auto stdlib_mega_vk = std::make_shared(builder.get(), ivc_verification_key.mega); // Dummy aggregation object until we do proper aggregation aggregation_state agg_obj = @@ -23,7 +22,8 @@ ClientIVCRecursiveVerifier::Output ClientIVCRecursiveVerifier::verify(const Clie verifier.verify_proof(proof.mega_proof, agg_obj); // Perform Goblin recursive verification - GoblinVerifier goblin_verifier{ builder.get(), verifier_input.goblin_input }; + GoblinVerifierInput goblin_verification_key{ ivc_verification_key.eccvm, ivc_verification_key.translator }; + GoblinVerifier goblin_verifier{ builder.get(), goblin_verification_key }; GoblinRecursiveVerifierOutput output = goblin_verifier.verify(proof.goblin_proof); return output; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp index db36f16230a..822a83cb8d2 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp @@ -15,6 +15,7 @@ class ClientIVCRecursiveVerifier { using GoblinVerifier = GoblinRecursiveVerifier; using Flavor = RecursiveFlavor::NativeFlavor; using VerificationKey = Flavor::VerificationKey; + using IVCVerificationKey = ClientIVC::VerificationKey; public: using Proof = ClientIVC::Proof; @@ -27,14 +28,14 @@ class ClientIVCRecursiveVerifier { GoblinVerifierInput goblin_input; }; - ClientIVCRecursiveVerifier(std::shared_ptr builder, VerifierInput& verifier_input) + ClientIVCRecursiveVerifier(std::shared_ptr builder, IVCVerificationKey& ivc_verification_key) : builder(builder) - , verifier_input(verifier_input){}; + , ivc_verification_key(ivc_verification_key){}; Output verify(const ClientIVC::Proof&); private: std::shared_ptr builder; - VerifierInput verifier_input; + IVCVerificationKey ivc_verification_key; }; } // namespace bb::stdlib::recursion::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.test.cpp index 3ce5a457400..dcee5a4eb73 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.test.cpp @@ -1,6 +1,7 @@ #include "barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/client_ivc/client_ivc.hpp" +#include "barretenberg/client_ivc/test_bench_shared.hpp" #include "barretenberg/common/test.hpp" namespace bb::stdlib::recursion::honk { @@ -8,16 +9,15 @@ class ClientIVCRecursionTests : public testing::Test { public: using Builder = UltraCircuitBuilder; using ClientIVCVerifier = ClientIVCRecursiveVerifier; - using VerifierInput = ClientIVCVerifier::VerifierInput; using FoldVerifierInput = ClientIVCVerifier::FoldVerifierInput; - using GoblinVerifierInput = ClientIVCVerifier::GoblinVerifierInput; - using DeciderVerificationKey = FoldVerifierInput::DeciderVK; - using ECCVMVK = GoblinVerifier::ECCVMVerificationKey; - using TranslatorVK = GoblinVerifier::TranslatorVerificationKey; using Proof = ClientIVC::Proof; using Flavor = UltraRollupRecursiveFlavor_; using NativeFlavor = Flavor::NativeFlavor; using UltraRecursiveVerifier = UltraRecursiveVerifier_; + using MockCircuitProducer = PrivateFunctionExecutionMockCircuitProducer; + using IVCVerificationKey = ClientIVC::VerificationKey; + + static constexpr TraceSettings trace_settings{ CLIENT_IVC_BENCH_STRUCTURE }; static void SetUpTestSuite() { @@ -27,7 +27,7 @@ class ClientIVCRecursionTests : public testing::Test { struct ClientIVCProverOutput { Proof proof; - VerifierInput verifier_input; + IVCVerificationKey ivc_vk; }; /** @@ -36,22 +36,15 @@ class ClientIVCRecursionTests : public testing::Test { */ static ClientIVCProverOutput construct_client_ivc_prover_output(ClientIVC& ivc) { - using Builder = ClientIVC::ClientCircuit; - + // Construct and accumulate a series of mocked private function execution circuits + MockCircuitProducer circuit_producer; size_t NUM_CIRCUITS = 2; for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { - Builder circuit{ ivc.goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(circuit); - circuit.databus_propagation_data.is_kernel = (idx % 2 == 1); // every second circuit is a kernel + auto circuit = circuit_producer.create_next_circuit(ivc); ivc.accumulate(circuit); } - Proof proof = ivc.prove(); - GoblinVerifierInput goblin_verifier_input{ std::make_shared(ivc.goblin.get_eccvm_proving_key()), - std::make_shared( - ivc.goblin.get_translator_proving_key()) }; - - return { proof, { ivc.honk_vk, goblin_verifier_input } }; + return { ivc.prove(), ivc.get_vk() }; } }; @@ -61,8 +54,8 @@ class ClientIVCRecursionTests : public testing::Test { */ TEST_F(ClientIVCRecursionTests, NativeVerification) { - ClientIVC ivc{ {}, /*auto_verify_mode=*/true }; - auto [proof, verifier_input] = construct_client_ivc_prover_output(ivc); + ClientIVC ivc{ trace_settings }; + auto [proof, ivc_vk] = construct_client_ivc_prover_output(ivc); // Confirm that the IVC proof can be natively verified EXPECT_TRUE(ivc.verify(proof)); @@ -77,12 +70,12 @@ TEST_F(ClientIVCRecursionTests, Basic) using CIVCRecVerifierOutput = ClientIVCRecursiveVerifier::Output; // Generate a genuine ClientIVC prover output - ClientIVC ivc{ {}, /*auto_verify_mode=*/true }; - auto [proof, verifier_input] = construct_client_ivc_prover_output(ivc); + ClientIVC ivc{ trace_settings }; + auto [proof, ivc_vk] = construct_client_ivc_prover_output(ivc); // Construct the ClientIVC recursive verifier auto builder = std::make_shared(); - ClientIVCVerifier verifier{ builder, verifier_input }; + ClientIVCVerifier verifier{ builder, ivc_vk }; // Generate the recursive verification circuit CIVCRecVerifierOutput output = verifier.verify(proof); @@ -100,12 +93,12 @@ TEST_F(ClientIVCRecursionTests, ClientTubeBase) using CIVCRecVerifierOutput = ClientIVCRecursiveVerifier::Output; // Generate a genuine ClientIVC prover output - ClientIVC ivc{ {}, /*auto_verify_mode=*/true }; - auto [proof, verifier_input] = construct_client_ivc_prover_output(ivc); + ClientIVC ivc{ trace_settings }; + auto [proof, ivc_vk] = construct_client_ivc_prover_output(ivc); // Construct the ClientIVC recursive verifier auto tube_builder = std::make_shared(); - ClientIVCVerifier verifier{ tube_builder, verifier_input }; + ClientIVCVerifier verifier{ tube_builder, ivc_vk }; // Generate the recursive verification circuit CIVCRecVerifierOutput client_ivc_rec_verifier_output = verifier.verify(proof); diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 9c5be4da622..788a5645e72 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -201,7 +201,6 @@ export async function executeBbClientIvcProof( bytecodeStackPath: string, witnessStackPath: string, log: LogFn, - noAutoVerify = false, ): Promise { // Check that the working directory exists try { @@ -238,9 +237,7 @@ export async function executeBbClientIvcProof( '--input_type', 'runtime_stack', ]; - if (noAutoVerify) { - args.push('--no_auto_verify'); - } + const timer = new Timer(); const logFunction = (message: string) => { log(`bb - ${message}`); diff --git a/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts index 614329564cd..53f18d20c2e 100644 --- a/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts @@ -105,7 +105,6 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver { path.join(directory, 'acir.msgpack'), path.join(directory, 'witnesses.msgpack'), this.log.info, - true, ); if (provingResult.status === BB_RESULT.FAILURE) { diff --git a/yarn-project/ivc-integration/src/native_client_ivc_integration.test.ts b/yarn-project/ivc-integration/src/native_client_ivc_integration.test.ts index ae14f3cdf39..9572a436fb2 100644 --- a/yarn-project/ivc-integration/src/native_client_ivc_integration.test.ts +++ b/yarn-project/ivc-integration/src/native_client_ivc_integration.test.ts @@ -40,7 +40,6 @@ describe('Client IVC Integration', () => { path.join(bbWorkingDirectory, 'acir.msgpack'), path.join(bbWorkingDirectory, 'witnesses.msgpack'), logger.info, - true, ); if (provingResult.status === BB_RESULT.FAILURE) {