Skip to content

Commit

Permalink
Merge fc844f1 into 0d0646d
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro authored Aug 13, 2024
2 parents 0d0646d + fc844f1 commit 2d7e694
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 178 deletions.
71 changes: 0 additions & 71 deletions barretenberg/cpp/src/barretenberg/common/constexpr_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,6 @@
#include <tuple>
#include <utility>

/**
* @brief constexpr_utils defines some helper methods that perform some stl-equivalent operations
* but in a constexpr context over quantities known at compile-time
*
* Current methods are:
*
* constexpr_for : loop over a range , where the size_t iterator `i` is a constexpr variable
* constexpr_find : find if an element is in an array
*/
namespace bb {

/**
Expand Down Expand Up @@ -97,66 +88,4 @@ template <size_t Start, size_t End, size_t Inc, class F> constexpr void constexp
}
}

/**
* @brief returns true/false depending on whether `key` is in `container`
*
* @tparam container i.e. what are we looking in?
* @tparam key i.e. what are we looking for?
* @return true found!
* @return false not found!
*
* @details method is constexpr and can be used in static_asserts
*/
template <const auto& container, auto key> constexpr bool constexpr_find()
{
// using ElementType = typename std::remove_extent<ContainerType>::type;
bool found = false;
constexpr_for<0, container.size(), 1>([&]<size_t k>() {
if constexpr (std::get<k>(container) == key) {
found = true;
}
});
return found;
}

/**
* @brief Create a constexpr array object whose elements contain a default value
*
* @tparam T type contained in the array
* @tparam Is index sequence
* @param value the value each array element is being initialized to
* @return constexpr std::array<T, sizeof...(Is)>
*
* @details This method is used to create constexpr arrays whose encapsulated type:
*
* 1. HAS NO CONSTEXPR DEFAULT CONSTRUCTOR
* 2. HAS A CONSTEXPR COPY CONSTRUCTOR
*
* An example of this is bb::field_t
* (the default constructor does not default assign values to the field_t member variables for efficiency reasons, to
* reduce the time require to construct large arrays of field elements. This means the default constructor for field_t
* cannot be constexpr)
*/
template <typename T, std::size_t... Is>
constexpr std::array<T, sizeof...(Is)> create_array(T value, std::index_sequence<Is...> /*unused*/)
{
// cast Is to void to remove the warning: unused value
std::array<T, sizeof...(Is)> result = { { (static_cast<void>(Is), value)... } };
return result;
}

/**
* @brief Create a constexpr array object whose values all are 0
*
* @tparam T
* @tparam N
* @return constexpr std::array<T, N>
*
* @details Use in the same context as create_array, i.e. when encapsulated type has a default constructor that is not
* constexpr
*/
template <typename T, size_t N> constexpr std::array<T, N> create_empty_array()
{
return create_array(T(0), std::make_index_sequence<N>());
}
}; // namespace bb
156 changes: 52 additions & 104 deletions barretenberg/cpp/src/barretenberg/flavor/flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,90 +262,49 @@ auto get_unshifted_then_shifted(const auto& all_entities)
return concatenate(all_entities.get_unshifted(), all_entities.get_shifted());
};

template <typename Tuple, size_t... I>
static constexpr auto _compute_max_partial_relation_length_internal([[maybe_unused]] std::index_sequence<I...>)
{
constexpr std::array<size_t, sizeof...(I)> lengths = { std::tuple_element_t<I, Tuple>::RELATION_LENGTH... };
return *std::max_element(lengths.begin(), lengths.end());
}

/**
* @brief Utility function to find max PARTIAL_RELATION_LENGTH tuples of Relations.
* @details The "partial length" of a relation is 1 + the degree of the relation, where any challenges used in the
* relation are as constants, not as variables..
*/
template <typename Tuple, std::size_t Index = 0> static constexpr size_t compute_max_partial_relation_length()
{
return _compute_max_partial_relation_length_internal<Tuple>(std::make_index_sequence<std::tuple_size_v<Tuple>>());
}

template <typename Tuple, size_t... I>
static constexpr auto _compute_max_total_relation_length_internal([[maybe_unused]] std::index_sequence<I...>)
template <typename Tuple, bool ZK = false> constexpr size_t compute_max_partial_relation_length()
{
constexpr std::array<size_t, sizeof...(I)> lengths = { std::tuple_element_t<I, Tuple>::TOTAL_RELATION_LENGTH... };
return *std::max_element(lengths.begin(), lengths.end());
constexpr auto seq = std::make_index_sequence<std::tuple_size_v<Tuple>>();
return []<std::size_t... Is>(std::index_sequence<Is...>) {
if constexpr (ZK) {
return std::max({ std::tuple_element_t<Is, Tuple>::ZK_RELATION_LENGTH... });
} else {
return std::max({ std::tuple_element_t<Is, Tuple>::RELATION_LENGTH... });
}
}(seq);
}

