SNARKS via IPs

A SNARK stands for a succinct proof that a certain statement is true. Succinct here is meaning that the proof is "short". For example, I have a statement:

  • I know an such that .

In SNARK, the proof should be short and fast to verify. A trivial proof of the above statement is to simply send to the verifier. However, that proof is not short; it is as big as . Verification is also not fast, as the verifier has to hash the entire message to actually see the proof.

A SNARK can have a proof size of few KBs and verification should take at most seconds.

Interactive Proofs: Motivation & Model

First, we will see what Interactive Proofs (IP)s are and how they differ from a SNARK. Then, we will look at building a SNARK using the IPs.

In an interactive proof, there are two parties: a prover and a verifier .

  • solves a problem (has some claim), and tells the answer (proves the claim) to .
  • Then, they start to have a conversation. 's goal is to convince that the answer is correct.
sequenceDiagram
	actor P as Prover
	actor V as Verifier

	note over P, V: claim x
	loop i = 1, 2, ...
		P ->> V: answer_i
		V ->> P: question_i
	end
	note over V: accept/reject

There are two requirements to this:

  • Completeness: an honest can convince to accept.
  • (Statistical) Soundness: If is dishonest, then will catch this with very high probability. In other words, it is negligibly probable that a dishonest can convince .
    • Note that this must hold even if is computationally unbounded, and is actively trying to fool .
    • If soundness holds only against polynomial-time , then the protocol is actually called an interactive argument, not an interactive proof.

Soundness vs. Knowledge Soundness

With that, we must make note on the different between "soundness" and "knowledge soundness". In a previous lecture by Prof. Boneh, we have talked about knowledge soundness in particular.

So, now let us think of a circuit satisfiability case. Let be some public arithmetic circuit

where is some public statement and is some secret witness. Let us look at the types of "soundness" with this example:

  • Soundness: accepts
  • Knowledge soundness: accepts "knows"

As we can see, knowledge soundness is "stronger" than soundness, the prover MUST know the existing witness.

However, soundness itself can be valid in some cases even when knowledge soundness has no meaning. This is usually in cases where there is no "natural" witness. For example, can claim that the output of a program given by on the public input is 42. Well, witness is not used in the program, so there is really nothing to "know" here.

The vice-versa is true too, where knowledge soundness means something but you don't really care about soundness. This is usually in cases where the soundness is trivial. For example, knows the secret key to some Bitcoin account. Well, there does exist a private key to that account for sure. In a "sound" protocol, the verifier could just say "yep, can't argue with that" and accept, without breaking soundness itself.

  • SNARK's that don't have knowledge soundness are called SNARGs, they are studied too!

Public Verifiability

Interactive proofs and arguments only convince the party that is choosing/sending the random challenges, which is bad if there are many verifiers and prover must interact with each of them separately.

