Try   HackMD

Compressed SNARK description

High-level

Traits

We add a BatchedRelaxedR1CSSNARKTrait which generalizes the existing RelaxedR1CSSNARKTrait in src/traits/snark.rs. The main difference is that the setup, prove and verify methods take as inputs slices of

  • R1CS shapes S
  • Relaxed R1CS instances U
  • Relaxed R1CS witnesses W

We also implement a CompressedSNARK proof for the SuperNova RecursiveSNARK. The main differences with the original are

  • We initializes the instance/witness pairs for non-folded primary circuits to their default values
  • The primary circuits are proved using an implementation of BatchedRelaxedR1CSSNARK.

In src/spartan, we implement batched versions of snark.rs and pp_snark.rs in batched.rs and batched_ppsnark.rs.
The BatchedRelaxedR1CSSNARK structs in both cases resemble their non-batched counter-parts, except that fields containing commitments or evaluations are replaced with vectors of the same elements. The Sumcheck and PCS proofs are batched so their count remains constant with regards to the number of instances.

The proving/verification keys are also mainly the same, apart from having to store parameters for each individual circuit being proved.

Batching Strategy

The implementation attempts to mirror the existing SNARK and pp-SNARK as much as possible.

In the "IOP" portion of the protocol, where the prover sends commitments to polynomials or evaluations thereof, and the verifier responds with challenges, we simply repeat this step for each instance. The prover messages are added to the transcript in batches, and stored in the proof as vectors.

The Sumcheck claims are set up slightly differently to account for circuits of different sizes. In particular, when a claim of size

m is batched in a Sumcheck over
nm
rounds, we create separate EqPolynomials for each instance. Given a single random challenge
r
, we use the first
m
components of
r=(1,r2,r4,,r2n1)
to define the EqPolynomial for a claim over
m
variables. This ensures all polynomials within a claim have the same size. We explain in the next section how we modified Sumcheck to handle multiple claims of possibly different sizes.

Since the original SNARKs already implement batching of MLE evaluations, we are able to reuse the code to batch all polynomials across the several instances. We explain the subtleties of the batching argument for the ppSNARK in a later section.

Batched Sumcheck

Multiple Sumcheck claims can be batched together by running the protocol over a random-linear combination of the input claims. The existing implementation of ppSNARK already includes this functionality, though we augmented it to handle instances defined over fewer variables.

A Sumcheck instance implements the SumcheckEngine trait. It may be composed of multiple independent claims of the type

σj=x{0,1}nFj(P0(x),P1(x),),
where
Fj
is a multivariate polynomial of degree
d
, and
P0,P1,
are multi-linear polynomials in
n
variables.

In rounds

i=0,1,,n1 after receiving challenges
r=r0,,ri1
, the prover computes for each claim
j
the evaluations at
X=0,2,,d1
of the univariate polynomial
Sj(Xi)=x{0,1}ni1Fj(P0(r,Xi,x),P1(r,Xi,x),,)

The prover sends the random linear combination of all univariate polynomials
Sj(X)
and obtains the Fiat-Shamir challenge
ri
, which is used to bound the variable
Xi
of the multilinear polynomials
P0,P1,
.

After the

n-th round, the prover sends
v0,v1,
equal to the multi-linear evaluations of
P0,P1,
at
r=(r0,,rn1)
.

Non-uniform instances

We can use the same Sumcheck instantiation to batch instances of different sizes.
Let

m<n be the number of variables for the instance

σ=x{0,1}mF(P0(x),P1(x),),

where

P0,P1, are multi-linear polynomials over
m
variables.

We can prove this claim with

n-round Sumcheck by considering the equivalent scaled instance
2nmσσ=x{0,1}nmx{0,1}mF(P0(x),P1(x),).

Here, we "lift" the

m-variate polynomials
P0,P1,
to
n
variables
(X0,,Xn1)
by evaluating them over
(Xnm,,Xn1)
.

In rounds

