Try   HackMD

FFlonk Comments and Optimizations

(Optimized) PCS of ShPlonk

This PCS is composed by the following algorithms:

  1. gen(d)
    . The generator algorithm outputs
    srs=([1]1,[x]1,[x2]1,,[xd1]1,[1]2,[x]2)
    for a random (and secret)
    xF
    .
  2. com(fi)
    . Given a polynomial
    fiF<d[X]
    , the committer algorithm outputs
    [fi(x)]1
    .
  3. open({cmi}k,{Si}k,{ri}k;{fi}k)
    . The opening algorithm works as follows, where
    k
    is the number of committed polynomials,
    {cmi}k
    are the alleged commitments to
    {fi}k
    ,
    T={z1,,zt}
    is the set of opening points,
    {Si}k
    is the opening set for the
    i
    -th polynomial, and
    {ri}k
    are the polynomials interpolating the alleged the openings. Assume for simplicity that
    k=2
    and that
    S1={z1}
    and
    S2={z2}
    .
    1. V sends a random challenge
      γF
      .
    2. P sends
      W=[(f/ZT)(x)]1
      , where:
      f(X)=(Xz2)(f1(X)r1(X))+γ(Xz1)(f2(X)r2(X)).
      In the normal batched KZG, V would stop here and simply use pairings to check the correctness. In ShPlonk, however, there is one extra round to reduce verifier complexity.
    3. V sends a random evaluation point
      zF
      .
    4. P sends
      W=[L(x)(zz2)(xz)]1
      , where:
      L(X)=(zz2)(f1(X)r1(z))+γ(zz1)(f2(X)r2(z))ZT(z)f(X)ZT(X).
      This protocol improves the original shPlonk, by one verifier scalar multiplication, by normalizing the definition of
      L
      dividing it by
      (zz2)
      . Notice that
      L(z)=f(z)f(z)=0
      .
    5. TOFINISH. verifier check

PCS of Fflonk

This PCS differs from the previous one in that the commitment to a set of polynomials

fiF<d[X], is carried on by computing the polynomial:
g(X)=f1(Xt)+f2(Xt)X++ft(Xt)Xt1,

and outputting
[g(x)]1
.

One Vector of Polynomials and One Evaluation Point

Assume

z=ht.

Then, to open

f1,,ft at
{f1(z),,ft(z)}
, open
g
at
{h,hω,hω2,,hωt1}
, where
ω
is a primitive
t
-th root of unity. To this end, compute the following two sets:
Z¯=rootst(z)={h,hω,,hωt1},S¯={f1(z),f2(z),,ft(z)},

and compute the set:
S¯=S¯(Z¯)={f1(z)+f2(z)h++ft(z)ht1,,f1(z)+f2(z)hω++ft(z)(hω)t1}

and notice that
S¯={g(h),g(hω),,g(hωt1)}
.

Finally, engage in the

open(cm,Z¯,S¯;g) protocol.

One Vector of Polynomials and Multiple Evaluation Points

Assume

z1=h1t,,zk=hkt. Then, basically run the previous protocol on each of the evaluations points.

Then, to open

f1,,ft at
{[f1(z1),f2(z1),,ft(z1)],,[f1(zk),f2(zk),,ft(zk)]}
, open
g
at
{[h1,h1ω,,h1ωt1],,[hk,hkω,,hkωt1]}
, where
ω
is a primitive
t
-th root of unity. To this end, compute the following two sets:
Z¯=rootst(z)={[h1,h1ω,,h1ωt1],,[hk,hkω,,hkωt1]},S¯={[f1(z1),f2(z1),,ft(z1)],,[f1(zk),f2(zk),,ft(zk)]},

and compute the set
S¯={[g(h1),g(h1ω),,g(h1ωt1)],,[g(hk),g(hkω),,g(hkωt1)]}
.

Finally, engage in the

open(cm,Z¯,S¯;g) protocol.

Multiple Vectors of Polynomials and Multiple Evaluation Points

