diff --git a/barretenberg/cpp/docs/src/sumcheck-outline.md b/barretenberg/cpp/docs/src/sumcheck-outline.md
new file mode 100644
index 00000000000..3685b6c8d29
--- /dev/null
+++ b/barretenberg/cpp/docs/src/sumcheck-outline.md
@@ -0,0 +1,457 @@
+# Sumcheck Implementation
+We implement a Zero-Knowledge Sumcheck protocol for relations of a very general form.
+
+The implementation consists of several components.
+- [Non-ZK Sumcheck:](#NonZKSumcheck)
+ We sketch an implementation of the non-zero-knowledge Sumcheck, introduce the main abstractions and the components of the proof system. In [Witness Information Leakage](#NonZKSumcheckLeakage), we determine the sources allowing the verifier to learn the witness information during Sumcheck.
+
+- [Masking Round Univariates with Libra:](#LibraTechnique)
+ To prevent the witness values from leaking through the coefficients of Sumcheck round univariates, we apply a technique introduced in Libra: Succinct Zero-Knowledge Proofs with Optimal Prover Computation.
+ Being represented in Lagrange basis, Libra masking polynomials lead to very simple formulas for contributions to Sumcheck round univariates, see [the following section](#LibraRoundUnivariates).
+ In section [Libra Costs](#LibraCosts), we assess the overhead caused by adding the Libra technique.
+ Although the contribution in field operations is almost negligible, it adds non-trivial expenses during the opening procedure.
+
+- [Masking Evaluations of Multilinear Witnesses:](#MaskingEvalsOfWitnesses)
+ At the stage of proving their evaluations at the challenge point, the multilinear witness polynomials fed to Sumcheck must not reveal any private information.
+ We use a modification of Construction 3 described in Libra allowing the prover to open a new multilinear polynomial in \f$d\f$ variables, where \f$2^d\f$ is the circuit size, which is derived from the witnesses by adding a product of a random scalar and a public quadratic polynomial in \f$d\f$ variables
+
+- [Total Costs:](#ZKCosts) The effect of adding Libra technique and masking evaluations of multilinear witnesses is assessed, and the theoretical upper bound on prover's work is compared to the implemenation costs.
+
+Non ZK-Sumcheck Outline {#NonZKSumcheck}
+========
+- - -
+ ### Sumcheck Relation {#SumcheckRelation}
+
+ Given multilinear polynomials \f$ P_1,\ldots, P_N \in \mathbb{F}[X_0,\ldots, X_{d-1}] \f$ and a polynomial \f$ F \f$ in \f$ N \f$ variables, we run Sumcheck over the polynomial
+ \f{align}{
+ \tilde{F}
+ (X_0,\ldots, X_{d-1}) =
+ pow_{\beta}(X_0,\ldots, X_{d-1}) \cdot F\left( P_1 (X_0,\ldots, X_{d-1}), \ldots, P_N (X_0,\ldots, X_{d-1}) \right)
+ \f}
+to establish that \f$ F(P_1(\vec \ell),\ldots, P_N(\vec \ell) ) = 0 \f$, i.e. that \f$ F \f$ is satisfied at every
+point \f$\vec \ell \{0,1\}^d\f$.
+
+ In the implementation, the relation polynomial \f$ F \f$ is specified by the Flavor.
+ \todo Docs for Flavors and Relations.
+
+ ### Main Parameters {#MainParameters}
+
+The following constants are used in this exposition.
+
+ | Notation | | \f$ \sim \f$ Upper Bound |
+ --------------------|---------------|-----------|
+ | \f$ d \f$ | \ref multivariate_d "number of variables" in multilinear polynomials \f$ P_1,\ldots, P_N\f$ | \f$ 20 \f$ |
+ | \f$ N \f$ | number of Prover Polynomials specified by Flavor's parameter \p NUM_ALL_ENTITIES | \f$ 60 \f$ |
+ | \f$ N_w \f$ | number of Witness Polynomials specified by Flavor's parameter \p NUM_WITNESS_ENTITIES | \f$ 17 \f$ |
+ | \f$ n \f$ | \ref multivariate_n "size of the hypercube", i.e. \f$ 2^d\f$. | \f$ 2^{20} \f$ |
+ | \f$ D \f$ | \ref bb::SumcheckProverRound< Flavor >::BATCHED_RELATION_PARTIAL_LENGTH "total degree of" \f$\tilde{F}\f$ as a polynomial in \f$P_1,\ldots, P_N\f$ incremented by 1 | \f$ 12 \f$ |
+ | \f$ D_w\f$ | [maximum witness degree](#MaximumWitnessDegree) of \f$ F \f$ | \f$ 5 \f$ |
+
+\todo Compute precise upper bounds.
+
+#### Maximum Witness Degree {#MaximumWitnessDegree}
+The significance of this parameter becomes apparent in Section [Masking Evaluations of Multilinear Witnesses](#MaskingEvalsOfWitnesses). It is formally defined as follows
+\f{align}{
+ D_w = \deg_{P_1, \ldots, P_{N_w}} F(P_1,\ldots, P_{N})
+\f}
+where by \f$ \deg_{P_1, \ldots, P_{N_w}} \f$ we mean the total degree of the relation polynomial \f$ F \f$ in the witness polynomials \f$ P_1,\ldots, P_{N_w}\f$ considered as variables.
+
+For example, given a polynomial \f$P_1 + P_{N_w+1} \cdot P_{N_w + 2} \cdot P_{1}^2 \cdot P_{2}\f$ in prover polynomials, where \f$N_w>2\f$, its witness degree \f$ D_w \f$ is \f$3\f$, whereas its total degree \f$D\f$ is equal to \f$ 6 \f$.
+
+## Sumcheck Prover Algorithm {#NonZKSumcheckProver}
+- - -
+We remark that prior to running Sumcheck, the prover commits to multilinear polynomials \f$P_1,\ldots, P_{N_w}\f$, and sends the commitments to the verifier and that the total sum and the relation polynomial \f$ \tilde F \f$ are public.
+
+The prover algorithm is implemented in the \ref bb::SumcheckProver< Flavor > "Sumcheck Prover" class. See its documentation for a more detailed description of methods described below. The Sumcheck Round routine is abstracted into \ref bb::SumcheckProverRound< Flavor > "Sumcheck Prover Round" class, which contains most computational steps.
+
+
+
+#### Set up Prover Polynomials {#ProverPolynomialsSetup}
+
+The polynomials \f$P_1,\ldots, P_N\f$ are abstracted in the class ProverPolynomials specific to a Flavor, e.g. \ref bb::GoblinUltraFlavor::ProverPolynomials "Goblin Ultra Flavor".
+Sumcheck Prover algorithm takes a reference to an object of this class.
+
+#### Compute Round Univariates and add them to Transcript {#ComputeRoundUnivariates}
+The prover evaluates the round univariate
+\f{align}{
+ \tilde{S}^i = \sum_{\vec \ell \in \{0,1\}^{d-1-i}} \tilde{F}\left(P_1(u_0,\ldots, u_{i-1}, X_i,\vec \ell), \ldots, P_N(u_0,\ldots, u_{i-1}, X_i,\vec \ell)\right)
+\f}
+over the domain \f$ 0,\ldots, D \f$. In fact, it is more efficient to perform this computation sub-relation-wise, because the degrees of individual subrelations as polynomials in \f$ P_1,\ldots, P_N\f$ are generally smaller than \f$D\f$ defined in [Main Parameters](#MainParameters). Taking this into account, for a given subrelation of \f$F\f$, we perform expensive subrelation evaluations at points \f$(u_0,\ldots, u_{i-1}, k, \vec \ell)\f$ for \f$\ell \in \{0,1\}^{d-1-i} \f$ and \f$k\f$ from \f$0\f$ only up to the degree of the subrelation as a polynomial in \f$P_1,\ldots,P_N\f$ incremented by \f$1\f$.
+
+At the implementation level, the evaluations of \f$\tilde{S}^i\f$ are obtained using the method \ref bb::SumcheckProverRound< Flavor >::compute_univariate "compute univariate" consisting of the following sub-methods:
+
+ - \ref bb::SumcheckProverRound::extend_edges "Extend evaluations" of linear univariate
+polynomials \f$ P_j(u_0,\ldots, u_{i-1}, X_i, \vec \ell) \f$ to the domain \f$0,\ldots, D\f$. It is a cheap operation applied only once for every \f$\vec \ell \in \{0,1\}^d\f$ which allows to compute subrelations of \f$ F \f$ at such arguments.
+ - \ref bb::SumcheckProverRound::accumulate_relation_univariates "Accumulate per-relation contributions" of the extended
+polynomials to auxiliary univariates \f$ T^i(X_i)\f$ defined in \ref SumcheckProverContributionsofPow "this section"
+ - \ref bb::SumcheckProverRound::extend_and_batch_univariates "Extend and batch the subrelation contributions"
+multiplying by the constants \f$c_i\f$ and the evaluations of \f$ ( (1−X_i) + X_i\cdot \beta_i ) \f$ stemming from \f$F\f$ being multiplied by \f$pow_{\beta}\f$.
+
+#### Get Round Challenge {#GetRoundChallenge}
+
+After computing Round Univariate and adding its evaluations \f$\tilde{S}^i(0),\ldots, \tilde{S}^i(D)\f$ to the transcript, the prover generates Round Challenge \f$ u_i \f$ by hashing the transcript.
+
+#### Populate/Update Book-keeping Table {#BookKeepingTable}
+To keep prover's work linear in the number of coefficients of \f$P_1,\ldots, P_N\f$, we \ref bb::SumcheckProver< Flavor >::partially_evaluate "populate" a table of \f$\texttt{partially_evaluated_polynomials}\f$ after getting the first challenge \f$ u_0 \f$ with the values \f$P_j(u_0,\vec \ell )\f$, namely
+\f{align}{
+ \texttt{partially_evaluated_polynomials}_{\ell,j} \gets P_j(0, \ell) + u_{0} \cdot \left(P_j(1, \vec \ell) - P_j(0, \ell)\right) \f}
+for \f$ \vec \ell \in \{0,1\}^{d-1}\f$ identified with the binary representation of \f$ 0\leq \ell \leq 2^{d-1}-1\f$.
+
+In Round \f$0< i \leq d-1\f$, the prover algorithm \ref bb::SumcheckProver< Flavor >::partially_evaluate "updates" the top \f$ 2^{d-1 - i}\f$ values in the book-keeping table
+\f{align}{
+ \texttt{partially_evaluated_polynomials}_{\ell,j} \gets \texttt{partially_evaluated_polynomials}_{2 \ell,j} + u_{i} \cdot (\texttt{partially_evaluated_polynomials}_{2\ell+1,j} - \texttt{partially_evaluated_polynomials}_{2\ell,j}) \f}
+ where \f$\vec \ell \in \{0,1\}^{d-1-i}\f$.
+ After the final update, i.e. when \f$ i = d-1 \f$, the upper row of the table contains the evaluations of Prover Polynomials at the challenge point \f$ (u_0,\ldots, u_{d-1}) \f$.
+
+
+#### Add Claimed Evaluations to Transcript {#ClaimedEvaluations}
+After computing the last challenge \f$ u_{d-1} \f$ in Round \f$ d-1 \f$ and updating \f$
+\texttt{partially_evaluated_polynomials} \f$, the prover looks into the top row of the table containing evaluations
+\f$P_1(u_0,\ldots, u_{d-1}), \ldots, P_N(u_0,\ldots, u_{d-1})\f$ and concatenates these values with the last challenge
+to the transcript.
+
+
+
+
+## Sumcheck Verifier Algorithm {#NonZKSumcheckVerifier}
+- - -
+
+The verifier algorithm is implemented in the \ref bb::SumcheckVerifier< Flavor > "Sumcheck Verifier" class. See its documentation for a more detailed description of methods described below. The Sumcheck Round verification routine is abstracted into \ref bb::SumcheckVerifierRound< Flavor > "Sumcheck Verifier Round" class.
+
+The verifier's work reduces to the following.
+
+For \f$ i = 0,\ldots, d-1\f$:
+ - Using \ref bb::BaseTranscript::receive_from_prover "receive_from_prover" method from \ref bb::BaseTranscript< TranscriptParams > "Base Transcript Class", extract the evaluations of Round Univariate \f$ \tilde{S}^i(0),\ldots, \tilde{S}^i(D) \f$ from the transcript.
+ - \ref bb::SumcheckVerifierRound< Flavor >::check_sum "Check target sum": \f$\quad \sigma_{
+ i } \stackrel{?}{=} \tilde{S}^i(0) + \tilde{S}^i(1) \f$.
+ - \ref bb::BaseTranscript::get_challenge "Get the next challenge" \f$u_i\f$ by hashing the transcript.
+ method.
+ - \ref bb::SumcheckVerifierRound< Flavor >::compute_next_target_sum "Compute next target sum" :\f$ \quad \sigma_{i+1}
+ \gets \tilde{S}^i(u_i) \f$
+
+### Verifier's Data before Final Step {#SumcheckVerifierData}
+Entering the final round, the verifier has already checked that
+\f$\quad \sigma_{ d-1 } = \tilde{S}^{d-1}(0) + \tilde{S}^{d-1}(1) \f$
+and computed \f$\sigma_d = \tilde{S}^{d-1}(u_{d-1})\f$.
+
+### Final Verification Step {#NonZKSumcheckVerification}
+- Extract claimed evaluations of prover polynomials \f$P_1,\ldots, P_N\f$ at the challenge point \f$
+ (u_0,\ldots,u_{d-1}) \f$ from the transcript and \ref bb::SumcheckVerifierRound< Flavor >::compute_full_honk_relation_purported_value "compute evaluation:"
+ \f{align}{\tilde{F}\left( P_1(u_0,\ldots, u_{d-1}), \ldots, P_N(u_0,\ldots, u_{d-1}) \right)\f}
+
+- Compare \f$ \sigma_d \f$ against the evaluation of \f$ \tilde{F} \f$ at \f$P_1(u_0,\ldots, u_{d-1}), \ldots,
+ P_N(u_0,\ldots, u_{d-1})\f$:
+ \f{align}{\quad \sigma_{ d } \stackrel{?}{=} \tilde{F}\left(P_1(u_{0}, \ldots, u_{d-1}),\ldots, P_N(u_0,\ldots,
+ u_{d-1})\right)\f}
+
+
+## Witness Information Leakage {#NonZKSumcheckLeakage}
+
+--------
+
+As explained in Section 13.3 of Proofs, Arguments, and Zero-Knowledge, there are two main sources that leak prover's private information:
+- Evaluations of Round Univariates \f$ \tilde{S}^i\f$
+- Evaluations of witness polynomials \f$P_1,\ldots, P_{N_w}\f$ that the prover sends and proves at the last step of Sumcheck.
+
+These issues are resolved by enhancing Sumcheck with a technique that randomizes any given number of evaluations of \f$\tilde{S}^{i} \f$ and a technique that randomizes evaluations of witness polynomials \f$ P_1,\ldots, P_{N_w} \f$ at the challenge point \f$(u_0,\ldots, u_{d-1})\f$ obtained in Sumcheck.
+
+-------
+
+Masking Round Univariates with Libra {#LibraTechnique}
+========
+-----
+
+## Main Idea of Libra {#LibraMainIdea}
+
+To prevent the witness information leakage through the Round Univariates determined by their evaluations over the domain \f$ \{0,\ldots, \tilde{D}\}\f$, where \f$\tilde{D} \geq D\f$, the Sumcheck Prover masks them using a low-degree multivariate polynomial
+\f{align}{
+ G \gets \sum_{i=0}^{d-1} g_{i}(X_i),
+\f}
+where
+\f{align}{
+ g_{i} = \sum_{j=0}^{\tilde{D}} g_{i,j} \cdot L_{j,\{0,\ldots, D\}}(X_i) \quad \text{for } (g_{i,j}) \gets_{\$} \mathbb{F}^{d\cdot (\tilde{D}+1)}
+\f}
+and \f$L_{j, \{0,\ldots, \tilde{D}\}}\f$ is the \f$j\f$th univariate Lagrange polynomial for the domain \f$\{0,\ldots, \tilde{D}\}\f$. Recall that \f$\deg_{X_i} \left(L_{j, \{0,\ldots, \tilde{D}\}} (X_i)\right) = \tilde{D}\f$.
+
+Set
+\f{align}{
+ \gamma \gets \sum_{\vec \ell \in \{0,1\}^{d}} G(\vec \ell)
+\f}
+as the value that the honest prover sends to the verifier, and let \f$\rho\f$ be the verifier's challenge.
+Then instead of proving that \f$\sum \tilde{F}\left(\vec \ell\right) =\sigma\f$ as in [Non-ZK Sumcheck](\ref NonZKSumcheck), we run the protocol that establishes that
+\f{align}{
+ \sum_{\vec \ell \in\{0,1\}^{d}} \left(\tilde{F}(P_1(\vec \ell), \ldots, P_N(\vec \ell)) + \rho \cdot G(\vec \ell)\right) = \sigma + \rho \cdot \gamma.
+\f}
+### Properties of Libra Masking Polynomial {#PropertiesOfTheMaskingPolynomial}
+
+Observe that \f$ G \f$ has several important properties
+- For \f$ i = 0,\ldots, d-1\f$, the partial degrees \f$ \deg_{X_i} G = \tilde{D}\f$.
+- The coefficients of \f$ G \f$ are independent and uniformly distributed.
+- Evaluations of \f$ G \f$ at \f$ \vec \ell \in \{0,1\}^d\f$ and related Sumcheck Round Univariates are efficiently computable.
+
+The first two properties imply that the evaluations over the domain \f$ \{0,\ldots, \tilde{D}\}\f$ defining Libra Round Univariates , i.e. round univariates for \f$ G \f$, are independent and uniformly distributed.
+Moreover, since Round Univariates for \f$ \tilde{F} + \rho\cdot G\f$ are the sums of respective unvariates, the second property and the condition \f$ \tilde{D}\geq D \f$ ensure that the evaluations \f$ \tilde{S}^i(0),\ldots,\tilde{S}^i(\tilde D)\f$ defined in [Compute Round Univariates](#ComputeRoundUnivariates) are hidden by random scalars obtained as evaluations of Libra Round Univariates, which are described explicitly [below](#LibraRoundUnivariates).
+
+### Example {#LibraPolynomialExample}
+If in every round of Sumcheck, the prover aims to hide only \f$2\f$ evaluations the Round Univariate, i.e. if \f$\tilde{D} = 1\f$, the masking polynomial \f$ G \f$ has the following form
+\f{align}{
+ G = \left( g_{0,0} (1- X_0) + g_{0,1} X_0 \right) + \ldots + \left( g_{d-1,0} (1- X_{d-1}) + g_{d-1,1} X_{d-1} \right).
+\f}
+## Implementation {#LibraImplementation}
+
+### Committing to Libra Masking Polynomial {#LibraCommitments}
+
+To commit to multivariate polynomial \f$ G \f$, the prover commits to the tuple of univariate polynomials \f$ (g_0,\ldots, g_{d-1})\f$.
+
+### Computing Target Sum {#LibraTargetSum}
+Since \f$G\f$ is a polynomial of a very special form, the computation of \f$\gamma\f$ reduces to the following
+\f{align}{
+ \sum_{\vec \ell \in \{0,1\}^{d}} G(\vec \ell) = \sum_{i=0}^{d-1} \sum_{\vec \ell \in \{0,1\}^{d}} g_{i}(\ell_i) = 2^{d-1} \sum_{i = 0}^{d-1} \left( g_i(0) + g_i(1) \right),
+\f}
+since the evaluations of \f$ g_i \f$ at \f$\vec \ell \in \{0,1\}^{d}\f$ depend only on \f$ \ell_i \f$, and therefore, there are \f$2^{d-1}\f$ summands \f$ g_i(0) \f$ corresponding to the points \f$\vec \ell\f$ with \f$\ell_i=0\f$ and \f$2^{d-1}\f$ summands \f$ g_i(1) \f$ corresponding to \f$\vec \ell\f$ with \f$\ell_i=1\f$.
+
+We set
+\f{align}{
+ \texttt{libra_total_sum} \gets 2^{d-1} \sum_{i = 0}^{d-1} \left( g_i(0) + g_i(1) \right)
+\f}
+
+### Pre-computed Data and Book-Keeping {#LibraBookKeeping}
+As in [Sumcheck Book-keeping](#BookKeepingTable), we use a table of evaluations of Libra univariates to avoid extra computational costs.
+Namely, before Round \f$ i \f$, the prover needs the table of values
+\f{align}{
+ \texttt{libra_table}_{j,k} \gets \rho \cdot 2^{d-1-i} \cdot g_{j,k} \text{ for } j= i,\ldots, d-1, \text{ and } k=0,\ldots, \tilde{D}
+\f}
+and the term
+\f{align}{
+ \texttt{libra_running_sum} \gets \rho \cdot 2^{d-1-i}\left( \sum_{j=0}^{i-1}g_j(u_j) + \sum_{j = i+1}^{d-1} ( g_{j,0} + g_{j,1}) \right).
+\f}
+
+### First Round {#LibraFirstRound}
+
+The prover computes first Libra round univariate
+\f{align}{
+ \texttt{libra_univariate}_0(X_0) = \rho \cdot \sum_{\vec \ell \in \{0,1\}^{d-1}} G(X_0,\vec \ell) =
+ 2^{d-1} \rho\cdot g_0(X_0) + 2^{d-1} \rho \cdot \sum_{i=1}^{d-1}\left(g_i(0)+g_i(1)\right)
+\f}
+which could be expressed as follows
+\f{align}{
+ \texttt{libra_univariate}_0 (k) \gets \texttt{libra_table}_{0,k} + \texttt{libra_running_sum}
+\f}
+for \f$k=0,\ldots, \tilde{D}\f$.
+
+When the prover receives the challenge \f$u_0\f$, it computes the value \f$g_0(u_0)\f$ using \ref bb::Univariate::evaluate "evaluate" method, updates the running sum
+\f{align}{
+ \texttt{libra_running_sum} \gets 2^{-1} \cdot \left( (g_0(u_0) + \texttt{libra_running_sum}) - (\texttt{libra_table}_{1,0} + \texttt{libra_table}_{1,1})\right)
+\f}
+and updates the libra table by releasing the first column and multiplying reamining terms by \f$1/2\f$.
+
+### Round Univariates in Subsequent Rounds {#LibraRoundUnivariates}
+Similarly, to compute the contribution of Libra masking polynomial \f$G\f$ to the round univariates \f$\tilde{S}_i\f$ defined in [Compute Round Univariates](#ComputeRoundUnivariates), consider
+\f{align}{
+ \texttt{libra_univariate}_i(X_i) = \rho \cdot \sum_{\vec \ell \in \{0,1\}^{d-1 - i}} G(u_0,\ldots, u_{i-1}, X_{i}, \vec \ell) =
+ \rho \cdot 2^{d-1 - i} \left( \sum_{j = 0}^{i-1} g_j(u_{j}) + g_{i}(X_i) + \sum_{j=i+1}^{d-1} \left(g_{j,0} + g_{j,1}\right) \right)
+\f}
+Therefore, the contribution of the \f$\texttt{libra_univariate}_{i}(X_{i})\f$ at \f$X_{i} = k\f$ to \f$\tilde{S}^i(k)\f$, where \f$k=0,\ldots, \tilde{D}\f$, is given by the formula
+\f{align}{
+ \texttt{libra_univariate}_i(k) = \rho \cdot 2^{d-1-i} \left(\sum_{j = 0}^{i-1} g_j(u_{j}) + g_{i,k}+ \sum_{j=i+1}^{d-1}\left(g_{j,0}+g_{j,1}\right)\right) = \texttt{libra_table}_{i,k} + \texttt{libra_running_sum}.
+\f}
+
+### Updating Partial Evaluations {#LibraUpdatePartialEvaluations}
+In Rounds \f$ i = 1,\ldots d-2\f$, after correcting Sumcheck round univariate \f$S_{i}(X_{i})\f$ by \f$ \texttt{libra_univariate}_i(X_i)\f$, the prover gets the challenge \f$u_{i}\f$, computes the value \f$\texttt{libra_univariate}_{i}(u_{i})\f$ and updates the running sum
+\f{align}{
+ \texttt{libra_running_sum} \gets 2^{-1} \cdot \left( (g_i(u_i) + \texttt{libra_running_sum}) - (\texttt{libra_table}_{i+1,0} + \texttt{libra_table}_{i+1,1})\right)
+\f}
+
+
+
+### Final Round {#LibraFinalRound}
+After sending the evaluations of \f$\texttt{libra_univariate}_{d-1}\f$ at over the domain \f$\{0,\ldots, \tilde{D}\}\f$, the prover gets the last challenge \f$u_{d-1}\f$ and has to send the claimed evaluation \f$G(u_0,\ldots, u_{d-1})\f$. It boils down to sending and proving the evaluations
+\f{align}{
+ v_i = g_i(u_i) \text{ for } i = 0,\ldots, d-1.
+\f}
+## Libra Costs {#LibraCosts}
+
+The overhead in prover's field operations is linear in \f$ d\cdot \tilde D \f$ with a small constant and therefore, is negligible compared to the number of field operations performed during the main Sumcheck routine.
+
+The main expenses are caused by proving the evaluations of \f$ g_i (u_i) = v_i\f$ in the [Final Round](\ref LibraFinalRound).
+Using the PCS introduced in Section 4 of Efficient polynomial commitment schemes for multiple points and polynomials also known as Shplonk, we reduce the costs of opening \f$ d \f$ univariate polynomials \f$ g_i \f$, each at different \f$ u_i \f$ to the following:
+
+
+ | Prover | Verifier
+ |
---|
Group Operations |
+ \f$ 2 \cdot \tilde D+1\f$ |
+ \f$ d + 3 \f$ |
+
+
+ Field Operations |
+ \f$ O\left(d\cdot (\tilde{D} +1) + \tilde{D} \log(\tilde{D})\right)\f$ |
+ |
+
+
+ Pairings |
+ |
+ 2 |
+
+
+ Proof Size |
+ 2 group elements |
+
+
+
+Masking Evaluations of Multilinear Witnesses {#MaskingEvalsOfWitnesses}
+========
+- - -
+
+At the last step of Sumcheck, the Prover adds the evaluations of multilinear polynomials \f$P_1,\ldots, P_N \f$ at the challenge point \f$\vec u = (u_0,\ldots, u_{d-1})\f$ to the trasncript.
+
+Let \f$ N_w\leq N\f$ and assume that \f$ P_1,\ldots, P_{N_w}\f$ are witness polynomials.
+To mask their evaluations at the challenge point\f$\vec u\f$, the prover samples
+\f{align}{\rho_1,\ldots \rho_{N_w} \gets_{\$} \mathbb{F}^{N_w}\f}
+and sets
+\f{align}{
+ \texttt{masked_witness_polynomial}_j(X_0,\ldots, X_{d-1}) = \widehat{P}_j \gets P_j(X_0,\ldots, X_{d-1}) + \rho_j \cdot \left(\sum_{k=0}^{d-1} X_k(1-X_k) \right).
+\f}
+
+
+Note that for any relation \f$F\f$, we have
+\f{align}{
+ \sum_{\ell \in \{0,1\}^d} pow_{\beta}(X_0,\ldots, X_{d-1}) \cdot F\left(P_1(\ell), \ldots, P_N(\ell)\right)
+ = pow_{\beta}(X_0,\ldots, X_{d-1}) \sum_{\ell \in \{0,1\}^d} F\left(\widehat{P}_1(\ell), \ldots, \widehat{P}_{N_w}(\ell), P_{N_w+1}(\ell), \ldots, P_{N}(\ell)\right)
+\f}
+as \f$P_j\f$ and \f$\widehat{P}_j\f$ agree on the hypercube \f$\{0,1\}^d\f$ for \f$j=1,\ldots, N_w\f$.
+
+### Committing to Prover Polynomials {#CommittingToMaskedWitnesses}
+
+The prover commits to \f$P_j\f$ for \f$j=1,\ldots, N\f$ and to \f$\rho_j\f$ for \f$ j=1, \ldots, N_w\f$ as multilinear polynomials and sends the commitments to the verifier.
+
+### Evaluation Phase {#MaskedEvaluationProtocol}
+At the end of Sumcheck, instead of proving evaluations of witness polynomials \f$P_j\f$ at \f$\vec u\f$ for \f$j=1,\ldots, N_w\f$, the prover opens multilinear polynomials
+\f{align}{
+ \widehat{P}_j^{\vec u} \gets P_j(X_0,\ldots, X_{d-1}) + \rho_j \cdot \left(\sum_{k=0}^{d-1} u_k(1-u_k) \right).
+\f}
+It is important to notice that the verifier could evaluate public polynomial \f$\sum_{k=0}^{d-1} X_k(1-X_k)\f$ and derive the commitments to \f$\widehat{P}_j^{\vec u}\f$ on its own.
+
+The remaining prover polynomials \f$P_{N_w+1}, \ldots, P_{N}\f$ are evaluated at \f$ \vec u \f$ and their evaluations are proved without any modifications.
+
+### Security Check {#SecurityCheck}
+Before proving the evaluations of \f$\widehat{P}_j^{\vec u} \f$, the prover checks that \f$\vec u\f$ does not satisfy the equation \f$\sum_{k=0}^{d-1} X_k(1-X_k) = 0\f$, which generally has many solutions outside of the hypercube \f$\{0,1\}^d\f$.
+
+### Degrees of Round Univariates {#DegreesRoundUnivariatesZK}
+
+Since masked witness polynomials \f$\widehat{P}_j\f$ are of degree \f$2\f$ in every variable, the degree of Sumcheck round univariates is also affected.
+Namely, we set
+\f{align}{
+ \tilde{D} = \max_{i\in\{0,\ldots,d-1\}} \left\{\deg_{X_i} F\left(\widehat{P}_1(X_0,\ldots,X_{d-1}),\ldots, \widehat{P}_{N_w}(X_0,\ldots, X_{d-1}),\widehat{P}_{N_w+1}(X_0,\ldots, X_{d-1}), \ldots, \widehat{P}_{N}(X_0,\ldots, X_{d-1}) \right) \right\} \leq D + D_{w}
+\f}
+for \f$D\f$ and \f$ D_w \f$ defined in [Parameters](\ref MainParameters).
+
+In every round of Sumcheck, the Prover sends univariate polynomials \f$\tilde{S}^i(X_i)\f$ represented by their evaluations at \f$X_i = 0,\ldots, \tilde{D}\f$.
+
+Note that \f$ \tilde{D} \f$ sets up the corresponding parameter of [Libra](#LibraImplementation)
+
+### Book-keeping Tables {#BookKeepingMaskingWitnesses}
+To reduce the computation costs, the prover precomputes the table
+\f{align}{
+ \texttt{masking_terms_evaluations}_{k,j}\gets \rho_j \cdot (1-k) k
+\f}
+for \f$j=1, \ldots, N_w\f$ and \f$ k=2,\ldots, \tilde{D} \f$ and stores the vector of running quadratic terms
+\f{align}{
+ \texttt{running_quadratic_term}_j \gets \rho_j \cdot \sum_{k=0}^{i-1} (1-u_k) u_k.
+\f}
+
+
+### Computing Evaluations of Round Univariates {#RoundUnivariatesMaskedEval}
+In Round \f$i \in \{0,\ldots, d-1\}\f$, the prover computes univariate polynomials
+\f{align}{
+ \widehat{S}^i(X_i) = \sum_{\vec\ell \in \{0,1\}^{d-1-i}} F\left(\widehat{P}_1(u_0,\ldots, u_{i-1}, X_i, \vec \ell),\ldots,\widehat{P}_{N_w}(u_0,\ldots, u_{i-1}, X_i, \vec \ell), P_{N_w+1}(u_0,\ldots, u_{i-1}, X_i, \vec \ell), \ldots, P_{N}(u_0,\ldots, u_{i-1}, X_i, \vec \ell) \right)
+\f}
+which reduces to computing at most \f$ (D+ D_w + 1) \times N \times 2^{d-1 - i}\f$ values
+\f{align}{
+ &\ P_j(u_0,\ldots, u_{i-1}, k, \vec \ell) + \rho_j \cdot \sum_{k=0}^{i-1} u_k(1-u_k) + \rho_j\cdot (1-k) k \quad \text{ for } j=1,\ldots, N_w\\
+ &\ P_j(u_0,\ldots, u_{i-1}, k, \vec \ell) \quad \text { for } j= N_w+1,\ldots, N
+\f}
+The values \f$ \texttt{running_quadratic_term}_j = \rho_j \cdot \sum_{k=0}^{i-1} u_k(1-u_k)\f$ are available from Round \f$i-1\f$.
+The products \f$ \rho_j \cdot (1-k) k\f$ are taken from the table \f$ \texttt{masking_terms_evaluations}\f$.
+
+The prover performs an extra addition per evaluation \f$\widehat{P}_j(u_0,\ldots, u_{i-1}, k, \vec \ell)\f$ for \f$k=0,1\f$ and two extra additions per evaluation for \f$k=2,\ldots, D+D_w\f$ compared to evaluating the original witness polynomials \f$P_j\f$.
+It results in \f$2 (D+D_w) N_w (2^d-1) \f$ extra additions compared to [Non-ZK-Sumcheck](#NonZKSumcheck).
+
+Upon receiving the round challenge \f$ u_i\f$, the prover prepares the correcting term for the next round
+\f{align}{
+ \texttt{running_quadratic_terms}_j \gets \texttt{running_quadratic_terms}_j + \rho_j \cdot (1-u_i) u_i .
+\f}
+
+### Witness Evaluation Masking Costs {#MaskingCosts}
+In contrast to non-ZK-Sumcheck, the prover needs to compute \f$\tilde{D} \sim D+D_w \f$ evaluations of round univariates \f$S_i\f$, which results in
+\f{align}{
+ ((D+D_w)\cdot N + C_a \cdot (D+D_w) + 2\cdot N + 2\cdot (D+D_w) N_w ) (2^d - 1)
+\f}
+addditions and
+\f{align}{
+ (C_m\cdot (D+D_w) + N) \cdot (2^d -1)
+\f}
+multiplications, where \f$C_a\f$ and \f$C_m\f$ are constants corresponding to the number of additions and multiplications required to evaluate the relation polynomial \f$F\f$.
+
+The overhead is summarized in the following table.
+
+
+ | Prover | Verifier
+ |
---|
Group Operations |
+ \f$ + N_w\f$ MSMs of size \f$2^d\f$ (same group element) |
+ \f$ + N_w\f$ MSMs of size 2 |
+
+
+ Field Operations |
+ \f$\times(1+ D_w/D) \f$ |
+ \f$\times(1+D_w/D) \f$ |
+
+
+ Communication |
+ \f$ + N_w\f$ group elements; \f$ +D_w\cdot d\f$ field elements |
+
+
+
+ZK Costs {#ZKCosts}
+========
+- - -
+
+The total costs of ZK Sumcheck are obtained from [Libra Costs](#LibraCosts) and [Witness Evaluation Masking Costs](#MaskingCosts).
+
+
+ | Prover | Verifier
+ |
---|
Group Operations |
+ \f$+ d\f$ MSMs of size \f$(D+D_w)\f$ = [Libra Commitments](#LibraCommitments)
+ \f$+ \left(2 \cdot (D+D_w) D+1\right)\f$ group ops = shplonk
+ \f$+ N_w\f$ MSMs of size \f$2^d\f$ (same group element multiplied by \f$\rho_1,\ldots,\rho_{N_w}\f$)
+ |
+ \f$ + (d + 3) \f$ group ops
+ \f$ + N_w\f$ MSMs of size \f$2\f$
+ |
+
+
+ Field Operations |
+ \f$ \times D_w/D \f$ |
+ \f$ \times D_w/D \f$ |
+
+
+ Pairings |
+ |
+ + 2 |
+
+
+ Communication |
+ \f$+ (d+ 2)\f$ group elements for Libra; \f$+N_w\f$ group elements for witness masking
+ \f$+ D_w \cdot d \f$ field elements |
+
+
+
+## Theoretic Field Operations vs. Implementation
+
+The table above sets a reasonable upper bound on the amount of prover's field operations.
+However, in the implementation, the relation \f$ F \f$ is computed as a vector of its subrelations, which allows us to decrease the costs of computing the round univariates. Namely, for a given subrelation \f$ F_j \f$, its maximum partial degree \f$D_j\f$ and its witness degree \f$D_{w,j} \f$ are generally less than \f$ D\f$ and \f$ D_w \f$, respectively.
+Therefore, we compute \f$ F_j \f$'s contribution to Sumcheck Round Univariates by evaluating the univariate polynomial
+\f{align}{
+ \sum_{\vec \ell\in \{0,1\}^{d-1-i}} pow_{\beta}(u_0,\ldots, u_{i-1}, X_i, \vec \ell) \cdot F_j(u_0,\ldots, u_{i-1}, X_i,\vec \ell)
+\f}
+at \f$ X_i = 0,\ldots, D_i + D_{w,i}\f$ and extend the resulting univariate of degree \f$D_j+D_{w,j}\f$ to the entire domain \f$\{ 0,\ldots, D+D_w\}\f$, which is way cheaper than evaluating the sum above at \f$ X_i = D_{j}+ D_{w,j}+1, \ldots, D+ D_w \f$
+
diff --git a/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp b/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp
index 3ab59ad5705..583a9d3ddf1 100644
--- a/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp
+++ b/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp
@@ -7,109 +7,67 @@
#include
namespace bb {
-/**
- * @brief Succinct representation of the `pow` polynomial that can be partially evaluated variable-by-variable.
- * pow_{\vec{β}}(X_0,X_1,..,X_{d-1}) = \prod_{0≤l struct PowPolynomial {
- // \vec{β} = {β_0, β_1,.., β_{d-1}}
+ /**
+ * @brief The challenges \f$(\beta_0,\ldots, \beta_{d-1}) \f$
+ *
+ */
std::vector betas;
- // The values of pow_\vec{β}(i) for i=0,..,2^d - 1 for the given \vec{β}
+ /**
+ * @brief The consecutive evaluations \f$ pow_{\ell}(\beta) = pow_{\beta}(\vec \ell) \f$ for \f$\vec \ell\f$
+ * identified with the integers \f$\ell = 0,\ldots, 2^d-1\f$
+ *
+ */
std::vector pow_betas;
-
- // At round l of sumcheck this will point to the l-th element in \vec{β}
+ /**
+ * @brief In Round \f$ i\f$ of Sumcheck, it points to the \f$ i \f$-th element in \f$ \vec \beta \f$
+ *
+ */
size_t current_element_idx = 0;
-
- // At round l of sumcheck, the periodicity represents the fixed interval at which elements not containing either of
- // β_0,..,β_l appear in pow_betas
+ /**
+ * @brief In Round \f$ i\f$ of Sumcheck, the periodicity equals to \f$ 2^{i+1}\f$ and represents the fixed interval
+ * at which elements not containing either of \f$ (\beta_0,\ldots ,β_i)\f$ appear in #pow_betas.
+ *
+ */
size_t periodicity = 2;
-
- // The value c_l obtained by partially evaluating one variable in the power polynomial at each round. At the
- // end of round l in the sumcheck protocol, variable X_l is replaced by a verifier challenge u_l. The partial
- // evaluation result is updated to represent pow(u_0,.., u_{l-1}) = \prod_{0 ≤ k < l} ( (1-u_k) + u_k⋅β_k).
+ /**
+ * @brief The value \f$c_i\f$ obtained by partially evaluating one variable in the power polynomial at each round.
+ * At the end of Round \f$ i \f$ in the sumcheck protocol, variable \f$X_i\f$ is replaced by the challenge \f$u_i
+ * \f$. The partial evaluation result is updated to represent \f$ pow_{\beta}(u_0,.., u_{i}) = \prod_{k=0}^{i} (
+ * (1-u_k) + u_k\cdot \beta_k) \f$.
+ *
+ */
FF partial_evaluation_result = FF(1);
explicit PowPolynomial(const std::vector& betas)
: betas(betas)
{}
-
+ /**
+ * @brief Retruns the element in #pow_betas at place #idx.
+ *
+ * @param idx
+ * @return FF const&
+ */
FF const& operator[](size_t idx) const { return pow_betas[idx]; }
-
+ /**
+ * @brief Computes the component at index #current_element_idx in #betas.
+ *
+ * @return FF
+ */
FF current_element() const { return betas[current_element_idx]; }
/**
- * @brief Evaluate the monomial ((1−X_l) + X_l⋅β_l) in the challenge point X_l=u_l.
+ * @brief Evaluate \f$ ((1−X_{i}) + X_{i}\cdot \beta_{i})\f$ at the challenge point \f$ X_{i}=u_{i} \f$.
*/
FF univariate_eval(FF challenge) const { return (FF(1) + (challenge * (betas[current_element_idx] - FF(1)))); };
/**
- * @brief Parially evaluate the pow polynomial in X_l and updating the value c_l -> c_{l+1}.
- *
- * @param challenge l-th verifier challenge u_l
+ * @brief Partially evaluate the \f$pow_{\beta} \f$-polynomial at the new challenge and update \f$ c_i \f$
+ * @details Update the constant \f$c_{i} \to c_{i+1} \f$ multiplying it by \f$pow_{\beta}\f$'s factor \f$\left(
+ * (1-X_i) + X_i\cdot \beta_i\right)\vert_{X_i = u_i}\f$ computed by \ref univariate_eval.
+ * @param challenge \f$ i \f$-th verifier challenge \f$ u_{i}\f$
*/
void partially_evaluate(FF challenge)
{
@@ -120,7 +78,8 @@ template struct PowPolynomial {
}
/**
- * @brief Given \vec{β} = {β_0,...,β_{d-1}} compute pow_\vec{β}(i) for i=0,...,2^{d}-1
+ * @brief Given \f$ \vec\beta = (\beta_0,...,\beta_{d-1})\f$ compute \f$ pow_{\ell}(\vec \beta) = pow_{\beta}(\vec
+ * \ell)\f$ for \f$ \ell =0,\ldots,2^{d}-1\f$.
*
*/
BB_PROFILE void compute_values()
@@ -158,4 +117,72 @@ template struct PowPolynomial {
});
}
};
+/**<
+ * @struct PowPolynomial
+ * @brief Implementation of the methods for the \f$pow_{\ell}\f$-polynomials used in ProtoGalaxy and
+\f$pow_{\beta}\f$-polynomials used in Sumcheck.
+ *
+ * @details
+ * ## PowPolynomial in Protogalaxy
+ *
+ * \todo Expand this while completing PG docs.
+ *
+ * For \f$0\leq \ell \leq 2^d-1 \f$, the \f$pow_{\ell} \f$-polynomials used in Protogalaxy is a multilinear polynomial
+defined by the formula
+ * \f{align} pow_{\ell}(X_0,\ldots, X_{d-1})
+ = \prod_{k=0}^{d-1} ( ( 1-\ell_k ) + \ell_k \cdot X_k )
+ = \prod_{k=0}^{d-1} X_{k}^{ \ell_k }
+ \f}
+ *where \f$(\ell_0,\ldots, \ell_{d-1})\f$ is the binary representation of \f$\ell \f$.
+ *
+ *
+ ## Pow-contributions to Round Univariates in Sumcheck {#PowContributions}
+ * For a fixed \f$ \vec \beta \in \mathbb{F}^d\f$, the map \f$ \ell \mapsto pow_{\ell} (\vec \beta)\f$ defines a
+ polynomial \f{align}{ pow_{\beta} (X_0,\ldots, X_{d-1}) = \prod_{k=0}^{d-1} (1- X_k + X_k \cdot \beta_k)
+ \f}
+such that \f$ pow_{\beta} (\vec \ell) = pow_{\ell} (\vec \beta) \f$ for any \f$0\leq \ell \leq 2^d-1 \f$ and any vector
+\f$(\beta_0,\ldots, \beta_{d-1}) \in \mathbb{F} ^d\f$.
+
+ * Let \f$ i \f$ be the current Sumcheck round, \f$ i \in \{0, …, d-1\}\f$ and \f$ u_{0}, ..., u_{i-1} \f$ be the
+challenges generated in Rounds \f$ 0 \f$ to \f$ i-1\f$.
+ *
+ * In Round \f$ i \f$, we iterate over the points \f$ (\ell_{i+1}, \ldots, \ell_{d-1}) \in
+\{0,1\}^{d-1-i}\f$.
+Define a univariate polynomial \f$pow_{\beta}^i(X_i, \vec \ell) \f$ as follows
+ * \f{align}{ pow_{\beta}^i(X_i, \vec \ell) = pow_{\beta} ( u_{0}, ..., u_{i-1}, X_i, \ell_{i+1}, \ldots,
+\ell_{d-1}) = c_i \cdot ( (1−X_i) + X_i \cdot \beta_i ) \cdot \beta_{i+1}^{\ell_{i+1}}\cdot \cdots \cdot
+\beta_{d-1}^{\ell_{d-1}}, \f} where \f$ c_i = \prod_{k=0}^{i-1} (1- u_k + u_k \cdot \beta_k) \f$. It will be used below
+to simplify the computation of Sumcheck round univariates.
+
+ ### Computing Sumcheck Round Univariates
+ * We identify \f$ \vec \ell = (\ell_{i+1}, \ldots, \ell_{d-1}) \in \{0,1\}^{d-1 - i}\f$ with the binary representation
+of the integer \f$ \ell \in \{0,\ldots, 2^{d-1-i}-1 \}\f$.
+ *
+ * Set
+ \f{align}{S^i_{\ell}( X_i ) = F( u_{0}, ..., u_{i-1}, X_{i}, \vec \ell ), \f}
+ * i.e. \f$ S^{i}_{\ell}( X_i ) \f$ is the univariate of the full relation \f$ F \f$ defined by its partial evaluation
+at \f$(u_0,\ldots,u_{i-1}, \ell_{i+1},\ldots, \ell_{d-1}) \f$
+ * which is an alpha-linear-combination of the subrelations evaluated at this point.
+ *
+ * In Round \f$i\f$, the prover
+ * \ref bb::SumcheckProverRound< Flavor >::compute_univariate "computes the univariate polynomial" for the relation
+defined by \f$ \tilde{F} (X_0,\ldots, X_{d-1}) = pow_{\beta}(X_0,\ldots, X_{d-1}) \cdot F\f$, namely
+ * \f{align}{
+ \tilde{S}^{i}(X_i) = \sum_{ \ell = 0} ^{2^{d-i-1}-1} pow^i_\beta ( X_i, \ell_{i+1}, \ldots, \ell_{d-1} )
+S^i_{\ell}( X_i )
+ * = c_i \cdot ( (1−X_i) + X_i\cdot \beta_i ) \cdot \sum_{ \ell = 0} ^{2^{d-i-1}-1} \beta_{i+1}^{\ell_{i+1}}
+\cdot \ldots \cdot \beta_{d-1}^{\ell_{d-1}} \cdot S^i_{\ell}( X_i ) \f}
+ *
+ * Define
+ \f{align} T^{i}( X_i ) = \sum_{\ell = 0}^{2^{d-i-1}-1} \beta_{i+1}^{\ell_{i+1}} \cdot \ldots \cdot
+\beta_{d-1}^{\ell_{d-1}} \cdot S^{i}_{\ell}( X_i ) \f} then \f$ \deg_{X_i} (T^i) \leq \deg_{X_i} S^i \f$.
+ ### Features of PowPolynomial used by Sumcheck Prover
+ - The factor \f$ c_i \f$ is the #partial_evaluation_result, it is updated by \ref partially_evaluate.
+ - The challenges \f$(\beta_0,\ldots, \beta_{d-1}) \f$ are recorded in #betas.
+ - The consecutive evaluations \f$ pow_{\ell}(\vec \beta) = pow_{\beta}(\vec \ell) \f$ for \f$\vec \ell\f$ identified
+with the integers \f$\ell = 0,\ldots, 2^d-1\f$ represented in binary are pre-computed by \ref compute_values and stored
+in #pow_betas.
+ *
+ */
+
} // namespace bb
\ No newline at end of file
diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp
index 56a4fc3e9b1..5a78502f149 100644
--- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp
+++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp
@@ -7,6 +7,112 @@
namespace bb {
+/*! \brief The implementation of the sumcheck Prover for statements of the form \f$\sum_{\vec \ell \in \{0,1\}^d}
+pow_{\beta}(\vec \ell) \cdot F \left(P_1(\vec \ell),\ldots, P_N(\vec \ell) \right) = 0 \f$ for multilinear polynomials
+\f$P_1, \ldots, P_N \f$.
+
+ \details
+ \section SumcheckProverNotation Notation and Setup
+
+ \subsection SumcheckProverObtainingPolynomials Obtaining Prover/Honk Polynomials
+ The Sumcheck is applied to multivariate polynomials
+\f$P_1, \ldots, P_N\f$ that are specidied by \p Flavor. Namely, \ref prove "prove method" obtains \p full_polynomials by
+reference from \p Flavor 's \ref ProverPolynomials "prover polynomials". In particular, their number \f$N\f$ is
+specified by the \p Flavor.
+
+ ### Sumcheck Relation
+ Given multilinear polynomials \f$ P_1,\ldots, P_N \in \mathbb{F}[X_0,\ldots, X_{d-1}] \f$ and a relation \f$ F \f$
+which is a polynomial in \f$ N \f$ variables, we use Sumcheck over the polynomial
+ * \f{align}{
+ \tilde{F}
+ (X_0,\ldots, X_{d-1}) =
+ pow_{\beta}(X_0,\ldots, X_{d-1}) \cdot F\left( P_1 (X_0,\ldots, X_{d-1}), \ldots, P_N (X_0,\ldots, X_{d-1}) \right)
+ \f}
+to establish that \f$ F(P_1(\vec \ell),\ldots, P_N(\vec \ell) ) = 0 \f$, i.e. that \f$ F \f$ is satisfied, at every
+point of \f$\{0,1\}^d\f$.
+
+ In the implementation, the relation polynomial \f$ F \f$ is determined by \p Flavor::Relations which is fed to \ref
+bb::SumcheckProverRound "Sumcheck Round Prover".
+
+ ## Input and Parameters
+ The following constants are used:
+ - \f$ d \f$ \ref multivariate_d "the number of variables" in the multilinear polynomials
+ - \f$ n \f$ \ref multivariate_n "the size of the hypercube", i.e. \f$ 2^d\f$.
+ - \f$ D = \f$ \ref bb::SumcheckProverRound< Flavor >::BATCHED_RELATION_PARTIAL_LENGTH "total degree of"
+\f$\tilde{F}\f$ as a polynomial in \f$P_1,\ldots, P_N\f$ incremented by 1.
+
+
+ ## Honk Polynomials and Partially Evaluated Polynomials
+
+ Given \f$ N \f$ Honk \ref ProverPolynomials "Prover Polynomials" \f$ P_1, \ldots, P_N \f$, i.e. multilinear polynomials
+in \f$ d \f$ variables.
+
+### Round 0
+At initialization, \ref ProverPolynomials "Prover Polynomials"
+are submitted by reference into \p full_polynomials, which is a two-dimensional array with \f$N\f$ columns and \f$2^d\f$
+rows, whose entries are defined as follows \f$\texttt{full_polynomials}_{i,j} = P_j(\vec i) \f$. Here, \f$ \vec i \in
+\{0,1\}^d \f$ is identified with the binary representation of the integer \f$ 0 \leq i \leq 2^d-1 \f$.
+
+When the first challenge \f$ u_0 \f$ is computed, the method \ref partially_evaluate "partially evaluate" takes as input
+\p full_polynomials and populates \ref partially_evaluated_polynomials "a new book-keeping table" denoted by
+\f$\texttt{partially_evaluated_polynomials} \f$. Its \f$ n/2 = 2^{d-1} \f$ rows will represent the evaluations
+\f$ P_i(u_0, X_1, ..., X_{d-1}) \f$, which are multilinear polynomials in \f$ d-1 \f$ variables.
+
+
+More precisely, it is a table with \f$ 2^{d-1} \f$ rows and \f$ N \f$ columns, such that
+ \f{align}{ \texttt{partially_evaluated_polynomials}_{i,j} = &\ P_j(0, i_1,\ldots, i_{d-1}) + u_0 \cdot
+(P_j(1,i_1,\ldots, i_{d-1})) - P_j(0, i_1,\ldots, i_{d-1})) \\ = &\ \texttt{full_polynomials}_{2 i,j} + u_0 \cdot
+(\texttt{full_polynomials}_{2i+1,j} - \texttt{full_polynomials}_{2 i,j}) \f}
+
+### Updating Partial Evaluations in Subsequent Rounds
+In Round \f$ i < d-1\f$, \ref partially_evaluate "partially evaluate" updates the first \f$ 2^{d-1 - i} \f$ rows of
+\f$\texttt{partially_evaluated_polynomials}\f$ with the evaluations \f$ P_1(u_0,\ldots, u_i, \vec \ell),\ldots,
+P_N(u_0,\ldots, u_i, \vec \ell)\f$ for \f$\vec \ell \in \{0,1\}^{d-1-i}\f$.
+The details are specified in \ref partially_evaluate "the corresponding docs."
+
+### Final Step
+After computing the last challenge \f$ u_{d-1} \f$ in Round \f$ d-1 \f$ and updating \f$
+\texttt{partially_evaluated_polynomials} \f$, the prover looks into the 'top' row of the table containing evaluations
+\f$P_1(u_0,\ldots, u_{d-1}), \ldots, P_N(u_0,\ldots, u_{d-1})\f$ and concatenates these values with the last challenge
+to the transcript.
+
+## Round Univariates
+
+\subsubsection SumcheckProverContributionsofPow Contributions of PowPolynomial
+
+ * Let \f$ \vec \beta = (\beta_0,\ldots, \beta_{d-1}) \in \mathbb{F}\f$ be a vector of challenges.
+ *
+ * In Round \f$i\f$, a univariate polynomial \f$ \tilde S^{i}(X_{i}) \f$ for the relation defined by \f$ \tilde{F}(X)\f$
+is computed as follows. First, we introduce notation
+ - \f$ c_i = pow_{\beta}(u_0,\ldots, u_{i-1}) \f$
+ - \f$ T^{i}( X_i ) = \sum_{ \ell = 0} ^{2^{d-i-1}-1} \beta_{i+1}^{\ell_{i+1}} \cdot \ldots \cdot
+\beta_{d-1}^{\ell_{d-1}} \cdot S^i_{\ell}( X_i ) \f$
+ - \f$ S^i_{\ell} (X_i) = F \left(P_1(u_0,\ldots, u_{i-1}, X_i, \vec \ell), \ldots, P_1(u_0,\ldots, u_{i-1}, X_i, \vec
+\ell) \right) \f$
+
+ As explained in \ref bb::PowPolynomial "PowPolynomial",
+ \f{align}{
+ \tilde{S}^{i}(X_i) = \sum_{ \ell = 0} ^{2^{d-i-1}-1} pow^i_\beta ( X_i, \ell_{i+1}, \ldots, \ell_{d-1} ) \cdot
+S^i_{\ell}( X_i ) = c_i\cdot ( (1−X_i) + X_i\cdot \beta_i ) \cdot \sum_{\ell = 0}^{2^{d-i-1}-1} \beta_{i+1}^{\ell_{i+1}}
+\cdot \ldots \cdot \beta_{d-1}^{\ell_{d-1}} \cdot S^{i}_{\ell}( X_i ). \f}
+ *
+### Computing Round Univariates
+The evaluations of the round univariate \f$ \tilde{S}^i \f$ over the domain \f$0,\ldots, D \f$ are obtained by the
+method \ref bb::SumcheckProverRound< Flavor >::compute_univariate "compute_univariate". The
+implementation consists of the following sub-methods:
+
+ - \ref bb::SumcheckProverRound::extend_edges "Extend evaluations" of linear univariate
+polynomials \f$ P_j(u_0,\ldots, u_{i-1}, X_i, \vec \ell) \f$ to the domain \f$0,\ldots, D\f$.
+ - \ref bb::SumcheckProverRound::accumulate_relation_univariates "Accumulate per-relation contributions" of the extended
+polynomials to \f$ T^i(X_i)\f$
+ - \ref bb::SumcheckProverRound::extend_and_batch_univariates "Extend and batch the subrelation contibutions"
+multiplying by the constants \f$c_i\f$ and the evaluations of \f$ ( (1−X_i) + X_i\cdot \beta_i ) \f$.
+## Transcript Operations
+After computing Round univariates and adding them to the transcript, the prover generates round challenge by hashing the
+transcript. These operations are taken care of by \ref bb::BaseTranscript "Transcript Class" methods.
+## Output
+The Sumcheck output is specified by \ref bb::SumcheckOutput< Flavor >.
+ */
template class SumcheckProver {
public:
@@ -18,7 +124,15 @@ template class SumcheckProver {
using Instance = ProverInstance_;
using RelationSeparator = typename Flavor::RelationSeparator;
+ /**
+ * @brief The size of the hypercube, i.e. \f$ 2^d\f$.
+ *
+ */
const size_t multivariate_n;
+ /**
+ * @brief The number of variables
+ *
+ */
const size_t multivariate_d;
std::shared_ptr transcript;
@@ -26,37 +140,14 @@ template class SumcheckProver {
/**
*
- * @brief (partially_evaluated_polynomials) Suppose the Honk polynomials (multilinear in d variables) are called P_1,
- ..., P_N.
- * At initialization,
- * we think of these as lying in a two-dimensional array, where each column records the value of one P_i on H^d.
- * After the first round, the array will be updated (partially evaluated), so that the first n/2 rows will represent
- the
- * evaluations P_i(u0, X1, ..., X_{d-1}) as a low-degree extension on H^{d-1}. In reality, we elude copying all
- * of the polynomial-defining data by only populating partially_evaluated_polynomials after the first round. I.e.:
-
- We imagine all of the defining polynomial data in a matrix like this:
- | P_1 | P_2 | P_3 | P_4 | ... | P_N | N = number of multivariatesk
- |-----------------------------------|
- group 0 --| * | * | * | * | ... | * | vertex 0
- \-| * | * | * | * | ... | * | vertex 1
- group 1 --| * | * | * | * | ... | * | vertex 2
- \-| * | * | * | * | ... | * | vertex 3
- | * | * | * | * | ... | * |
- group m-1 --| * | * | * | * | ... | * | vertex n-2
- \-| * | * | * | * | ... | * | vertex n-1
- m = n/2
- *
- Each group consists of N edges |, and our construction of univariates and partial evaluation
- *
- operations naturally operate on these groups of edges
-
+ * @brief Container for partially evaluated Prover Polynomials at a current challenge. Upon computing challenge \f$
+ u_i \f$, the first \f$2^{d-1-i}\f$ rows are updated using \ref bb::SumcheckProver< Flavor >::partially_evaluate
+ "partially evaluate" method.
*
* NOTE: With ~40 columns, prob only want to allocate 256 EdgeGroup's at once to keep stack under 1MB?
* TODO(#224)(Cody): might want to just do C-style multidimensional array? for guaranteed adjacency?
*/
PartiallyEvaluatedMultivariates partially_evaluated_polynomials;
-
// prover instantiates sumcheck with circuit size and a prover transcript
SumcheckProver(size_t multivariate_n, const std::shared_ptr& transcript)
: multivariate_n(multivariate_n)
@@ -66,8 +157,8 @@ template class SumcheckProver {
, partially_evaluated_polynomials(multivariate_n){};
/**
- * @brief Compute univariate restriction place in transcript, generate challenge, partially evaluate,... repeat
- * until final round, then compute multivariate evaluations and place in transcript.
+ * @brief Compute round univariate, place it in transcript, compute challenge, partially evaluate. Repeat
+ * until final round, then get full evaluations of prover polynomials, and place them in transcript.
*/
SumcheckOutput prove(std::shared_ptr instance)
{
@@ -78,11 +169,16 @@ template class SumcheckProver {
};
/**
- * @brief Compute univariate restriction place in transcript, generate challenge, partially evaluate,... repeat
- * until final round, then compute multivariate evaluations and place in transcript.
- *
- * @details
+ * @brief Compute round univariate, place it in transcript, compute challenge, partially evaluate. Repeat
+ * until final round, then get full evaluations of prover polynomials, and place them in transcript.
+ * @details See Detailed description of \ref bb::SumcheckProver< Flavor > "Sumcheck Prover .
+ * @param full_polynomials Container for ProverPolynomials
+ * @param relation_parameters
+ * @param alpha Batching challenge for subrelations.
+ * @param gate_challenges
+ * @return SumcheckOutput
*/
+
SumcheckOutput prove(ProverPolynomials& full_polynomials,
const bb::RelationParameters& relation_parameters,
const RelationSeparator alpha,
@@ -95,8 +191,8 @@ template class SumcheckProver {
std::vector multivariate_challenge;
multivariate_challenge.reserve(multivariate_d);
- // First round
- // This populates partially_evaluated_polynomials.
+ // In the first round, we compute the first univariate polynomial and populate the book-keeping table of
+ // #partially_evaluated_polynomials, which has \f$ n/2 \f$ rows and \f$ N \f$ columns.
auto round_univariate = round.compute_univariate(full_polynomials, relation_parameters, pow_univariate, alpha);
transcript->send_to_verifier("Sumcheck:univariate_0", round_univariate);
FF round_challenge = transcript->template get_challenge("Sumcheck:u_0");
@@ -118,7 +214,7 @@ template class SumcheckProver {
round.round_size = round.round_size >> 1;
}
- // Final round: Extract multivariate evaluations from partially_evaluated_polynomials and add to transcript
+ // Final round: Extract multivariate evaluations from #partially_evaluated_polynomials and add to transcript
ClaimedEvaluations multivariate_evaluations;
for (auto [eval, poly] :
zip_view(multivariate_evaluations.get_all(), partially_evaluated_polynomials.get_all())) {
@@ -130,19 +226,38 @@ template class SumcheckProver {
};
/**
- * @brief Evaluate at the round challenge and prepare class for next round.
- * Illustration of layout in example of first round when d==3 (showing just one Honk polynomial,
- * i.e., what happens in just one column of our two-dimensional array):
*
- * groups vertex terms collected vertex terms groups after partial evaluation
- * g0 -- v0 (1-X0)(1-X1)(1-X2) --- (v0(1-X0) + v1 X0) (1-X1)(1-X2) ---- (v0(1-u0) + v1 u0) (1-X1)(1-X2)
- * \- v1 X0 (1-X1)(1-X2) --/ --- (v2(1-u0) + v3 u0) X1 (1-X2)
- * g1 -- v2 (1-X0) X1 (1-X2) --- (v2(1-X0) + v3 X0) X1 (1-X2)-/ -- (v4(1-u0) + v5 u0) (1-X1) X2
- * \- v3 X0 X1 (1-X2) --/ / - (v6(1-u0) + v7 u0) X1 X2
- * g2 -- v4 (1-X0)(1-X1) X2 --- (v4(1-X0) + v5 X0) (1-X1) X2 -/ /
- * \- v5 X0 (1-X1) X2 --/ /
- * g3 -- v6 (1-X0) X1 X2 --- (v6(1-X0) + v7 X0) X1 X2 -/
- * \- v7 X0 X1 X2 --/
+ @brief Evaluate Honk polynomials at the round challenge and prepare class for next round.
+ @details At initialization, \ref ProverPolynomials "Prover Polynomials"
+ are submitted by reference into \p full_polynomials, which is a two-dimensional array defined as \f{align}{
+ \texttt{full_polynomials}_{i,j} = P_j(\vec i). \f} Here, \f$ \vec i \in \{0,1\}^d \f$ is identified with the binary
+ representation of the integer \f$ 0 \leq i \leq 2^d-1 \f$.
+
+ * When the first challenge \f$ u_0 \f$ is computed, the method \ref partially_evaluate "partially evaluate" takes
+ as input \p full_polynomials and populates \ref partially_evaluated_polynomials "a new book-keeping table" denoted
+ \f$\texttt{partially_evaluated_polynomials}\f$. Its \f$ n/2 = 2^{d-1} \f$ rows represent the evaluations \f$
+ P_i(u_0, X_1, ..., X_{d-1}) \f$, which are multilinear polynomials in \f$ d-1 \f$ variables.
+ * More precisely, it is a table \f$ 2^{d-1} \f$ rows and \f$ N \f$ columns, such that
+ \f{align}{ \texttt{partially_evaluated_polynomials}_{i,j} = &\ P_j(0, i_1,\ldots, i_{d-1}) + u_0 \cdot (P_j(1,
+ i_1,\ldots, i_{d-1})) - P_j(0, i_1,\ldots, i_{d-1})) \\ = &\ \texttt{full_polynomials}_{2 i,j} + u_0 \cdot
+ (\texttt{full_polynomials}_{2i+1,j} - \texttt{full_polynomials}_{2 i,j}) \f}
+ * We elude copying all of the polynomial-defining data by only populating \ref partially_evaluated_polynomials
+ after the first round.
+
+ * In Round \f$0 class SumcheckProver {
};
/**
* @brief Evaluate at the round challenge and prepare class for next round.
- * Specialization for array, see generic version above.
+ * Specialization for array, see \ref bb::SumcheckProver::partially_evaluate "generic version".
*/
template
void partially_evaluate(std::array& polynomials, size_t round_size, FF round_challenge)
@@ -171,20 +286,72 @@ template class SumcheckProver {
});
};
};
-
+/*! \brief Implementation of the sumcheck Verifier for statements of the form \f$\sum_{\vec \ell \in \{0,1\}^d}
+ pow_{\beta}(\vec \ell) \cdot F \left(P_1(\vec \ell),\ldots, P_N(\vec \ell) \right) = 0 \f$ for multilinear
+ polynomials \f$P_1, \ldots, P_N \f$.
+ *
+ \class SumcheckVerifier
+ \details
+ * Init:
+ * - Claimed Sumcheck sum: \f$\quad \sigma_{ 0 } \gets 0 \f$
+ *
+ * For \f$ i = 0,\ldots, d-1\f$:
+ * - Extract Round Univariate's \f$\tilde{F}\f$ evaluations at \f$0,\ldots, D \f$ from the transcript using \ref
+ bb::BaseTranscript::receive_from_prover "receive_from_prover" method from \ref bb::BaseTranscript< TranscriptParams >
+ "Base Transcript Class".
+ * - \ref bb::SumcheckVerifierRound< Flavor >::check_sum "Check target sum": \f$\quad \sigma_{
+ i } \stackrel{?}{=} \tilde{S}^i(0) + \tilde{S}^i(1) \f$
+ * - Compute the challenge \f$u_i\f$ from the transcript using \ref bb::BaseTranscript::get_challenge "get_challenge"
+ method.
+ * - \ref bb::SumcheckVerifierRound< Flavor >::compute_next_target_sum "Compute next target sum" :\f$ \quad \sigma_{i+1}
+ \gets \tilde{S}^i(u_i) \f$
+ * ### Verifier's Data before Final Step
+ * Entering the final round, the Verifier has already checked that \f$\quad \sigma_{ d-1 } = \tilde{S}^{d-2}(u_{d-2})
+ \stackrel{?}{=} \tilde{S}^{d-1}(0) + \tilde{S}^{d-1}(1) \f$ and computed \f$\sigma_d = \tilde{S}^{d-1}(u_{d-1})\f$.
+ * ### Final Verification Step
+ * - Extract \ref ClaimedEvaluations of prover polynomials \f$P_1,\ldots, P_N\f$ at the challenge point \f$
+ (u_0,\ldots,u_{d-1}) \f$ from the transcript and \ref bb::SumcheckVerifierRound< Flavor
+ >::compute_full_honk_relation_purported_value "compute evaluation:"
+ \f{align}{\tilde{F}\left( P_1(u_0,\ldots, u_{d-1}), \ldots, P_N(u_0,\ldots, u_{d-1}) \right)\f}
+ and store it at \f$ \texttt{full_honk_relation_purported_value} \f$.
+ * - Compare \f$ \sigma_d \f$ against the evaluation of \f$ \tilde{F} \f$ at \f$P_1(u_0,\ldots, u_{d-1}), \ldots,
+ P_N(u_0,\ldots, u_{d-1})\f$:
+ * \f{align}{\quad \sigma_{ d } \stackrel{?}{=} \tilde{F}\left(P_1(u_{0}, \ldots, u_{d-1}),\ldots, P_N(u_0,\ldots,
+ u_{d-1})\right)\f}
+
+ \snippet cpp/src/barretenberg/sumcheck/sumcheck.hpp Final Verification Step
+
+ */
template class SumcheckVerifier {
public:
using Utils = bb::RelationUtils;
using FF = typename Flavor::FF;
+ /**
+ * @brief Container type for the evaluations of Prover Polynomials \f$P_1,\ldots,P_N\f$ at the challenge point
+ * \f$(u_0,\ldots, u_{d-1}) \f$.
+ *
+ */
using ClaimedEvaluations = typename Flavor::AllValues;
using Transcript = typename Flavor::Transcript;
using RelationSeparator = typename Flavor::RelationSeparator;
+ /**
+ * @brief Maximum partial algebraic degree of the relation \f$\tilde F = pow_{\beta} \cdot F \f$, i.e. \ref
+ * MAX_PARTIAL_RELATION_LENGTH "MAX_PARTIAL_RELATION_LENGTH + 1".
+ */
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH;
+ /**
+ * @brief The number of Prover Polynomials \f$ P_1, \ldots, P_N \f$ specified by the Flavor.
+ *
+ */
static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES;
-
+ /**
+ * @brief Number of variables in Prover Polynomials.
+ *
+ */
const size_t multivariate_d;
+
std::shared_ptr transcript;
SumcheckVerifierRound round;
@@ -193,7 +360,6 @@ template class SumcheckVerifier {
: multivariate_d(multivariate_d)
, transcript(transcript)
, round(target_sum){};
-
/**
* @brief Extract round univariate, check sum, generate challenge, compute next target sum..., repeat until
* final round, then use purported evaluations to generate purported full Honk relation value and check against
@@ -249,13 +415,14 @@ template class SumcheckVerifier {
purported_evaluations, relation_parameters, pow_univariate, alpha);
bool checked = false;
+ //! [Final Verification Step]
if constexpr (IsRecursiveFlavor) {
checked = (full_honk_relation_purported_value == round.target_total_sum).get_value();
} else {
checked = (full_honk_relation_purported_value == round.target_total_sum);
}
verified = verified && checked;
-
+ //! [Final Verification Step]
return SumcheckOutput{ multivariate_challenge, purported_evaluations, verified };
};
};
diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp
index 65624855545..9abd4a2feb0 100644
--- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp
+++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp
@@ -7,17 +7,19 @@
namespace bb {
/**
- * @brief Contains the multi-linear evaluations of the polynomials at the challenge point 'u'.
- * These are computed by the prover and need to be checked using a multi-linear PCS like Gemini.
+ * @brief Contains the evaluations of multilinear polynomials \f$ P_1, \ldots, P_N\f$ at the challenge point \f$\vec u
+ * =(u_0,\ldots, u_{d-1})\f$. These are computed by \ref bb::SumcheckProver< Flavor > "Sumcheck Prover" and need to be
+ * checked using Zeromorph.
*/
template struct SumcheckOutput {
using FF = typename Flavor::FF;
using ClaimedEvaluations = typename Flavor::AllValues;
- // u = (u_0, ..., u_{d-1})
+ // \f$ \vec u = (u_0, ..., u_{d-1}) \f$
std::vector challenge;
- // Evaluations in `u` of the polynomials used in Sumcheck
+ // Evaluations in \f$ \vec u \f$ of the polynomials used in Sumcheck
ClaimedEvaluations claimed_evaluations;
- // Whether or not the claimed multilinear evaluations and final sumcheck evaluation have been confirmed
+ // Whether or not the evaluations of multilinear polynomials \f$ P_1, \ldots, P_N \f$ and final Sumcheck evaluation
+ // have been confirmed
std::optional verified = false; // optional b/c this struct is shared by the Prover/Verifier
};
} // namespace bb
diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp
index 51bdf446605..0cbed010cf4 100644
--- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp
+++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp
@@ -8,40 +8,19 @@
namespace bb {
-/*
- Notation: The polynomial P(X0, X1) that is the low-degree extension of its values vij = P(i,j)
- for i,j ∈ H = {0,1} is conveniently recorded as follows:
- (0,1)-----(1,1) v01 ------ v11
- | | | | P(X0,X1) = (v00 * (1-X0) + v10 * X0) * (1-X1)
- X1 | H^2 | | P(X0,X1) | + (v01 * (1-X0) + v11 * X0) * X1
- | | | |
- (0,0) ---- (1,0) v00 -------v10
- X0
-*/
-
-/*
- Example: There are two low-degree extensions Y1, Y2 over the square H^2 in the Cartesian plane.
-
- 3 -------- 7 4 -------- 8
- | | | | Let F(X0, X1) = G(Y1, Y2) = G0(Y1(X0, X1), Y2(X0, X1))
- | Y1 | | Y2 | + α G1(Y1(X0, X1), Y2(X0, X1)),
- | | | | where the relations are G0(Y1, Y2) = Y1 * Y2
- 1 -------- 5 2 -------- 6 and G1(Y1, Y2) = Y1 + Y2.
-
- G1, G2 together comprise the Relations.
-
- In the first round, the computations will relate elements along horizontal lines. As a mnemonic, we
- use the term "edge" for the linear, univariate polynomials corresponding to the four lines
- 1 - 5
- 2 - 6
- 3 - 7
- 4 - 8
-
- The polynomials Y1, Y2 are stored in an array in Multivariates. In the first round, these are arrays
- of spans living outside of the Multivariates object, and in sebsequent rounds these are arrays of field
- elements that are stored in the Multivariates. The rationale for adopting this model is to
- avoid copying the full-length polynomials; this way, the largest polynomial array stores in a
- Multivariates class is multivariates_n/2.
+/*! \brief Imlementation of the Sumcheck prover round.
+ \class SumcheckProverRound
+ \details
+The evaluations of the round univariate \f$ \tilde{S}^i \f$ over the domain \f$0,\ldots, D \f$ are obtained by the
+method \ref bb::SumcheckProverRound< Flavor >::compute_univariate "compute univariate". The
+implementation consists of the following sub-methods:
+
+ - \ref bb::SumcheckProverRound::extend_edges "Extend evaluations" of linear univariate
+ polynomials \f$ P_j(u_0,\ldots, u_{i-1}, X_i, \vec \ell) \f$ to the domain \f$0,\ldots, D\f$.
+ - \ref bb::SumcheckProverRound::accumulate_relation_univariates "Accumulate per-relation contributions" of the extended
+polynomials to \f$ T^i(X_i)\f$
+ - \ref bb::SumcheckProverRound::extend_and_batch_univariates "Extend and batch the subrelation contibutions"
+ multiplying by the constants \f$c_i\f$ and the evaluations of \f$ ( (1−X_i) + X_i\cdot \beta_i ) \f$.
Note: This class uses recursive function calls with template parameters. This is a common trick that is used to force
the compiler to unroll loops. The idea is that a function that is only called once will always be inlined, and since
@@ -59,11 +38,25 @@ template class SumcheckProverRound {
public:
using FF = typename Flavor::FF;
using ExtendedEdges = typename Flavor::ExtendedEdges;
-
- size_t round_size; // a power of 2
-
+ /**
+ * @brief In Round \f$i = 0,\ldots, d-1\f$, equals \f$2^{d-i}\f$.
+ */
+ size_t round_size;
+ /**
+ * @brief Number of batched sub-relations in \f$F\f$ specified by Flavor.
+ *
+ */
static constexpr size_t NUM_RELATIONS = Flavor::NUM_RELATIONS;
+ /**
+ * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials
+ * \f$P_1,\ldots, P_N\f$.
+ */
static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::MAX_PARTIAL_RELATION_LENGTH;
+ /**
+ * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials
+ * \f$P_1,\ldots, P_N\f$ incremented by 1, i.e. it is equal \ref MAX_PARTIAL_RELATION_LENGTH
+ * "MAX_PARTIAL_RELATION_LENGTH + 1".
+ */
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH;
SumcheckTupleOfTuplesOfUnivariates univariate_accumulators;
@@ -77,11 +70,30 @@ template class SumcheckProverRound {
}
/**
- * @brief Extend each edge in the edge group at to max-relation-length-many values.
+ * @brief To compute the round univariate in Round \f$i\f$, the prover first computes the values of Honk
+ polynomials \f$ P_1,\ldots, P_N \f$ at the points of the form \f$ (u_0,\ldots, u_{i-1}, k, \vec \ell)\f$ for \f$
+ k=0,\ldots, D \f$, where \f$ D \f$ is defined as
+ * \ref BATCHED_RELATION_PARTIAL_LENGTH "partial algebraic degree of the relation multiplied by pow-polynomial"
*
- * @details Should only be called externally with relation_idx equal to 0.
- * In practice, multivariates is one of ProverPolynomials or FoldedPolynomials.
+ * @details In the first round, \ref extend_edges "extend edges" method receives required evaluations from the
+ prover polynomials.
+ * In the subsequent rounds, the method receives partially evaluated polynomials.
*
+ * In both cases, in Round \f$ i \f$, \ref extend_edges "the method" receives \f$(0, \vec \ell) \in
+ \{0,1\}\times\{0,1\}^{d-1 - i} \f$, accesses the evaluations \f$ P_j\left(u_0,\ldots, u_{i-1}, 0, \vec \ell\right)
+ \f$ and \f$ P_j\left(u_0,\ldots, u_{i-1}, 1, \vec \ell\right) \f$ of \f$ N \f$ linear polynomials \f$
+ P_j\left(u_0,\ldots, u_{i-1}, X_{i}, \vec \ell \right) \f$ that are already available either from the prover's
+ input in the first round, or from the \ref multivariates table. Using general method
+ \ref bb::Univariate::extend_to "extend_to", the evaluations of these polynomials are extended from the
+ domain \f$ \{0,1\} \f$ to the domain \f$ \{0,\ldots, D\} \f$ required for the computation of the round univariate.
+
+ * Should only be called externally with relation_idx equal to 0.
+ * In practice, #multivariates is either ProverPolynomials or PartiallyEvaluatedMultivariates.
+ *
+ * @param edge_idx A point \f$(0, \vec \ell) \in \{0,1\}^{d-i} \f$, where \f$ i\in \{0,\ldots, d-1\}\f$ is Round
+ number.
+ * @param extended_edges Container for the evaluations of \f$P_j(u_0,\ldots, u_{i-1}, k, \vec \ell) \f$ for
+ \f$k=0,\ldots, D\f$ and \f$j=1,\ldots,N\f$.
*/
template
void extend_edges(ExtendedEdges& extended_edges,
@@ -95,9 +107,26 @@ template class SumcheckProverRound {
}
/**
- * @brief Return the evaluations of the univariate restriction (S_l(X_l) in the thesis) at num_multivariates-many
- * values. Most likely this will end up being S_l(0), ... , S_l(t-1) where t is around 12. At the end, reset all
+ * @brief Return the evaluations of the univariate round polynomials \f$ \tilde{S}_{i} (X_{i}) \f$ at \f$ X_{i } =
+ 0,\ldots, D \f$. Most likely, \f$ D \f$ is around \f$ 12 \f$. At the
+ * end, reset all
* univariate accumulators to be zero.
+ * @details First, the vector of \ref pow_challenges "pow challenges" is computed.
+ * Then, multi-threading is being set up.
+ * Compute the evaluations of partially evaluated Honk polynomials \f$ P_j\left(u_0,\ldots, u_{i-1}, X_{i} , \vec
+ \ell \right) \f$
+ * for \f$ X_{i} = 2, \ldots, D \f$ using \ref extend_edges "extend edges" method.
+ * This method invokes more general \ref bb::Univariate::extend_to "extend_to" method that in this case
+ reduces to a very simple expression \f{align}{ P_j\left( u_0,\ldots, u_{i-1}, k, \vec \ell \right) = P_j\left(
+ u_0,\ldots, u_{i-1}, k-1, \vec \ell \right) + P_j\left( u_0,\ldots, u_{i-1}, 1, \vec \ell \right) - P_j\left(
+ u_0,\ldots, u_{i-1}, 0, \vec \ell \right) \f},
+ * where \f$ k=2,\ldots, D \f$.
+ * For a given \f$ \vec \ell \in \{0,1\}^{d -1 -i} \f$,
+ * we invoke \ref accumulate_relation_univariates "accumulate relation univariates" to compute the contributions of
+ \f$ P_1\left(u_0,\ldots, u_{i-1}, k, \vec \ell \right) \f$,
+ ..., \f$ P_N\left(u_0,\ldots, u_{i-1}, k, \vec \ell \right) \f$ to every sub-relation.
+ * Finally, the accumulators for individual relations' contributions are summed with appropriate factors using
+ method \ref extend_and_batch_univariates "extend and batch univariates".
*/
template
bb::Univariate compute_univariate(
@@ -134,9 +163,11 @@ template class SumcheckProverRound {
for (size_t edge_idx = start; edge_idx < end; edge_idx += 2) {
extend_edges(extended_edges[thread_idx], polynomials, edge_idx);
- // Compute the i-th edge's univariate contribution,
- // scale it by the corresponding pow contribution and add it to the accumulators for Sˡ(Xₗ). The pow
- // contribution represents the elements of pow(\vec{β}) not containing β_0,..., β_l
+ // Compute the \f$ \ell \f$-th edge's univariate contribution,
+ // scale it by the corresponding \f$ pow_{\beta} \f$ contribution and add it to the accumulators for \f$
+ // \tilde{S}^i(X_i) \f$. If \f$ \ell \f$'s binary representation is given by \f$ (\ell_{i+1},\ldots,
+ // \ell_{d-1})\f$, the \f$ pow_{\beta}\f$-contribution is \f$\beta_{i+1}^{\ell_{i+1}} \cdot \ldots \cdot
+ // \beta_{d-1}^{\ell_{d-1}}\f$.
accumulate_relation_univariates(thread_univariate_accumulators[thread_idx],
extended_edges[thread_idx],
relation_parameters,
@@ -155,8 +186,20 @@ template class SumcheckProverRound {
}
/**
- * @brief Given a tuple t = (t_0, t_1, ..., t_{NUM_SUBRELATIONS-1}) and a challenge α,
- * return t_0 + αt_1 + ... + α^{NUM_SUBRELATIONS-1}t_{NUM_SUBRELATIONS-1}).
+ * @brief Given a tuple of tuples of extended per-relation contributions, \f$ (t_0, t_1, \ldots,
+ * t_{\text{NUM_SUBRELATIONS}-1}) \f$ and a challenge \f$ \alpha \f$, scale them by the relation separator
+ * \f$\alpha\f$, extend to the correct degree, and take the sum multiplying by \f$pow_{\beta}\f$-contributions.
+ *
+ * @details This method receives as input the univariate accumulators computed by \ref
+ * accumulate_relation_univariates "accumulate relation univariates" after passing through the entire hypercube and
+ * applying \ref bb::RelationUtils::add_nested_tuples "add_nested_tuples" method to join the threads. The
+ * accumulators are scaled using the method \ref bb::RelationUtils< Flavor >::scale_univariates "scale univariates",
+ * extended to the degree \f$ D \f$ and summed with appropriate \f$pow_{\beta}\f$-factors using \ref
+ * extend_and_batch_univariates "extend and batch univariates method" to return a vector \f$(\tilde{S}^i(0), \ldots,
+ * \tilde{S}^i(D))\f$.
+ *
+ * @param challenge Challenge \f$\alpha\f$.
+ * @param pow_polynomial Round \f$pow_{\beta}\f$-factor given by \f$ ( (1−u_i) + u_i\cdot \beta_i )\f$.
*/
template
static ExtendedUnivariate batch_over_relations(ContainerOverSubrelations& univariate_accumulators,
@@ -175,12 +218,17 @@ template class SumcheckProverRound {
}
/**
- * @brief Extend Univariates to specified size then sum them
- *
+ * @brief Extend Univariates then sum them multiplying by the current \f$ pow_{\beta} \f$-contributions.
+ * @details Since the sub-relations comprising full Honk relation are of different degrees, the computation of the
+ * evaluations of round univariate \f$ \tilde{S}_{i}(X_{i}) \f$ at points \f$ X_{i} = 0,\ldots, D \f$ requires to
+ * extend evaluations of individual relations to the domain \f$ 0,\ldots, D\f$. Moreover, linearly independent
+ * sub-relations, i.e. whose validity is being checked at every point of the hypercube, are multiplied by the
+ * constant \f$ c_i = pow_\beta(u_0,\ldots, u_{i-1}) \f$ and the current \f$pow_{\beta}\f$-factor \f$ ( (1−X_i) +
+ * X_i\cdot \beta_i ) \vert_{X_i = k} \f$ for \f$ k = 0,\ldots, D\f$.
* @tparam extended_size Size after extension
* @param tuple A tuple of tuples of Univariates
- * @param result A Univariate of length extended_size
- * @param pow_polynomial Power polynomial univariate
+ * @param result Round univariate \f$ \tilde{S}^i\f$ represented by its evaluations over \f$ \{0,\ldots, D\} \f$.
+ * @param pow_polynomial Round \f$pow_{\beta}\f$-factor \f$ ( (1−X_i) + X_i\cdot \beta_i )\f$.
*/
template
static void extend_and_batch_univariates(const TupleOfTuplesOfUnivariates& tuple,
@@ -188,7 +236,7 @@ template class SumcheckProverRound {
const bb::PowPolynomial& pow_polynomial)
{
ExtendedUnivariate extended_random_polynomial;
- // Random poly R(X) = (1-X) + X.zeta_pow
+ // Pow-Factor \f$ (1-X) + X\beta_i \f$
auto random_polynomial = bb::Univariate({ 1, pow_polynomial.current_element() });
extended_random_polynomial = random_polynomial.template extend_to();
@@ -201,13 +249,13 @@ template class SumcheckProverRound {
// Except from the log derivative subrelation, each other subrelation in part is required to be 0 hence we
// multiply by the power polynomial. As the sumcheck prover is required to send a univariate to the
// verifier, we additionally need a univariate contribution from the pow polynomial which is the
- // extended_random_polynomial.
+ // extended_random_polynomial which is the
if (!is_subrelation_linearly_independent) {
result += extended;
} else {
// Multiply by the pow polynomial univariate contribution and the partial
- // evaluation result c_l (i.e. pow(u_0,...,u_{l-1})) where u_0,...,u_{l-1} are the verifier challenges
- // from previous rounds)
+ // evaluation result c_i (i.e. \f$ pow(u_0,...,u_{l-1})) \f$ where \f$(u_0,...,u_{i-1})\f$ are the
+ // verifier challenges from previous rounds.
result += extended * extended_random_polynomial * pow_polynomial.partial_evaluation_result;
}
};
@@ -216,19 +264,28 @@ template class SumcheckProverRound {
private:
/**
- * @brief For a given edge, calculate the contribution of each relation to the prover round univariate (S_l in the
- * thesis).
- *
- * @details In Round l, the univariate S_l computed by the prover is computed as follows:
- * - Outer loop: iterate through the points on the boolean hypercube of dimension = log(round_size), skipping
- * every other point. On each iteration, create a Univariate (an 'edge') for each
- * multivariate.
- * - Inner loop: iterate through the relations, feeding each relation the present collection of edges. Each
- * relation adds a contribution
+ * @brief In Round \f$ i \f$, for a given point \f$ \vec \ell \in \{0,1\}^{d-1 - i}\f$, calculate the contribution
+ * of each sub-relation to \f$ T^i(X_i) \f$.
*
- * Result: for each relation, a univariate of some degree is computed by accumulating the contributions of each
- * group of edges. These are stored in `univariate_accumulators`. Adding these univariates together, with
- * appropriate scaling factors, produces S_l.
+ * @details In Round \f$ i \f$, this method computes the univariate \f$ T^i(X_i) \f$ deined in \ref
+ *SumcheckProverContributionsofPow "this section". It is done as follows:
+ * - Outer loop: iterate through the "edge" points \f$ (0,\vec \ell) \f$ on the boolean hypercube \f$\{0,1\}\times
+ * \{0,1\}^{d-1 - i}\f$, i.e. skipping every other point. On each iteration, apply \ref extend_edges "extend edges".
+ * - Inner loop: iterate through the sub-relations, feeding each relation the "the group of edges", i.e. the
+ * evaluations \f$ P_1(u_0,\ldots, u_{i-1}, k, \vec \ell), \ldots, P_N(u_0,\ldots, u_{i-1}, k, \vec \ell) \f$. Each
+ * relation Flavor is endowed with \p accumulate method that computes its contribution to \f$
+ * T^i(X_{i}) \f$
+ *\ref extend_and_batch_univariates "Adding these univariates together", with appropriate scaling factors, produces
+ *required evaluations of \f$ \tilde S^i \f$.
+ * @param univariate_accumulators The container for per-thread-per-relation univariate contributions output by \ref
+ *accumulate_relation_univariates "accumulate relation univariates" for the previous "groups of edges".
+ * @param extended_edges Contains tuples of evaluations of \f$ P_j\left(u_0,\ldots, u_{i-1}, k, \vec \ell \right)
+ *\f$, for \f$ j=1,\ldots, N \f$, \f$ k \in \{0,\ldots, D\} \f$ and fixed \f$\vec \ell \in \{0,1\}^{d-1 - i} \f$.
+ * @param scaling_factor In Round \f$ i \f$, for \f$ (\ell_{i+1}, \ldots, \ell_{d-1}) \in \{0,1\}^{d-1-i}\f$ takes
+ *an element of \ref bb::PowPolynomial< FF >::pow_betas "vector of powers of challenges" at index \f$ 2^{i+1}
+ *(\ell_{i+1} 2^{i+1} +\ldots + \ell_{d-1} 2^{d-1})\f$.
+ * @result #univariate_accumulators are updated with the contribution from the current group of edges. For each
+ * relation, a univariate of some degree is computed by accumulating the contributions of each group of edges.
*/
template
void accumulate_relation_univariates(SumcheckTupleOfTuplesOfUnivariates& univariate_accumulators,
@@ -261,6 +318,18 @@ template class SumcheckProverRound {
}
};
+/*!\brief Implementation of the Sumcheck Verifier Round
+ \class SumcheckVerifierRound
+ \details This Flavor contains the methods
+ * - \ref bb::SumcheckVerifierRound< Flavor >::check_sum "Check target sum": \f$\quad \sigma_{
+ i } \stackrel{?}{=} \tilde{S}^i(0) + \tilde{S}^i(1) \f$
+ * - \ref bb::SumcheckVerifierRound< Flavor >::compute_next_target_sum "Compute next target
+ sum" :\f$ \quad \sigma_{i+1} \gets \tilde{S}^i(u_i) \f$ required in Round \f$ i = 0,\ldots, d-1 \f$.
+ *
+ * The last step of the verifification requires to compute the value \f$ pow(u_0,\ldots, u_{d-1}) \cdot F
+ \left(P_1(u_0,\ldots, u_{d-1}), \ldots, P_N(u_0,\ldots, u_{d-1}) \right) \f$ implemented as
+ * - \ref compute_full_honk_relation_purported_value method needed at the last verification step.
+ */
template class SumcheckVerifierRound {
using Utils = bb::RelationUtils;
using Relations = typename Flavor::Relations;
@@ -272,27 +341,37 @@ template class SumcheckVerifierRound {
using ClaimedEvaluations = typename Flavor::AllValues;
bool round_failed = false;
-
+ /**
+ * @brief Number of batched sub-relations in \f$F\f$ specified by Flavor.
+ *
+ */
static constexpr size_t NUM_RELATIONS = Flavor::NUM_RELATIONS;
+ /**
+ * @brief The partial algebraic degree of the relation \f$\tilde F = pow \cdot F \f$, i.e. \ref
+ * MAX_PARTIAL_RELATION_LENGTH "MAX_PARTIAL_RELATION_LENGTH + 1".
+ */
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH;
FF target_total_sum = 0;
TupleOfArraysOfValues relation_evaluations;
-
// Verifier constructor
explicit SumcheckVerifierRound(FF target_total_sum = 0)
: target_total_sum(target_total_sum)
{
Utils::zero_elements(relation_evaluations);
};
-
+ /**
+ * @brief Check that the round target sum is correct
+ * @details The verifier receives the claimed evaluations of the round univariate \f$ \tilde{S}^i \f$ at \f$X_i =
+ * 0,\ldots, D \f$ and checks \f$\sigma_i = \tilde{S}^{i-1}(u_{i-1}) \stackrel{?}{=} \tilde{S}^i(0) + \tilde{S}^i(1)
+ * \f$
+ * @param univariate Round univariate \f$\tilde{S}^{i}\f$ represented by its evaluations over \f$0,\ldots,D\f$.
+ *
+ */
bool check_sum(bb::Univariate& univariate)
{
- // S^{l}(0) = ( (1−0) + 0⋅ζ^{ 2^l } ) ⋅ T^{l}(0) = T^{l}(0)
- // S^{l}(1) = ( (1−1) + 1⋅ζ^{ 2^l } ) ⋅ T^{l}(1) = ζ^{ 2^l } ⋅ T^{l}(1)
FF total_sum = univariate.value_at(0) + univariate.value_at(1);
- // target_total_sum = sigma_{l} =
// TODO(#673): Conditionals like this can go away once native verification is is just recursive verification
// with a simulated builder.
bool sumcheck_round_failed(false);
@@ -310,27 +389,26 @@ template class SumcheckVerifierRound {
/**
* @brief After checking that the univariate is good for this round, compute the next target sum.
*
- * @param univariate T^l(X), given by its evaluations over {0,1,2,...},
- * equal to S^{l}(X)/( (1−X) + X⋅ζ^{ 2^l } )
- * @param round_challenge u_l
- * @return FF sigma_{l+1} = S^l(u_l)
+ * @param univariate \f$ \tilde{S}^i(X) \f$, given by its evaluations over \f$ \{0,1,2,\ldots, D\}\f$.
+ * @param round_challenge \f$ u_i\f$
+ * @return FF \f$ \sigma_{i+1} = \tilde{S}^i(u_i)\f$
*/
FF compute_next_target_sum(bb::Univariate& univariate, FF& round_challenge)
{
- // Evaluate T^{l}(u_{l})
+ // Evaluate \f$\tilde{S}^{i}(u_{i}) \f$
target_total_sum = univariate.evaluate(round_challenge);
return target_total_sum;
}
/**
- * @brief General purpose method for applying a tuple of arrays (of FFs)
+ * @brief Given the evaluations \f$P_1(u_0,\ldots, u_{d-1}), \ldots, P_N(u_0,\ldots, u_{d-1}) \f$ of the
+ * ProverPolynomials at the challenge point \f$(u_0,\ldots, u_{d-1})\f$ stored in \p purported_evaluations, this
+ * method computes the evaluation of \f$ \tilde{F} \f$ taking these values as arguments.
*
- * @tparam Operation Any operation valid on elements of the inner arrays (FFs)
- * @param tuple Tuple of arrays (of FFs)
*/
// also copy paste in PG
// so instead of having claimed evaluations of each relation in part you have the actual evaluations
- // kill the pow_univariat
+ // kill the pow_univariate
FF compute_full_honk_relation_purported_value(ClaimedEvaluations purported_evaluations,
const bb::RelationParameters& relation_parameters,
const bb::PowPolynomial& pow_polynomial,