0i<nm, the univariate polynomial
S(Xi)
is constant and given by
S(Xi)=x{0,1}nmi1x{0,1}mF(P0(x),P1(x),,)2nmi1σ

Given the initial claim
σ
, the prover produces the evaluations of
S(Xi)
without having to perform any work.
Moreover, binding the polynomials
P0,P1
to
ri
has no effect, so we do not need to update the list of evaluations.

Once the prover reaches rounds

nmi<n, the protocol proceeds as usual. We note though that in the final phase, the prover sends the evaluations
v0,v1,
of the polynomials
P0,P1,
at
r=(rnm,,rn1)
.

Implementation

In order to minimize the amount of changes to the existing ppsnark.rs code, we implemented the above technique by recreating a prove_helper method which handles batching of multiple instances of different sizes. Our changes are compatible with the existing Instances implementing the SumcheckEngine trait.

The prove_helper function takes as input multiple SumcheckEngine implementations, each of which contains one or more independent claims. These claims hold over multilinear polynomials of the same size contained in the instance struct. It is assumed that all instances have degree 3. We let

n be the total number of Sumcheck rounds.

Let

I={Ij}j be a set of instances, where
Ij
is defined by

  • Number of variables
    mj
  • Multi-linear polynomials
    {Pj,}
    over variables
    (Xnmj,,Xn1)
  • Initial claims
    σj={σj,k}k
    .
  • Combination functions
    {Fj,k}k

For each instance at index

j and each sub-claim at index
k
it holds that
σj,k=x{0,1}mjFj,k(Pj,0(x),Pj,1(x),)

At the start of the protocol, the verifier sends a challenge
s
used for the random linear combination of claims. For notational simplicity, we define
sj,k
as the power of
s
corresponding to the claim
σj,k
. The full batched claim is given by

j,ksj,k2nmjσj,k=j,ksj,k(x{0,1}nmjx{0,1}mjFj,k(Pj,0(x),Pj,1(x),))

  1. Get
    sF
    from verifier
  2. Set initial batched scaled claim
    e0=j,ksj,k2nmjσj,k
  3. For rounds
    0i<n
    1. Let
      r=(r0,,ri1)
      be the verifier challenges from the previous rounds
    2. For each claim
      k
      in instance
      j
      , compute the univariate polynomial
      Sj,k(i)(Xi)
      • If
        mj<ni
        , set
        Sj,k(i)(Xi)2nimj1σj,k
      • Otherwise, compute evaluate it the usual way by evaluating the sum
        x{0,1}ni1Fj,k(Pj,0(r,Xi,x),Pj,1(r,Xi,x),)
        at
        Xi=0,2,3
    3. Compute the batched univariate polynomial
      S(i)(Xi)=j,ksj,kSj,k(i)(Xi)
      , noting that
      S(i)(1)=eiS(i)(0)
    4. Send
      S(i)(Xi)
      to the verifier and get challenge
      ri
      (the linear coefficient is removed to save on hashing costs)
    5. Compute next batched claimed sum
      ei+1=S(i)(ri)
    6. For each instance
      j
      bind all polynomials
      {Pj,}
      to
      Xi=ri
      • If
        mj<ni
        , then
        Xi
        is not a variable of the polynomial
        Pj,
        so do nothing
      • Else compute the
        2ni1
        evaluation of the multilinear polynomial
        Pj,(r0,,ri,Xi+1,,Xn1)
        in
        ni1
        variables
  4. At the end of the protocol, send to the verifier the evaluations
    {vj,}j,
    for each polynomial at index
    of the instance
    j
    , where
    vj,=Pj,(rnmj,,rn1)