/**
* @brief Utility function to find max TOTAL_RELATION_LENGTH among tuples of Relations.
* @details The "total length" of a relation is 1 + the degree of the relation, where any challenges used in the
* relation are regarded as variables.
*/
template <typename Tuple> static constexpr size_t compute_max_total_relation_length()
{
return _compute_max_total_relation_length_internal<Tuple>(std::make_index_sequence<std::tuple_size_v<Tuple>>());
}

template <typename Tuple, size_t... I>
static constexpr auto _compute_number_of_subrelations_internal([[maybe_unused]] std::index_sequence<I...>)
template <typename Tuple, bool ZK = false> constexpr size_t compute_max_total_relation_length()
{
constexpr std::array<size_t, sizeof...(I)> lengths = {
std::tuple_element_t<I, Tuple>::SUBRELATION_PARTIAL_LENGTHS.size()...
};
return std::accumulate(lengths.begin(), lengths.end(), 0);
constexpr auto seq = std::make_index_sequence<std::tuple_size_v<Tuple>>();
return []<std::size_t... Is>(std::index_sequence<Is...>) {
if constexpr (ZK) {
return std::max({ std::tuple_element_t<Is, Tuple>::ZK_TOTAL_RELATION_LENGTH... });
} else {
return std::max({ std::tuple_element_t<Is, Tuple>::TOTAL_RELATION_LENGTH... });
}
}(seq);
}

/**
* @brief Utility function to find the number of subrelations.
*/
template <typename Tuple> static constexpr size_t compute_number_of_subrelations()
{
return _compute_number_of_subrelations_internal<Tuple>(std::make_index_sequence<std::tuple_size_v<Tuple>>());
}

template <typename Tuple, size_t NUM_INSTANCES, bool optimised = false, size_t... I>
static constexpr auto _create_protogalaxy_tuple_of_tuples_of_univariates_internal(
[[maybe_unused]] std::index_sequence<I...>)
template <typename Tuple> constexpr size_t compute_number_of_subrelations()
{
if constexpr (optimised) {
return std::make_tuple(
typename std::tuple_element_t<I, Tuple>::template OptimisedProtogalaxyTupleOfUnivariatesOverSubrelations<
NUM_INSTANCES>{}...);
} else {
return std::make_tuple(
typename std::tuple_element_t<I, Tuple>::template ProtogalaxyTupleOfUnivariatesOverSubrelations<
NUM_INSTANCES>{}...);
}
}

/**
* @brief Takes a Tuple of objects in the Relation class and recursively computes the maximum among partial
* subrelation lengths incremented by corresponding subrelation witness degrees over all
* subrelations of given relations. This method is required to compute the size of
* Round Univariates in ZK Sumcheck.
* @tparam Tuple
* @tparam Index
* @return constexpr size_t
*/
template <typename Tuple, std::size_t Index = 0> static constexpr size_t compute_max_total_zk_relation_length()
{
if constexpr (Index >= std::tuple_size<Tuple>::value) {
return 0; // Return 0 when reach end of the tuple
} else {
constexpr size_t current_zk_length = std::tuple_element<Index, Tuple>::type::ZK_TOTAL_RELATION_LENGTH;
constexpr size_t next_zk_length = compute_max_total_zk_relation_length<Tuple, Index + 1>();
return (current_zk_length > next_zk_length) ? current_zk_length : next_zk_length;
}
constexpr auto seq = std::make_index_sequence<std::tuple_size_v<Tuple>>();
return []<std::size_t... I>(std::index_sequence<I...>) {
return (0 + ... + std::tuple_element_t<I, Tuple>::SUBRELATION_PARTIAL_LENGTHS.size());
}(seq);
}

/**
Expand All @@ -356,64 +315,53 @@ template <typename Tuple, std::size_t Index = 0> static constexpr size_t compute
* @tparam optimised Enable optimised version with skipping some of the computation
*/
template <typename Tuple, size_t NUM_INSTANCES, bool optimised = false>
static constexpr auto create_protogalaxy_tuple_of_tuples_of_univariates()
{
return _create_protogalaxy_tuple_of_tuples_of_univariates_internal<Tuple, NUM_INSTANCES, optimised>(
std::make_index_sequence<std::tuple_size_v<Tuple>>());
}

template <typename Tuple, size_t... I>
static constexpr auto _create_sumcheck_tuple_of_tuples_of_univariates_internal(
[[maybe_unused]] std::index_sequence<I...>)
constexpr auto create_protogalaxy_tuple_of_tuples_of_univariates()
{
return std::make_tuple(typename std::tuple_element_t<I, Tuple>::SumcheckTupleOfUnivariatesOverSubrelations{}...);
constexpr auto seq = std::make_index_sequence<std::tuple_size_v<Tuple>>();
return []<size_t... I>(std::index_sequence<I...>) {
if constexpr (optimised) {
return std::make_tuple(
typename std::tuple_element_t<I, Tuple>::
template OptimisedProtogalaxyTupleOfUnivariatesOverSubrelations<NUM_INSTANCES>{}...);
} else {
return std::make_tuple(
typename std::tuple_element_t<I, Tuple>::template ProtogalaxyTupleOfUnivariatesOverSubrelations<
NUM_INSTANCES>{}...);
}
}(seq);
}