Thankfully, we have something called Fiat-Shamir Transform [Fiat, Shamir'87], where a public-coin protocol (an IP where randomness is public) can be made public & non-interactive! The trick is to use a random oracle model (via a hash function in practice) to generate the required randomness on your own.

So, in summary:

Interactive ProofsSNARKs
InteractiveNon-Interactive
Information Theoretically Secure (aka Statistically Secure)Computationally Secure (?)
Not necessarily Knowledge SoundKnowledge Sound

Trivial SNARK is not a SNARK

What is the trivial way to prove that you know some such that ? Well, you could just send right? This has two problems, both against the "succinctness" of a SNARK:

  • could be large 🔴
  • computing could take a lot of time 🔴
  • actually non-interactive when you think about it 🟢

Slightly trivial SNARKs from Interactive Proofs (IPs)

Let us look at the trivial proof from an interactive proof perspective (making it slightly less trivial). Now, the prover will send to the verifier, and somehow convince that the sent satisfies .

  • w could still be large 🔴
  • the verification is a lot faster, verifier is not computing directly! 🟢
  • interactive 🔴

Note that since is sent to the verifier, the supposedly secret witness is no more secret.

Actual SNARKs!

What actually happens in a SNARK is that, instead of sending explicitly, the prover will cryptographically commit to and send that commitment. Again, an IP is used to convince that the committed satisfies .

In doing so, the prover will reveal just enough about the committed to allow the verifier to run its checks in the interactive proof.

  • commitment of is succinct 🟢
  • verification is fast 🟢
  • seems interactive, but can be made non-interactive using Fiat-Shamir transform. The trick there is to use a cryptographic hash function as a source of randomness 🟢

Functional Commitment Schemes

We had talked about some very important functional commitment schemes:

  • Polynomial Commitments: Committing to a univariate polynomial where that fancy notation stands for the set of all univariate polynomials of degree at most .
  • Multilinear Commitments: Committing to a multilinear polynomial in which is the set of all the multilinear polynomials in at most variables, each variable with degree at most 1. Here is an example multilinear polynomial: .
  • Vector Commitments: Committing to a vector which is a vector of elements. With our commitment, we would like to be able to open any cell at a later time, such that . Merkle Tree is an example of vector commitment scheme.

Merkle Tree

Merkle Tree is a very famous vector commitment scheme, and we will look a bit deeper to that. Here is a vector commitment to the vector [m, y, v, e, c, t, o, r].

flowchart BT
	h2 --> h1
	h3 --> h1
	h4 --> h2
	h5 --> h2
  h6 --> h3
  h7 --> h3
  m --> h4
  y --> h4
	v --> h5
  e --> h5
  c --> h6
  t --> h6
  o --> h7
  r --> h7

In this binary tree, every node is made up of the hash of its children:

  • and so on…

The leaf nodes are the elements of the committed vector, m, y, v, and such. The root is the commitment to this vector!

When the prover is asked to show that indeed some element of the vector exists at some position, it will provide only the necessary nodes. For example, a verifier could ask "is there really a t at position 6?". The prover will give: c, t, and . The verifier will do the following:

Then, the verifier will compare the calculate to the root given as a commitment by the prover. If they match, then t is indeed at that specific position in the committed vector! The way this cryptographically works is due to collision resistance in hash functions, more detailed explanation can be found in the video.

In summary, a Merkle Tree works as follows:

  • The root is the commitment to the vector.
  • The reveal a value in the commitment (which is a leaf in the tree) prover does the following:
    • Send sibling hashes of all nodes on root-to-leaf path.
    • Verifier checks if the hashes are consistent with the root hash.
    • The size of this proof to reveal a value is hash values.
  • This is a binding scheme: once the root hash is sent, the committer is bound to the committed vector.
    • Opening any leaf to two different values requires finding a hash collision, assumed to be intractable.

Example: Committing to a univariate

Let us think about the [m, y, v, e, c, t, o, r] commitment example above. Suppose that you have a polynomial so this polynomial has values defined over a very small . The degree should be small too, say something like .

To commit to this polynomial, the prover could simply commit to the following vector:

Here, is just some dummy value.

flowchart BT
	h2 --> h1
	h3 --> h1
	h4 --> h2
	h5 --> h2
  h6 --> h3
  h7 --> h3
  f0 --> h4
  f1 --> h4
	f2 --> h5
  f3 --> h5
  f4 --> h6
  f5 --> h6
  f6 --> h7
  * --> h7

Basically, the prover committed to all evaluations of the polynomial. The verifier can ask for some specific evaluation, by asking to reveal some position in the tree (for example is at the third leaf).

Well, is this really a good method? No, it has quite huge problems actually.

  • First of all, there are nodes in this tree. Evaluating that many elements for large like is a nightmare. We would instead want to have some total evaluation time proportional to the degree bound .
  • Speaking of degree, notice that the verifier has no idea if indeed the committed polynomial has degree at most .

We will see ways to solve these problems within the lecture!

Recall: SZDL Lemma

In our previous lectures, we have touched upon a very important fact: for some univariate polynomial what is the probability that for some ? Well, if it is degree then it has roots, meaning that there are exactly points where evaluates to 0. How many total points are there? The answer is . So in short:

For very large and small this probability becomes negligible; meaning that you can't really come up with some random field element and find that , it is a tiny probability. Following on this "zero-test" fact, you can obtain an "equality-test" with the same reasoning:

So if you have two polynomials and they both evaluate to the same thing, chances are they are the same polynomial!

Schwarts-Zippel-Demillo-Lipton Lemma is a multi-variate generalization of this fact. Let be -variate polynomials of total degree at most . Total degree refers to the maximum sum of degrees of all variables in any term, for example has a total degree due to the first term. The lemma states that:

The reason we mention SZDL in particular is that:

  • interactive proofs tend to make use of multivariate polynomials rather than univariate polynomials.
  • Instead of having a univariate polynomial with a large degree , you can have a multivariate polynomial with a smaller degree which in turn reduces the proof size and makes things much more efficient.

Low-Degree & Multilinear Extensions

We now have some math to do, but do not fear; it will be quite useful!

Definition [Extension]: Given a function , a -variate polynomial over is said to extend if .

Definition [Multilinear Extension]: Any function has a unique multilinear extension (MLE) denoted .

  • Multilinear means the polynomial has degree at most 1 in each variable. For example, is multilinear, but is not.

Example:

Let us think of some function defined over the domain .

Here is the multilinear extension for , shown as which is:

You can check that for it holds that . This multilinear extension is obtained using Lagrange Interpolation, we may get to that later.

Are there other extensions? Well, we have said that multilinear extension is unique, but there are other non-multilinear extensions of . For example:

also works for the inputs in , but it is a quadratic extension (total degree is 2).

Relation to Interactive Proofs

The important fact we must realize about multilinear extensions is the following: consider some functions defined over . Both of these functions have unique MLE's . The cool thing is: if there are any disagreeing inputs such that their evaluations on and are not equal, then the MLEs of these functions will disagree on almost all the points within their domain!

You might think of how the hash of an input changes drastically even if the input is changed slightly. This kind of resembles that, if the two functions have different evaluations on the set of points that they are defined on, then the MLE will have many many different evaluations on a lot of points.

The multilinear extensions "blow up & amplify" the tiny differences between , so that you can see the resulting extreme differences in the extensions .

Quick Evaluation of MLEs

Given as input all evaluations of a function , for any point there is an -time algorithm for evaluating the MLE .

The trick is using Lagrange Interpolation. For every input , define the multilinear Lagrange basis polynomial as follows:

It can be shown that you can get the evaluations of using these:

For each the result can be computed with field operations. As such, the overall algorithm for points takes time . Using dynamic programming, this can be reduced to .

The Sum-Check Protocol

We will now examine a seminal work [Lund-Fortnow-Karloff-Nissan'90], known as the sum-check protocol.

We have a verifier with oracle access to some -variate polynomial over field . The goal of this verifier is compute the quantity:

If you look closely, this sum is actually sum of all evaluations of in . In the naive method, the verifier would query each input, and find the sum in a total of queries. We will consider this to be a costly operation.

Instead, a prover will compute the sum and convince a verifier that this sum is correct. In doing so, the verifier will make only a single query to the oracle! Let's see how. Denote as prover and as verifier.

  • Start: sends the claimed answer . The protocol must check that indeed:

  • Round 1: sends univariate polynomial claimed to equal (H standing for honest):

This sum is basically almost , but instead of we use the variable . Since the entire thing is a sum, and is the only variable; this whole thing is a univariate polynomial.

  • Round 1 Check: now checks that , basically filling in the missing sums for .
    • If this check passes, then can now believe that is the correct answer so long as . Well, how can we check that ?
    • Remember that if two polynomials agree at a random point, they are highly likely to be equal! So, picks a random point and checks that .
    • Calculating is easy for the verifier, it's just some univariate polynomial with a not-so-high degree. However, the verifier does not know .
  • Recursion into Round 2: If you look at the form of , it looks a lot like the sum . So, you can think of doing the same operations for and then do the entire thing to verify the sum .

  • Recursion into Rounds 3, 4, …, : The verifier and prover keep doing this until the last round.
  • Final Round (Round ): Like before, sends univariate polynomial claim to equal which is:

  • Final Round Check: now checks that .
    • Again, if this check passes must make sure that . However, we don't have to recurse anymore!
    • Notice that is just a single query to the . So, can pick a random point and immediately query the oracle to find .
    • No need for anymore rounds, just a single oracle query was enough.

Analysis

  • Completeness: This holds by design, if prover sends the prescribed univariate polynomial in each round, then all of verifier's checks will pass.
  • Soundness: If the prover does not send the prescribed messages, then the verifier rejects with probability at least where is the maximum degree of in any variable.
    • For example, will make this probability which is tiny.
    • You can prove this by induction on the number of variable , see the video for the proof.
  • Cost: Total communication is field elements.
    • sends messages with each being a univariate polynomial of degree at most .
    • sends messages, each being a random field element.
    • runtime is and runtime is , here is the time required to evaluate at one point.

Application: Counting Triangles in a Graph

To demonstrate how sum-check protocol can be applied, we will look at an interactive proof about counting triangles in a graph.

  • Given Input: , representing the adjacency matrix of a graph.
  • Desired Output: which counts the triangles, as if all three points are 1 (meaning that there is an edge) then the term is counted, but if there is only a single 0 there the term is ignored.
  • Fastest known algorithm runs in matrix-multiplication time, currently about .

The protocol works as follows:

  • Interpret the matrix matrix as if it's a function . The video has a great example showing how this works. Basically, to see what value a cell within the matrix contains, you evaluate the function with the respective inputs.
  • Remember SZDL lemma, meaning that there is a unique multilinear extension for that function .
  • Define the polynomial .
  • Apply the sum-check protocol to to compute:

How much is the cost of this protocol?

  • Total communication is .
  • Verifier runtime is , which is linear in the size of matrix. This runtime is dominated by evaluating in the final round of the sum-check protocol.
  • Prover runtime is .

SNARK for Circuit-Satisfiability

Let us get to the highlight of this lecture: how to use all this knowledge for circuit satisfiability? Recall that in this problem we have an arithmetic circuit over of size and output . The prover claims to know a witness such that . For simplicitly, let's take the public input to be empty.

Transcript

We will use a notion of transcript, which is defined as an assignment of a value to every gate in the circuit. A transcript is a correct transcript if it assigns the gate values obtained by evaluating the circuit on a valid witness .

Consider the circuit below:

flowchart BT
	a_1((a_1)) --> X1[x]
	a_1 --> X1[x]
	a_2((a_2)) --> X2[x]
	a_2 --> X2[x]
	a_3((a_3)) --> X3[x]
	a_3 --> X3[x]
	a_4((a_4)) --> X4[x]
	a_4 --> X4[x]
	X1 --> A1[+]
	X2 --> A1[+]
	X3 --> A2[+]
	X4 --> A2[+]
	A1 --> A3[+]
	A2 --> A3[+]

A correct transcript for this circuit yielding output 5 would be the following assignment:

flowchart BT
	a_1((1)) --> X1[1]
	a_1 --> X1
	a_2((0)) --> X2[0]
	a_2 --> X2
	a_3((2)) --> X3[4]
	a_3 --> X3
	a_4((0)) --> X4[0]
	a_4 --> X4
	X1 --> A1[1]
	X2 --> A1
	X3 --> A2[4]
	X4 --> A2
	A1 --> A3[5]
	A2 --> A3

Remember the trick of viewing a matrix as a function back in the "counting triangles" example? Well, we can do a similar trick for transcripts too!

A transcript can be viewed as a function . Assign each gate in a -bit label and view as a function mapping gate labels to . Basically, by giving the correct gate label to this function you can select a value at the circuit transcript, something like for the example above.

Polynomial-IOP for SNARK

Recall that our SNARK is all about proving that we know a secret witness such that for some public input and arithmetic circuit it holds that . Denote the circuit size as .

  • First, we will construct the correct transcript of , which we denote as . We have talked about how this happens in the previous section.
  • Prover will calculate the extension of to obtain a polynomial . This extension is the first message sent to the verifier.

  • The verifier needs to verify that this is indeed true, but it will only make a few evaluations of in doing so.

We have talked about why using extensions was a good idea for this kind of proof. Remember that if there is even just a single tiny error in the transcript, the extension of this transcript will disagree on almost all points with respect to the correct transcript.

Alright then, how do we do it?

Step 1: Moving from to

First, we will construct a -variate polynomial such that: extends a correct transcript if and only if . To evaluate for any , it should suffice to evaluate at only 3 inputs.

As a sketch of the proof, define as the following:

We have two new functions here, let's just quickly introduce what they are:

  • is a multilinear extension of a wiring predicate of a circuit, which returns 1 if and only if is an addition gate and it's two inputs are gates and .
  • is a multilinear extension of a wiring predicate of a circuit, which returns 1 if and only if is a multiplication gate and it's two inputs are gates and .

With this definition, notice what happens:

  • If then . For this to be zero, is required.
  • If then . For this to be zero, is required.
  • Otherwise, .

As such, if the addition and multiplications in the extension behave correctly with respect to the correct transcription , then the sum of evaluating the points on should be 0. As a further note, in structured circuits (circuits with repeating structure & wiring) the computation of and can be made a bit more efficient.

What we accomplish by doing this is the following: the original claim is that extends a correct transcript . This is quite a complicated thing to show per se, there may be many things going on with . on the other hand requires a more simpler structure, just check if the result is 0 for all the inputs.

Note that is sometimes referred to as boolean hypercube within the lecture. This is because is a boolean hypercube (specifically the corners of the hypercube can be labeled as the elements of this set) and we want to vanish over variables using this hypercube.

Step 2: Proving

So, how can the verifier check that indeed ? In doing so, verifier should only evaluate at a single point!

Using a Quotient Polynomial: Imagine for a moment that were a univariate polynomial . In that case, this would be defined over some subset and we would want to check that .

There is a well-known result in polynomials that will be very useful here: if and only if it is divisible by the vanishing polynomial for . The vanishing polynomial is defined as :

The polynomial IOP will work as follows:

  • sends a polynomial such that .
  • verifies this by picking a random and checking .

This approach is not really the best approach though; it has problems.

  • First of all, is not univariate, it is obviously -variate.
  • Having the prover find and send the quotient polynomial is expensive.
  • In the final SNARK, this would mean applying polynomial commitment to additional polynomials, increasing the cost.

Well, we say that there are problems but this approach is actually used by well-known schemes: Marlin, Plonk and Groth16.

Using Sum-Check Protocol: An alternative approach for this step, which we have been foreshadowing throughout this lecture, is the sum-check protocol!

Sum-check handles multi-variate polynomials, and it doesn't require to send additional large polynomials. The sum-check we are interested in is the following:

To capture the general idea, we are working with integers instead of finite field here. When we square the result like that, the entire sum is zero if and only if is zero for all inputs.

  • In the end, the verifier will only compute for some random inputs, and it suffices to compute for that.
  • Outside of these evaluations, runs in time
  • performs field operations given a witness .

That concludes this rather dense lecture! Don't be discouraged if you didn't understand the entire thing, I don't think any of us can really get it in a single run.