Introduction
The KZG commitment was introduced in . The time required for commitment is proportional to the degree of the polynomial, and the commitment consists of a single G1 element, which is C=[P(s)]1 for given P(X).
The opening proof W for a point x is defined as:
W=[s−xP(s)−y]1 Verification is performed using the following equation:
e(W,[s]2−[x]2)⋅e(C−[y]1,[1]2)=?1 However, when proving over AIR, multiple polynomials need to be opened at x and ω⋅x. In PLONK-based schemes that support custom gates, such as Halo2, polynomials must be opened at various opening points in different combinations. One of the efficient methods for proving in batch settings is SHPlonk, which was introduced in .
Background
We'll now see how opens multiple polynomials at multiple points. Let's start with simple cases.
Opening Multiple Polynomials at a Single Point
Suppose two polynomials, P0(X) and P1(X), are opened at x with corresponding values y0 and y1.
The verifier provides α←F to the prover.
The prover generates the following opening proof W:
W=[s−xP(s)−y]1 Where P(X):=P0(X)+α⋅P1(X) and y:=y0+α⋅y1.
Verification is performed using the following equation:
e(W,[s]2−[x]2)⋅e(C−[y]1,[−1]2)=?1 Where C:=C0+α⋅C1 and C0,C1 are commitments of P0(X),P1(X) respectively.
This approach is almost identical to opening a single polynomial at a single point, with the only difference being the random linear combination applied to the polynomials before constructing the proof.
Opening a Single Polynomial at Multiple Points
Suppose a polynomial P(X) is opened at two points, x0 and x1, with corresponding values y0 and y1.
The prover generates the following opening proof W:
W=[(s−x0)(s−x1)P(s)−r(s)]1 Where r(X) is defined as:
r(X):={P(x0)P(x1) if X=x0 if X=x1 Verification is performed using the following equation:
e(W,[(s−x0)(s−x1)]2)⋅e(C−[r(s)]1,[−1]2)=?1 Where C is the commitment of P(X).
There are two key issues with this naive approach:
Increasing G2 parameters: As the number of opening points increases, the required G2 parameters also increase. For instance, in this case, [s2]2 is required.
Expensive group operation in G2: Operations in G2 are computationally expensive, leading to higher gas consumption in on-chain, and inefficient in recursive proof generation.
To solve these issues, we modify the protocol as follows:
The prover generates 2 opening proofs, W0 and W1:
W0=[s−x0Q0(s)],W1=[s−x1Q1(s)] Where Q0(X):=P(X)−y0 and Q1(X):=P(X)−y1.
The verifier uses α←F to verify the following equation:
e([Q0(s)]1+α⋅[Q1(s)]1+x0⋅W0+α⋅x1⋅W1,[1]2)⋅e(−W0−α⋅W1,[s]2)=?1 The verifier can obtain [Q0(s)]1,[Q1(s)]1 by computing C−[y0]1 and C−[y1]1 respectively.
Proof.
By extracting the exponent components, it can be confirmed that the verification equation holds.
==Q0(s)+α⋅Q1(s)+(x0−s)⋅s−x0Q0(s)+α⋅(x1−s)⋅s−x1Q1(s)Q0(s)+α⋅Q1(s)−Q0(s)−α⋅Q1(s)0 Now the number of required G2 parameters is now constant, and the group operations in G2 are eliminated.
Opening Multiple Polynomials at Multiple Points
P0(X) is opened at x0 with value y0.
P1(X) is opened at x0,x1 with values y1,y2.
P2(X) is opened at x0,x1 with values y3,y4.
The verifier provides α←F to the prover.
The prover generates 2 opening proofs, W0 and W1:
W0=[s−x0Q0(s)]1,W1=[s−x1Q1(s)]1 Where Q0(X):=P0(X)−y0+α(P1(X)−y1)+α2(P2(X)−y3) and Q1(X):=P1(X)−y2+α(P2(X)−y4).
Verification is performed with β←F using the following equation:
e([Q0(s)]1+β⋅[Q1(s)]1+x0⋅W0+β⋅x1⋅W1,[1]2)⋅e(−W0−β⋅W1,[s]2)=?1 The verifier can obtain [Q0(s)]1,[Q1(s)]1 by computing α(α(C2−[y3]1)+C1−[y1]1)+C0−[y0]1 and α(C2−[y4]1)+C1−[y2]1 respectively, where C0,C1,C2 are the commitments of P0(X),P1(X),P2(X).
If there are n polynomials of degree d, and each polynomial is opened at t points, the following holds:
srs size: (d+1)G1,2G2
srs stands for "structure reference string".
Prover work: O(d⋅t)G1,O(t⋅dlogd)F
To compute each division in X−xiQi(X), it takes O(dlogd)F operations.
To compute each proof Wi, it takes O(d)G1 operations.
Proof length: tG1
Verifier work: O(n⋅t)G1,2P
To compute all of [Qi(s)]1, it takes O(n⋅t)G1 operations.
Here, Gi represents scalar multiplication in Gi, F represents addition or multiplication in F, and P denotes a pairing operation.
SHPlonk enables a smaller proof length and faster verifier work for this case.
Protocol Explanation
Version 1
To illustrate this scheme, let's use the same example as before. If we group the opening points, we can form two sets: S0={x0} and S1={x0,x1}. The complete set of opening points is then T={x0,x1}.
The zero polynomial ZS(X) on S={x0,…,xn−1} is defined as:
ZS(X):=(X−x0)⋯(X−xn−1) The opening proof W is constructed as follows:
The verifier provides α,β←F to the prover.
The prover computes W=[h(s)]1 as follows:
h(X):=ZS0(X)Q0(X)+β⋅ZS1(X)Q1(X) Where Q0(X):=P0(X)−y0,Q1(X):=P1(X)−r0(X)+α(P2(X)−r1(X)),r0(X),r0(X) and r1(X) are defined as follows:
r0(X):={P1(x0)P1(x1) if X=x0 if X=x1,r1(X):={P2(x0)P2(x1) if X=x0 if X=x1 To verify the opening proof W, the following steps are performed:
Compute Z0 and Z1 using Zi:=[ZT∖Si(s)]2:
Z0=[s]2−[x1]2,Z1=[1]2 Verify using the following equation:
e([Q0(s)]1,Z0)⋅e(β⋅[Q1(s)]1,Z1)=?e(W,[ZT(s)]2) The verifier can obtain [Q0(s)]1,[Q1(s)]1 by computing C0−[y0]1 and α(C2−[r1(s)]1)+C1−[r0(s)]1 respectively, where C0,C1,C2 are commitments of P0(X),P1(X),P2(X).
Proof.
Extracting the exponent components from the above equation, we obtain:
==Q0(s)⋅ZT∖S0(s)+β⋅Q1(s)⋅ZT∖S1(s)(ZS0(s)Q0(s)+β⋅ZS1(s)Q1(s))⋅ZT(s)h(s)⋅ZT(s) Thus, the verification equation holds.
If there are n polynomials of degree d, and each polynomial is opened at t points, the computational costs are as follows:
The number of opening sets s: 1≤s≤n
srs size: (d+1)G1,(t+1)G2
Prover work: O(d)G1,O(d⋅n+s⋅dlogd)F
This doesn't account for computation of each ri(X), since they are normally small operations.
To compute all of Qi(X), it takes O(d⋅n)F operations.
To compute each ZSi(X)Qi(X), it takes O(dlogd)F operations.
To compute a proof W, it takes O(d)G1 operations.
Proof length: 1G1
Verifier work: O(n)G1,O(s⋅t)G2,(s+1)P
To compute all of [Qi(s)]1, it takes O(n)G1 operations.
To compute [ZT(s)]2, it takes O(t)G2 operations.
To compute each Zi, it takes O(t)G2 operations.
Here, Gi represents scalar multiplication in Gi, F represents addition or multiplication in F, and P denotes a pairing operation.
Prover Complexity: The prover must evaluate the polynomials at every point in T, which increases the number of opening points to n⋅t.
ZK Proof Size: The ZK proof size increases because it must include all the opened values.
It's important to distinguish between two types of proofs here. The Proof mentioned earlier refers specifically to proving polynomial openings. However, in this context, the ZK Proof not only includes the opening proof but also contains commitments and the opened values themselves.
Version 2
Version 2 addresses the issues from the previous approach by introducing one additional proof.
The opening proofs W,W′ are constructed as follows:
The verifier provides α,β←F to the prover.
The prover computes W=[h(s)]1 as follows:
h(X):=ZT(X)f(X) Where f(X) is defined as:
f(X):=ZT∖S0(X)⋅Q0(X)+β⋅ZT∖S1(X)⋅Q1(X) where Q0(X):=P0(X)−y0,Q1(X):=P1(X)−r0(X)+α(P2(X)−r1(X)),r0(X),r0(X) and r1(X) are defined as follows:
r0(X):={P1(x0)P1(x1) if X=x0 if X=x1,r1(X):={P2(x0)P2(x1) if X=x0 if X=x1 The verifier provides z←F to the prover.
The prover computes W′ as follows:
W′=[s−zL(s)]1 Where L(X) is defined as:
L(X):=fz(X)−ZT(z)⋅h(X) Here, fz(X) is defined as:
fz(X):=ZT∖S0(z)(P0(X)−y0)+β⋅ZT∖S1(z)(P1(X)−r0(z)+α(P2(X)−r1(z))) The polynomial L(X) is crucial in solving the issues from the previous approach. Unlike Qi(X), which vanishes at multiple points, this L(X) now vanishes at single point at z because:
L(z)=f(z)−ZT(z)⋅h(z)=0 To verify the opening proofs, the verifier checks the following equation:
e([fz(s)]1−ZT(z)⋅W,[1]2)=?e(W′,[s]2−[z]2) The verifier can obtain [fz(s)]1 as follows:
[fz(s)]1=β⋅ZT∖S1(z)(α(C2−[r1(z)]1)+C1−[r0(z)]1)+ZT∖S0(z)(C0−[y0]1) Where C0,C1,C2 are commitments of P0(X),P1(X),P2(X).
Proof.
Extracting the exponent terms from the above equation, we obtain:
==fz(s)−ZT(z)⋅h(s)L(s)s−zL(s)⋅(s−z) Thus, the verification equation holds.
If there are n polynomials of degree d, and each polynomial is opened at most t points, the computational costs are as follows:
The number of opening sets s: 1≤s≤n
srs size: (d+1)G1,2G2
Prover work: O(d)G1,O(d⋅n+s⋅dlogd)F
To compute all of Qi(X), it takes O(d⋅n)F operations.
To compute each ZT∖Si⋅Qi(X), it takes O(dlogd)F operations.
To compute ZT(X)f(X) and X−zL(X), it takes O(dlogd)F operations.
To compute L(X), it takes O(d⋅n) operations.
To compute a proof W,W′, it takes O(d)G1 operations.
Proof length: 2G1
Verifier work: O(n)G1,O(1)G2,2P
To compute all of [f(z)]1, it takes O(n)G1 operations.
Here, Gi represents scalar multiplication in Gi, F represents addition or multiplication in F, and P denotes a pairing operation.
Optimization on Version 2.
When constructing W′, it can be "normalized", to save one of the scalar multiplications like below.
W′=[ZT∖S0(z)⋅(s−z)L(s)]1 Then, the verification logic is changed accordingly:
e([ZT∖S0(z)fz(s)]1−ZT∖S0(z)ZT(z)⋅W,[1]2)=?e(W′,[s]2−[z]2) The verifier can obtain ZT∖S0(z)[fz(s)]1 as follows:
ZT∖S0(z)[fz(s)]1=β⋅ZT∖S0(z)ZT∖S1(z)(α(C2−[r1(z)]1)+C1−[r0(z)]1)+(C0−[y0]1) Notice that the rightmost part of the equation doesn't have scalar multiplication any more.
Conclusion
By summarizing the key metrics in the following table, we can see that SHPlonk demonstrates superior efficiency compared to GWC19.
SRS size
Prover work
Prover length
Verifier work
SHPlonk offers a more efficient proof system, balancing prover and verifier costs while keeping proof sizes minimal. Depending on the use case, Version 1 is preferable for minimizing proof length, whereas Version 2 provides a more scalable solution with constant G2 parameters and a fixed number of pairing operations while removing scalar multiplications in G2.
References