From eb8c280e8a1d4911fa649115332796be4f4e28bd Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Thu, 28 Mar 2024 20:21:01 +0000 Subject: [PATCH 01/14] manually set lagranges and vanishing poly --- .../src/barretenberg/protogalaxy/protogalaxy_prover.cpp | 6 ++++++ .../src/barretenberg/protogalaxy/protogalaxy_prover.hpp | 7 ++++--- .../src/barretenberg/protogalaxy/protogalaxy_verifier.cpp | 2 -- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index a1cb41cef73f..e4d5550e31f8 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -53,6 +53,12 @@ std::shared_ptr ProtoGalaxyProver_ lagranges{ FF(1) - challenge, challenge }; + if (ProverInstances::NUM == 3) { + vanishing_polynomial_at_challenge *= (challenge - FF(2)); + lagranges = { (FF(1) - challenge) * (FF(2) - challenge) / (FF(2)), + challenge * (FF(2) - challenge), + challenge * (FF(1) - challenge) / FF(2) }; + } // TODO(https://github.com/AztecProtocol/barretenberg/issues/881): bad pattern auto next_accumulator = std::make_shared(); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp index ca5233c5eba5..f6ce595d9021 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp @@ -77,8 +77,6 @@ template class ProtoGalaxyProver_ { /** * @brief Prior to folding, we need to finalize the given instances and add all their public data ϕ to the * transcript, labelled by their corresponding instance index for domain separation. - * TODO(https://github.com/AztecProtocol/barretenberg/issues/795):The rounds prior to actual proving/folding are - * common between decider and folding verifier and could be somehow shared so we do not duplicate code so much. */ void prepare_for_folding(); @@ -399,7 +397,10 @@ template class ProtoGalaxyProver_ { auto idx = point - ProverInstances::NUM; auto lagrange_0 = FF(1) - FF(point); auto vanishing_polynomial = FF(point) * (FF(point) - 1); - + if (ProverInstances::NUM == 3) { + lagrange_0 = (FF(1) - FF(point)) * (FF(2) - FF(point)) / (FF(2)); + vanishing_polynomial *= (FF(point) - 2); + } combiner_quotient_evals[idx] = (combiner.value_at(point) - compressed_perturbator * lagrange_0) * vanishing_polynomial.invert(); } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index b47ba04a2923..2016df2e6ba8 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -20,8 +20,6 @@ void ProtoGalaxyVerifier_::receive_and_finalise_instance(cons } } -// TODO(https://github.com/AztecProtocol/barretenberg/issues/795): The rounds prior to actual verifying are common -// between decider and folding verifier and could be somehow shared so we do not duplicate code so much. template void ProtoGalaxyVerifier_::prepare_for_folding(const std::vector& fold_data) { From 4908a07d26a903710023bedd71e930a70533049c Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Fri, 29 Mar 2024 17:21:01 +0000 Subject: [PATCH 02/14] test to fold k=2 --- .../protogalaxy/protogalaxy.test.cpp | 56 +++++++++++++++++++ .../protogalaxy/protogalaxy_prover.cpp | 3 + .../protogalaxy/protogalaxy_verifier.cpp | 3 + 3 files changed, 62 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 453e0d844d75..85808ca29668 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -403,6 +403,57 @@ template class ProtoGalaxyTests : public testing::Test { EXPECT_EQ(prover_accumulator_2->target_sum == verifier_accumulator_2->target_sum, false); decide_and_verify(prover_accumulator_2, verifier_accumulator_2, false); } + + static void test_fold_3_instances() + { + auto builder_1 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_1); + auto prover_instance_1 = std::make_shared(builder_1); + auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); + auto verifier_instance_1 = std::make_shared(verification_key_1); + + auto builder_2 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_2); + auto prover_instance_2 = std::make_shared(builder_2); + auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); + auto verifier_instance_2 = std::make_shared(verification_key_2); + + auto builder_3 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_3); + auto prover_instance_3 = std::make_shared(builder_3); + auto verification_key_3 = std::make_shared(prover_instance_3->proving_key); + auto verifier_instance_3 = std::make_shared(verification_key_3); + + ProtoGalaxyProver_> folding_prover( + { prover_instance_1, prover_instance_2, prover_instance_3 }); + ProtoGalaxyVerifier_> folding_verifier( + { verifier_instance_1, verifier_instance_2, verifier_instance_3 }); + + auto [prover_accumulator, folding_proof] = folding_prover.fold_instances(); + auto verifier_accumulator = folding_verifier.verify_folding_proof(folding_proof); + // auto [prover_accumulator, verifier_accumulator] = + // fold_and_verify({ prover_instance_1, prover_instance_2, prover_instance_3 }, + // { verifier_instance_1, verifier_instance_2, verifier_instance_3 }); + + // check_accumulator_target_sum_manual(prover_accumulator, true); + auto instance_size = prover_accumulator->proving_key->circuit_size; + auto expected_honk_evals = ProtoGalaxyProver_>::compute_full_honk_evaluations( + prover_accumulator->prover_polynomials, + prover_accumulator->alphas, + prover_accumulator->relation_parameters); + // Construct pow(\vec{betas*}) as in the paper + auto expected_pows = PowPolynomial(prover_accumulator->gate_challenges); + expected_pows.compute_values(); + + // Compute the corresponding target sum and create a dummy accumulator + auto expected_target_sum = FF(0); + for (size_t i = 0; i < instance_size; i++) { + expected_target_sum += expected_honk_evals[i] * expected_pows[i]; + } + EXPECT_EQ(prover_accumulator->target_sum == expected_target_sum, true); + + decide_and_verify(prover_accumulator, verifier_accumulator, true); + } }; } // namespace @@ -452,4 +503,9 @@ TYPED_TEST(ProtoGalaxyTests, TamperedCommitment) TYPED_TEST(ProtoGalaxyTests, TamperedAccumulatorPolynomial) { TestFixture::test_tampered_accumulator_polynomial(); +} + +TYPED_TEST(ProtoGalaxyTests, Fold3Instances) +{ + TestFixture::test_fold_3_instances(); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index e4d5550e31f8..d712604960d7 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -209,4 +209,7 @@ FoldingResult ProtoGalaxyProver_>; template class ProtoGalaxyProver_>; + +template class ProtoGalaxyProver_>; +template class ProtoGalaxyProver_>; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index 2016df2e6ba8..d652b185e0d3 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -159,4 +159,7 @@ std::shared_ptr ProtoGalaxyVerifier_>; template class ProtoGalaxyVerifier_>; + +template class ProtoGalaxyVerifier_>; +template class ProtoGalaxyVerifier_>; } // namespace bb \ No newline at end of file From 30dbebe94149db6f60852d2e569c306372434f11 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 1 Apr 2024 20:25:38 +0000 Subject: [PATCH 03/14] got folding k=2 working! --- .../cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp | 4 ++-- .../src/barretenberg/protogalaxy/protogalaxy_prover.cpp | 6 +++--- .../src/barretenberg/protogalaxy/protogalaxy_prover.hpp | 2 +- .../src/barretenberg/protogalaxy/protogalaxy_verifier.cpp | 8 +++++++- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index df05c33fd21e..a70d768690e4 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -435,8 +435,8 @@ template class ProtoGalaxyTests : public testing::Test { // fold_and_verify({ prover_instance_1, prover_instance_2, prover_instance_3 }, // { verifier_instance_1, verifier_instance_2, verifier_instance_3 }); - // check_accumulator_target_sum_manual(prover_accumulator, true); - auto instance_size = prover_accumulator->proving_key->circuit_size; + check_accumulator_target_sum_manual(prover_accumulator, true); + auto instance_size = prover_accumulator->proving_key.circuit_size; auto expected_honk_evals = ProtoGalaxyProver_>::compute_full_honk_evaluations( prover_accumulator->prover_polynomials, prover_accumulator->alphas, diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index 3a0730d5e7e8..3b7dc3d253ea 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -48,12 +48,12 @@ std::shared_ptr ProtoGalaxyProver_ lagranges{ FF(1) - challenge, challenge }; - if (ProverInstances::NUM == 3) { + std::array lagranges{ FF(1) - challenge, challenge }; + if constexpr (ProverInstances::NUM == 3) { vanishing_polynomial_at_challenge *= (challenge - FF(2)); lagranges = { (FF(1) - challenge) * (FF(2) - challenge) / (FF(2)), challenge * (FF(2) - challenge), - challenge * (FF(1) - challenge) / FF(2) }; + challenge * (challenge - FF(1)) / FF(2) }; } // TODO(https://github.com/AztecProtocol/barretenberg/issues/881): bad pattern diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp index a6d262366e74..a0d952653016 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp @@ -397,7 +397,7 @@ template class ProtoGalaxyProver_ { auto idx = point - ProverInstances::NUM; auto lagrange_0 = FF(1) - FF(point); auto vanishing_polynomial = FF(point) * (FF(point) - 1); - if (ProverInstances::NUM == 3) { + if constexpr (ProverInstances::NUM == 3) { lagrange_0 = (FF(1) - FF(point)) * (FF(2) - FF(point)) / (FF(2)); vanishing_polynomial *= (FF(point) - 2); } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index de4a41e52e20..da9e9501208a 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -72,7 +72,13 @@ std::shared_ptr ProtoGalaxyVerifier_{ FF(1) - combiner_challenge, combiner_challenge }; + auto lagranges = std::array{ FF(1) - combiner_challenge, combiner_challenge }; + if constexpr (VerifierInstances::NUM == 3) { + vanishing_polynomial_at_challenge *= (combiner_challenge - FF(2)); + lagranges = { (FF(1) - combiner_challenge) * (FF(2) - combiner_challenge) / (FF(2)), + combiner_challenge * (FF(2) - combiner_challenge), + combiner_challenge * (combiner_challenge - FF(1)) / FF(2) }; + } // TODO(https://github.com/AztecProtocol/barretenberg/issues/881): bad pattern auto next_accumulator = std::make_shared(accumulator->verification_key); From e386a21adb4434babec2c0f8975decd85e1b7200 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 2 Apr 2024 22:19:25 +0000 Subject: [PATCH 04/14] added specialized barycentric extension for length 3 --- .../src/barretenberg/polynomials/univariate.hpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp index 03467a23f7b2..44796b7379fa 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp @@ -284,10 +284,25 @@ template class Univariate if constexpr (LENGTH == 2) { Fr delta = value_at(1) - value_at(0); static_assert(EXTENDED_LENGTH != 0); - for (size_t idx = domain_start; idx < EXTENDED_DOMAIN_END - 1; idx++) { + for (size_t idx = domain_end - 1; idx < EXTENDED_DOMAIN_END - 1; idx++) { result.value_at(idx + 1) = result.value_at(idx) + delta; } return result; + } else if constexpr (LENGTH == 3) { + Fr c = value_at(0); + Fr a = (value_at(2) + c) / Fr(2) - value_at(1); + Fr b = value_at(1) - a - c; + Fr a2 = a + a; + Fr a_mul = a2; + for (size_t i = 0; i < domain_end - 2; i++) { + a_mul += a2; + } + Fr extra = a_mul + a + b; + for (size_t idx = domain_end - 1; idx < EXTENDED_DOMAIN_END - 1; idx++) { + result.value_at(idx + 1) = result.value_at(idx) + extra; + extra += a2; + } + return result; } else { for (size_t k = domain_end; k != EXTENDED_DOMAIN_END; ++k) { result.value_at(k) = 0; From 6c64e89373e695da64a26f19c76ba82a872fae4b Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 2 Apr 2024 22:54:46 +0000 Subject: [PATCH 05/14] added benchmark for folding multiple instances --- .../protogalaxy_bench/protogalaxy.bench.cpp | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp index 581e43a6db87..727d666a95b9 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp @@ -39,8 +39,41 @@ template void fold_one(State& state) noexcept } } +// Fold twos instances into an accumulator. +template void fold_two(State& state) noexcept +{ + using ProverInstance = ProverInstance_; + using Instance = ProverInstance; + using Instances = ProverInstances_; + using ProtoGalaxyProver = ProtoGalaxyProver_; + using Builder = typename Flavor::CircuitBuilder; + + bb::srs::init_crs_factory("../srs_db/ignition"); + + auto log2_num_gates = static_cast(state.range(0)); + + const auto construct_instance = [&]() { + Builder builder; + MockCircuits::construct_arithmetic_circuit(builder, log2_num_gates); + return std::make_shared(builder); + }; + + std::shared_ptr instance_1 = construct_instance(); + std::shared_ptr instance_2 = construct_instance(); + std::shared_ptr instance_3 = construct_instance(); + + ProtoGalaxyProver folding_prover({ instance_1, instance_2, instance_3 }); + + for (auto _ : state) { + auto proof = folding_prover.fold_instances(); + } +} + BENCHMARK(fold_one)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); BENCHMARK(fold_one)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); + +BENCHMARK(fold_two)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); +BENCHMARK(fold_two)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); } // namespace bb BENCHMARK_MAIN(); From f44d46d09fa05f83382f1e6dfc01d73a0c7bf840 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 2 Apr 2024 23:14:16 +0000 Subject: [PATCH 06/14] precompute inverse of 2 --- .../cpp/src/barretenberg/ecc/fields/field_declarations.hpp | 1 + barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp index 87a10938677a..86e23c473fe5 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp @@ -247,6 +247,7 @@ template struct alignas(32) field { BB_INLINE constexpr field pow(const uint256_t& exponent) const noexcept; BB_INLINE constexpr field pow(uint64_t exponent) const noexcept; + static constexpr uint256_t inverse_two = field(2).invert(); static constexpr uint256_t modulus_minus_two = uint256_t(Params::modulus_0 - 2ULL, Params::modulus_1, Params::modulus_2, Params::modulus_3); constexpr field invert() const noexcept; diff --git a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp index 44796b7379fa..3d11f35dbcc5 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp @@ -290,7 +290,7 @@ template class Univariate return result; } else if constexpr (LENGTH == 3) { Fr c = value_at(0); - Fr a = (value_at(2) + c) / Fr(2) - value_at(1); + Fr a = (value_at(2) + c) * Fr::inverse_two - value_at(1); Fr b = value_at(1) - a - c; Fr a2 = a + a; Fr a_mul = a2; From feaf9e2e3d35e003c7e046e3436a856853215d5f Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Wed, 3 Apr 2024 22:54:34 +0000 Subject: [PATCH 07/14] added folding k=3 with custom extend_to --- .../protogalaxy_bench/protogalaxy.bench.cpp | 35 ++++++ .../ecc/fields/field_declarations.hpp | 1 - .../barretenberg/polynomials/univariate.hpp | 47 +++++++- .../protogalaxy/protogalaxy.test.cpp | 108 +++++++++++++++++- .../protogalaxy/protogalaxy_prover.cpp | 25 +++- .../protogalaxy/protogalaxy_prover.hpp | 42 ++++--- .../protogalaxy/protogalaxy_verifier.cpp | 29 ++++- 7 files changed, 252 insertions(+), 35 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp index 727d666a95b9..277340e8592d 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp @@ -69,11 +69,46 @@ template void fold_two(State& state) noexcept } } +// Fold three instances into an accumulator. +template void fold_three(State& state) noexcept +{ + using ProverInstance = ProverInstance_; + using Instance = ProverInstance; + using Instances = ProverInstances_; + using ProtoGalaxyProver = ProtoGalaxyProver_; + using Builder = typename Flavor::CircuitBuilder; + + bb::srs::init_crs_factory("../srs_db/ignition"); + + auto log2_num_gates = static_cast(state.range(0)); + + const auto construct_instance = [&]() { + Builder builder; + MockCircuits::construct_arithmetic_circuit(builder, log2_num_gates); + return std::make_shared(builder); + }; + + std::shared_ptr instance_1 = construct_instance(); + std::shared_ptr instance_2 = construct_instance(); + std::shared_ptr instance_3 = construct_instance(); + std::shared_ptr instance_4 = construct_instance(); + + ProtoGalaxyProver folding_prover({ instance_1, instance_2, instance_3, instance_4 }); + + for (auto _ : state) { + auto proof = folding_prover.fold_instances(); + } +} + BENCHMARK(fold_one)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); BENCHMARK(fold_one)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); BENCHMARK(fold_two)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); BENCHMARK(fold_two)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); + +BENCHMARK(fold_three)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); +BENCHMARK(fold_three)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); + } // namespace bb BENCHMARK_MAIN(); diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp index 86e23c473fe5..87a10938677a 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp @@ -247,7 +247,6 @@ template struct alignas(32) field { BB_INLINE constexpr field pow(const uint256_t& exponent) const noexcept; BB_INLINE constexpr field pow(uint64_t exponent) const noexcept; - static constexpr uint256_t inverse_two = field(2).invert(); static constexpr uint256_t modulus_minus_two = uint256_t(Params::modulus_0 - 2ULL, Params::modulus_1, Params::modulus_2, Params::modulus_3); constexpr field invert() const noexcept; diff --git a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp index 3d11f35dbcc5..4e6cc391cd6d 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp @@ -281,6 +281,7 @@ template class Univariate std::copy(evaluations.begin(), evaluations.end(), result.evaluations.begin()); + static constexpr Fr inverse_two = Fr(2).invert(); if constexpr (LENGTH == 2) { Fr delta = value_at(1) - value_at(0); static_assert(EXTENDED_LENGTH != 0); @@ -289,9 +290,9 @@ template class Univariate } return result; } else if constexpr (LENGTH == 3) { - Fr c = value_at(0); - Fr a = (value_at(2) + c) * Fr::inverse_two - value_at(1); - Fr b = value_at(1) - a - c; + // Based off https://hackmd.io/@aztec-network/SyR45cmOq?type=view + Fr a = (value_at(2) + value_at(0)) * inverse_two - value_at(1); + Fr b = value_at(1) - a - value_at(0); Fr a2 = a + a; Fr a_mul = a2; for (size_t i = 0; i < domain_end - 2; i++) { @@ -303,6 +304,46 @@ template class Univariate extra += a2; } return result; + } else if constexpr (LENGTH == 4) { + static constexpr Fr inverse_six = Fr(6).invert(); + + // These formulas were found by inverting the matrix representation of the coefficients of the 4 evaluations + // 19 adds, 7 subtracts, 3 muls + Fr zero_times_3 = value_at(0) + value_at(0) + value_at(0); + Fr zero_times_6 = zero_times_3 + zero_times_3; + Fr zero_times_12 = zero_times_6 + zero_times_6; + Fr one_times_3 = value_at(1) + value_at(1) + value_at(1); + Fr one_times_6 = one_times_3 + one_times_3; + Fr two_times_3 = value_at(2) + value_at(2) + value_at(2); + Fr three_times_2 = value_at(3) + value_at(3); + Fr three_times_3 = three_times_2 + value_at(3); + + Fr one_minus_two_times_3 = one_times_3 - two_times_3; + Fr one_minus_two_times_6 = one_minus_two_times_3 + one_minus_two_times_3; + Fr one_minus_two_times_12 = one_minus_two_times_6 + one_minus_two_times_6; + Fr a = (one_minus_two_times_3 + value_at(3) - value_at(0)) * inverse_six; // compute a in 1 muls and 4 adds + Fr b = (zero_times_6 - one_minus_two_times_12 - one_times_3 - three_times_3) * inverse_six; + Fr c = (value_at(0) - zero_times_12 + one_minus_two_times_12 + one_times_6 + two_times_3 + three_times_2) * + inverse_six; + + // -1/6, 1/2, -1/2, 1/6 + // 1, -5/2, 2, -1/2 + // -11/6, 3, -3/2, 1/3 + // 1, 0, 0, 0 + // 5 adds + Fr a_plus_b = a + b; + Fr a_plus_b_times_2 = a_plus_b + a_plus_b; + size_t start_idx_sqr = (domain_end - 1) * (domain_end - 1); + size_t idx_sqr_three = start_idx_sqr + start_idx_sqr + start_idx_sqr; + Fr three_a_plus_two_b = a_plus_b_times_2 + a; + Fr linear_term = Fr(domain_end - 1) * three_a_plus_two_b; + for (size_t idx = domain_end - 1; idx < EXTENDED_DOMAIN_END - 1; idx++) { + result.value_at(idx + 1) = result.value_at(idx) + a * Fr(idx_sqr_three) + linear_term + (a_plus_b + c); + size_t sqr_delta = idx + idx + 1; + idx_sqr_three += sqr_delta + sqr_delta + sqr_delta; + linear_term += three_a_plus_two_b; + } + return result; } else { for (size_t k = domain_end; k != EXTENDED_DOMAIN_END; ++k) { result.value_at(k) = 0; diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index a70d768690e4..9721b204bd05 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -404,7 +404,48 @@ template class ProtoGalaxyTests : public testing::Test { decide_and_verify(prover_accumulator_2, verifier_accumulator_2, false); } - static void test_fold_3_instances() + static void test_fold_1_instance() + { + auto builder_1 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_1); + auto prover_instance_1 = std::make_shared(builder_1); + auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); + auto verifier_instance_1 = std::make_shared(verification_key_1); + + auto builder_2 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_2); + auto prover_instance_2 = std::make_shared(builder_2); + auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); + auto verifier_instance_2 = std::make_shared(verification_key_2); + + ProtoGalaxyProver_> folding_prover({ prover_instance_1, prover_instance_2 }); + ProtoGalaxyVerifier_> 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); + + check_accumulator_target_sum_manual(prover_accumulator, true); + auto instance_size = prover_accumulator->proving_key.circuit_size; + auto expected_honk_evals = ProtoGalaxyProver_>::compute_full_honk_evaluations( + prover_accumulator->prover_polynomials, + prover_accumulator->alphas, + prover_accumulator->relation_parameters); + // Construct pow(\vec{betas*}) as in the paper + auto expected_pows = PowPolynomial(prover_accumulator->gate_challenges); + expected_pows.compute_values(); + + // Compute the corresponding target sum and create a dummy accumulator + auto expected_target_sum = FF(0); + for (size_t i = 0; i < instance_size; i++) { + expected_target_sum += expected_honk_evals[i] * expected_pows[i]; + } + EXPECT_EQ(prover_accumulator->target_sum == expected_target_sum, true); + + decide_and_verify(prover_accumulator, verifier_accumulator, true); + } + + static void test_fold_2_instances() { auto builder_1 = typename Flavor::CircuitBuilder(); construct_circuit(builder_1); @@ -431,9 +472,60 @@ template class ProtoGalaxyTests : public testing::Test { auto [prover_accumulator, folding_proof] = folding_prover.fold_instances(); auto verifier_accumulator = folding_verifier.verify_folding_proof(folding_proof); - // auto [prover_accumulator, verifier_accumulator] = - // fold_and_verify({ prover_instance_1, prover_instance_2, prover_instance_3 }, - // { verifier_instance_1, verifier_instance_2, verifier_instance_3 }); + + check_accumulator_target_sum_manual(prover_accumulator, true); + auto instance_size = prover_accumulator->proving_key.circuit_size; + auto expected_honk_evals = ProtoGalaxyProver_>::compute_full_honk_evaluations( + prover_accumulator->prover_polynomials, + prover_accumulator->alphas, + prover_accumulator->relation_parameters); + // Construct pow(\vec{betas*}) as in the paper + auto expected_pows = PowPolynomial(prover_accumulator->gate_challenges); + expected_pows.compute_values(); + + // Compute the corresponding target sum and create a dummy accumulator + auto expected_target_sum = FF(0); + for (size_t i = 0; i < instance_size; i++) { + expected_target_sum += expected_honk_evals[i] * expected_pows[i]; + } + EXPECT_EQ(prover_accumulator->target_sum == expected_target_sum, true); + + decide_and_verify(prover_accumulator, verifier_accumulator, true); + } + + static void test_fold_3_instances() + { + auto builder_1 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_1); + auto prover_instance_1 = std::make_shared(builder_1); + auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); + auto verifier_instance_1 = std::make_shared(verification_key_1); + + auto builder_2 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_2); + auto prover_instance_2 = std::make_shared(builder_2); + auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); + auto verifier_instance_2 = std::make_shared(verification_key_2); + + auto builder_3 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_3); + auto prover_instance_3 = std::make_shared(builder_3); + auto verification_key_3 = std::make_shared(prover_instance_3->proving_key); + auto verifier_instance_3 = std::make_shared(verification_key_3); + + auto builder_4 = typename Flavor::CircuitBuilder(); + construct_circuit(builder_4); + auto prover_instance_4 = std::make_shared(builder_4); + auto verification_key_4 = std::make_shared(prover_instance_4->proving_key); + auto verifier_instance_4 = std::make_shared(verification_key_4); + + ProtoGalaxyProver_> folding_prover( + { prover_instance_1, prover_instance_2, prover_instance_3, prover_instance_4 }); + ProtoGalaxyVerifier_> folding_verifier( + { verifier_instance_1, verifier_instance_2, verifier_instance_3, verifier_instance_4 }); + + auto [prover_accumulator, folding_proof] = folding_prover.fold_instances(); + auto verifier_accumulator = folding_verifier.verify_folding_proof(folding_proof); check_accumulator_target_sum_manual(prover_accumulator, true); auto instance_size = prover_accumulator->proving_key.circuit_size; @@ -505,6 +597,14 @@ TYPED_TEST(ProtoGalaxyTests, TamperedAccumulatorPolynomial) TestFixture::test_tampered_accumulator_polynomial(); } +TYPED_TEST(ProtoGalaxyTests, Fold1Instance) +{ + TestFixture::test_fold_1_instance(); +} +TYPED_TEST(ProtoGalaxyTests, Fold2Instances) +{ + TestFixture::test_fold_2_instances(); +} TYPED_TEST(ProtoGalaxyTests, Fold3Instances) { TestFixture::test_fold_3_instances(); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index 3b7dc3d253ea..c3fa160730fa 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -47,13 +47,24 @@ std::shared_ptr ProtoGalaxyProver_ lagranges{ FF(1) - challenge, challenge }; - if constexpr (ProverInstances::NUM == 3) { - vanishing_polynomial_at_challenge *= (challenge - FF(2)); - lagranges = { (FF(1) - challenge) * (FF(2) - challenge) / (FF(2)), + FF vanishing_polynomial_at_challenge; + std::array lagranges; + constexpr FF inverse_two = FF(2).invert(); + constexpr FF inverse_six = FF(6).invert(); + if constexpr (ProverInstances::NUM == 2) { + vanishing_polynomial_at_challenge = challenge * (challenge - FF(1)); + lagranges = { FF(1) - challenge, challenge }; + } else if constexpr (ProverInstances::NUM == 3) { + vanishing_polynomial_at_challenge = challenge * (challenge - FF(1)) * (challenge - FF(2)); + lagranges = { (FF(1) - challenge) * (FF(2) - challenge) * inverse_two, challenge * (FF(2) - challenge), challenge * (challenge - FF(1)) / FF(2) }; + } else if (ProverInstances::NUM == 4) { + vanishing_polynomial_at_challenge = challenge * (challenge - FF(1)) * (challenge - FF(2)) * (challenge - FF(3)); + lagranges = { (FF(1) - challenge) * (FF(2) - challenge) * (FF(3) - challenge) * inverse_six, + challenge * (FF(2) - challenge) * (FF(3) - challenge) * inverse_two, + challenge * (challenge - FF(1)) * (FF(3) - challenge) * inverse_two, + challenge * (challenge - FF(1)) * (challenge - FF(2)) * inverse_six }; } // TODO(https://github.com/AztecProtocol/barretenberg/issues/881): bad pattern @@ -192,6 +203,7 @@ template void ProtoGalaxyProver_::accum template FoldingResult ProtoGalaxyProver_::fold_instances() { + info("here in fold_instances"); BB_OP_COUNT_TIME_NAME("ProtogalaxyProver::fold_instances"); preparation_round(); perturbator_round(); @@ -206,4 +218,7 @@ template class ProtoGalaxyProver_>; template class ProtoGalaxyProver_>; template class ProtoGalaxyProver_>; + +template class ProtoGalaxyProver_>; +template class ProtoGalaxyProver_>; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp index a0d952653016..5e37ba3a30cd 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp @@ -393,13 +393,21 @@ template class ProtoGalaxyProver_ { // Compute the combiner quotient polynomial as evaluations on points that are not in the vanishing set. // + constexpr FF inverse_two = FF(2).invert(); + constexpr FF inverse_six = FF(6).invert(); for (size_t point = ProverInstances::NUM; point < combiner.size(); point++) { auto idx = point - ProverInstances::NUM; - auto lagrange_0 = FF(1) - FF(point); - auto vanishing_polynomial = FF(point) * (FF(point) - 1); - if constexpr (ProverInstances::NUM == 3) { - lagrange_0 = (FF(1) - FF(point)) * (FF(2) - FF(point)) / (FF(2)); - vanishing_polynomial *= (FF(point) - 2); + FF lagrange_0; + FF vanishing_polynomial; + if constexpr (ProverInstances::NUM == 2) { + lagrange_0 = FF(1) - FF(point); + vanishing_polynomial = FF(point) * (FF(point) - 1); + } else if constexpr (ProverInstances::NUM == 3) { + lagrange_0 = (FF(1) - FF(point)) * (FF(2) - FF(point)) * inverse_two; + vanishing_polynomial = FF(point) * (FF(point) - 1) * (FF(point) - 2); + } else if constexpr (ProverInstances::NUM == 4) { + lagrange_0 = (FF(1) - FF(point)) * (FF(2) - FF(point)) * (FF(3) - FF(point)) * inverse_six; + vanishing_polynomial = FF(point) * (FF(point) - 1) * (FF(point) - 2) * (FF(point) - 3); } combiner_quotient_evals[idx] = (combiner.value_at(point) - compressed_perturbator * lagrange_0) * vanishing_polynomial.invert(); @@ -411,11 +419,11 @@ template class ProtoGalaxyProver_ { } /** - * @brief Combine each relation parameter, in part, from all the instances into univariates, used in the computation - * of combiner. - * @details For a given relation parameter type, extract that parameter from each instance, place the values in a - * univariate (i.e., sum them against an appropriate univariate Lagrange basis) and then extended as needed during - * the constuction of the combiner. + * @brief Combine each relation parameter, in part, from all the instances into univariates, used in the + * computation of combiner. + * @details For a given relation parameter type, extract that parameter from each instance, place the values in + * a univariate (i.e., sum them against an appropriate univariate Lagrange basis) and then extended as needed + * during the constuction of the combiner. */ static void combine_relation_parameters(ProverInstances& instances) { @@ -458,13 +466,15 @@ template class ProtoGalaxyProver_ { * parameters * (\vec{\beta*}, e*) to the verifier and return the complete accumulator * - * @details At this stage, we assume that the instances have the same size and the same number of public parameter.s + * @details At this stage, we assume that the instances have the same size and the same number of public + * parameter.s * @param instances * @param combiner_quotient polynomial K in the paper * @param challenge * @param compressed_perturbator * - * TODO(https://github.com/AztecProtocol/barretenberg/issues/796): optimise the construction of the new accumulator + * TODO(https://github.com/AztecProtocol/barretenberg/issues/796): optimise the construction of the new + * accumulator */ std::shared_ptr compute_next_accumulator( ProverInstances& instances, @@ -473,8 +483,8 @@ template class ProtoGalaxyProver_ { const FF& compressed_perturbator); /** - * @brief Finalise the prover instances that will be folded: complete computation of all the witness polynomials and - * compute commitments. Send commitments to the verifier and retrieve challenges. + * @brief Finalise the prover instances that will be folded: complete computation of all the witness polynomials + * and compute commitments. Send commitments to the verifier and retrieve challenges. * */ void preparation_round(); @@ -486,8 +496,8 @@ template class ProtoGalaxyProver_ { void perturbator_round(); /** - * @brief Compute combiner (G polynomial in the paper) and then its quotient (K polynomial), whose coefficient will - * be sent to the verifier. + * @brief Compute combiner (G polynomial in the paper) and then its quotient (K polynomial), whose coefficient + * will be sent to the verifier. * */ void combiner_quotient_round(); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index da9e9501208a..865be97c1eaf 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -71,13 +71,27 @@ std::shared_ptr ProtoGalaxyVerifier_template get_challenge("combiner_quotient_challenge"); auto combiner_quotient_at_challenge = combiner_quotient.evaluate(combiner_challenge); - auto vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)); - auto lagranges = std::array{ FF(1) - combiner_challenge, combiner_challenge }; - if constexpr (VerifierInstances::NUM == 3) { - vanishing_polynomial_at_challenge *= (combiner_challenge - FF(2)); - lagranges = { (FF(1) - combiner_challenge) * (FF(2) - combiner_challenge) / (FF(2)), + constexpr FF inverse_two = FF(2).invert(); + constexpr FF inverse_six = FF(6).invert(); + FF vanishing_polynomial_at_challenge; + std::array lagranges; + if constexpr (VerifierInstances::NUM == 2) { + vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)); + lagranges = { FF(1) - combiner_challenge, combiner_challenge }; + } else if constexpr (VerifierInstances::NUM == 3) { + vanishing_polynomial_at_challenge = + combiner_challenge * (combiner_challenge - FF(1)) * (combiner_challenge - FF(2)); + lagranges = { (FF(1) - combiner_challenge) * (FF(2) - combiner_challenge) * inverse_two, combiner_challenge * (FF(2) - combiner_challenge), - combiner_challenge * (combiner_challenge - FF(1)) / FF(2) }; + combiner_challenge * (combiner_challenge - FF(1)) * inverse_two }; + } else if (VerifierInstances::NUM == 4) { + vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)) * + (combiner_challenge - FF(2)) * (combiner_challenge - FF(3)); + lagranges = { (FF(1) - combiner_challenge) * (FF(2) - combiner_challenge) * (FF(3) - combiner_challenge) * + inverse_six, + combiner_challenge * (FF(2) - combiner_challenge) * (FF(3) - combiner_challenge) * inverse_two, + combiner_challenge * (combiner_challenge - FF(1)) * (FF(3) - combiner_challenge) * inverse_two, + combiner_challenge * (combiner_challenge - FF(1)) * (combiner_challenge - FF(2)) * inverse_six }; } // TODO(https://github.com/AztecProtocol/barretenberg/issues/881): bad pattern @@ -164,4 +178,7 @@ template class ProtoGalaxyVerifier_>; template class ProtoGalaxyVerifier_>; template class ProtoGalaxyVerifier_>; + +template class ProtoGalaxyVerifier_>; +template class ProtoGalaxyVerifier_>; } // namespace bb \ No newline at end of file From 4ec0955f7d6dbad270f3564c85eaf8741530745a Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Wed, 3 Apr 2024 23:10:38 +0000 Subject: [PATCH 08/14] scripts for analyzing protogalaxy bench --- .../cpp/scripts/analyze_client_ivc_bench.py | 15 ++++- .../cpp/scripts/analyze_protogalaxy_bench.py | 61 +++++++++++++++++++ .../cpp/scripts/benchmark_protogalaxy.sh | 25 ++++++++ .../protogalaxy_bench/protogalaxy.bench.cpp | 4 ++ .../protogalaxy/protogalaxy_prover.cpp | 1 - 5 files changed, 102 insertions(+), 4 deletions(-) create mode 100755 barretenberg/cpp/scripts/analyze_protogalaxy_bench.py create mode 100755 barretenberg/cpp/scripts/benchmark_protogalaxy.sh diff --git a/barretenberg/cpp/scripts/analyze_client_ivc_bench.py b/barretenberg/cpp/scripts/analyze_client_ivc_bench.py index 7f83664a03e6..fecd12e8fb91 100644 --- a/barretenberg/cpp/scripts/analyze_client_ivc_bench.py +++ b/barretenberg/cpp/scripts/analyze_client_ivc_bench.py @@ -31,7 +31,10 @@ print( f"{column['function']:<{max_label_length}}{column['ms']:>8} {column['%']:>8}") for key in to_keep: - time_ms = bench[key]/1e6 + if key not in bench: + time_ms = 0 + else: + time_ms = bench[key]/1e6 print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/sum_of_kept_times_ms:>8.2%}") # Validate that kept times account for most of the total measured time. @@ -45,7 +48,10 @@ print( f"{column['function']:<{max_label_length}}{column['ms']:>8} {column['%']:>7}") for key in ['commit(t)', 'compute_combiner(t)', 'compute_perturbator(t)', 'compute_univariate(t)']: - time_ms = bench[key]/1e6 + if key not in bench: + time_ms = 0 + else: + time_ms = bench[key]/1e6 print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/sum_of_kept_times_ms:>8.2%}") print('\nBreakdown of ProtogalaxyProver::fold_instances:') @@ -57,7 +63,10 @@ ] max_label_length = max(len(label) for label in protogalaxy_round_labels) for key in protogalaxy_round_labels: - time_ms = bench[key]/1e6 + if key not in bench: + time_ms = 0 + else: + time_ms = bench[key]/1e6 total_time_ms = bench["ProtogalaxyProver::fold_instances(t)"]/1e6 print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/total_time_ms:>8.2%}") diff --git a/barretenberg/cpp/scripts/analyze_protogalaxy_bench.py b/barretenberg/cpp/scripts/analyze_protogalaxy_bench.py new file mode 100755 index 000000000000..6852ca31f307 --- /dev/null +++ b/barretenberg/cpp/scripts/analyze_protogalaxy_bench.py @@ -0,0 +1,61 @@ +import json +from pathlib import Path + +PREFIX = Path("build-op-count-time") +PROTOGALAXY_BENCH_JSON = Path("protogalaxy_bench.json") +BENCHMARK = "fold_three/16" + +# Single out an independent set of functions accounting for most of BENCHMARK's real_time +to_keep = [ + "ProtogalaxyProver::fold_instances(t)", +] +with open(PREFIX/PROTOGALAXY_BENCH_JSON, "r") as read_file: + read_result = json.load(read_file) + for _bench in read_result["benchmarks"]: + print(_bench) + if _bench["name"] == BENCHMARK: + bench = _bench +bench_components = dict(filter(lambda x: x[0] in to_keep, bench.items())) + +# For each kept time, get the proportion over all kept times. +sum_of_kept_times_ms = sum(float(time) + for _, time in bench_components.items())/1e6 +max_label_length = max(len(label) for label in to_keep) +column = {"function": "function", "ms": "ms", "%": "% sum"} +print( + f"{column['function']:<{max_label_length}}{column['ms']:>8} {column['%']:>8}") +for key in to_keep: + time_ms = bench[key]/1e6 + print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/sum_of_kept_times_ms:>8.2%}") + +# Validate that kept times account for most of the total measured time. +total_time_ms = bench["real_time"] +totals = '\nTotal time accounted for: {:.0f}ms/{:.0f}ms = {:.2%}' +totals = totals.format( + sum_of_kept_times_ms, total_time_ms, sum_of_kept_times_ms/total_time_ms) +print(totals) + +print("\nMajor contributors:") +print( + f"{column['function']:<{max_label_length}}{column['ms']:>8} {column['%']:>7}") +for key in ['commit(t)', 'compute_combiner(t)', 'compute_perturbator(t)', 'compute_univariate(t)']: + if key not in bench: + time_ms = 0 + else: + time_ms = bench[key]/1e6 + print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/sum_of_kept_times_ms:>8.2%}") + +print('\nBreakdown of ProtogalaxyProver::fold_instances:') +protogalaxy_round_labels = [ + "ProtoGalaxyProver_::preparation_round(t)", + "ProtoGalaxyProver_::perturbator_round(t)", + "ProtoGalaxyProver_::combiner_quotient_round(t)", + "ProtoGalaxyProver_::accumulator_update_round(t)" +] +max_label_length = max(len(label) for label in protogalaxy_round_labels) +for key in protogalaxy_round_labels: + time_ms = bench[key]/1e6 + total_time_ms = bench["ProtogalaxyProver::fold_instances(t)"]/1e6 + print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/total_time_ms:>8.2%}") + + diff --git a/barretenberg/cpp/scripts/benchmark_protogalaxy.sh b/barretenberg/cpp/scripts/benchmark_protogalaxy.sh new file mode 100755 index 000000000000..8eb4d808c3f0 --- /dev/null +++ b/barretenberg/cpp/scripts/benchmark_protogalaxy.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -eu + +TARGET="protogalaxy_bench" +FILTER="/16$" +BUILD_DIR=build-op-count-time + +# Move above script dir. +cd $(dirname $0)/.. + +# Measure the benchmarks with ops time counting +./scripts/benchmark_remote.sh protogalaxy_bench\ + "./protogalaxy_bench --benchmark_filter=$FILTER\ + --benchmark_out=$TARGET.json\ + --benchmark_out_format=json"\ + op-count-time\ + build-op-count-time + +# Retrieve output from benching instance +cd $BUILD_DIR +scp $BB_SSH_KEY $BB_SSH_INSTANCE:$BB_SSH_CPP_PATH/build/$TARGET.json . + +# Analyze the results +cd ../ +python3 ./scripts/analyze_protogalaxy_bench.py diff --git a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp index 277340e8592d..55573d230298 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp @@ -1,5 +1,6 @@ #include +#include "barretenberg/common/op_count_google_bench.hpp" #include "barretenberg/protogalaxy/protogalaxy_prover.hpp" #include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" @@ -35,6 +36,7 @@ template void fold_one(State& state) noexcept ProtoGalaxyProver folding_prover({ instance_1, instance_2 }); for (auto _ : state) { + BB_REPORT_OP_COUNT_IN_BENCH(state); auto proof = folding_prover.fold_instances(); } } @@ -65,6 +67,7 @@ template void fold_two(State& state) noexcept ProtoGalaxyProver folding_prover({ instance_1, instance_2, instance_3 }); for (auto _ : state) { + BB_REPORT_OP_COUNT_IN_BENCH(state); auto proof = folding_prover.fold_instances(); } } @@ -96,6 +99,7 @@ template void fold_three(State& state) noexcept ProtoGalaxyProver folding_prover({ instance_1, instance_2, instance_3, instance_4 }); for (auto _ : state) { + BB_REPORT_OP_COUNT_IN_BENCH(state); auto proof = folding_prover.fold_instances(); } } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index c3fa160730fa..ccf344ec9a05 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -203,7 +203,6 @@ template void ProtoGalaxyProver_::accum template FoldingResult ProtoGalaxyProver_::fold_instances() { - info("here in fold_instances"); BB_OP_COUNT_TIME_NAME("ProtogalaxyProver::fold_instances"); preparation_round(); perturbator_round(); From 0ae260118894e12326e80e604b7f3cf1918c92d5 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Thu, 4 Apr 2024 16:29:54 +0000 Subject: [PATCH 09/14] big optimization to remove muls --- .../src/barretenberg/polynomials/univariate.hpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp index 4e6cc391cd6d..8908f3681e31 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp @@ -335,12 +335,19 @@ template class Univariate Fr a_plus_b_times_2 = a_plus_b + a_plus_b; size_t start_idx_sqr = (domain_end - 1) * (domain_end - 1); size_t idx_sqr_three = start_idx_sqr + start_idx_sqr + start_idx_sqr; + Fr idx_sqr_three_times_a = Fr(idx_sqr_three) * a; + Fr x_a_term = Fr(6 * (domain_end - 1)) * a; + Fr three_a = a + a + a; + Fr six_a = three_a + three_a; + Fr three_a_plus_two_b = a_plus_b_times_2 + a; - Fr linear_term = Fr(domain_end - 1) * three_a_plus_two_b; + Fr linear_term = Fr(domain_end - 1) * three_a_plus_two_b + (a_plus_b + c); for (size_t idx = domain_end - 1; idx < EXTENDED_DOMAIN_END - 1; idx++) { - result.value_at(idx + 1) = result.value_at(idx) + a * Fr(idx_sqr_three) + linear_term + (a_plus_b + c); - size_t sqr_delta = idx + idx + 1; - idx_sqr_three += sqr_delta + sqr_delta + sqr_delta; + result.value_at(idx + 1) = result.value_at(idx) + idx_sqr_three_times_a + linear_term; + + idx_sqr_three_times_a += x_a_term + three_a; + x_a_term += six_a; + linear_term += three_a_plus_two_b; } return result; From 4073295c0727ff5c003a8b882371b6033aa1b8f1 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Thu, 4 Apr 2024 16:30:15 +0000 Subject: [PATCH 10/14] clean up tests and missing constexpr --- .../protogalaxy/protogalaxy.test.cpp | 245 ++++-------------- .../protogalaxy/protogalaxy_prover.cpp | 4 +- 2 files changed, 46 insertions(+), 203 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 9721b204bd05..e2bf001c3186 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -36,6 +36,9 @@ template class ProtoGalaxyTests : public testing::Test { using FoldingProver = ProtoGalaxyProver_; using FoldingVerifier = ProtoGalaxyVerifier_; + using TupleOfInstances = + std::tuple>, std::vector>>; + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } static void construct_circuit(Builder& builder) @@ -56,6 +59,23 @@ template class ProtoGalaxyTests : public testing::Test { } } + // constructs num_insts number of prover and verifier instances + static TupleOfInstances construct_instances(size_t num_insts) + { + TupleOfInstances instances; + for (size_t idx = 0; idx < num_insts; idx++) { + auto builder = typename Flavor::CircuitBuilder(); + construct_circuit(builder); + + auto prover_instance = std::make_shared(builder); + auto verification_key = std::make_shared(prover_instance->proving_key); + auto verifier_instance = std::make_shared(verification_key); + get<0>(instances).emplace_back(prover_instance); + get<1>(instances).emplace_back(verifier_instance); + } + return instances; + } + static ProverPolynomials construct_full_prover_polynomials(auto& input_polynomials) { ProverPolynomials full_polynomials; @@ -299,32 +319,13 @@ template class ProtoGalaxyTests : public testing::Test { */ static void test_full_protogalaxy() { - auto builder_1 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_1); - - auto prover_instance_1 = std::make_shared(builder_1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - - auto builder_2 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_2); - auto prover_instance_2 = std::make_shared(builder_2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); - auto [prover_accumulator, verifier_accumulator] = - fold_and_verify({ prover_instance_1, prover_instance_2 }, { verifier_instance_1, verifier_instance_2 }); - + TupleOfInstances insts = construct_instances(2); + auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(insts), get<1>(insts)); check_accumulator_target_sum_manual(prover_accumulator, true); - auto builder_3 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_3); - auto prover_instance_3 = std::make_shared(builder_3); - auto verification_key_3 = std::make_shared(prover_instance_3->proving_key); - auto verifier_instance_3 = std::make_shared(verification_key_3); - + TupleOfInstances insts_2 = construct_instances(1); // just one set of prover/verifier instances auto [prover_accumulator_2, verifier_accumulator_2] = - fold_and_verify({ prover_accumulator, prover_instance_3 }, { verifier_accumulator, verifier_instance_3 }); - + fold_and_verify({ prover_accumulator, get<0>(insts_2)[0] }, { verifier_accumulator, get<1>(insts_2)[0] }); check_accumulator_target_sum_manual(prover_accumulator_2, true); decide_and_verify(prover_accumulator_2, verifier_accumulator_2, true); @@ -336,32 +337,16 @@ template class ProtoGalaxyTests : public testing::Test { */ static void test_tampered_commitment() { - auto builder_1 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_1); - - auto prover_instance_1 = std::make_shared(builder_1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - - auto builder_2 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_2); - auto prover_instance_2 = std::make_shared(builder_2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); - auto [prover_accumulator, verifier_accumulator] = - fold_and_verify({ prover_instance_1, prover_instance_2 }, { verifier_instance_1, verifier_instance_2 }); + TupleOfInstances insts = construct_instances(2); + auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(insts), get<1>(insts)); check_accumulator_target_sum_manual(prover_accumulator, true); + // Tamper with a commitment verifier_accumulator->witness_commitments.w_l = Projective(Affine::random_element()); - auto builder_3 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_3); - auto prover_instance_3 = std::make_shared(builder_3); - auto verification_key_3 = std::make_shared(prover_instance_3->proving_key); - auto verifier_instance_3 = std::make_shared(verification_key_3); + TupleOfInstances insts_2 = construct_instances(1); // just one set of prover/verifier instances auto [prover_accumulator_2, verifier_accumulator_2] = - fold_and_verify({ prover_accumulator, prover_instance_3 }, { verifier_accumulator, verifier_instance_3 }); - + fold_and_verify({ prover_accumulator, get<0>(insts_2)[0] }, { verifier_accumulator, get<1>(insts_2)[0] }); check_accumulator_target_sum_manual(prover_accumulator_2, true); decide_and_verify(prover_accumulator_2, verifier_accumulator_2, false); @@ -374,175 +359,33 @@ template class ProtoGalaxyTests : public testing::Test { */ static void test_tampered_accumulator_polynomial() { - auto builder_1 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_1); - - auto prover_instance_1 = std::make_shared(builder_1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - - auto builder_2 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_2); - auto prover_instance_2 = std::make_shared(builder_2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); - auto [prover_accumulator, verifier_accumulator] = - fold_and_verify({ prover_instance_1, prover_instance_2 }, { verifier_instance_1, verifier_instance_2 }); + TupleOfInstances insts = construct_instances(2); + auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(insts), get<1>(insts)); check_accumulator_target_sum_manual(prover_accumulator, true); - auto builder_3 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_3); - auto prover_instance_3 = std::make_shared(builder_3); - auto verification_key_3 = std::make_shared(prover_instance_3->proving_key); - auto verifier_instance_3 = std::make_shared(verification_key_3); - + // Tamper with an accumulator polynomial prover_accumulator->prover_polynomials.w_l[1] = FF::random_element(); + check_accumulator_target_sum_manual(prover_accumulator, false); + + TupleOfInstances insts_2 = construct_instances(1); // just one set of prover/verifier instances auto [prover_accumulator_2, verifier_accumulator_2] = - fold_and_verify({ prover_accumulator, prover_instance_3 }, { verifier_accumulator, verifier_instance_3 }); + fold_and_verify({ prover_accumulator, get<0>(insts_2)[0] }, { verifier_accumulator, get<1>(insts_2)[0] }); EXPECT_EQ(prover_accumulator_2->target_sum == verifier_accumulator_2->target_sum, false); decide_and_verify(prover_accumulator_2, verifier_accumulator_2, false); } - static void test_fold_1_instance() + template static void test_fold_k_instances() { - auto builder_1 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_1); - auto prover_instance_1 = std::make_shared(builder_1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - - auto builder_2 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_2); - auto prover_instance_2 = std::make_shared(builder_2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); - - ProtoGalaxyProver_> folding_prover({ prover_instance_1, prover_instance_2 }); - ProtoGalaxyVerifier_> folding_verifier( - { verifier_instance_1, verifier_instance_2 }); + constexpr size_t total_insts = k + 1; + TupleOfInstances insts = construct_instances(total_insts); - auto [prover_accumulator, folding_proof] = folding_prover.fold_instances(); - auto verifier_accumulator = folding_verifier.verify_folding_proof(folding_proof); - - check_accumulator_target_sum_manual(prover_accumulator, true); - auto instance_size = prover_accumulator->proving_key.circuit_size; - auto expected_honk_evals = ProtoGalaxyProver_>::compute_full_honk_evaluations( - prover_accumulator->prover_polynomials, - prover_accumulator->alphas, - prover_accumulator->relation_parameters); - // Construct pow(\vec{betas*}) as in the paper - auto expected_pows = PowPolynomial(prover_accumulator->gate_challenges); - expected_pows.compute_values(); - - // Compute the corresponding target sum and create a dummy accumulator - auto expected_target_sum = FF(0); - for (size_t i = 0; i < instance_size; i++) { - expected_target_sum += expected_honk_evals[i] * expected_pows[i]; - } - EXPECT_EQ(prover_accumulator->target_sum == expected_target_sum, true); - - decide_and_verify(prover_accumulator, verifier_accumulator, true); - } - - static void test_fold_2_instances() - { - auto builder_1 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_1); - auto prover_instance_1 = std::make_shared(builder_1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - - auto builder_2 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_2); - auto prover_instance_2 = std::make_shared(builder_2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); - - auto builder_3 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_3); - auto prover_instance_3 = std::make_shared(builder_3); - auto verification_key_3 = std::make_shared(prover_instance_3->proving_key); - auto verifier_instance_3 = std::make_shared(verification_key_3); - - ProtoGalaxyProver_> folding_prover( - { prover_instance_1, prover_instance_2, prover_instance_3 }); - ProtoGalaxyVerifier_> folding_verifier( - { verifier_instance_1, verifier_instance_2, verifier_instance_3 }); - - auto [prover_accumulator, folding_proof] = folding_prover.fold_instances(); - auto verifier_accumulator = folding_verifier.verify_folding_proof(folding_proof); - - check_accumulator_target_sum_manual(prover_accumulator, true); - auto instance_size = prover_accumulator->proving_key.circuit_size; - auto expected_honk_evals = ProtoGalaxyProver_>::compute_full_honk_evaluations( - prover_accumulator->prover_polynomials, - prover_accumulator->alphas, - prover_accumulator->relation_parameters); - // Construct pow(\vec{betas*}) as in the paper - auto expected_pows = PowPolynomial(prover_accumulator->gate_challenges); - expected_pows.compute_values(); - - // Compute the corresponding target sum and create a dummy accumulator - auto expected_target_sum = FF(0); - for (size_t i = 0; i < instance_size; i++) { - expected_target_sum += expected_honk_evals[i] * expected_pows[i]; - } - EXPECT_EQ(prover_accumulator->target_sum == expected_target_sum, true); - - decide_and_verify(prover_accumulator, verifier_accumulator, true); - } - - static void test_fold_3_instances() - { - auto builder_1 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_1); - auto prover_instance_1 = std::make_shared(builder_1); - auto verification_key_1 = std::make_shared(prover_instance_1->proving_key); - auto verifier_instance_1 = std::make_shared(verification_key_1); - - auto builder_2 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_2); - auto prover_instance_2 = std::make_shared(builder_2); - auto verification_key_2 = std::make_shared(prover_instance_2->proving_key); - auto verifier_instance_2 = std::make_shared(verification_key_2); - - auto builder_3 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_3); - auto prover_instance_3 = std::make_shared(builder_3); - auto verification_key_3 = std::make_shared(prover_instance_3->proving_key); - auto verifier_instance_3 = std::make_shared(verification_key_3); - - auto builder_4 = typename Flavor::CircuitBuilder(); - construct_circuit(builder_4); - auto prover_instance_4 = std::make_shared(builder_4); - auto verification_key_4 = std::make_shared(prover_instance_4->proving_key); - auto verifier_instance_4 = std::make_shared(verification_key_4); - - ProtoGalaxyProver_> folding_prover( - { prover_instance_1, prover_instance_2, prover_instance_3, prover_instance_4 }); - ProtoGalaxyVerifier_> folding_verifier( - { verifier_instance_1, verifier_instance_2, verifier_instance_3, verifier_instance_4 }); + ProtoGalaxyProver_> folding_prover(get<0>(insts)); + ProtoGalaxyVerifier_> folding_verifier(get<1>(insts)); auto [prover_accumulator, folding_proof] = folding_prover.fold_instances(); auto verifier_accumulator = folding_verifier.verify_folding_proof(folding_proof); - check_accumulator_target_sum_manual(prover_accumulator, true); - auto instance_size = prover_accumulator->proving_key.circuit_size; - auto expected_honk_evals = ProtoGalaxyProver_>::compute_full_honk_evaluations( - prover_accumulator->prover_polynomials, - prover_accumulator->alphas, - prover_accumulator->relation_parameters); - // Construct pow(\vec{betas*}) as in the paper - auto expected_pows = PowPolynomial(prover_accumulator->gate_challenges); - expected_pows.compute_values(); - - // Compute the corresponding target sum and create a dummy accumulator - auto expected_target_sum = FF(0); - for (size_t i = 0; i < instance_size; i++) { - expected_target_sum += expected_honk_evals[i] * expected_pows[i]; - } - EXPECT_EQ(prover_accumulator->target_sum == expected_target_sum, true); decide_and_verify(prover_accumulator, verifier_accumulator, true); } @@ -599,13 +442,13 @@ TYPED_TEST(ProtoGalaxyTests, TamperedAccumulatorPolynomial) TYPED_TEST(ProtoGalaxyTests, Fold1Instance) { - TestFixture::test_fold_1_instance(); + TestFixture::template test_fold_k_instances<1>(); } TYPED_TEST(ProtoGalaxyTests, Fold2Instances) { - TestFixture::test_fold_2_instances(); + TestFixture::template test_fold_k_instances<2>(); } TYPED_TEST(ProtoGalaxyTests, Fold3Instances) { - TestFixture::test_fold_3_instances(); + TestFixture::template test_fold_k_instances<3>(); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index ccf344ec9a05..e14cb5e2d5e9 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -50,7 +50,6 @@ std::shared_ptr ProtoGalaxyProver_ lagranges; constexpr FF inverse_two = FF(2).invert(); - constexpr FF inverse_six = FF(6).invert(); if constexpr (ProverInstances::NUM == 2) { vanishing_polynomial_at_challenge = challenge * (challenge - FF(1)); lagranges = { FF(1) - challenge, challenge }; @@ -59,7 +58,8 @@ std::shared_ptr ProtoGalaxyProver_ Date: Thu, 4 Apr 2024 16:34:34 +0000 Subject: [PATCH 11/14] added missing constexpr in verifier --- .../cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index 865be97c1eaf..0122a9455161 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -72,7 +72,6 @@ std::shared_ptr ProtoGalaxyVerifier_ lagranges; if constexpr (VerifierInstances::NUM == 2) { @@ -84,7 +83,8 @@ std::shared_ptr ProtoGalaxyVerifier_ Date: Thu, 4 Apr 2024 16:38:06 +0000 Subject: [PATCH 12/14] clean up of bench --- .../cpp/scripts/analyze_protogalaxy_bench.py | 2 +- .../protogalaxy_bench/protogalaxy.bench.cpp | 86 +++---------------- 2 files changed, 13 insertions(+), 75 deletions(-) diff --git a/barretenberg/cpp/scripts/analyze_protogalaxy_bench.py b/barretenberg/cpp/scripts/analyze_protogalaxy_bench.py index 6852ca31f307..9d9cf756c47c 100755 --- a/barretenberg/cpp/scripts/analyze_protogalaxy_bench.py +++ b/barretenberg/cpp/scripts/analyze_protogalaxy_bench.py @@ -3,7 +3,7 @@ PREFIX = Path("build-op-count-time") PROTOGALAXY_BENCH_JSON = Path("protogalaxy_bench.json") -BENCHMARK = "fold_three/16" +BENCHMARK = "fold_k/16" # Single out an independent set of functions accounting for most of BENCHMARK's real_time to_keep = [ diff --git a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp index 55573d230298..cc97192a1ea2 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp @@ -12,11 +12,11 @@ using namespace benchmark; namespace bb { // Fold one instance into an accumulator. -template void fold_one(State& state) noexcept +template void fold_k(State& state) noexcept { using ProverInstance = ProverInstance_; using Instance = ProverInstance; - using Instances = ProverInstances_; + using Instances = ProverInstances_; using ProtoGalaxyProver = ProtoGalaxyProver_; using Builder = typename Flavor::CircuitBuilder; @@ -29,74 +29,12 @@ template void fold_one(State& state) noexcept MockCircuits::construct_arithmetic_circuit(builder, log2_num_gates); return std::make_shared(builder); }; - - std::shared_ptr instance_1 = construct_instance(); - std::shared_ptr instance_2 = construct_instance(); - - ProtoGalaxyProver folding_prover({ instance_1, instance_2 }); - - for (auto _ : state) { - BB_REPORT_OP_COUNT_IN_BENCH(state); - auto proof = folding_prover.fold_instances(); - } -} - -// Fold twos instances into an accumulator. -template void fold_two(State& state) noexcept -{ - using ProverInstance = ProverInstance_; - using Instance = ProverInstance; - using Instances = ProverInstances_; - using ProtoGalaxyProver = ProtoGalaxyProver_; - using Builder = typename Flavor::CircuitBuilder; - - bb::srs::init_crs_factory("../srs_db/ignition"); - - auto log2_num_gates = static_cast(state.range(0)); - - const auto construct_instance = [&]() { - Builder builder; - MockCircuits::construct_arithmetic_circuit(builder, log2_num_gates); - return std::make_shared(builder); - }; - - std::shared_ptr instance_1 = construct_instance(); - std::shared_ptr instance_2 = construct_instance(); - std::shared_ptr instance_3 = construct_instance(); - - ProtoGalaxyProver folding_prover({ instance_1, instance_2, instance_3 }); - - for (auto _ : state) { - BB_REPORT_OP_COUNT_IN_BENCH(state); - auto proof = folding_prover.fold_instances(); + std::vector> instances; + for (size_t i = 0; i < k + 1; ++i) { + instances.emplace_back(construct_instance()); } -} - -// Fold three instances into an accumulator. -template void fold_three(State& state) noexcept -{ - using ProverInstance = ProverInstance_; - using Instance = ProverInstance; - using Instances = ProverInstances_; - using ProtoGalaxyProver = ProtoGalaxyProver_; - using Builder = typename Flavor::CircuitBuilder; - - bb::srs::init_crs_factory("../srs_db/ignition"); - - auto log2_num_gates = static_cast(state.range(0)); - - const auto construct_instance = [&]() { - Builder builder; - MockCircuits::construct_arithmetic_circuit(builder, log2_num_gates); - return std::make_shared(builder); - }; - - std::shared_ptr instance_1 = construct_instance(); - std::shared_ptr instance_2 = construct_instance(); - std::shared_ptr instance_3 = construct_instance(); - std::shared_ptr instance_4 = construct_instance(); - ProtoGalaxyProver folding_prover({ instance_1, instance_2, instance_3, instance_4 }); + ProtoGalaxyProver folding_prover(instances); for (auto _ : state) { BB_REPORT_OP_COUNT_IN_BENCH(state); @@ -104,14 +42,14 @@ template void fold_three(State& state) noexcept } } -BENCHMARK(fold_one)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); -BENCHMARK(fold_one)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); +BENCHMARK(fold_k)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); +BENCHMARK(fold_k)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); -BENCHMARK(fold_two)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); -BENCHMARK(fold_two)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); +BENCHMARK(fold_k)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); +BENCHMARK(fold_k)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); -BENCHMARK(fold_three)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); -BENCHMARK(fold_three)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); +BENCHMARK(fold_k)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); +BENCHMARK(fold_k)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond); } // namespace bb From 1fd33b4219b795d5f7d497217ca6c9a5a5020f42 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Fri, 5 Apr 2024 20:23:10 +0000 Subject: [PATCH 13/14] added univariate extend_to comment --- .../barretenberg/polynomials/univariate.hpp | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp index 8908f3681e31..aedc13537875 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp @@ -291,6 +291,7 @@ template class Univariate return result; } else if constexpr (LENGTH == 3) { // Based off https://hackmd.io/@aztec-network/SyR45cmOq?type=view + // The technique used here is the same as the length == 3 case below. Fr a = (value_at(2) + value_at(0)) * inverse_two - value_at(1); Fr b = value_at(1) - a - value_at(0); Fr a2 = a + a; @@ -305,10 +306,29 @@ template class Univariate } return result; } else if constexpr (LENGTH == 4) { - static constexpr Fr inverse_six = Fr(6).invert(); - - // These formulas were found by inverting the matrix representation of the coefficients of the 4 evaluations - // 19 adds, 7 subtracts, 3 muls + static constexpr Fr inverse_six = Fr(6).invert(); // computed at compile time for efficiency + + // To compute a barycentric extension, we can compute the coefficients of the univariate. + // We have the evaluation of the polynomial at the domain (which is assumed to be 0, 1, 2, 3). + // Therefore, we have the 4 linear equations from plugging into f(x) = ax^3 + bx^2 + cx + d: + // a*0 + b*0 + c*0 + d = f(0) + // a*1 + b*1 + c*1 + d = f(1) + // a*2^3 + b*2^2 + c*2 + d = f(2) + // a*3^3 + b*3^2 + c*3 + d = f(3) + // These equations can be rewritten as a matrix equation M * [a, b, c, d] = [f(0), f(1), f(2), f(3)], where + // M is: + // 0, 0, 0, 1 + // 1, 1, 1, 1 + // 2^3, 2^2, 2, 1 + // 3^3, 3^2, 3, 1 + // We can invert this matrix in order to compute a, b, c, d: + // -1/6, 1/2, -1/2, 1/6 + // 1, -5/2, 2, -1/2 + // -11/6, 3, -3/2, 1/3 + // 1, 0, 0, 0 + // To compute these values, we can multiply everything by 6 and multiply by inverse_six at the end for each + // coefficient The resulting computation here does 18 field adds, 6 subtracts, 3 muls to compute a, b, c, + // and d. Fr zero_times_3 = value_at(0) + value_at(0) + value_at(0); Fr zero_times_6 = zero_times_3 + zero_times_3; Fr zero_times_12 = zero_times_6 + zero_times_6; @@ -326,11 +346,8 @@ template class Univariate Fr c = (value_at(0) - zero_times_12 + one_minus_two_times_12 + one_times_6 + two_times_3 + three_times_2) * inverse_six; - // -1/6, 1/2, -1/2, 1/6 - // 1, -5/2, 2, -1/2 - // -11/6, 3, -3/2, 1/3 - // 1, 0, 0, 0 - // 5 adds + // Then, outside of the a, b, c, d computation, we need to do some extra precomputation + // This work is 3 field muls, 8 adds Fr a_plus_b = a + b; Fr a_plus_b_times_2 = a_plus_b + a_plus_b; size_t start_idx_sqr = (domain_end - 1) * (domain_end - 1); @@ -342,6 +359,7 @@ template class Univariate Fr three_a_plus_two_b = a_plus_b_times_2 + a; Fr linear_term = Fr(domain_end - 1) * three_a_plus_two_b + (a_plus_b + c); + // For each new evaluation, we do only 6 field additions and 0 muls. for (size_t idx = domain_end - 1; idx < EXTENDED_DOMAIN_END - 1; idx++) { result.value_at(idx + 1) = result.value_at(idx) + idx_sqr_three_times_a + linear_term; From ba8d500c174ca0ee23a22ff308dd497f6a4e7e1c Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 8 Apr 2024 20:15:42 +0000 Subject: [PATCH 14/14] added asserts and left TODO for parallelization --- .../benchmark/protogalaxy_bench/protogalaxy.bench.cpp | 1 + .../protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp | 2 ++ .../cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp | 1 + .../cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp | 1 + .../cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp | 2 ++ .../cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp | 1 + 6 files changed, 8 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp index cc97192a1ea2..6a0877c23b18 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp @@ -30,6 +30,7 @@ template void fold_k(State& state) noexcept return std::make_shared(builder); }; std::vector> instances; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/938): Parallelize this loop for (size_t i = 0; i < k + 1; ++i) { instances.emplace_back(construct_instance()); } diff --git a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp index c8b5714e4e69..70ce12e3aabc 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp @@ -26,6 +26,8 @@ void _bench_round(::benchmark::State& state, void (*F)(ProtoGalaxyProver_(builder); }; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/938): Parallelize this loop, also extend to more than + // k=1 std::shared_ptr prover_instance_1 = construct_instance(); std::shared_ptr prover_instance_2 = construct_instance(); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index e2bf001c3186..bf72f4ca5eba 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -63,6 +63,7 @@ template class ProtoGalaxyTests : public testing::Test { static TupleOfInstances construct_instances(size_t num_insts) { TupleOfInstances instances; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/938): Parallelize this loop for (size_t idx = 0; idx < num_insts; idx++) { auto builder = typename Flavor::CircuitBuilder(); construct_circuit(builder); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index e14cb5e2d5e9..ccafde8cc61e 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -66,6 +66,7 @@ std::shared_ptr ProtoGalaxyProver_ class ProtoGalaxyProver_ { lagrange_0 = (FF(1) - FF(point)) * (FF(2) - FF(point)) * (FF(3) - FF(point)) * inverse_six; vanishing_polynomial = FF(point) * (FF(point) - 1) * (FF(point) - 2) * (FF(point) - 3); } + static_assert(ProverInstances::NUM < 5); + combiner_quotient_evals[idx] = (combiner.value_at(point) - compressed_perturbator * lagrange_0) * vanishing_polynomial.invert(); } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index 0122a9455161..f086c1d5b290 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -93,6 +93,7 @@ std::shared_ptr ProtoGalaxyVerifier_(accumulator->verification_key);