diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp index eed7d43370d..21490b283cf 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp @@ -259,8 +259,6 @@ template class UltraHonkArith { UltraHonkTraceBlock ecc_op; UltraHonkTraceBlock pub_inputs; UltraHonkTraceBlock arithmetic; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/919): Change: DeltaRangeConstraint --> - // DeltaRangeConstraint UltraHonkTraceBlock delta_range; UltraHonkTraceBlock elliptic; UltraHonkTraceBlock aux; diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 5d2675649bf..78899bc1a22 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -71,6 +71,8 @@ void compute_grand_product(const size_t circuit_size, const size_t end = (thread_idx + 1) * block_size; typename Flavor::AllValues evaluations; auto evaluations_view = evaluations.get_all(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940): construction of evaluations is equivalent to + // calling get_row which creates full copies. avoid? for (size_t i = start; i < end; ++i) { for (auto [eval, full_poly] : zip_view(evaluations_view, full_polynomials_view)) { eval = full_poly.size() > i ? full_poly[i] : 0; diff --git a/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp index 144ebdf9808..ea8e4b40e73 100644 --- a/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp @@ -49,6 +49,15 @@ template class AuxiliaryRelationImpl { 1 // RAM consistency sub-relation 3 }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_aux.value_at(0).is_zero() && in.q_aux.value_at(1).is_zero()); + } + /** * @brief Expression for the generalized permutation sort gate. * @details The following explanation is reproduced from the Plonk analog 'plookup_auxiliary_widget': diff --git a/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp index dee7759db07..25429fbc002 100644 --- a/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp @@ -14,6 +14,15 @@ template class DeltaRangeConstraintRelationImpl { 6 // range constrain sub-relation 4 }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_delta_range.value_at(0).is_zero() && in.q_delta_range.value_at(1).is_zero()); + } + /** * @brief Expression for the generalized permutation sort gate. * @details The relation is defined as C(in(X)...) = diff --git a/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp index f6201145fba..2c0b2a85062 100644 --- a/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp @@ -14,6 +14,15 @@ template class EllipticRelationImpl { 6, // y-coordinate sub-relation }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_elliptic.value_at(0).is_zero() && in.q_elliptic.value_at(1).is_zero()); + } + // TODO(@zac-williamson #2609 find more generic way of doing this) static constexpr FF get_curve_b() { diff --git a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp index a9a4bd3fb47..337469bd5c8 100644 --- a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp @@ -31,6 +31,18 @@ template class LookupRelationImpl { 4, // grand product construction sub-relation 0 // left-shiftable polynomial sub-relation }; + + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip([[maybe_unused]] const AllEntities& in) + { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/952): figure out why skip condition described in + // issue causes failures in acir tests. + return false; + } + /** * @brief Get the grand product polynomial object (either from the proving key or AllEntities depending on context) * diff --git a/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp index d52fe2951eb..8ff08be35d2 100644 --- a/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp @@ -17,6 +17,18 @@ template class UltraPermutationRelationImpl { 0 // left-shiftable polynomial sub-relation }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + // If z_perm == z_perm_shift, this implies that none of the wire values for the present input are involved in + // non-trivial copy constraints. + return (in.z_perm.value_at(0) == in.z_perm_shift.value_at(0) && + in.z_perm.value_at(1) == in.z_perm_shift.value_at(1)); + } + inline static auto& get_grand_product_polynomial(auto& in) { return in.z_perm; } inline static auto& get_shifted_grand_product_polynomial(auto& in) { return in.z_perm_shift; } diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index 274b644db9c..29d082b4a4e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -13,6 +13,15 @@ template class Poseidon2ExternalRelationImpl { 7, // external poseidon2 round sub-relation for fourth value }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_poseidon2_external.value_at(0).is_zero() && in.q_poseidon2_external.value_at(1).is_zero()); + } + /** * @brief Expression for the poseidon2 external round relation, based on E_i in Section 6 of * https://eprint.iacr.org/2023/323.pdf. diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index db4d4b02576..e2199935868 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -15,6 +15,15 @@ template class Poseidon2InternalRelationImpl { 7, // internal poseidon2 round sub-relation for fourth value }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_poseidon2_internal.value_at(0).is_zero() && in.q_poseidon2_internal.value_at(1).is_zero()); + } + /** * @brief Expression for the poseidon2 internal round relation, based on I_i in Section 6 of * https://eprint.iacr.org/2023/323.pdf. diff --git a/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp b/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp index be4b8732254..aa4ba8820b7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp @@ -111,6 +111,21 @@ consteval std::array compute_composed_subrelation_part * */ +/** + * @brief Check if the relation has a static skip method to determine if accumulation of its result can be + * optimised away based on a single check + * + * @details The skip function should return true if relation can be skipped and false if it can't + * @tparam Relation The relation type + * @tparam AllEntities The type containing UnivariateViews with witness and selector values + */ +template +concept isSkippable = requires(const AllEntities& input) { + { + Relation::is_active(input) + } -> std::same_as; + }; + /** * @brief A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the * contribution of a given relation to the corresponding accumulator. diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp index 898e3a7d144..7a5a1e0d917 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp @@ -12,6 +12,15 @@ template class UltraArithmeticRelationImpl { 5 // secondary arithmetic sub-relation }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_arith.value_at(0).is_zero() && in.q_arith.value_at(1).is_zero()); + } + /** * @brief Expression for the Ultra Arithmetic gate. * @details This relation encapsulates several idenitities, toggled by the value of q_arith in [0, 1, 2, 3, ...]. diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index b3129797af4..de237e915de 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -237,8 +237,21 @@ template class SumcheckProverRound { const FF& scaling_factor) { using Relation = std::tuple_element_t; - Relation::accumulate( - std::get(univariate_accumulators), extended_edges, relation_parameters, scaling_factor); + + // Check if the relation is skippable to speed up accumulation + if constexpr (!isSkippable) { + // If not, accumulate normally + Relation::accumulate( + std::get(univariate_accumulators), extended_edges, relation_parameters, scaling_factor); + } else { + // If so, only compute the contribution if the relation is active + if (!Relation::skip(extended_edges, relation_parameters)) { + Relation::accumulate(std::get(univariate_accumulators), + extended_edges, + relation_parameters, + scaling_factor); + } + } // Repeat for the next relation. if constexpr (relation_idx + 1 < NUM_RELATIONS) {