diff --git a/barretenberg/cpp/src/barretenberg/common/parallel_for_mutex_pool.cpp b/barretenberg/cpp/src/barretenberg/common/parallel_for_mutex_pool.cpp index 16b922b99c8b..6f8a0b6ea5d9 100644 --- a/barretenberg/cpp/src/barretenberg/common/parallel_for_mutex_pool.cpp +++ b/barretenberg/cpp/src/barretenberg/common/parallel_for_mutex_pool.cpp @@ -1,3 +1,4 @@ +#include "barretenberg/common/throw_or_abort.hpp" #ifndef NO_MULTITHREADING #include "log.hpp" #include "thread.hpp" @@ -124,10 +125,18 @@ namespace bb { void parallel_for_mutex_pool(size_t num_iterations, const std::function& func) { static ThreadPool pool(get_num_cpus() - 1); - + // Note that if this is used safely, we don't need the std::atomic_bool (can use bool), but if we are catching the + // mess up case of nesting parallel_for this should be atomic + static std::atomic_bool nested = false; + // Check if we are already in a nested parallel_for_mutex_pool call + bool expected = false; + if (!nested.compare_exchange_strong(expected, true)) { + throw_or_abort("Error: Nested parallel_for_mutex_pool calls are not allowed."); + } // info("starting job with iterations: ", num_iterations); pool.start_tasks(num_iterations, func); // info("done"); + nested = false; } } // namespace bb #endif \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp index 4c47ac5086b2..6664a4d5ab03 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp @@ -327,53 +327,56 @@ TEST(Protogalaxy, CombinerOptimizationConsistency) run_test(false); }; -TEST(Protogalaxy, CombinerOn4Instances) -{ - constexpr size_t NUM_INSTANCES = 4; - using ProverInstance = ProverInstance_; - using ProverInstances = ProverInstances_; - using ProtoGalaxyProver = ProtoGalaxyProver_; - - const auto zero_all_selectors = [](auto& polys) { - std::fill(polys.q_arith.begin(), polys.q_arith.end(), 0); - std::fill(polys.q_delta_range.begin(), polys.q_delta_range.end(), 0); - std::fill(polys.q_elliptic.begin(), polys.q_elliptic.end(), 0); - std::fill(polys.q_aux.begin(), polys.q_aux.end(), 0); - std::fill(polys.q_lookup.begin(), polys.q_lookup.end(), 0); - std::fill(polys.q_4.begin(), polys.q_4.end(), 0); - std::fill(polys.w_4.begin(), polys.w_4.end(), 0); - std::fill(polys.w_4_shift.begin(), polys.w_4_shift.end(), 0); - }; - - auto run_test = [&]() { - std::vector> instance_data(NUM_INSTANCES); - ProtoGalaxyProver prover; - - for (size_t idx = 0; idx < NUM_INSTANCES; idx++) { - auto instance = std::make_shared(); - auto prover_polynomials = get_zero_prover_polynomials( - /*log_circuit_size=*/1); - instance->proving_key.polynomials = std::move(prover_polynomials); - instance->proving_key.circuit_size = 2; - instance_data[idx] = instance; - } - - ProverInstances instances{ instance_data }; - instances.alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only - - zero_all_selectors(instances[0]->proving_key.polynomials); - zero_all_selectors(instances[1]->proving_key.polynomials); - zero_all_selectors(instances[2]->proving_key.polynomials); - zero_all_selectors(instances[3]->proving_key.polynomials); - - auto pow_polynomial = PowPolynomial(std::vector{ 2 }); - auto result = prover.compute_combiner(instances, pow_polynomial); - auto optimised_result = prover.compute_combiner(instances, pow_polynomial); - std::array zeroes; - std::fill(zeroes.begin(), zeroes.end(), 0); - auto expected_result = Univariate(zeroes); - EXPECT_EQ(result, expected_result); - EXPECT_EQ(optimised_result, expected_result); - }; - run_test(); -}; +// Tests a combiner on 4 instances, note currently we don't plan +// to fold with num instances > 2, this would require an additional explicit instantiation in +// protogalaxy_prover_ultra.cpp. Currently, we rather save the compile time. +// TEST(Protogalaxy, CombinerOn4Instances) +// { +// constexpr size_t NUM_INSTANCES = 4; +// using ProverInstance = ProverInstance_; +// using ProverInstances = ProverInstances_; +// using ProtoGalaxyProver = ProtoGalaxyProver_; + +// const auto zero_all_selectors = [](auto& polys) { +// std::fill(polys.q_arith.begin(), polys.q_arith.end(), 0); +// std::fill(polys.q_delta_range.begin(), polys.q_delta_range.end(), 0); +// std::fill(polys.q_elliptic.begin(), polys.q_elliptic.end(), 0); +// std::fill(polys.q_aux.begin(), polys.q_aux.end(), 0); +// std::fill(polys.q_lookup.begin(), polys.q_lookup.end(), 0); +// std::fill(polys.q_4.begin(), polys.q_4.end(), 0); +// std::fill(polys.w_4.begin(), polys.w_4.end(), 0); +// std::fill(polys.w_4_shift.begin(), polys.w_4_shift.end(), 0); +// }; + +// auto run_test = [&]() { +// std::vector> instance_data(NUM_INSTANCES); +// ProtoGalaxyProver prover; + +// for (size_t idx = 0; idx < NUM_INSTANCES; idx++) { +// auto instance = std::make_shared(); +// auto prover_polynomials = get_zero_prover_polynomials( +// /*log_circuit_size=*/1); +// instance->proving_key.polynomials = std::move(prover_polynomials); +// instance->proving_key.circuit_size = 2; +// instance_data[idx] = instance; +// } + +// ProverInstances instances{ instance_data }; +// instances.alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only + +// zero_all_selectors(instances[0]->proving_key.polynomials); +// zero_all_selectors(instances[1]->proving_key.polynomials); +// zero_all_selectors(instances[2]->proving_key.polynomials); +// zero_all_selectors(instances[3]->proving_key.polynomials); + +// auto pow_polynomial = PowPolynomial(std::vector{ 2 }); +// auto result = prover.compute_combiner(instances, pow_polynomial); +// auto optimised_result = prover.compute_combiner(instances, pow_polynomial); +// std::array zeroes; +// std::fill(zeroes.begin(), zeroes.end(), 0); +// auto expected_result = Univariate(zeroes); +// EXPECT_EQ(result, expected_result); +// EXPECT_EQ(optimised_result, expected_result); +// }; +// run_test(); +// }; diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp index e45c5448b696..537e044eb65f 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp @@ -123,18 +123,9 @@ template class ProtoGalaxyProver_ { return pows; } - static std::vector update_gate_challenges(const FF perturbator_challenge, + static std::vector update_gate_challenges(FF perturbator_challenge, const std::vector& gate_challenges, - const std::vector& round_challenges) - { - auto log_instance_size = gate_challenges.size(); - std::vector next_gate_challenges(log_instance_size); - - for (size_t idx = 0; idx < log_instance_size; idx++) { - next_gate_challenges[idx] = gate_challenges[idx] + perturbator_challenge * round_challenges[idx]; - } - return next_gate_challenges; - } + const std::vector& round_challenges); // Returns the accumulator, which is the first element in ProverInstances. The accumulator is assumed to have the // FoldingParameters set and be the result of a previous round of folding. @@ -154,51 +145,7 @@ template class ProtoGalaxyProver_ { */ static std::vector compute_full_honk_evaluations(const ProverPolynomials& instance_polynomials, const RelationSeparator& alpha, - const RelationParameters& relation_parameters) - { - auto instance_size = instance_polynomials.get_polynomial_size(); - std::vector full_honk_evaluations(instance_size); - std::vector linearly_dependent_contributions(instance_size); -#ifndef NO_MULTITHREADING - std::mutex evaluation_mutex; -#endif - auto linearly_dependent_contribution_accumulator = FF(0); - run_loop_in_parallel(instance_size, [&](size_t start_row, size_t end_row) { - auto thread_accumulator = FF(0); - for (size_t row = start_row; row < end_row; row++) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940): avoid get_row if possible. - auto row_evaluations = instance_polynomials.get_row(row); - RelationEvaluations relation_evaluations; - Utils::zero_elements(relation_evaluations); - - // Note that the evaluations are accumulated with the gate separation challenge - // being 1 at this stage, as this specific randomness is added later through the - // power polynomial univariate specific to ProtoGalaxy - Utils::template accumulate_relation_evaluations<>( - row_evaluations, relation_evaluations, relation_parameters, FF(1)); - - auto output = FF(0); - auto running_challenge = FF(1); - - // Sum relation evaluations, batched by their corresponding relation separator challenge, to - // get the value of the full honk relation at a specific row - auto linearly_dependent_contribution = FF(0); - Utils::scale_and_batch_elements( - relation_evaluations, alpha, running_challenge, output, linearly_dependent_contribution); - thread_accumulator += linearly_dependent_contribution; - - full_honk_evaluations[row] = output; - } - { -#ifndef NO_MULTITHREADING - std::unique_lock evaluation_lock(evaluation_mutex); -#endif - linearly_dependent_contribution_accumulator += thread_accumulator; - } - }); - full_honk_evaluations[0] += linearly_dependent_contribution_accumulator; - return full_honk_evaluations; - } + const RelationParameters& relation_parameters); /** * @brief Recursively compute the parent nodes of each level in the tree, starting from the leaves. Note that at @@ -208,34 +155,7 @@ template class ProtoGalaxyProver_ { static std::vector construct_coefficients_tree(const std::vector& betas, const std::vector& deltas, const std::vector>& prev_level_coeffs, - size_t level = 1) - { - // if we are at level t in the tree, where t = logn and n is the instance size, we have reached the root which - // contains the coefficients of the perturbator polynomial - if (level == betas.size()) { - return prev_level_coeffs[0]; - } - - auto degree = level + 1; - auto prev_level_width = prev_level_coeffs.size(); - // we need degree + 1 terms to represent the intermediate polynomials - std::vector> level_coeffs(prev_level_width >> 1, std::vector(degree + 1, 0)); - run_loop_in_parallel( - prev_level_width >> 1, - [&](size_t start, size_t end) { - for (size_t node = start << 1; node < end << 1; node += 2) { - auto parent = node >> 1; - std::copy( - prev_level_coeffs[node].begin(), prev_level_coeffs[node].end(), level_coeffs[parent].begin()); - for (size_t d = 0; d < degree; d++) { - level_coeffs[parent][d] += prev_level_coeffs[node + 1][d] * betas[level]; - level_coeffs[parent][d + 1] += prev_level_coeffs[node + 1][d] * deltas[level]; - } - } - }, - /*no_multhreading_if_less_or_equal=*/8); - return construct_coefficients_tree(betas, deltas, level_coeffs, level + 1); - } + size_t level = 1); /** * @brief We construct the coefficients of the perturbator polynomial in O(n) time following the technique in @@ -249,22 +169,7 @@ template class ProtoGalaxyProver_ { */ static std::vector construct_perturbator_coefficients(const std::vector& betas, const std::vector& deltas, - const std::vector& full_honk_evaluations) - { - auto width = full_honk_evaluations.size(); - std::vector> first_level_coeffs(width >> 1, std::vector(2, 0)); - run_loop_in_parallel(width >> 1, [&](size_t start, size_t end) { - // Run loop in parallel can divide the domain in such way that the indices are odd, which we can't tolerate - // here, so first we divide the width by two, enable parallelism and then reconstruct even start and end - for (size_t node = start << 1; node < end << 1; node += 2) { - auto parent = node >> 1; - first_level_coeffs[parent][0] = - full_honk_evaluations[node] + full_honk_evaluations[node + 1] * betas[0]; - first_level_coeffs[parent][1] = full_honk_evaluations[node + 1] * deltas[0]; - } - }); - return construct_coefficients_tree(betas, deltas, first_level_coeffs); - } + const std::vector& full_honk_evaluations); /** * @brief Construct the power perturbator polynomial F(X) in coefficient form from the accumulator, representing the @@ -272,17 +177,8 @@ template class ProtoGalaxyProver_ { * * */ - static LegacyPolynomial compute_perturbator(const std::shared_ptr accumulator, - const std::vector& deltas) - { - BB_OP_COUNT_TIME(); - auto full_honk_evaluations = compute_full_honk_evaluations( - accumulator->proving_key.polynomials, accumulator->alphas, accumulator->relation_parameters); - const auto betas = accumulator->gate_challenges; - assert(betas.size() == deltas.size()); - auto coeffs = construct_perturbator_coefficients(betas, deltas, full_honk_evaluations); - return LegacyPolynomial(coeffs); - } + static LegacyPolynomial compute_perturbator(std::shared_ptr accumulator, + const std::vector& deltas); OptimisedTupleOfTuplesOfUnivariates optimised_univariate_accumulators; TupleOfTuplesOfUnivariates univariate_accumulators; @@ -543,36 +439,13 @@ template class ProtoGalaxyProver_ { static void deoptimise_univariates(const OptimisedTupleOfTuplesOfUnivariates& optimised_univariate_accumulators, TupleOfTuplesOfUnivariates& new_univariate_accumulators - ) - { - auto deoptimise = [&](auto& element) { - auto& optimised_element = std::get(std::get(optimised_univariate_accumulators)); - element = optimised_element.convert(); - }; - - Utils::template apply_to_tuple_of_tuples<0, 0>(new_univariate_accumulators, deoptimise); - } + ); static ExtendedUnivariateWithRandomization batch_over_relations(TupleOfTuplesOfUnivariates& univariate_accumulators, - const CombinedRelationSeparator& alpha) - { - // First relation does not get multiplied by a batching challenge - auto result = std::get<0>(std::get<0>(univariate_accumulators)) - .template extend_to(); - size_t idx = 0; - auto scale_and_sum = [&](auto& element) { - auto extended = element.template extend_to(); - extended *= alpha[idx]; - result += extended; - idx++; - }; - - Utils::template apply_to_tuple_of_tuples<0, 1>(univariate_accumulators, scale_and_sum); - Utils::zero_univariates(univariate_accumulators); - - return result; - } + const CombinedRelationSeparator& alpha); + static std::pair> + _compute_vanishing_polynomial_and_lagranges(const FF& challenge); /** * @brief Compute the combiner quotient defined as $K$ polynomial in the paper. * @@ -581,38 +454,7 @@ template class ProtoGalaxyProver_ { * */ static Univariate compute_combiner_quotient( - const FF compressed_perturbator, ExtendedUnivariateWithRandomization combiner) - { - std::array combiner_quotient_evals = {}; - - // 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; - 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); - } - static_assert(ProverInstances::NUM < 5); - - combiner_quotient_evals[idx] = - (combiner.value_at(point) - compressed_perturbator * lagrange_0) * vanishing_polynomial.invert(); - } - - Univariate combiner_quotient( - combiner_quotient_evals); - return combiner_quotient; - } + FF compressed_perturbator, ExtendedUnivariateWithRandomization combiner); /** * @brief Combine each relation parameter, in part, from all the instances into univariates, used in the @@ -621,44 +463,14 @@ template class ProtoGalaxyProver_ { * 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) - { - size_t param_idx = 0; - auto to_fold = instances.relation_parameters.get_to_fold(); - auto to_fold_optimised = instances.optimised_relation_parameters.get_to_fold(); - for (auto [folded_parameter, optimised_folded_parameter] : zip_view(to_fold, to_fold_optimised)) { - Univariate tmp(0); - size_t instance_idx = 0; - for (auto& instance : instances) { - tmp.value_at(instance_idx) = instance->relation_parameters.get_to_fold()[param_idx]; - instance_idx++; - } - folded_parameter = tmp.template extend_to(); - optimised_folded_parameter = - tmp.template extend_to(); - param_idx++; - } - } + static void combine_relation_parameters(ProverInstances& instances); /** * @brief Combine the relation batching parameters (alphas) from each instance into a univariate, used in the * computation of combiner. * */ - static void combine_alpha(ProverInstances& instances) - { - size_t alpha_idx = 0; - for (auto& alpha : instances.alphas) { - Univariate tmp; - size_t instance_idx = 0; - for (auto& instance : instances) { - tmp.value_at(instance_idx) = instance->alphas[alpha_idx]; - instance_idx++; - } - alpha = tmp.template extend_to(); - alpha_idx++; - } - } + static void combine_alpha(ProverInstances& instances); /** * @brief Compute the next accumulator (ϕ*, ω*, \vec{\beta*}, e*), send the public data ϕ* and the folding diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp index 4199e2cf8ede..17d50d6238fb 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp @@ -3,6 +3,221 @@ #include "barretenberg/ultra_honk/oink_prover.hpp" #include "protogalaxy_prover.hpp" namespace bb { +// See protogalaxy_prover.hpp for details +template +std::vector::FF> ProtoGalaxyProver_< + ProverInstances_>::compute_full_honk_evaluations(const ProverPolynomials& instance_polynomials, + const RelationSeparator& alpha, + const RelationParameters& relation_parameters) +{ + auto instance_size = instance_polynomials.get_polynomial_size(); + std::vector full_honk_evaluations(instance_size); + std::vector linearly_dependent_contributions(instance_size); +#ifndef NO_MULTITHREADING + std::mutex evaluation_mutex; +#endif + auto linearly_dependent_contribution_accumulator = FF(0); + run_loop_in_parallel(instance_size, [&](size_t start_row, size_t end_row) { + auto thread_accumulator = FF(0); + for (size_t row = start_row; row < end_row; row++) { + auto row_evaluations = instance_polynomials.get_row(row); + RelationEvaluations relation_evaluations; + Utils::zero_elements(relation_evaluations); + + Utils::template accumulate_relation_evaluations<>( + row_evaluations, relation_evaluations, relation_parameters, FF(1)); + + auto output = FF(0); + auto running_challenge = FF(1); + auto linearly_dependent_contribution = FF(0); + Utils::scale_and_batch_elements( + relation_evaluations, alpha, running_challenge, output, linearly_dependent_contribution); + thread_accumulator += linearly_dependent_contribution; + + full_honk_evaluations[row] = output; + } +#ifndef NO_MULTITHREADING + std::unique_lock evaluation_lock(evaluation_mutex); +#endif + linearly_dependent_contribution_accumulator += thread_accumulator; + }); + full_honk_evaluations[0] += linearly_dependent_contribution_accumulator; + return full_honk_evaluations; +} + +// See protogalaxy_prover.hpp for details +template +std::vector::FF> ProtoGalaxyProver_< + ProverInstances_>::construct_coefficients_tree(const std::vector& betas, + const std::vector& deltas, + const std::vector>& prev_level_coeffs, + size_t level) +{ + if (level == betas.size()) { + return prev_level_coeffs[0]; + } + + auto degree = level + 1; + auto prev_level_width = prev_level_coeffs.size(); + std::vector> level_coeffs(prev_level_width >> 1, std::vector(degree + 1, 0)); + run_loop_in_parallel( + prev_level_width >> 1, + [&](size_t start, size_t end) { + for (size_t node = start << 1; node < end << 1; node += 2) { + auto parent = node >> 1; + std::copy(prev_level_coeffs[node].begin(), prev_level_coeffs[node].end(), level_coeffs[parent].begin()); + for (size_t d = 0; d < degree; d++) { + level_coeffs[parent][d] += prev_level_coeffs[node + 1][d] * betas[level]; + level_coeffs[parent][d + 1] += prev_level_coeffs[node + 1][d] * deltas[level]; + } + } + }, + /*no_multhreading_if_less_or_equal=*/8); + return construct_coefficients_tree(betas, deltas, level_coeffs, level + 1); +} + +// See protogalaxy_prover.hpp for details +template +std::vector::FF> ProtoGalaxyProver_< + ProverInstances_>::construct_perturbator_coefficients(const std::vector& betas, + const std::vector& deltas, + const std::vector& full_honk_evaluations) +{ + auto width = full_honk_evaluations.size(); + std::vector> first_level_coeffs(width >> 1, std::vector(2, 0)); + run_loop_in_parallel(width >> 1, [&](size_t start, size_t end) { + for (size_t node = start << 1; node < end << 1; node += 2) { + auto parent = node >> 1; + first_level_coeffs[parent][0] = full_honk_evaluations[node] + full_honk_evaluations[node + 1] * betas[0]; + first_level_coeffs[parent][1] = full_honk_evaluations[node + 1] * deltas[0]; + } + }); + return construct_coefficients_tree(betas, deltas, first_level_coeffs); +} + +// See protogalaxy_prover.hpp for details +template +LegacyPolynomial::FF> ProtoGalaxyProver_< + ProverInstances_>::compute_perturbator(const std::shared_ptr accumulator, const std::vector& deltas) +{ + BB_OP_COUNT_TIME(); + auto full_honk_evaluations = compute_full_honk_evaluations( + accumulator->proving_key.polynomials, accumulator->alphas, accumulator->relation_parameters); + const auto betas = accumulator->gate_challenges; + assert(betas.size() == deltas.size()); + auto coeffs = construct_perturbator_coefficients(betas, deltas, full_honk_evaluations); + return LegacyPolynomial(coeffs); +} + +// See protogalaxy_prover.hpp for details +template +void ProtoGalaxyProver_::deoptimise_univariates( + const OptimisedTupleOfTuplesOfUnivariates& optimised_univariate_accumulators, + TupleOfTuplesOfUnivariates& new_univariate_accumulators) +{ + auto deoptimise = [&](auto& element) { + auto& optimised_element = std::get(std::get(optimised_univariate_accumulators)); + element = optimised_element.convert(); + }; + + Utils::template apply_to_tuple_of_tuples<0, 0>(new_univariate_accumulators, deoptimise); +} + +template +ProtoGalaxyProver_::ExtendedUnivariateWithRandomization ProtoGalaxyProver_< + ProverInstances_>::batch_over_relations(TupleOfTuplesOfUnivariates& univariate_accumulators, + const CombinedRelationSeparator& alpha) +{ + auto result = std::get<0>(std::get<0>(univariate_accumulators)) + .template extend_to(); + size_t idx = 0; + auto scale_and_sum = [&](auto& element) { + auto extended = element.template extend_to(); + extended *= alpha[idx]; + result += extended; + idx++; + }; + + Utils::template apply_to_tuple_of_tuples<0, 1>(univariate_accumulators, scale_and_sum); + Utils::zero_univariates(univariate_accumulators); + + return result; +} + +// See protogalaxy_prover.hpp for details +template +Univariate::FF, + ProverInstances_::BATCHED_EXTENDED_LENGTH, + ProverInstances_::NUM> +ProtoGalaxyProver_::compute_combiner_quotient(const FF compressed_perturbator, + ExtendedUnivariateWithRandomization combiner) +{ + std::array combiner_quotient_evals = {}; + + 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; + 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); + } + static_assert(ProverInstances::NUM < 5); + + combiner_quotient_evals[idx] = + (combiner.value_at(point) - compressed_perturbator * lagrange_0) * vanishing_polynomial.invert(); + } + + Univariate combiner_quotient( + combiner_quotient_evals); + return combiner_quotient; +} + +// See protogalaxy_prover.hpp for details +template +void ProtoGalaxyProver_::combine_relation_parameters(ProverInstances& instances) +{ + size_t param_idx = 0; + auto to_fold = instances.relation_parameters.get_to_fold(); + auto to_fold_optimised = instances.optimised_relation_parameters.get_to_fold(); + for (auto [folded_parameter, optimised_folded_parameter] : zip_view(to_fold, to_fold_optimised)) { + Univariate tmp(0); + size_t instance_idx = 0; + for (auto& instance : instances) { + tmp.value_at(instance_idx) = instance->relation_parameters.get_to_fold()[param_idx]; + instance_idx++; + } + folded_parameter = tmp.template extend_to(); + optimised_folded_parameter = + tmp.template extend_to(); + param_idx++; + } +} + +// See protogalaxy_prover.hpp for details +template void ProtoGalaxyProver_::combine_alpha(ProverInstances& instances) +{ + size_t alpha_idx = 0; + for (auto& alpha : instances.alphas) { + Univariate tmp; + size_t instance_idx = 0; + for (auto& instance : instances) { + tmp.value_at(instance_idx) = instance->alphas[alpha_idx]; + instance_idx++; + } + alpha = tmp.template extend_to(); + alpha_idx++; + } +} + template void ProtoGalaxyProver_::finalise_and_send_instance(std::shared_ptr instance, const std::string& domain_separator) @@ -35,21 +250,19 @@ template void ProtoGalaxyProver_::prepa } } +/** + * @brief Given the challenge \gamma, compute Z(\gamma) and {L_0(\gamma),L_1(\gamma)} + * TODO(https://github.com/AztecProtocol/barretenberg/issues/764): Generalize the vanishing polynomial formula + * and the computation of Lagrange basis for k instances + */ template -std::shared_ptr ProtoGalaxyProver_::compute_next_accumulator( - ProverInstances& instances, - Univariate& combiner_quotient, - FF& challenge, - const FF& compressed_perturbator) +std::pair> +ProtoGalaxyProver_::_compute_vanishing_polynomial_and_lagranges(const FF& challenge) { - auto combiner_quotient_at_challenge = combiner_quotient.evaluate(challenge); - - // Given the challenge \gamma, compute Z(\gamma) and {L_0(\gamma),L_1(\gamma)} - // TODO(https://github.com/AztecProtocol/barretenberg/issues/764): Generalize the vanishing polynomial formula - // and the computation of Lagrange basis for k instances FF vanishing_polynomial_at_challenge; std::array lagranges; constexpr FF inverse_two = FF(2).invert(); + if constexpr (ProverInstances::NUM == 2) { vanishing_polynomial_at_challenge = challenge * (challenge - FF(1)); lagranges = { FF(1) - challenge, challenge }; @@ -68,6 +281,19 @@ std::shared_ptr ProtoGalaxyProver_ +std::shared_ptr ProtoGalaxyProver_::compute_next_accumulator( + ProverInstances& instances, + Univariate& combiner_quotient, + FF& challenge, + const FF& compressed_perturbator) +{ + auto combiner_quotient_at_challenge = combiner_quotient.evaluate(challenge); + auto [vanishing_polynomial_at_challenge, lagranges] = _compute_vanishing_polynomial_and_lagranges(challenge); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/881): bad pattern auto next_accumulator = std::move(instances[0]); next_accumulator->is_accumulator = true; @@ -81,27 +307,16 @@ std::shared_ptr ProtoGalaxyProver_proving_key.polynomials.get_all(); - run_loop_in_parallel(Flavor::NUM_FOLDED_ENTITIES, [&](size_t start_idx, size_t end_idx) { - for (size_t poly_idx = start_idx; poly_idx < end_idx; poly_idx++) { - auto& acc_poly = accumulator_polys[poly_idx]; - for (auto& acc_el : acc_poly) { - acc_el *= lagranges[0]; - } - } - }); + for (size_t poly_idx = 0; poly_idx < Flavor::NUM_FOLDED_ENTITIES; poly_idx++) { + accumulator_polys[poly_idx] *= lagranges[0]; + } // Fold the proving key polynomials for (size_t inst_idx = 1; inst_idx < ProverInstances::NUM; inst_idx++) { auto input_polys = instances[inst_idx]->proving_key.polynomials.get_all(); - run_loop_in_parallel(Flavor::NUM_FOLDED_ENTITIES, [&](size_t start_idx, size_t end_idx) { - for (size_t poly_idx = start_idx; poly_idx < end_idx; poly_idx++) { - auto& acc_poly = accumulator_polys[poly_idx]; - auto& inst_poly = input_polys[poly_idx]; - for (auto [acc_el, inst_el] : zip_view(acc_poly, inst_poly)) { - acc_el += inst_el * lagranges[inst_idx]; - } - } - }); + for (size_t poly_idx = 0; poly_idx < Flavor::NUM_FOLDED_ENTITIES; poly_idx++) { + accumulator_polys[poly_idx].add_scaled(input_polys[poly_idx], lagranges[inst_idx]); + } } // Evaluate the combined batching α_i univariate at challenge to obtain next α_i and send it to the @@ -153,6 +368,21 @@ template void ProtoGalaxyProver_::pertu } }; +template +std::vector::FF> bb::ProtoGalaxyProver_< + ProverInstances_>::update_gate_challenges(const FF perturbator_challenge, + const std::vector& gate_challenges, + const std::vector& round_challenges) +{ + auto log_instance_size = gate_challenges.size(); + std::vector next_gate_challenges(log_instance_size); + + for (size_t idx = 0; idx < log_instance_size; idx++) { + next_gate_challenges[idx] = gate_challenges[idx] + perturbator_challenge * round_challenges[idx]; + } + return next_gate_challenges; +} + template void ProtoGalaxyProver_::combiner_quotient_round() { BB_OP_COUNT_TIME_NAME("ProtoGalaxyProver_::combiner_quotient_round"); diff --git a/yarn-project/README.md b/yarn-project/README.md index 24a95b23bff7..ef499215bcc8 100644 --- a/yarn-project/README.md +++ b/yarn-project/README.md @@ -29,7 +29,7 @@ yarn formatting ## Tests -To run tests for a specific package, in its folder just run +To run tests for a specific package, in its folder just run: ``` yarn test @@ -48,7 +48,7 @@ Consider installing the Prettier and ESLint extensions if using VSCode. Configur ## Package.json inheritance -To simplify the management of all package.json files, we have a custom script that injects the contents of `package.common.json` into all packages that reference it via the `inherits` custom field. To run the script, just run +To simplify the management of all package.json files, we have a custom script that injects the contents of `package.common.json` into all packages that reference it via the `inherits` custom field. To run the script, just run ``` yarn prepare @@ -81,7 +81,7 @@ source /tmp/.bash_env* BUILD_SYSTEM_DEBUG=1 COMMIT_TAG= ``` -4. Follow the [`deploy-npm` script](./deploy_npm.sh). +4. Follow the [`deploy-npm` script](./deploy_npm.sh). - Best to run the `deploy_package()` method line by line by manually setting `REPOSITORY` var. - Extract `VERSION` as the script shows (in the eg it should be 0.8.8) - Skip the version existing checks like `if [ "$VERSION" == "$PUBLISHED_VERSION" ]` and `if [ "$VERSION" != "$HIGHER_VERSION" ]`. Since this is our first time deploying the package, `PUBLISHED_VERSION` and `HIGHER_VERSION` will be empty and hence these checks would fail. These checks are necessary in the CI for continual releases.