The SumcheckProof::verify_batch algorithm only considers the flattened list of claims

  1. Sample batching challenge
    s
  2. Compute batched scaled claim
    e0=j,ksj,k2nmjσj,k
  3. For rounds
    0i<n
    1. Get
      S(i)(Xi)
      from the prover by recomputing the linear term using the relation
      S(i)(0)+S(i)(1)=ei
    2. Sample round challenge
      ri
    3. Evaluate
      ei+1=S(i)(ri)
  4. Receive evaluations
    {vj,}
    from the prover
    • Note that for polynomials like
      eq
      or
      pow
      appearing in one of the claims at index
      j
      , the verifier computes them manually over
      (rnmj,,rn1)
  5. Check that
    en=j,ksj,kFj,k(vj,0,vj,1,)

If the verifier accepts the final check, it must then check that all polynomial evaluations are correct.

Note that this batching technique implemented in the ppSNARK's prove_helper method was also ported to the prove_quad_batch and prove_cubic_with_additive_term_batch methods of spartan::sumcheck::SumcheckProof.

Batched PCS

At the start of the protocol, the prover will have compute commitments to polynomials

{Pj,}j, where
Pj,
is defined over
mj
variables. Again we let
n=maxj{mj}
be the maximum number of variables.

We assume the PCS supports opening multilinear polynomials over

n variables. It is represented in memory by its list of evaluations
[Pi]i=02n1
which yields the expression
P(X0,,Xn1)=i=02n1PiLi(X0,,Xn).

We commit to this polynomial by computing the MSM with the commitment key base points

[Gi]i=02n1. That is
C=i=02n1PiGi.

If a polynomial is defined over

m<n variables, it has
2m
evaluations
[Pi]i=02m1
. When committing to it, we interpret the evaluations at indices
2mi<2n
as zeros so that
C=i=02n1PiGi=i=02m1PiGi.

This interpretation allows us to compute the MSM using only
O(2m)
group operations.

Effectively, we have committed to the polynomial

P(X0,,Xn1)=L0(X0,,Xnm1)i=02m1PiLi(Xnm,,Xn1).
During Sumcheck though, for polynomial defined over
m<n
variables, we receive evaluations
v=P(rnm,,rn1)=i=02m1PiLi(rnm,,rn1).

In order to open

v using the commitment
C
, we need to transform
v
into an evaluation
v
for the polynomial
P

v=L0(r0,,rnm1)vj=P(r0,,rn1).

Implementation

For each evaluation

vj, provided by the Sumcheck prover, both parties compute a batched PCS evaluation instance
u=(C,(r0,,rn1),v)
and the prover computes the witness polynomial
w=P(X0,,Xn1)
, such that

  • P(r0,,rn1)=v
  • Commit(P)=C
  1. Verifier samples batching challenge
    cF
    , and both compute powers
    {sj,}
  2. For each instance
    j
    • vj,=L0(r0,,rnmj1)vj,
  3. Compute batched instance values
    • C=j,sj,Cj,
    • v=j,sj,vj,
  4. The prover computes
    P(X0,,Xn1)=j,sj,Pj,(X0,,Xn1)
    , where the individual polynomials
    Pj,
    are interpreted as a list of the first
    2mj
    evaluations over the
    n
    -dimensional hypercube.

Batched Sumcheck PCS Reduction

In the non-pre-processing SNARK, the verifier needs to verify the evaluations of multiple multi-linear polynomials at various points defined by the inner and outer Sumcheck instances. Unfortunately, the polynomial commitment schemes only support batching of evaluations for polynomials opened at the same point.

Since the creation of the opening argument is expensive, the original implementation uses a specialized Sumcheck argument to reduce each evaluation to an evaluation at a common point. All of these can be batched via random linear combination so that only a single PCS opening argument needs to be created.

Let

n be the maximum number of variables over all polynomials being opened. Let
[((Ci,ei,xi,ni),Pi)]i
be a list of polynomial evaluation instances, where:

  • Pi
    represents the MLE polynomial, interpolating values
    [Pi,j]j=02ni1
    over
    {0,1}mi
    .
  • Ci
    is a commitment to the polynomial
    P
    , such that
    Ci=j=02ni1Pi,jGi
  • ei
    is the evaluation of
    Pi
    queried at
    xiFni
    , where
    Pi
    is defined as
    Pi(X0,,Xni1)=i=02ni1Pi,jLi(X0,,Xni1)