Generalize the previous protocol and engage in the

open({cmi},Z¯,S¯;{gi}) protocol. I don't write it to avoid crazy notation, but this is the one applied in the following section.

Adding Zero-Knowledge (with Dummy Gates)

In the PlonK paper, in the order for the protocol to be zero-knowledge, the authors add to some witness-related polynomial a blinding polynomial

bF[X] as follows:
a(X):=b(X)ZH(X)+i=1nwiLi(X).

To guarantee zero-knowledge, the degree of this polynomial should be at least equal to the number of revealed evaluations of
a
that the prover sends to the verifier in the opening phase of the KZG commitment scheme. This strategy ends up defining polynomials with degree
n+deg(b)
, which is inefficient for practical scenarios in which
n
is a power of two.

To avoid this issue, we proceed as follows. From now on, let

m be the circuit size (that is, the number of gates) and let
n
be the closest power of two such that
nm+4
.

Wiring Polynomials

We add zero-knowledge to the wiring polynomials

a,b,c by sampling blinding factors
b1,,b6F
and defining:
a(X):=i=1mwiLi(X)+b1Lm+1(X)+b2Lm+2(X),b(X):=i=1mwm+iLi(X)+b3Lm+1(X)+b4Lm+2(X),c(X):=i=1mw2m+iLi(X)+b5Lm+1(X)+b6Lm+2(X),

where note that
a(ωi)=b(ωi)=c(ωi)=0
for all
i{m+3,m+4,,n}
. In essence, we are adding dummy gates that will be satisfied by definition and not because of the circuit.

Now, let's look at the satisfiability of the following constraint, for each

xH:
qL(x)a(x)+qR(x)b(x)+qO(x)c(x)+qM(x)a(x)b(x)+qC(x)+PI(x)=0

  • For
    i=1,,m
    the constraint is satisfied if the associated values satisfy the given circuit. In fact, we can safely assume that the number of public inputs is lower than
    m
    , so the public input polynomial
    PI
    evaluates to
    0
    in the forthcoming cases.
  • For
    i=m+1
    the constraint becomes:
    qL(ωm+1)b1+qR(ωm+1)b3+qO(ωm+1)b5+qM(ωm+1)b1b3+qC(ωm+1)=0,

    which is satisfied by setting all the selectors equal to
    0
    at
    ωm+1
    . The same happens in the case
    i=m+2
    .
  • For
    i=m+3,,n
    we simply set
    qC(ωi)=0
    . Notice that while the rest of the selectors could evaluate to any value from
    F
    (without affecting the soundness of the protocol), so we set them to
    0
    for simplicity of the exposition.

To summary, the only change we have to do with respect to the original protocol is to define the selector polynomials as follows:

qL(X)=i=1mqLiLi(X),qR(X)=i=1mqRiLi(X),qO(X)=i=1mqOiLi(X),qM(X)=i=1mqMiLi(X),qC(X)=i=1mqCiLi(X).

Grand-Product Polynomial

We add zero-knowledge to the grand-product polynomial

z by sampling blinding factors
b7,b8,b9F
and defining:
z(X):= L1(X)+i=1m1(Li+1(X)j=1i(wj+βωj+γ)(wm+j+βk1ωj+γ)(w2m+j+βk2ωj+γ)(wj+βσ(j)+γ)(wm+j+βσ(m+j)+γ)(w2m+j+βσ(2m+j)+γ)) +Lm+1(X)+b7Lm+2(X)+b8Lm+3(X)+b9Lm+4(X)+i=m+5nLi(X).

Now, let's look at the satisfiability of the following constraint, for each

