diff --git a/barretenberg/cpp/scripts/line_count.py b/barretenberg/cpp/scripts/line_count.py index 4b03ed12cc36..5f116b9ef0fe 100755 --- a/barretenberg/cpp/scripts/line_count.py +++ b/barretenberg/cpp/scripts/line_count.py @@ -55,7 +55,6 @@ "transcript": 1, "translator_vm": 1, "ultra_honk": 1, - "ultra_vanilla_client_ivc": 0, "vm": 0, "vm2": 0, "wasi": 0, diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index bab5478d359c..6385b813d26f 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -94,7 +94,6 @@ add_subdirectory(barretenberg/relations) add_subdirectory(barretenberg/serialize) add_subdirectory(barretenberg/solidity_helpers) add_subdirectory(barretenberg/srs) -add_subdirectory(barretenberg/ultra_vanilla_client_ivc) add_subdirectory(barretenberg/stdlib) add_subdirectory(barretenberg/stdlib_circuit_builders) add_subdirectory(barretenberg/sumcheck) @@ -154,7 +153,6 @@ set(BARRETENBERG_TARGET_OBJECTS $ $ $ - $ $ $ $ diff --git a/barretenberg/cpp/src/barretenberg/api/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/api/CMakeLists.txt index e2b251be44d2..b1c3d1cbb018 100644 --- a/barretenberg/cpp/src/barretenberg/api/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/api/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(api client_ivc ultra_vanilla_client_ivc dsl libdeflate::libdeflate_static) +barretenberg_module(api client_ivc dsl libdeflate::libdeflate_static) diff --git a/barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp b/barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp index 53e564006ceb..7dcb2b117f2b 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp @@ -13,7 +13,6 @@ #include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp" #include "barretenberg/srs/global_crs.hpp" -#include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/CMakeLists.txt deleted file mode 100644 index e8120167c08b..000000000000 --- a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -barretenberg_module(ultra_vanilla_client_ivc stdlib_honk_verifier) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.cpp deleted file mode 100644 index 614609b64ec8..000000000000 --- a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp" -#include "barretenberg/ultra_honk/oink_prover.hpp" - -namespace bb { - -void UltraVanillaClientIVC::accumulate(Circuit& circuit, const Proof& proof, const std::shared_ptr& vk) -{ - RecursiveVerifier verifier{ &circuit, std::make_shared(&circuit, vk) }; - AggregationObject agg_obj = AggregationObject::construct_default(circuit); - accumulator = verifier.verify_proof(proof, agg_obj).agg_obj; -} - -void UltraVanillaClientIVC::handle_accumulator(Circuit& circuit, const size_t step, const bool init_kzg_accumulator) -{ - if (step == 0) { - info("internal ivc step 0"); - aggregation_object = AggregationObject::construct_default(circuit); - } else { - info("internal ivc step ", step); - accumulate(circuit, previous_proof, previous_vk); - aggregation_object = accumulator; - } - if (init_kzg_accumulator) { - info("calling aggregation_object.set_public()"); - aggregation_object.set_public(); - } - vinfo("set accumulator indices"); -} - -HonkProof UltraVanillaClientIVC::prove(CircuitSource& source, - const bool cache_vks, - const bool init_kzg_accumulator) -{ - for (size_t step = 0; step < source.num_circuits(); step++) { - vinfo("about to call next..."); - auto [circuit, vk] = source.next(); - vinfo("got next pair from source"); - - handle_accumulator(circuit, step, init_kzg_accumulator); - - accumulator_value = { accumulator.P0.get_value(), accumulator.P1.get_value() }; - vinfo("set accumulator data"); - - auto proving_key = std::make_shared(circuit); - vinfo("built proving key"); - - if (step < source.num_circuits() - 1) { - UltraProver prover{ proving_key, commitment_key }; - vinfo("built prover"); - previous_proof = prover.construct_proof(); - vinfo("constructed proof"); - } else { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1294) Use UltraKeccakZKProver when it exists - UltraProver prover{ proving_key, commitment_key }; - previous_proof = prover.construct_proof(); - } - - previous_vk = vk ? vk : std::make_shared(proving_key->proving_key); - if (cache_vks) { - vk_cache.push_back(previous_vk); - } - } - return previous_proof; -}; - -bool UltraVanillaClientIVC::verify(const Proof& proof, const std::shared_ptr& vk) -{ - UltraVerifier verifer{ vk }; - bool verified = verifer.verify_proof(proof); - vinfo("proof verified: ", verified); - return verified; -} - -/** - * @brief Construct and verify a proof for the IVC - * @note Use of this method only makes sense when the prover and verifier are the same entity, e.g. in - * development/testing. - * - */ -bool UltraVanillaClientIVC::prove_and_verify(CircuitSource& source, - const bool cache_vks, - const bool init_kzg_accumulator) -{ - auto start = std::chrono::steady_clock::now(); - prove(source, cache_vks, init_kzg_accumulator); - auto end = std::chrono::steady_clock::now(); - auto diff = std::chrono::duration_cast(end - start); - vinfo("time to call UltraVanillaClientIVC::prove: ", diff.count(), " ms."); - - start = end; - bool verified = verify(previous_proof, previous_vk); - end = std::chrono::steady_clock::now(); - - diff = std::chrono::duration_cast(end - start); - vinfo("time to verify UltraVanillaClientIVC proof: ", diff.count(), " ms."); - - return verified; -} - -std::vector> UltraVanillaClientIVC::compute_vks( - CircuitSource& source) -{ - prove_and_verify(source, /*cache_vks=*/true); - return vk_cache; -}; - -} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp deleted file mode 100644 index d3574f81495d..000000000000 --- a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include "barretenberg/plonk_honk_shared/execution_trace/execution_trace_usage_tracker.hpp" -#include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp" -#include "barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp" -#include "barretenberg/stdlib/plonk_recursion/aggregation_state/aggregation_state.hpp" -#include "barretenberg/ultra_honk/ultra_prover.hpp" -#include "barretenberg/ultra_honk/ultra_verifier.hpp" -#include -namespace bb { - -/** - * @brief A function that produces a set of circuits and possibly their precomputed vks - * @details One has the option of not providing vks--just provide nullptr instead. - * This class is introduced as an experiment. We _could_ just use vectors of vks and shared_ptrs, but this limits - * applicability of the class because, in practice, we don't have sufficient memory to store all circuit builders at - * once. The idea is this class is applicable in both situations we care about testing via mocks (cf the test file for - * UltraVanillaClientIVC, which implements a source of mock circuits), and IVC of circuits written in Noir, where the - * source (not yet implemented) is ACIR and partial witnesses which are processed by our DSL code, expanding blackbox - * function calls. - * @todo Relocate this at the appropriate time, if it does become a standard interface. - */ -template - -class CircuitSource { - public: - struct Output { - Builder circuit; - std::shared_ptr vk; - }; - - virtual Output next(); - virtual size_t num_circuits() const; -}; - -/** - * @brief A class encapsulating multiple sequential steps of the IVC scheme that arises most naturally from recursive - * proof verification. - * - * @details "Vanilla" is in the colloquial sense of meaning "plain". "Client" refers to the fact that this is intended - * for executing proof construction in constrained environments. - */ -class UltraVanillaClientIVC { - - public: - using Flavor = UltraFlavor; - using FF = Flavor::FF; - using Circuit = UltraCircuitBuilder; - using PK = DeciderProvingKey_; - using VK = UltraFlavor::VerificationKey; - using Proof = HonkProof; - - using RecursiveFlavor = UltraRecursiveFlavor_; - using RecursiveVerifier = stdlib::recursion::honk::UltraRecursiveVerifier_; - using RecursiveVK = RecursiveFlavor::VerificationKey; - using Curve = stdlib::bn254; - using AggregationObject = stdlib::recursion::aggregation_state; - - /** - * @brief Append a recursive verifier and update the accumulator. - */ - void accumulate(Circuit&, const Proof&, const std::shared_ptr&); - - /** - * @brief Append a recursive verifier and update the accumulator. - */ - void handle_accumulator(Circuit&, const size_t, const bool); - - public: - std::shared_ptr> commitment_key; - Proof previous_proof; - std::shared_ptr previous_vk; - AggregationObject accumulator; - std::array accumulator_value; - AggregationObject aggregation_object; - std::vector> vk_cache; - - UltraVanillaClientIVC() = default; - UltraVanillaClientIVC(const size_t dyadic_size) - : commitment_key(std::make_shared>(dyadic_size)) - {} - - /** - * @brief Iterate through all circuits and prove each, appending a recursive verifier of the previous proof after - * the first step. - * @param source A source of circuits, possibly accompanied by precomputed verification keys. - * @param cache_vks If true, case the verification key that is computed. - * @return HonkProof A proof of the final circuit which through recursive verification, demonstrates that all - * circuits were satisfied, or one of them was not satisfied, depending on whether it verifies or does not verify. - */ - HonkProof prove(CircuitSource& source, - const bool cache_vks = false, - // if the first step does not contain an accumulator from an earlier recursive verification, we need - // to initialize the accumulator, otherwise we must not initialize it - const bool init_kzg_accumulator = true); - - /** - * @brief Verify an IVC proof. - * @details This verifies the final proof, including (natively) checking the pairing of the two points in the final - * accumulator. - * - * @param proof - * @param vk - * @return true All circuits provided have been satisfied. - * @return false Some circuit provided was not satisfied. - */ - static bool verify(const Proof& proof, const std::shared_ptr& vk); - - /** - * @brief Prove and then verify the proof. This is used for testing. - */ - bool prove_and_verify(CircuitSource& source, - const bool cache_vks = false, - // if the first step does not contain an accumulator from an earlier recursive verification, - // we need to initialize the accumulator, otherwise we must not initialize it - const bool init_kzg_accumulator = true); - - /** - * @brief Compute the verification key of each circuit provided by the source. - * @details This runs a full IVC prover. Our public interface provides a faster but more brittle method via dummy - * witnesses. This is a useful fallback that we might want for debugging. Currently it is used to test the prover - * flow that using precomputed verification keys. - */ - std::vector> compute_vks(CircuitSource& source); -}; -} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp deleted file mode 100644 index 21656305671b..000000000000 --- a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp" -#include "barretenberg/goblin/goblin.hpp" -#include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/protogalaxy/folding_test_utils.hpp" -#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include - -using namespace bb; - -class UltraVanillaClientIVCTests : public ::testing::Test { - protected: - static void SetUpTestSuite() - { - srs::init_crs_factory("../srs_db/ignition"); - srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } - - using Flavor = UltraVanillaClientIVC::Flavor; - using Builder = UltraCircuitBuilder; - using FF = typename Flavor::FF; - using VK = Flavor::VerificationKey; - using PK = DeciderProvingKey_; - - class MockCircuitSource : public CircuitSource { - std::vector _sizes; - std::vector> _vks; - uint32_t step{ 0 }; - - public: - MockCircuitSource(const std::vector& sizes) - : _sizes(sizes) - { - std::fill_n(std::back_inserter(_vks), sizes.size(), nullptr); - } - - MockCircuitSource(const MockCircuitSource& source_without_sizes, std::vector> vks) - : _sizes(source_without_sizes._sizes) - , _vks(vks) - {} - - Output next() override - { - Builder circuit; - MockCircuits::construct_arithmetic_circuit(circuit, _sizes[step]); - const auto& vk = _vks[step]; - ++step; - return { circuit, vk }; - } - - size_t num_circuits() const override - { - ASSERT(_sizes.size() == _vks.size()); - return _sizes.size(); - } - }; -}; - -TEST_F(UltraVanillaClientIVCTests, TwoCircuits) -{ - static constexpr size_t LOG_SIZE = 10; - UltraVanillaClientIVC ivc(1 << LOG_SIZE); - MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE } }; - EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); -}; - -TEST_F(UltraVanillaClientIVCTests, ThreeCircuits) -{ - static constexpr size_t LOG_SIZE = 10; - UltraVanillaClientIVC ivc(1 << LOG_SIZE); - MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE, LOG_SIZE } }; - EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); -}; - -/** - * @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys - * @details The test precomputes the keys via one pass of the ivc prover, then it uses them in a second pass. - */ -TEST_F(UltraVanillaClientIVCTests, PrecomputedVerificationKeys) -{ - - static constexpr size_t LOG_SIZE = 10; - - UltraVanillaClientIVC ivc_1(1 << LOG_SIZE); - MockCircuitSource circuit_source_no_vks{ { LOG_SIZE, LOG_SIZE } }; - auto vks = ivc_1.compute_vks(circuit_source_no_vks); - - UltraVanillaClientIVC ivc_2(1 << LOG_SIZE); // need to refactor accumulator_value use to reuse ivc_1 - MockCircuitSource circuit_source_with_vks{ circuit_source_no_vks, vks }; - EXPECT_TRUE(ivc_2.prove_and_verify(circuit_source_with_vks)); -}; - -// TODO(https://github.com/AztecProtocol/barretenberg/issues/1177) Implement failure tests