For each evaluation instance

i, the prover and verifier run the batched Sumcheck to prove the claim
ei=x{0,1}mieq(xi,x)Pi(x).

The protocol proceeds as described in [[Compressed SNARK#Batched Sumcheck]], where all claims are appropriately scaled to

n variables.

The output is a query point

rFn and evaluations
[vi=Pi(rnmi,,rn1)]i
, to which we can apply the same technique as the [[Compressed SNARK#Batched PCS]].

Implementation

The methods batch_eval_proveand
batch_eval_verify represent sub-protocols that reduce the task of checking the validity

[(ui,wi)]i=[((Ci,ei,ri,ni),Pi)]i, to only checking the opening of a single evaluation instance
(u,w)=((C,v,r,n);P)
.

  1. The verifier samples challenge
    ρ
    for the random linear combination of all Sumcheck claims defined above.
  2. Both parties run the batched Sumcheck protocol resulting in
    rFn
    and evaluations
    [vi]i
    .
  3. The verifier checks that
    iρieq(xi,r)vi
    evaluated to the final Sumcheck claim.
  4. The verifier samples
    γ
    and computes the new batched polynomial evaluation instance
    (C,v,r,n)
    • C=iγiCi
    • v=iγiL0(r0,,rnni1)vi
  5. The prover compute the corresponding polynomial
    P(X0,,Xn1)=iγiL0(X0,,Xnni1)Pi(Xnin,,Xn1)
  6. Both parties engage in the PCS opening argument for the resulting instance.

Bounded Witness Check

In the pre-processing SNARK, the Sumcheck claims of each RelaxedR1CS instance are padded to

2n=max{#constraints,2#variables,|A|+|B|+|C|}. If we let
2m=#variables
, then the witness vector
W
is of length
2m
, though we pad it to
2n
by adding zeros.

W(X0,,Xn1)=i=02m1WiLi(X0,,Xn1)=L0(X0,,Xnm1)i=02m1WiLi(Xnm,,Xn1).

The public input

X is a list of at most
2n
elements, which we also consider as a MLE. These are appended to
W
yielding the vector
Z=W||X2m+1
. Its MLE is given by:

Z(X0,,Xn1)=W(X0,,Xn1)+i=02m1XiL2m+i(X0,,Xn1)

The prover provides a commitment to

W by the verifier uses the values of
X
and computations of the Lagrange polynomials to derive an evaluation of
Z
.

The evaluation of

W is performed over
n
variables rather than the
m
variables it is actually defined over. We need to ensure that
W
does not "overflow" into the evaluation slots for
X
, which we do using a new Sumcheck instance using a special MaskedEqPolynomial.

eqm(r,i0,,in1)={0,if i0==inm1=0eq(r,i0,,in1),otherwise

This polynomial can be succinctly evaluated by noting that it is equal to

eq(r,X)(i=0nm1(1ri)(1Xi))(i=nmn1eq(ri,Xi)).
The Sumcheck instance we end up proving is
0=x{0,1}neqm(r,x)W(x).

By definition of

eqm, the sum equals 0 (with overwhelming probability) since in the first
2m
entries,
eqm
evaluates to 0 cancelling out the values of
W
, while it equals
eq(r,x)
in the remaining entries, forcing
W
to be be 0.

Implementation

We include this check as a separate SumcheckEngine implementation, defined in spartan::batched_ppsnark::WitnessBoundSumcheck. The constructor takes as input a random element

r, the maximum number of variables
m
, and the padded witness
WF2n
. It computes the evaluations of
eqm(r,X)
, where
r=(1,r2,r4,,r2n1)
.

One of the benefits of including this new instance is that the Sumcheck prover will have computed the multi-linear evaluation of

W, bypassing the need to compute it manually.