xH:
(a(x)+βx+γ)(b(x)+βk1x+γ)(c(x)+βk2x+γ)z(x)(a(x)+βSσ1(x)+γ)(b(x)+βSσ2(x)+γ)(c(x)+βSσ3(x)+γ)z(xω)=0.

  • For
    i=1,,m
    the constraints is satisfied if the
    z
    polynomial is correctly constructed.
  • For
    i=m+1
    the constraint becomes:
    (b1+βωm+1+γ)(b3+βk1ωm+1+γ)(b5+βk2ωm+1+γ)(b1+βSσ1(ωm+1)+γ)(b3+βSσ2(ωm+1)+γ)(b5+βSσ3(ωm+1)+γ)b7=0,

    which is not satisfied with overwhelming probability. Consequently, we should multiply both sides of the constraint by
    (xωm+1)
    . The same goes for the cases
    i=m+2,i=m+3
    and
    i=m+4
    , so we also multiply by
    (xωm+2),(xωm+3)
    and
    (xωm+4)
    as well.
  • For
    i=m+5,,n
    the constraint turns out to be:
    (βωi+γ)(βk1ωi+γ)(βk2ωi+γ)(βSσ1(ωi)+γ)(βSσ2(ωi)+γ)(βSσ3(ωi)+γ)=0,

    which is satisfied by setting
    Sσ1(ωi)=ωi,Sσ2(ωi)=k1ωi
    and
    Sσ3(ωi)=k2ωi
    , i.e., the permutation
    σ
    acts like the identity function for
    i{m+5,,n}
    .

Moreover, we should add a constraint attesting that

z is equal to one at
ωm+1
(since this is the point in which the "real" gates ends). Finally, notice that the
Sσ1,Sσ2,Sσ3
could evaluate to any value from
F
(without affecting the soundness of the protocol) for
i=m+1,,m+4
, so we set them to
1
for simplicity in their definition.

To summary, we must have to perform two changes. First, the new constraints of

Z become:
L1(X)(z(X)1))=0,[(a(X)+βX+γ)(b(X)+βk1X+γ)(c(X)+βk2X+γ)z(X)(a(X)+βSσ1(X)+γ)(b(X)+βSσ2(X)+γ)(c(X)+βSσ3(X)+γ)z(Xω)](Xωm+1)(Xωm+2)(Xωm+3)(Xωm+4)=0,Lm+1(X)(z(X)1))=0.

Second, we define the sigma polynomials as follows:

Sσ1(X)=i=1mσ(i)Li(X)+i=m+1nωiLi(X),Sσ2(X)=i=1mσ(m+i)Li(X)+i=m+1nk1ωiLi(X),Sσ3(X)=i=1mσ(2m+i)Li(X)+i=m+1nk2ωiLi(X).

Lagrange Polynomials

Keep in mind that Lagrange polynomials are different if points in which they are evaluated are distinct. For example, the Lagrange polynomial for

