Skip to content

Commit

Permalink
chore: adjusted flavors and relation types to zk sumcheck (#7500)
Browse files Browse the repository at this point in the history
Each flavor gets a constexpr flag HasZK which indicates whether it runs
with ZK or non-ZK Sumcheck.

avm_flavor.hpp: HasZK is false, haven't touched anything else.

Added several methods to the flavor.hpp and relation_types.hpp required
for ZK Sumcheck:
- Any Flavor that has ZK requires that the degrees of all sub-relation
univariates in SumcheckTupleOfTuplesOfUnivariates are incremented by the
corresponding SUBRELATION_WITNESS_DEGREES. It is achieved with the
method create_zk_sumcheck_tuple_of_tuples_of_univariates.
- The method compute_max_zk_length allows to compute the size of the
Sumcheck round univariates for a given Flavor.

Added UltraFlavorWithZK. ECCVM, Translator, and Mega Flavors will
receive their ZK versions later.

Added get_all_witnesses and get_non_witnesses getters to several
Flavors. Previously, there was no reasonable universal alternative to
get all witness polynomials including shits and derived ones. The second
getter contains all selector polynomials, public polynomials (like
Lagranges), shifts of public tables etc.
  • Loading branch information
iakovenkos authored Aug 12, 2024
1 parent 4be1833 commit b7efd07
Show file tree
Hide file tree
Showing 12 changed files with 279 additions and 50 deletions.
17 changes: 15 additions & 2 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class ECCVMFlavor {
using RelationSeparator = FF;
using MSM = bb::eccvm::MSM<CycleGroup>;

// Indicates that this flavor runs with non-ZK Sumcheck.
static constexpr bool HasZK = false;
static constexpr size_t NUM_WIRES = 85;

// The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often
Expand All @@ -49,6 +51,8 @@ class ECCVMFlavor {
static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 3;
// The total number of witness entities not including shifts.
static constexpr size_t NUM_WITNESS_ENTITIES = 87;
// The total number of witnesses including shifts and derived entities.
static constexpr size_t NUM_ALL_WITNESS_ENTITIES = 113;

using GrandProductRelations = std::tuple<ECCVMSetRelation<FF>>;
// define the tuple of Relations that comprise the Sumcheck relation
Expand Down Expand Up @@ -279,6 +283,7 @@ class ECCVMFlavor {
entities.precompute_select, // column 24
entities.z_perm }; // column 25
}

/**
* @brief A base class labelling all entities (for instance, all of the polynomials used by the prover during
* sumcheck) in this Honk variant along with particular subsets of interest
Expand Down Expand Up @@ -308,10 +313,18 @@ class ECCVMFlavor {
{
return concatenate(PrecomputedEntities<DataType>::get_all(), WitnessEntities<DataType>::get_all());
};

auto get_to_be_shifted() { return ECCVMFlavor::get_to_be_shifted<DataType>(*this); }
auto get_shifted() { return ShiftedEntities<DataType>::get_all(); };
// this getter is necessary for more uniform zk verifiers
auto get_shifted_witnesses() { return ShiftedEntities<DataType>::get_all(); };
auto get_precomputed() { return PrecomputedEntities<DataType>::get_all(); };
// the getter for all witnesses including derived and shifted ones
auto get_all_witnesses()
{
return concatenate(WitnessEntities<DataType>::get_all(), ShiftedEntities<DataType>::get_all());
};
// this getter is necessary for a universal ZK Sumcheck
auto get_non_witnesses() { return PrecomputedEntities<DataType>::get_all(); };
};

public:
Expand Down Expand Up @@ -1297,4 +1310,4 @@ class ECCVMFlavor {

// NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members)

} // namespace bb
} // namespace bb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ template <typename BuilderType> class ECCVMRecursiveFlavor_ {
using NativeVerificationKey = NativeFlavor::VerificationKey;
using PCS = IPA<Curve>;

// Indicates that this flavor runs with non-ZK Sumcheck.
static constexpr bool HasZK = false;
static constexpr size_t NUM_WIRES = ECCVMFlavor::NUM_WIRES;
// The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often
// need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`.
Expand Down Expand Up @@ -130,4 +132,4 @@ template <typename BuilderType> class ECCVMRecursiveFlavor_ {

}; // NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members)

} // namespace bb
} // namespace bb
49 changes: 45 additions & 4 deletions barretenberg/cpp/src/barretenberg/flavor/flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
* @note It would be ideal to codify more structure in these base class template and to have it imposed on the actual
* flavors, but our inheritance model is complicated as it is, and we saw no reasonable way to fix this.
*
* @note One asymmetry to note is in the use of the term "key". It is worthwhile to distinguish betwen prover/verifier
* @note One asymmetry to note is in the use of the term "key". It is worthwhile to distinguish between prover/verifier
* circuit data, and "keys" that consist of such data augmented with witness data (whether, raw, blinded, or polynomial
* commitments). Currently the proving key contains witness data, while the verification key does not.
* TODO(Cody): It would be nice to resolve this but it's not essential.
Expand Down Expand Up @@ -328,6 +328,26 @@ static constexpr auto _create_protogalaxy_tuple_of_tuples_of_univariates_interna
}
}

/**
* @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;
}
}

/**
* @brief Utility function to construct a container for the subrelation accumulators of Protogalaxy folding.
* @details The size of the outer tuple is equal to the number of relations. Each relation contributes an inner tuple of
Expand All @@ -349,6 +369,12 @@ static constexpr auto _create_sumcheck_tuple_of_tuples_of_univariates_internal(
return std::make_tuple(typename std::tuple_element_t<I, Tuple>::SumcheckTupleOfUnivariatesOverSubrelations{}...);
}

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
Expand All @@ -361,6 +387,19 @@ template <typename Tuple> static constexpr auto create_sumcheck_tuple_of_tuples_
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...>)
{
Expand All @@ -382,6 +421,7 @@ template <typename Tuple> static constexpr auto create_tuple_of_arrays_of_values
// Forward declare honk flavors
namespace bb {
class UltraFlavor;
class UltraFlavorWithZK;
class ECCVMFlavor;
class UltraKeccakFlavor;
class MegaFlavor;
Expand Down Expand Up @@ -415,13 +455,13 @@ template <typename T>
concept IsUltraPlonkFlavor = IsAnyOf<T, plonk::flavor::Ultra, UltraKeccakFlavor>;

template <typename T>
concept IsUltraPlonkOrHonk = IsAnyOf<T, plonk::flavor::Ultra, UltraFlavor, UltraKeccakFlavor, MegaFlavor>;
concept IsUltraPlonkOrHonk = IsAnyOf<T, plonk::flavor::Ultra, UltraFlavor, UltraKeccakFlavor, UltraFlavorWithZK, MegaFlavor>;

template <typename T>
concept IsHonkFlavor = IsAnyOf<T, UltraFlavor, UltraKeccakFlavor, MegaFlavor>;
concept IsHonkFlavor = IsAnyOf<T, UltraFlavor, UltraKeccakFlavor, UltraFlavorWithZK, MegaFlavor>;

template <typename T>
concept IsUltraFlavor = IsAnyOf<T, UltraFlavor, UltraKeccakFlavor, MegaFlavor>;
concept IsUltraFlavor = IsAnyOf<T, UltraFlavor, UltraKeccakFlavor, UltraFlavorWithZK, MegaFlavor>;

template <typename T>
concept IsGoblinFlavor = IsAnyOf<T, MegaFlavor,
Expand All @@ -448,6 +488,7 @@ template <typename T> concept IsGrumpkinFlavor = IsAnyOf<T, ECCVMFlavor>;
template <typename T> concept IsFoldingFlavor = IsAnyOf<T, UltraFlavor,
// Note(md): must be here to use oink prover
UltraKeccakFlavor,
UltraFlavorWithZK,
MegaFlavor,
UltraRecursiveFlavor_<UltraCircuitBuilder>,
UltraRecursiveFlavor_<MegaCircuitBuilder>,
Expand Down
35 changes: 35 additions & 0 deletions barretenberg/cpp/src/barretenberg/relations/relation_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ concept HasSubrelationLinearlyIndependentMember = requires(T) {

template <typename T>
concept HasParameterLengthAdjustmentsMember = requires { T::TOTAL_LENGTH_ADJUSTMENTS; };
// The concept needed to adjust the sumcheck univariate lengths in the case of ZK Flavors and to avoid adding redundant
// constants to the relations that are not used by ZK flavors
template <typename T>
concept HasWitnessDegrees = requires { T::SUBRELATION_WITNESS_DEGREES; };

/**
* @brief Check whether a given subrelation is linearly independent from the other subrelations.
Expand Down Expand Up @@ -66,6 +70,27 @@ consteval std::array<size_t, RelationImpl::SUBRELATION_PARTIAL_LENGTHS.size()> c
return RelationImpl::SUBRELATION_PARTIAL_LENGTHS;
}
};
/**
* @brief This metod adjusts the subrelation partial lengths to ZK Flavors.
*
* @tparam RelationImpl
* @return consteval
*/
template <typename RelationImpl>
consteval std::array<size_t, RelationImpl::SUBRELATION_PARTIAL_LENGTHS.size()> compute_zk_partial_subrelation_lengths()
{
if constexpr (HasWitnessDegrees<RelationImpl>) {
constexpr size_t NUM_SUBRELATIONS = RelationImpl::SUBRELATION_PARTIAL_LENGTHS.size();
std::array<size_t, NUM_SUBRELATIONS> result;
for (size_t idx = 0; idx < NUM_SUBRELATIONS; idx++) {
result[idx] =
RelationImpl::SUBRELATION_PARTIAL_LENGTHS[idx] + RelationImpl::SUBRELATION_WITNESS_DEGREES[idx];
}
return result;
} else {
return RelationImpl::SUBRELATION_PARTIAL_LENGTHS;
}
};

/**
* @brief Get the subrelation accumulators for the Protogalaxy combiner calculation.
Expand Down Expand Up @@ -139,12 +164,18 @@ template <typename RelationImpl> class Relation : public RelationImpl {

static constexpr std::array<size_t, RelationImpl::SUBRELATION_PARTIAL_LENGTHS.size()> SUBRELATION_TOTAL_LENGTHS =
compute_total_subrelation_lengths<RelationImpl>();
// Compute the subrelation partial lengths adjusted to ZK
static constexpr std::array<size_t, RelationImpl::SUBRELATION_PARTIAL_LENGTHS.size()> ZK_PARTIAL_LENGTHS =
compute_zk_partial_subrelation_lengths<RelationImpl>();

static constexpr size_t RELATION_LENGTH = *std::max_element(RelationImpl::SUBRELATION_PARTIAL_LENGTHS.begin(),
RelationImpl::SUBRELATION_PARTIAL_LENGTHS.end());

static constexpr size_t TOTAL_RELATION_LENGTH =
*std::max_element(SUBRELATION_TOTAL_LENGTHS.begin(), SUBRELATION_TOTAL_LENGTHS.end());
// Determine the maximum subrelation length in the case if ZK Flavors
static constexpr size_t ZK_TOTAL_RELATION_LENGTH =
*std::max_element(ZK_PARTIAL_LENGTHS.begin(), ZK_PARTIAL_LENGTHS.end());

template <size_t NUM_INSTANCES>
using ProtogalaxyTupleOfUnivariatesOverSubrelations =
Expand All @@ -157,6 +188,10 @@ template <typename RelationImpl> class Relation : public RelationImpl {
NUM_INSTANCES - 1>;
using SumcheckTupleOfUnivariatesOverSubrelations =
TupleOfUnivariates<FF, RelationImpl::SUBRELATION_PARTIAL_LENGTHS>;
// The containter constructor for sumcheck univariates corresponding to each subrelation in ZK Flavor's relations
using ZKSumcheckTupleOfUnivariatesOverSubrelations =
TupleOfUnivariates<FF, compute_zk_partial_subrelation_lengths<RelationImpl>()>;

using SumcheckArrayOfValuesOverSubrelations = ArrayOfValues<FF, RelationImpl::SUBRELATION_PARTIAL_LENGTHS>;

// These are commonly needed, most importantly, for explicitly instantiating
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class MegaFlavor {
using CommitmentKey = bb::CommitmentKey<Curve>;
using VerifierCommitmentKey = bb::VerifierCommitmentKey<Curve>;

// Indicates that this flavor runs with non-ZK Sumcheck.
static constexpr bool HasZK = false;
static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES;
// The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often
// need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`.
Expand Down Expand Up @@ -74,6 +76,8 @@ class MegaFlavor {
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1;
static constexpr size_t BATCHED_RELATION_TOTAL_LENGTH = MAX_TOTAL_RELATION_LENGTH + 1;
static constexpr size_t NUM_RELATIONS = std::tuple_size_v<Relations>;
// The total number of witnesses including shifts and derived entities.
static constexpr size_t NUM_ALL_WITNESS_ENTITIES = 23;

// For instances of this flavour, used in folding, we need a unique sumcheck batching challenges for each
// subrelation. This
Expand Down Expand Up @@ -196,6 +200,7 @@ class MegaFlavor {
return_data_read_counts, // column 21
return_data_read_tags, // column 22
return_data_inverses); // column 23
auto get_to_be_shifted() { return RefArray{ z_perm }; };
};

/**
Expand Down Expand Up @@ -230,6 +235,7 @@ class MegaFlavor {
this->return_data_inverses,
};
}
auto get_to_be_shifted() { return DerivedEntities<DataType>::get_to_be_shifted(); }

MSGPACK_FIELDS(this->w_l,
this->w_r,
Expand Down Expand Up @@ -257,18 +263,44 @@ class MegaFlavor {
this->return_data_inverses);
};

template <typename DataType> class ShiftedEntities {
/**
* @brief Class for ShiftedWitnessEntities, containing only shifted witness polynomials.
*/
template <typename DataType> class ShiftedWitnessEntities {
public:
DEFINE_FLAVOR_MEMBERS(DataType,
w_l_shift, // column 0
w_r_shift, // column 1
w_o_shift, // column 2
w_4_shift, // column 3
z_perm_shift) // column 4

auto get_shifted_witnesses() { return RefArray{ w_l_shift, w_r_shift, w_o_shift, w_4_shift, z_perm_shift }; };
};

/**
* @brief Class for ShiftedEntities, containing shifted witness and table polynomials.
*/
template <typename DataType> class ShiftedTables {
public:
DEFINE_FLAVOR_MEMBERS(DataType,
table_1_shift, // column 0
table_2_shift, // column 1
table_3_shift, // column 2
table_4_shift, // column 3
w_l_shift, // column 4
w_r_shift, // column 5
w_o_shift, // column 6
w_4_shift, // column 7
z_perm_shift) // column 8
table_4_shift // column 3
)
};

/**
* @brief Class for ShiftedEntities, containing shifted witness and table polynomials.
*/
template <typename DataType>
class ShiftedEntities : public ShiftedTables<DataType>, public ShiftedWitnessEntities<DataType> {
public:
DEFINE_COMPOUND_GET_ALL(ShiftedTables<DataType>, ShiftedWitnessEntities<DataType>)

auto get_shifted_witnesses() { return ShiftedWitnessEntities<DataType>::get_all(); };
auto get_shifted_tables() { return ShiftedTables<DataType>::get_all(); };
};

public:
Expand All @@ -288,25 +320,40 @@ class MegaFlavor {
public:
DEFINE_COMPOUND_GET_ALL(PrecomputedEntities<DataType>, WitnessEntities<DataType>, ShiftedEntities<DataType>)

auto get_wires() { return RefArray{ this->w_l, this->w_r, this->w_o, this->w_4 }; };
auto get_wires() { return WitnessEntities<DataType>::get_wires(); };
auto get_selectors() { return PrecomputedEntities<DataType>::get_selectors(); }
auto get_sigmas() { return RefArray{ this->sigma_1, this->sigma_2, this->sigma_3, this->sigma_4 }; };
auto get_ids() { return RefArray{ this->id_1, this->id_2, this->id_3, this->id_4 }; };
auto get_tables() { return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4 }; };
// Gemini-specific getters.
auto get_sigmas() { return PrecomputedEntities<DataType>::get_sigma_polynomials(); };
auto get_ids() { return PrecomputedEntities<DataType>::get_id_polynomials(); };
auto get_tables() { return PrecomputedEntities<DataType>::get_table_polynomials(); };
auto get_unshifted()
{
return concatenate(PrecomputedEntities<DataType>::get_all(), WitnessEntities<DataType>::get_all());
};

auto get_precomputed() { return PrecomputedEntities<DataType>::get_all(); }
auto get_witness() { return WitnessEntities<DataType>::get_all(); };
auto get_to_be_shifted()
{
return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l,
this->w_r, this->w_o, this->w_4, this->z_perm };
return concatenate(PrecomputedEntities<DataType>::get_table_polynomials(),
WitnessEntities<DataType>::get_wires(),
WitnessEntities<DataType>::get_to_be_shifted());
};
auto get_precomputed() { return PrecomputedEntities<DataType>::get_all(); }
auto get_shifted() { return ShiftedEntities<DataType>::get_all(); };
// getter for shifted witnesses
auto get_shifted_witnesses() { return ShiftedWitnessEntities<DataType>::get_all(); };
// getter for shifted tables
auto get_shifted_tables() { return ShiftedEntities<DataType>::get_shifted_tables(); };
// this getter is used in ZK Sumcheck, where all witness evaluations (including shifts) have to be masked
auto get_all_witnesses()
{
return concatenate(WitnessEntities<DataType>::get_all(),
ShiftedEntities<DataType>::get_shifted_witnesses());
};
// getter for the complement of all witnesses inside all entities
auto get_non_witnesses()
{
return concatenate(PrecomputedEntities<DataType>::get_all(),
ShiftedEntities<DataType>::get_shifted_tables());
};
};

/**
Expand Down
Loading

0 comments on commit b7efd07

Please sign in to comment.