template <typename Tuple, size_t... I>
static constexpr auto _create_zk_sumcheck_tuple_of_tuples_of_univariates_internal(
[[maybe_unused]] std::index_sequence<I...>)
{
return std::make_tuple(typename std::tuple_element_t<I, Tuple>::ZKSumcheckTupleOfUnivariatesOverSubrelations{}...);
}
/**
* @brief Utility function to construct a container for the subrelation accumulators of sumcheck proving.
* @details The size of the outer tuple is equal to the number of relations. Each relation contributes an inner tuple of
* univariates whose size is equal to the number of subrelations of the relation. The length of a univariate in an inner
* tuple is determined by the corresponding subrelation length.
*/
template <typename Tuple> static constexpr auto create_sumcheck_tuple_of_tuples_of_univariates()
template <typename Tuple, bool ZK = false> constexpr auto create_sumcheck_tuple_of_tuples_of_univariates()
{
return _create_sumcheck_tuple_of_tuples_of_univariates_internal<Tuple>(
std::make_index_sequence<std::tuple_size_v<Tuple>>());
}

/**
* @brief Recursive utility function to construct a container for the subrelation accumulators of ZK Sumcheck prover.
* @details The size of the outer tuple is equal to the number of relations. Each relation contributes an inner tuple of
* univariates whose size is equal to the number of subrelations of the relation. The length of a univariate in an inner
* tuple is determined by the corresponding zk subrelation length, i.e. by the subrelation partial length corrected by
* the corresponding witness degree.
*/
template <typename Tuple> static constexpr auto create_zk_sumcheck_tuple_of_tuples_of_univariates()
{
return _create_zk_sumcheck_tuple_of_tuples_of_univariates_internal<Tuple>(
std::make_index_sequence<std::tuple_size_v<Tuple>>());
}

template <typename Tuple, size_t... I>
static constexpr auto _create_tuple_of_arrays_of_values_internal([[maybe_unused]] std::index_sequence<I...>)
{
return std::make_tuple(typename std::tuple_element_t<I, Tuple>::SumcheckArrayOfValuesOverSubrelations{}...);
constexpr auto seq = std::make_index_sequence<std::tuple_size_v<Tuple>>();
return []<size_t... I>(std::index_sequence<I...>) {
if constexpr (ZK) {
return std::make_tuple(
typename std::tuple_element_t<I, Tuple>::ZKSumcheckTupleOfUnivariatesOverSubrelations{}...);
} else {
return std::make_tuple(
typename std::tuple_element_t<I, Tuple>::SumcheckTupleOfUnivariatesOverSubrelations{}...);
}
}(seq);
}

/**
* @brief Construct tuple of arrays
* @details Container for storing value of each identity in each relation. Each Relation contributes an array of
* length num-identities.
*/
template <typename Tuple> static constexpr auto create_tuple_of_arrays_of_values()
template <typename Tuple> constexpr auto create_tuple_of_arrays_of_values()
{
return _create_tuple_of_arrays_of_values_internal<Tuple>(std::make_index_sequence<std::tuple_size_v<Tuple>>());
constexpr auto seq = std::make_index_sequence<std::tuple_size_v<Tuple>>();
return []<size_t... I>(std::index_sequence<I...>) {
return std::make_tuple(typename std::tuple_element_t<I, Tuple>::SumcheckArrayOfValuesOverSubrelations{}...);
}(seq);
}

} // namespace bb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp"

namespace bb {

/*!
\brief Child class of UltraFlavor that runs with ZK Sumcheck.
\details
Expand All @@ -16,19 +17,20 @@ univariate accumuluator size has to be increased by the subrelation's witness de
\ref docs/src/sumcheck-outline.md "Sumcheck Outline".
*/
class UltraFlavorWithZK : public bb::UltraFlavor {

public:
// This flavor runs with ZK Sumcheck
static constexpr bool HasZK = true;
// Compute the maximum over all partial subrelation lengths incremented by the corresponding subrelation witness
// degrees for the Relations inherited from UltraFlavor
static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_total_zk_relation_length<Relations>();
static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_total_relation_length<Relations, HasZK>();
// Determine the number of evaluations of Prover and Libra Polynomials that the Prover sends to the Verifier in
// the rounds of ZK Sumcheck.
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1;
// Construct the container for the subrelations' contributions
using SumcheckTupleOfTuplesOfUnivariates = decltype(create_zk_sumcheck_tuple_of_tuples_of_univariates<Relations>());
using SumcheckTupleOfTuplesOfUnivariates =
decltype(create_sumcheck_tuple_of_tuples_of_univariates<Relations, HasZK>());
// Re-define ExtendedEdges to account for the incremented MAX_PARTIAL_RELATION_LENGTH
using ExtendedEdges = ProverUnivariates<MAX_PARTIAL_RELATION_LENGTH>;
};

} // namespace bb

0 comments on commit 2d7e694

Please sign in to comment.