H satisfies, for
i[n]
:
Li(x)={1if x=ωi10if x=ωj,ji1

and moreover
Li
is a polynomial of degree
n1
.

In contrast, the Lagrange polynomial

Li(S0) satisfies, for
i[8]
:
Li(S0)(x)={1if x=h0ω8i10if x=h0ω8j,ji1

the Lagrange polynomial
Li(S1)
satisfies, for
i[4]
:
Li(S1)(x)={1if x=h1ω4i10if x=h1ω4j,ji1

and the Lagrange polynomial
Li(S2)
satisfies, for
i{1,2,3}
and
j{4,5,6}
:
Li(S2)(x)={1if x=h2ω3i10otherwiseLj(S2)(x)={1if x=h3ω3j10otherwise

or more explicitly:
Li(X):=ωi1nXn1Xωi1,Li(S0)(X):=ω8i18h07X8h08(Xh0ω8i1),Li(S1)(X):=ω4i14h13X4h14(Xh1ω4i1),Li(S2)(X):=ω3i13h253h33h22X6(h23+h33)X3+h23h33(Xh2ω3i1),Lj(S2)(X):=ω3j13h353h23h32X6(h23+h33)X3+h23h33(Xh3ω3j1).

Division by a Polynomial of the form
Xmβ

Given a polynomial

p(X)=adXd++a1X+a0F[X] of degree
d
at least
m
and a field element
β
, the quotient of the division
p(X)/(Xmβ)
is the polynomial:
q(X):= adXdm+ad1X(d1)m++ad(m1)X(d(m1))m++(adm+adβ)X(dm)m++(ad(2m1)+ad(m1)β)X(d(2m1))m++(ad2m+admβ+adβ2)X(d2m)m++(ad(3m1)+ad(2m1)β+ad(m1)β2)X(d(3m1))m 

Basically,

q is a polynomial with the
m
leading coefficients equal to the
m
leading coefficients of
p
; the following
m
coefficients are of the form
ai+ajβ
, with
ji=m
; the following
m
coefficients are of the form
ai+ajβ+akβ2
, with
ji=kj=m
; and so on. Intuitively speaking, each
m
coefficients of
q
, one jumps from the actual coefficient of
p
with jumps of length
m
until "is possible" from bot to top. Consequently, the last
m
coefficients of
p
are never used for
q
.

For instance, if

p(X)=i=010aiXi and
m=2
, then:
q(X):= a10X8+a9X7+(a8+a10β)X6+(a7+a9β)X5++(a6+a8β+a10β2)X4+(a5+a7β+a9β2)X3++(a4+a6β+a8β2+a10β3)X2+(a3+a5β+a7β2+a9β3)X++(a2+a4β+a6β2+a8β3+a10β4)

Note that if

d2m1, then
q
is only composed of the
m
leading coefficients of
p
.

Alternative

function divideByVanishingCoset(p, n, b, p) {
  let q = Array(p.length).fill(0n);
  let r = [...p];
  for (let i = p.length - 1; i >= n; i--) {
    let leadingCoeff = r[i];
    if (leadingCoeff === 0n) continue;
    r[i] = 0n;
    r[i - n] = mod(r[i - n] + b * leadingCoeff, p);
    q[i - n] = mod(q[i - n] + leadingCoeff, p);
  }
  return [q, r];
}

We want to find polynomials

q and
r
such that
p(X)=q(X)(Xnβ)+r(X)
with
0deg(r)<n
. The following observation is crucial:
p(X)=0(Xnβ)+p(X)=0(Xnβ)+(p(X)pdXd)+pdXd==0(Xnβ)+(p(X)pdXd)+pdXdnXdβpdXdn+βpdXdn==0(Xnβ)+(p(X)pdXd)+pdXdn(Xdβ)+βpdXdn==pdXdn(Xnβ)+(p(X)pdXd+βpdXdn)

The idea is to lower the degree of
r
by correctly varying
q
and
r
while preserving the previous identity.

Generalization to Multiple Polynomials

Given a polynomial

p(X)=adXd++a1X+a0 of degree
d
at least
|T|=18
that is divisible by
ZT
, the following algorithm gives the quotient of the division
p/ZT
.

We start by noticing that:

ZT(X)=ZS0(X)ZS1(X)ZS2(X)=(X8z)(X4z)(X6z(1+ω)X3+z2ω)

Then, we proceed as follows:

  1. Divide

    p by
    ZS0
    to obtain the polynomial
    q0
    such that
    q0(X)ZS0(X)=p(X)
    .

  2. Divide

    q0 by
    ZS1
    to obtain the polynomial
    q1
    such that
    q1(X)ZS1(X)=q0(X)
    .

  3. Split

    ZS2(X)=(X6z(1+ω)X3+z2ω) as the multiplication of
    (X3z)
    and
    (X3zω)
    . Then:

    • Divide
      q1
      by
      (X3z)
      to obtain the polynomial
      q2
      s.t.
      q2(X)(X3z)=q1(X)
      .
    • Divide
      q2
      by
      (X3zω)
      to obtain the polynomial
      q3
      s.t.
      q3(X)(X3zω)=q2(X)
      .

The polynomial

q3(X) satisfies
ZT(X)q3(X)=p(X)
.

tags: PlonK