Chapter Four: Sum Check Protocol
Exploring the sum check protocol and it rust implementation
The Sum Check Protocol
The sum-check protocol is a fundamental sub-protocol used in various zero-knowledge proofs, particularly in the context of interactive proofs and zero-knowledge succinct non-interactive arguments of knowledge (zk-SNARKs). It was first introduced in the context of probabilistically checkable proofs (PCPs) by Lund, Fortnow, Karloff, and Nisan. The primary purpose of the sum-check protocol is to prove that a given polynomial, evaluated over a specified domain, sums to a particular value.
The sum-check protocol has served as the single most important “hammer” in the design of efficient interactive proofs. (from ProofsArgsAndZk). Suppose we are given a v-variate polynomial defined over a finite field . The purpose of the sum-check protocol is for the prover to provide the verifier with the following sum:
Performing the sum of the evaluations of a polynomial over the boolean hypercube may seem like a very simple task and not so useful especially when the polynomial is represented in the `Evaluation` form, make no mistake, a good number of problems can be translated into this form, having polynomial so big we would have to apply this principle to take advantage of the computational efficiency it births.
The Sum Check Protocol.
Recall this sum check protocol is an interactive protocol that can be made non-interactive using Fiat Shamir
, during this protocol layout we will be exploring this protocol in its interactive form but in the RUST implementation, we will be implementing the protocol as an interactive protocol.
Here is the equation for the sum
Problem Setup
• Prover and Verifier : The two main entities in the protocol.
• Multivariate Polynomial : The polynomial that the prover claims has a specific sum over a domain.
• Domain: Typically, this is for simplicity, meaning all variables can take values 0 or 1, this domain is popularly referred to as the Boolean hypercube.
Protocol Steps
Initialization: The prover and verifier agree on the polynomial and the claimed sum .
Step 1: Sum Reduction
The prover breaks down the original sum into a series of simpler sums. Starting with the outermost sum, the prover expresses it in terms of intermediate sums:
where:
The prover then sends the polynomial to the verifier. This process to achieving this is to reduce this multilinear polynomial to a univariate polynomial by performing a partial evaluation of this polynomial the boolean hypercube of length this would return a univariate polynomial that on evaluation at , and summing this evaluation, the result would be the sum of the polynomial .
Step 2: Verification and Recursive Check
The verifier checks that .
chooses a random element , and sends to .
The prover then defines:
Here comes the recursion
In the th round, for , sends to a univariate polynomial claimed to equal:
checks that , rejecting if not
chooses a random element , and sends r_j$ to $P.
In Round , sends to a univariate polynomial claimed to be equal . You notice that this is the first time the initial claim polynomial is needed for proof generations. checks 0. that .
chooses a random element and evaluates with a single Oracle query to . checks that , rejecting if not.
If has not yet been rejected, halts and accepts.
The sum-check protocol is a cornerstone in the realm of zero-knowledge proofs, especially within interactive proofs and zk-SNARKs. It plays a pivotal role in efficiently verifying that a polynomial sums to a specific value over a given domain, making it an invaluable tool in cryptographic applications. By leveraging the properties of the sum-check protocol, we can translate complex problems into manageable forms, optimizing computational efficiency and ensuring robust verification.
Through its iterative process of reducing multivariate polynomials to univariate forms and utilizing randomness to ensure soundness, the sum-check protocol exemplifies the ingenuity of zero-knowledge proofs. It ensures that the verifier can confidently accept or reject the prover’s claims with minimal interaction and computational overhead. As we delve deeper into the implementation of this protocol, particularly using Rust, we witness its practical applications and the elegance of its design, highlighting its significance in modern cryptographic systems.
SumCheck Protocol By Hand
This subsection would be focused on implementing the steps of the sum check protocol using an example, simulating the feeling of following the protocol step by step by hand.
given a polynomial,
The sum of the polynomial $f(x,y,z)$ over the Boolean hypercube is 12, this is how it was gotten.
This is the computation done by the prover and sends the result (the sum) to verifier to initialise the protocol.
The Protocol
The Prover and the verifier agrees on the
Polynomial
() andSum
. This is done practically by sending the polynomial alongside the computed sum to the verifier.Sum Reduction: The prover computes the polynomial making use of a multilinear polynomial partial evaluation:
This process from where and would be replaced with the boolean hypercube elements from the boolean hypercube of length to . This mathematically implies;
This polynomial which is yielded from the partial evaluation by the prover is sent to the verifier.
Verification and recursive check The verifier performs this check;
if the check fails the prover is been malicious the verifier halts the verification process. The verifier chooses a random number and sends to the prover.
Say ;
With this information, the prover define the polynomial;
This implies;
Performing reduction in the polynomial, still using the Boolean hypercube elements similar to what was done earlier on but this time the length of the Boolean hypercube is 1 less. Mathematically this would imply;
The prover sends to the verifier, then the verifier carries out this check;
This check passes! With this, the verifier can send another random number to the prover to compute the next claim. Say , the prover would respond with a Univariate polynomial; .
The verifier performs this check. The Verifier now performs the last check, verifier chooses another random number ;
Check:
If this check passes, the verifier is mathematically satisfied with the proof of the sum computation.
Where is the initial polynomial are all the random numbers sent by the verifier during the protocol interaction.
This Ends the Sum Check implementation by hand.
Notice it is only at the last round that the initial polynomial is needed, this can be used as a notch for making the RUST implementation more efficient. This also can be switched to using a polynomial commitment scheme for making this algorithm more memory cheap, we will be exploring this in the future.
SumCheck Rust Implementation
A step-by-step approach to building a sum check proving system.
Complete Implementation: Github Repo
The design approach we would be taken is very similar to the over implementations in this book.
Design the structural interface
Comment out the step needed for implementing this interface
Working on any utility function that would be need
Implement the complete interface
Write Unit test. :)
Drawing the Interface
We would be working with two structures to implement the Sum Check
protocol specifications;
Prover
Verifier
Prover Interface
Info:
The Generic
PrimeField
is gotten fromff
cratecalculate_sum
: This function would be used to compute the sum of the polynomial.compute_round_zero_poly
: This function computes the round zero polynomial during the Zeroth round of the Sum Check protocol.sum_check_proof
: This is the main function of the prover, computing theSumCheckProof
of the given polynomial.
Verifier Interface
info:
verify
: This function returns the validity state of of a givenSumCheckProof
, aTrue
ofFalse
.
Note: This is a non-interactive implementation, using Fiat Shamir transcript see Fiat Shamir if you haven't.
Defining Data Structures
We have gotten the interface on how the Sum check proof system implementation would be structured. The main Data structure we would be needing are;
Prover
poly
: This is the polynomial the sum check protocol would be ran on.round_poly
: This is a vector of polynomials yielded during the protocol processround_0_poly
: this is the first polynomial yielded during this protocol.sum
: this is the prover claimed sum.transcript
: this is the Fiat Shamir transcript used to make this protocol implementation non-interactive.
Verifier
The
Verifer
is a very simple structure, having just thetranscript
used for making this protocol non-interactive.SumCheckProof
On give a polynomial to the prover to run the sum check protocol on, the prover return this data structure and the data structure can be verified by the verifier.
polynomial
: this is the polynomial the sum check protocol was ran on.round_poly
: this is a vector of polynomials yielded during the sum check protocol.round_0_poly
: this is the first polynomial yielded during the sum check protocol.sum
: this is the sum that is to be proven.
Implementing Interfaces
Now the interface and data structures has been laid out properly, the next task item to handle is to implement these interfaces on the corresponding data structure, we would be starting with the Prover
.
Prover Interface Implementation
Before diving into the ProverInterface
Implementation, we would be implementing some functions;
Info:
new
: This function creates a new prover instance.new_with_sum
: This function crates a new prover instance with sum already computed.new_with_sum_and_round_zero
: This function creates a new prover instance, computes the sum and computes the round zero polynomial.
Implementing the prover interface
Let's dive in!
Here is something you need to know before going further, the Polynomial
structure used in the implementation, is a multilinear polynomial expressed as a Vec
of evaluations over the Boolean Hypercube
. Trust me, if you don't understand the boolean hypercube or how a polynomial structure can be expressed over the boolean hypercube, now would be the best time. resource
calculate_sum: This is simple the sum of the polynomials evaluation array.
compute_round_zero_poly: This is a very important function in the sum check protocol implementation, it computes the first polynomial yielded by the sum check protocol. This is achieved by iteratively performing a partial evaluation on the main polynomial over the boolean hypercube. After obtaining this polynomial, we need to update the transcript
, the transcript
accepts only bytes as input, the Polynomial
structure provided a utility function for getting the bytes representation of the polynomial structure using this method, to_bytes()
.
sum_check_proof: This is the main function for this Prover
implementation as it computes the SumCheckProof
. Starting off the proof generation process is, computing the round zero polynomial using the method, compute_round_zero_poly()
. Next, we would need a Vec
to hold all the samples
gotten from the transcript, recall this transcript
is emulating a random response from the Verifier
. The the next process is the iteration stage, a lot of compute happens here;
sample pseudo random responses from the
transcript
and also saving this in memory as we would be making use of this later on.Performing recursive partial evaluations on the main polynomial.
After every recursive partial evaluation, we would be appending the resulting multi-linear polynomial to the
transcipt
and push this polynomial to theround_poly
Vec
, this woud be using to create a instance of theSumCheckProof
.Using these data, create the
SumCheckProof
instance.
The Verifier Interface
This verifier interface houses just one function verify
which on providing a SumCheckProof
, it asserts if valid by returning a True
or False
.
verify: This function verifies the sum check proof by taking the following steps.
evaluate the
round_0_poly
at0
and1
and check if the result is same as the stated sum in theSumCheckProof
. if this passes, we can process with the protocol else returnFalse
.append the
round_0_poly
to thetranscript
, we are emulating the input the prover sent in to thetranscript
during proving, doing this we would obtain the samesamples
during verification.evaluate
poly_1
atrand_0
fromtranscript
and check if the evaluation ofpoly_0
at0
and1
is equal topoly_1
atrand_0
.append
poly_1
to thetranscript
repeat step 3 and 4 until the last round
at the last round, check if the evaluation of the last poly at rand(last) is equal to the evaluation of the main poly at all rands. This implies;
Return
True
if non of these checks fails.
SumCheck Protocol Over a Univariate Polynomial
Most if the most efficent use of the sum-check protocol is expressed when polynomails are in multilinear form, but the sum-check protocol is also useful on polynomails expressed as univariate polynomial. This section would be exploring how sum-check can come into play here. It is important to note that sum-check on univariate polynomail is relatively much more simplier.
the SumCheck PIOP verifies whether a univariate polynomial p(X) satisfies certain constraints over a set of evaluation points. For example, it can check whether the polynomial sums to a particular value over a domain $D$
Here:
• is a univariate polynomial.
• is a structured evaluation domain, often a coset of the roots of unity.
• is the claimed sum.
Steps in SumCheck PIOP (Univariate Case)
Prover’s Initial Claim: The prover claims: and commits to .
Verifier’s Random Challenge: The verifier sends a random challenge to the prover.
Prover’s Transformation: The prover reduces the claim to a new polynomial defined by: This reduction leverages the fact that summing over the domain can be encoded as evaluations of p(X) divided by a shifted X - r term.
Verifier’s Query: The verifier queries the value of , ensuring consistency with and the claimed sum .
references: Proofs, Arguments, and Zero-Knowledge by Justin Thaler
Last updated