diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/circuit_checker.hpp b/barretenberg/cpp/src/barretenberg/circuit_checker/circuit_checker.hpp index 8d232e75f3c9..9bec19411a51 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/circuit_checker.hpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/circuit_checker.hpp @@ -24,8 +24,7 @@ class CircuitChecker { template static bool check(const Builder& builder) { static_assert(IsCheckable); - - if constexpr (IsUltraBuilder) { + if constexpr (IsUltraBuilder || IsGoblinUltraBuilder) { return UltraCircuitChecker::check(builder); } else if constexpr (IsStandardBuilder) { return StandardCircuitChecker::check(builder); diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.cpp index 0ea1bbb6bf4a..0e647d603c56 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.cpp @@ -102,7 +102,7 @@ bool UltraCircuitChecker::check_block(Builder& builder, info("Failed Lookup check relation at row idx = ", idx); return false; } - if constexpr (IsGoblinBuilder) { + if constexpr (IsGoblinUltraBuilder) { result = result && check_relation(values, params); if (result == false) { info("Failed PoseidonInternal relation at row idx = ", idx); @@ -285,7 +285,7 @@ void UltraCircuitChecker::populate_values( values.q_elliptic = block.q_elliptic()[idx]; values.q_aux = block.q_aux()[idx]; values.q_lookup = block.q_lookup_type()[idx]; - if constexpr (IsGoblinBuilder) { + if constexpr (IsGoblinUltraBuilder) { values.q_busread = block.q_busread()[idx]; values.q_poseidon2_internal = block.q_poseidon2_internal()[idx]; values.q_poseidon2_external = block.q_poseidon2_external()[idx]; 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 fb10a67f9eb8..d4d06758e2ff 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 @@ -26,10 +26,12 @@ TEST_F(MockKernelTest, PinFoldingKernelSizes) 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 kernel circuit GoblinUltraCircuitBuilder kernel_circuit{ ivc.goblin.op_queue }; @@ -42,6 +44,7 @@ TEST_F(MockKernelTest, PinFoldingKernelSizes) 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, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 96ddd4337e55..32972a287810 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -119,7 +119,7 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo // TODO(https://github.com/AztecProtocol/barretenberg/issues/817): disable these for UGH for now since we're not yet // dealing with proper recursion - if constexpr (IsGoblinBuilder) { + if constexpr (IsGoblinUltraBuilder) { if (!constraint_system.recursion_constraints.empty()) { info("WARNING: this circuit contains recursion_constraints!"); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.cpp index aa3392130f63..4b14b10af7e0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.cpp @@ -17,7 +17,7 @@ namespace bb::stdlib { template typename Poseidon2Permutation::State Poseidon2Permutation::permutation( Builder* builder, const typename Poseidon2Permutation::State& input) - requires IsGoblinBuilder + requires IsGoblinUltraBuilder { // deep copy State current_state(input); @@ -120,7 +120,7 @@ typename Poseidon2Permutation::State Poseidon2Permutation typename Poseidon2Permutation::State Poseidon2Permutation::permutation( Builder* builder, const typename Poseidon2Permutation::State& input) - requires IsNotGoblinBuilder + requires IsNotGoblinUltraBuilder { // deep copy State current_state(input); @@ -156,7 +156,7 @@ typename Poseidon2Permutation::State Poseidon2Permutation void Poseidon2Permutation::add_round_constants( State& input, const typename Poseidon2Permutation::RoundConstants& rc) - requires IsNotGoblinBuilder + requires IsNotGoblinUltraBuilder { for (size_t i = 0; i < t; ++i) { @@ -166,7 +166,7 @@ void Poseidon2Permutation::add_round_constants( template void Poseidon2Permutation::apply_sbox(State& input) - requires IsNotGoblinBuilder + requires IsNotGoblinUltraBuilder { for (auto& in : input) { apply_single_sbox(in); @@ -175,7 +175,7 @@ void Poseidon2Permutation::apply_sbox(State& input) template void Poseidon2Permutation::apply_single_sbox(field_t& input) - requires IsNotGoblinBuilder + requires IsNotGoblinUltraBuilder { // hardcoded assumption that d = 5. should fix this or not make d configurable auto xx = input.sqr(); @@ -185,7 +185,7 @@ void Poseidon2Permutation::apply_single_sbox(field_t& template void Poseidon2Permutation::matrix_multiplication_internal(State& input) - requires IsNotGoblinBuilder + requires IsNotGoblinUltraBuilder { // for t = 4 auto sum = input[0]; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.hpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.hpp index d653f8718c9a..ba43c2786ef7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.hpp @@ -46,18 +46,18 @@ template class Poseidon2Permutation { * @return State */ static State permutation(Builder* builder, const State& input) - requires IsGoblinBuilder; + requires IsGoblinUltraBuilder; static State permutation(Builder* builder, const State& input) - requires IsNotGoblinBuilder; + requires IsNotGoblinUltraBuilder; static void add_round_constants(State& input, const RoundConstants& rc) - requires IsNotGoblinBuilder; + requires IsNotGoblinUltraBuilder; static void apply_sbox(State& input) - requires IsNotGoblinBuilder; + requires IsNotGoblinUltraBuilder; static void apply_single_sbox(field_t& input) - requires IsNotGoblinBuilder; + requires IsNotGoblinUltraBuilder; static void matrix_multiplication_internal(State& input) - requires IsNotGoblinBuilder; + requires IsNotGoblinUltraBuilder; /** * @brief Separate function to do just the first linear layer (equivalent to external matrix mul). diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp index 506d36f5c638..170af17e0acc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp @@ -44,4 +44,8 @@ std::array DeciderRecursiveVerifier_:: template class DeciderRecursiveVerifier_>; template class DeciderRecursiveVerifier_>; +template class DeciderRecursiveVerifier_>; +template class DeciderRecursiveVerifier_>; +template class DeciderRecursiveVerifier_>; +template class DeciderRecursiveVerifier_>; } // namespace bb::stdlib::recursion::honk diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp index 3f27a79e2c51..ad5e41af9f18 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp @@ -165,42 +165,17 @@ std::shared_ptr ProtoGalaxyRecursiveVerifi next_accumulator->verification_key->pcs_verification_key = accumulator->verification_key->pcs_verification_key; next_accumulator->verification_key->pub_inputs_offset = accumulator->verification_key->pub_inputs_offset; next_accumulator->public_inputs = accumulator->public_inputs; - size_t vk_idx = 0; - for (auto& expected_vk : next_accumulator->verification_key->get_all()) { - size_t inst = 0; - std::vector scalars; - std::vector commitments; - for (auto& instance : instances) { - scalars.emplace_back(lagranges[inst]); - commitments.emplace_back(instance->verification_key->get_all()[vk_idx]); - inst++; - } - expected_vk = Commitment::batch_mul(commitments, scalars); - vk_idx++; - } + next_accumulator->is_accumulator = true; - // Compute next folding parameters and verify against the ones received from the prover + // Compute next folding parameters next_accumulator->target_sum = perturbator_at_challenge * lagranges[0] + vanishing_polynomial_at_challenge * combiner_quotient_at_challenge; next_accumulator->gate_challenges = update_gate_challenges(perturbator_challenge, accumulator->gate_challenges, deltas); - // Compute ϕ and verify against the data received from the prover - auto& acc_witness_commitments = next_accumulator->witness_commitments; - size_t comm_idx = 0; - for (auto& comm : acc_witness_commitments.get_all()) { - std::vector scalars; - std::vector commitments; - size_t inst = 0; - for (auto& instance : instances) { - scalars.emplace_back(lagranges[inst]); - commitments.emplace_back(instance->witness_commitments.get_all()[comm_idx]); - inst++; - } - comm = Commitment::batch_mul(commitments, scalars); - comm_idx++; - } + // Compute ϕ + fold_commitments(lagranges, instances, next_accumulator); next_accumulator->public_inputs = std::vector(static_cast(next_accumulator->verification_key->num_public_inputs), 0); @@ -248,4 +223,12 @@ template class ProtoGalaxyRecursiveVerifier_< RecursiveVerifierInstances_, 2>>; template class ProtoGalaxyRecursiveVerifier_< RecursiveVerifierInstances_, 2>>; +template class ProtoGalaxyRecursiveVerifier_< + RecursiveVerifierInstances_, 2>>; +template class ProtoGalaxyRecursiveVerifier_< + RecursiveVerifierInstances_, 2>>; +template class ProtoGalaxyRecursiveVerifier_< + RecursiveVerifierInstances_, 2>>; +template class ProtoGalaxyRecursiveVerifier_< + RecursiveVerifierInstances_, 2>>; } // namespace bb::stdlib::recursion::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.hpp index 97bdbd8b5f6f..dbc78b944e63 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.hpp @@ -120,6 +120,83 @@ template class ProtoGalaxyRecursiveVerifier_ { } return result; }; + + /** + * @brief Hack method to fold the witness commitments and verification key without the batch_mul in the case where + * the recursive folding verifier is instantiated as a vanilla ultra circuit. + * + * @details In the folding recursive verifier we might hit the scenerio where we do a batch_mul(commitments, + * lagranges) where the commitments are equal. That is because when we add gates to ensure no zero commitments, + * these will be the same for all circuits, hitting an edge case in batch_mul that creates a failing constraint. + * Specifically, at some point in the algorithm we compute the difference between the points which, if they are + * equal, would be zero, case that is not supported. See https://github.com/AztecProtocol/barretenberg/issues/971. + */ + void fold_commitments(std::vector lagranges, + VerifierInstances& instances, + std::shared_ptr& accumulator) + requires IsUltraBuilder + { + using ElementNative = typename Flavor::Curve::ElementNative; + using AffineElementNative = typename Flavor::Curve::AffineElementNative; + + auto offset_generator = Commitment::from_witness(builder, AffineElementNative(ElementNative::random_element())); + + size_t vk_idx = 0; + for (auto& expected_vk : accumulator->verification_key->get_all()) { + expected_vk = offset_generator; + size_t inst = 0; + for (auto& instance : instances) { + expected_vk += instance->verification_key->get_all()[vk_idx] * lagranges[inst]; + inst++; + } + expected_vk -= offset_generator; + vk_idx++; + } + + size_t comm_idx = 0; + for (auto& comm : accumulator->witness_commitments.get_all()) { + comm = offset_generator; + size_t inst = 0; + for (auto& instance : instances) { + comm += instance->witness_commitments.get_all()[comm_idx] * lagranges[inst]; + inst++; + } + comm -= offset_generator; + comm_idx++; + } + } + + /** + * @brief Folds the witness commitments and verification key (part of ϕ) and stores the values in the accumulator. + * + * + */ + + void fold_commitments(std::vector lagranges, + VerifierInstances& instances, + std::shared_ptr& accumulator) + requires(!IsUltraBuilder) + { + size_t vk_idx = 0; + for (auto& expected_vk : accumulator->verification_key->get_all()) { + std::vector commitments; + for (auto& instance : instances) { + commitments.emplace_back(instance->verification_key->get_all()[vk_idx]); + } + expected_vk = Commitment::batch_mul(commitments, lagranges); + vk_idx++; + } + + size_t comm_idx = 0; + for (auto& comm : accumulator->witness_commitments.get_all()) { + std::vector commitments; + for (auto& instance : instances) { + commitments.emplace_back(instance->witness_commitments.get_all()[comm_idx]); + } + comm = Commitment::batch_mul(commitments, lagranges); + comm_idx++; + } + } }; } // namespace bb::stdlib::recursion::honk \ No newline at end of file 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 ebe037413566..4d18d9f59d5b 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 @@ -17,27 +17,34 @@ namespace bb::stdlib::recursion::honk { template class ProtoGalaxyRecursiveTests : public testing::Test { public: - using NativeFlavor = typename RecursiveFlavor::NativeFlavor; - using Builder = typename RecursiveFlavor::CircuitBuilder; - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - using ProverInstance = ::bb::ProverInstance_; - using VerifierInstance = ::bb::VerifierInstance_; - using RecursiveVerifierInstance = ::bb::stdlib::recursion::honk::RecursiveVerifierInstance_; - using Curve = bn254; - using Commitment = typename NativeFlavor::Commitment; - using FF = typename NativeFlavor::FF; - using DeciderProver = DeciderProver_; - using VerificationKey = typename NativeFlavor::VerificationKey; + // Define types for the inner circuit, i.e. the circuit whose proof will be recursively verified + using InnerFlavor = typename RecursiveFlavor::NativeFlavor; + using InnerProver = UltraProver_; + using InnerVerifier = UltraVerifier_; + using InnerBuilder = typename InnerFlavor::CircuitBuilder; + using InnerProverInstance = ProverInstance_; + using InnerVerifierInstance = ::bb::VerifierInstance_; + using InnerVerificationKey = typename InnerFlavor::VerificationKey; + using InnerCurve = bn254; + using Commitment = InnerFlavor::Commitment; + using FF = InnerFlavor::FF; + + // Defines types for the outer circuit, i.e. the circuit of the recursive verifier + using OuterBuilder = typename RecursiveFlavor::CircuitBuilder; + using OuterFlavor = std::conditional_t, GoblinUltraFlavor, UltraFlavor>; + using OuterProver = UltraProver_; + using OuterVerifier = UltraVerifier_; + using OuterProverInstance = ProverInstance_; using RecursiveVerifierInstances = ::bb::stdlib::recursion::honk::RecursiveVerifierInstances_; using FoldingRecursiveVerifier = ProtoGalaxyRecursiveVerifier_; using DeciderRecursiveVerifier = DeciderRecursiveVerifier_; - using NativeDeciderVerifier = DeciderVerifier_; - using NativeVerifierInstances = VerifierInstances_; - using NativeFoldingVerifier = ProtoGalaxyVerifier_; - using NativeProverInstances = ProverInstances_; - using NativeFoldingProver = ProtoGalaxyProver_; + using InnerDeciderProver = DeciderProver_; + using InnerDeciderVerifier = DeciderVerifier_; + using InnerVerifierInstances = VerifierInstances_; + using InnerProverInstances = ProverInstances_; + using InnerFoldingVerifier = ProtoGalaxyVerifier_; + using InnerFoldingProver = ProtoGalaxyProver_; static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } /** @@ -50,15 +57,14 @@ template class ProtoGalaxyRecursiveTests : public tes * TODO(https://github.com/AztecProtocol/barretenberg/issues/744): make testing utility with functionality shared * amongst test files */ - static void create_function_circuit(Builder& builder, size_t log_num_gates = 10) + static void create_function_circuit(InnerBuilder& builder, size_t log_num_gates = 10) { - using fr_ct = typename Curve::ScalarField; - using fq_ct = typename Curve::BaseField; - using public_witness_ct = typename Curve::public_witness_ct; - using witness_ct = typename Curve::witness_ct; - using byte_array_ct = typename Curve::byte_array_ct; - using fr = typename Curve::ScalarFieldNative; - using point = typename Curve::AffineElementNative; + using fr_ct = typename InnerCurve::ScalarField; + using fq_ct = typename InnerCurve::BaseField; + using public_witness_ct = typename InnerCurve::public_witness_ct; + using witness_ct = typename InnerCurve::witness_ct; + using byte_array_ct = typename InnerCurve::byte_array_ct; + using fr = typename InnerCurve::ScalarFieldNative; // Create 2^log_n many add gates based on input log num gates const size_t num_gates = 1 << log_num_gates; @@ -85,7 +91,7 @@ template class ProtoGalaxyRecursiveTests : public tes a = (a * b) + b + a; a = a.madd(b, c); } - pedersen_hash::hash({ a, b }); + pedersen_hash::hash({ a, b }); byte_array_ct to_hash(&builder, "nonsense test data"); blake3s(to_hash); @@ -97,31 +103,25 @@ template class ProtoGalaxyRecursiveTests : public tes fq_ct big_b(fr_ct(witness_ct(&builder, bigfield_data_b.to_montgomery_form())), fr_ct(witness_ct(&builder, 0))); big_a* big_b; - - if constexpr (IsGoblinBuilder) { - auto p = point::one() * fr::random_element(); - auto scalar = fr::random_element(); - builder.queue_ecc_mul_accum(p, scalar); - builder.queue_ecc_eq(); - } }; - static std::tuple, std::shared_ptr> fold_and_verify_native() + static std::tuple, std::shared_ptr> + fold_and_verify_native() { - Builder builder1; + InnerBuilder builder1; create_function_circuit(builder1); - Builder builder2; + InnerBuilder builder2; builder2.add_public_variable(FF(1)); create_function_circuit(builder2); - auto prover_instance_1 = std::make_shared(builder1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - auto prover_instance_2 = std::make_shared(builder2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); - NativeFoldingProver folding_prover({ prover_instance_1, prover_instance_2 }); - NativeFoldingVerifier folding_verifier({ verifier_instance_1, verifier_instance_2 }); + auto prover_instance_1 = std::make_shared(builder1); + auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); + auto verifier_instance_1 = std::make_shared(verification_key_1); + auto prover_instance_2 = std::make_shared(builder2); + auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); + auto verifier_instance_2 = std::make_shared(verification_key_2); + InnerFoldingProver folding_prover({ prover_instance_1, prover_instance_2 }); + InnerFoldingVerifier folding_verifier({ verifier_instance_1, verifier_instance_2 }); auto [prover_accumulator, folding_proof] = folding_prover.fold_instances(); auto verifier_accumulator = folding_verifier.verify_folding_proof(folding_proof); @@ -133,7 +133,7 @@ template class ProtoGalaxyRecursiveTests : public tes */ static void test_circuit() { - Builder builder; + InnerBuilder builder; create_function_circuit(builder); @@ -148,9 +148,9 @@ template class ProtoGalaxyRecursiveTests : public tes */ static void test_new_evaluate() { - Builder builder; - using fr_ct = typename bn254::ScalarField; - using fr = typename bn254::ScalarFieldNative; + OuterBuilder builder; + using fr_ct = typename bn254::ScalarField; + using fr = typename bn254::ScalarFieldNative; std::vector coeffs; std::vector coeffs_ct; @@ -175,24 +175,24 @@ template class ProtoGalaxyRecursiveTests : public tes static void test_recursive_folding() { // Create two arbitrary circuits for the first round of folding - Builder builder1; + InnerBuilder builder1; create_function_circuit(builder1); - Builder builder2; + InnerBuilder builder2; builder2.add_public_variable(FF(1)); create_function_circuit(builder2); - auto prover_instance_1 = std::make_shared(builder1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - auto prover_instance_2 = std::make_shared(builder2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); + auto prover_instance_1 = std::make_shared(builder1); + auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); + auto verifier_instance_1 = std::make_shared(verification_key_1); + auto prover_instance_2 = std::make_shared(builder2); + auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); + auto verifier_instance_2 = std::make_shared(verification_key_2); // Generate a folding proof - NativeFoldingProver folding_prover({ prover_instance_1, prover_instance_2 }); + InnerFoldingProver folding_prover({ prover_instance_1, prover_instance_2 }); auto folding_proof = folding_prover.fold_instances(); // Create a recursive folding verifier circuit for the folding proof of the two instances - Builder folding_circuit; + OuterBuilder folding_circuit; auto verifier = FoldingRecursiveVerifier(&folding_circuit, verifier_instance_1, { verifier_instance_2->verification_key }); verifier.verify_folding_proof(folding_proof.folding_data); @@ -201,7 +201,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 - NativeFoldingVerifier native_folding_verifier({ verifier_instance_1, verifier_instance_2 }); + InnerFoldingVerifier native_folding_verifier({ verifier_instance_1, verifier_instance_2 }); native_folding_verifier.verify_folding_proof(folding_proof.folding_data); // Ensure that the underlying native and recursive folding verification algorithms agree by ensuring the @@ -216,11 +216,11 @@ template class ProtoGalaxyRecursiveTests : public tes // Check for a failure flag in the recursive verifier circuit - { - auto instance = std::make_shared(folding_circuit); - Prover prover(instance); - auto verification_key = std::make_shared(instance->proving_key); - Verifier verifier(verification_key); + if constexpr (!IsSimulator) { + auto instance = std::make_shared(folding_circuit); + OuterProver prover(instance); + auto verification_key = std::make_shared(instance->proving_key); + OuterVerifier verifier(verification_key); auto proof = prover.construct_proof(); bool verified = verifier.verify_proof(proof); @@ -238,29 +238,29 @@ template class ProtoGalaxyRecursiveTests : public tes static void test_full_protogalaxy_recursive() { // Create two arbitrary circuits for the first round of folding - Builder builder1; + InnerBuilder builder1; create_function_circuit(builder1); - Builder builder2; + InnerBuilder builder2; builder2.add_public_variable(FF(1)); create_function_circuit(builder2); - auto prover_instance_1 = std::make_shared(builder1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - auto prover_instance_2 = std::make_shared(builder2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); + auto prover_instance_1 = std::make_shared(builder1); + auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); + auto verifier_instance_1 = std::make_shared(verification_key_1); + auto prover_instance_2 = std::make_shared(builder2); + auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); + auto verifier_instance_2 = std::make_shared(verification_key_2); // Generate a folding proof - NativeFoldingProver folding_prover({ prover_instance_1, prover_instance_2 }); + InnerFoldingProver folding_prover({ prover_instance_1, prover_instance_2 }); auto folding_proof = folding_prover.fold_instances(); // Create a recursive folding verifier circuit for the folding proof of the two instances - Builder folding_circuit; + 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 native_verifier_acc = std::make_shared(recursive_verifier_accumulator->get_value()); + auto native_verifier_acc = std::make_shared(recursive_verifier_accumulator->get_value()); info("Folding Recursive Verifier: num gates = ", folding_circuit.num_gates); // Check for a failure flag in the recursive verifier circuit @@ -268,7 +268,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 - NativeFoldingVerifier native_folding_verifier({ verifier_instance_1, verifier_instance_2 }); + InnerFoldingVerifier native_folding_verifier({ verifier_instance_1, verifier_instance_2 }); auto verifier_accumulator = native_folding_verifier.verify_folding_proof(folding_proof.folding_data); // Ensure that the underlying native and recursive folding verification algorithms agree by ensuring the @@ -281,10 +281,10 @@ template class ProtoGalaxyRecursiveTests : public tes << "Recursive Verifier/Verifier manifest discrepency in round " << i; } - DeciderProver decider_prover(folding_proof.accumulator); + InnerDeciderProver decider_prover(folding_proof.accumulator); auto decider_proof = decider_prover.construct_proof(); - Builder decider_circuit; + OuterBuilder decider_circuit; DeciderRecursiveVerifier decider_verifier{ &decider_circuit, native_verifier_acc }; auto pairing_points = decider_verifier.verify_proof(decider_proof); info("Decider Recursive Verifier: num gates = ", decider_circuit.num_gates); @@ -293,18 +293,18 @@ template class ProtoGalaxyRecursiveTests : public tes // Perform native verification then perform the pairing on the outputs of the recursive decider verifier and // check that the result agrees. - NativeDeciderVerifier native_decider_verifier(verifier_accumulator); + InnerDeciderVerifier native_decider_verifier(verifier_accumulator); auto native_result = native_decider_verifier.verify_proof(decider_proof); auto recursive_result = native_decider_verifier.accumulator->verification_key->pcs_verification_key->pairing_check( pairing_points[0].get_value(), pairing_points[1].get_value()); EXPECT_EQ(native_result, recursive_result); - { - auto instance = std::make_shared(decider_circuit); - Prover prover(instance); - auto verification_key = std::make_shared(instance->proving_key); - Verifier verifier(verification_key); + if constexpr (!IsSimulator) { + auto instance = std::make_shared(decider_circuit); + OuterProver prover(instance); + auto verification_key = std::make_shared(instance->proving_key); + OuterVerifier verifier(verification_key); auto proof = prover.construct_proof(); bool verified = verifier.verify_proof(proof); @@ -321,11 +321,11 @@ template class ProtoGalaxyRecursiveTests : public tes verifier_accumulator->target_sum = FF::random_element(); // Create a decider proof for the relaxed instance obtained through folding - DeciderProver decider_prover(prover_accumulator); + InnerDeciderProver decider_prover(prover_accumulator); auto decider_proof = decider_prover.construct_proof(); // Create a decider verifier circuit for recursively verifying the decider proof - Builder decider_circuit; + OuterBuilder decider_circuit; DeciderRecursiveVerifier decider_verifier{ &decider_circuit, verifier_accumulator }; decider_verifier.verify_proof(decider_proof); info("Decider Recursive Verifier: num gates = ", decider_circuit.num_gates); @@ -340,22 +340,22 @@ template class ProtoGalaxyRecursiveTests : public tes auto [prover_accumulator, verifier_accumulator] = fold_and_verify_native(); // Create another circuit to do a second round of folding - Builder builder; + InnerBuilder builder; create_function_circuit(builder); - auto prover_inst = std::make_shared(builder); - auto verification_key = std::make_shared(prover_inst->proving_key); - auto verifier_inst = std::make_shared(verification_key); + auto prover_inst = std::make_shared(builder); + auto verification_key = std::make_shared(prover_inst->proving_key); + auto verifier_inst = std::make_shared(verification_key); prover_accumulator->proving_key.polynomials.w_l[1] = FF::random_element(); // Generate a folding proof with the incorrect polynomials which would result in the prover having the wrong // target sum - NativeFoldingProver folding_prover({ prover_accumulator, prover_inst }); + InnerFoldingProver folding_prover({ prover_accumulator, prover_inst }); auto folding_proof = folding_prover.fold_instances(); // Create a recursive folding verifier circuit for the folding proof of the two instances with the untampered // commitments - Builder folding_circuit; + OuterBuilder folding_circuit; FoldingRecursiveVerifier verifier{ &folding_circuit, verifier_accumulator, { verifier_inst->verification_key } }; @@ -365,7 +365,12 @@ template class ProtoGalaxyRecursiveTests : public tes }; }; -using FlavorTypes = testing::Types>; +using FlavorTypes = testing::Types, + GoblinUltraRecursiveFlavor_, + UltraRecursiveFlavor_, + UltraRecursiveFlavor_, + UltraRecursiveFlavor_, + GoblinUltraRecursiveFlavor_>; TYPED_TEST_SUITE(ProtoGalaxyRecursiveTests, FlavorTypes); TYPED_TEST(ProtoGalaxyRecursiveTests, InnerCircuit) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp index 90233b9dcb35..16a10acdc804 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp @@ -33,7 +33,7 @@ template class RecursiveVerifierTest : public testing // Defines types for the outer circuit, i.e. the circuit of the recursive verifier using OuterBuilder = typename RecursiveFlavor::CircuitBuilder; - using OuterFlavor = std::conditional_t, GoblinUltraFlavor, UltraFlavor>; + using OuterFlavor = std::conditional_t, GoblinUltraFlavor, UltraFlavor>; using OuterProver = UltraProver_; using OuterVerifier = UltraVerifier_; using OuterProverInstance = ProverInstance_; @@ -198,10 +198,6 @@ template class RecursiveVerifierTest : public testing // Check 3: Construct and verify a proof of the recursive verifier circuit if constexpr (!IsSimulator) { - using OuterFlavor = std::conditional_t, GoblinUltraFlavor, UltraFlavor>; - using OuterProver = UltraProver_; - using OuterVerifier = UltraVerifier_; - using OuterProverInstance = ProverInstance_; auto instance = std::make_shared(outer_circuit); OuterProver prover(instance); auto verification_key = std::make_shared(instance->proving_key); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp index 51cdb25c7901..d29426515cf8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp @@ -14,7 +14,7 @@ // designed to have efficient bb::g1 operations, a developer might accidentally write inefficient circuits // using biggroup functions that do not use the OpQueue. We use this concept to prevent compilation of such functions. template -concept IsNotGoblinInefficiencyTrap = !(IsGoblinBuilder && std::same_as); +concept IsNotGoblinInefficiencyTrap = !(IsGoblinUltraBuilder && std::same_as); namespace bb::stdlib { @@ -210,7 +210,7 @@ template class element { // i.e. for the bn254 curve, the template param is `typename = void` // for any other curve, there is no template param template ::value>> - requires(IsNotGoblinBuilder) // TODO(https://github.com/AztecProtocol/barretenberg/issues/707) + requires(IsNotGoblinUltraBuilder) // TODO(https://github.com/AztecProtocol/barretenberg/issues/707) static element bn254_endo_batch_mul(const std::vector& big_points, const std::vector& big_scalars, const std::vector& small_points, @@ -218,7 +218,7 @@ template class element { const size_t max_num_small_bits); template ::value>> - requires(IsNotGoblinBuilder) // TODO(https://github.com/AztecProtocol/barretenberg/issues/707) + requires(IsNotGoblinUltraBuilder) // TODO(https://github.com/AztecProtocol/barretenberg/issues/707) static element bn254_endo_batch_mul_with_generator(const std::vector& big_points, const std::vector& big_scalars, const std::vector& small_points, diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp index b8d8e7a76301..0a5dc15f047a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp @@ -827,7 +827,7 @@ using TestTypes = testing::Types -concept HasGoblinBuilder = IsGoblinBuilder; +concept HasGoblinBuilder = IsGoblinUltraBuilder; TYPED_TEST(stdlib_biggroup, add) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp index 5e03f8a58daf..1e22aa831eef 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp @@ -21,7 +21,7 @@ namespace bb::stdlib { **/ template template - requires(IsNotGoblinBuilder) + requires(IsNotGoblinUltraBuilder) element element::bn254_endo_batch_mul_with_generator( const std::vector& big_points, const std::vector& big_scalars, @@ -216,7 +216,7 @@ element element::bn254_endo_batch_mul_with_generator **/ template template - requires(IsNotGoblinBuilder) + requires(IsNotGoblinUltraBuilder) element element::bn254_endo_batch_mul(const std::vector& big_points, const std::vector& big_scalars, const std::vector& small_points, diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp index e1557f4b5f99..cca0199439d6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp @@ -56,7 +56,7 @@ element& element::operator=(element&& other) template element element::operator+(const element& other) const { - if constexpr (IsGoblinBuilder && std::same_as) { + if constexpr (IsGoblinUltraBuilder && std::same_as) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/707) Optimize // Current gate count: 6398 std::vector points{ *this, other }; @@ -74,7 +74,7 @@ element element::operator+(const element& other) con template element element::operator-(const element& other) const { - if constexpr (IsGoblinBuilder && std::same_as) { + if constexpr (IsGoblinUltraBuilder && std::same_as) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/707) Optimize std::vector points{ *this, other }; std::vector scalars{ 1, -Fr(1) }; @@ -107,10 +107,12 @@ element element::operator-(const element& other) con template std::array, 2> element::add_sub(const element& other) const { - if constexpr (IsGoblinBuilder && std::same_as) { + if constexpr (IsGoblinUltraBuilder && std::same_as) { return { *this + other, *this - other }; } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/971): This will fail when the two elements are the same + // even in the case of a valid circuit other.x.assert_is_not_equal(x); const Fq denominator = other.x - x; @@ -634,7 +636,7 @@ element element::batch_mul(const std::vector && std::same_as) { + if constexpr (IsGoblinUltraBuilder && std::same_as) { return goblin_batch_mul(points, scalars); } else { @@ -715,7 +717,7 @@ element element::operator*(const Fr& scalar) const * **/ - if constexpr (IsGoblinBuilder && std::same_as) { + if constexpr (IsGoblinUltraBuilder && std::same_as) { std::vector points{ *this }; std::vector scalars{ scalar }; return goblin_batch_mul(points, scalars); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp index b16e5c636d85..0df5acd1af52 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp @@ -14,12 +14,11 @@ concept HasPlookup = bb::IsAnyOf concept IsStandardBuilder = bb::IsAnyOf, bb::StandardCircuitBuilder_>; template -concept IsUltraBuilder = bb::IsAnyOf; - +concept IsUltraBuilder = bb::IsAnyOf; template -concept IsGoblinBuilder = bb::IsAnyOf; +concept IsGoblinUltraBuilder = bb::IsAnyOf; template -concept IsNotGoblinBuilder = !IsGoblinBuilder; +concept IsNotGoblinUltraBuilder = !IsGoblinUltraBuilder; template concept IsSimulator = bb::IsAnyOf;