Try   HackMD

EPF Week 7 Update 8 & 9

After going through Dankrad's IPA note with Pedersen and then going through a few more resources on IPA. I finally realised how IPA multipoint really worked!

Intro

Here I'll talk about how we can open multiple polynomials at different points.
Finally aggregating to 1 proof, 1 commitment and 1 scalar.

Definition

Given

m IPA commitments
C0=[f0(X)]...Cm1=[fm1(X)]
, prove evaluations:

f0(z0)=y0fm1(zm1)=ym1

where

zi{0,...,d1}

Prover

  1. Let
    rH(C0,...Cm1,z0,...,zm1,y0,...,ym1)

g(X)=r0f0(X)y0Xz0+r1f1(X)y1Xz1++rm1fm1(X)ym1Xzm1

The prover initially commits to

g(X), we denote this by
D
or
[g(X)]
.

Now the prover has to convince the verifier that

D is a commitment to
g(X)
. We do this by evaluating
g(X)
at some random point
t
.

We can split the evaluation into

g1(t) and
g2(t)
,
g2(t)
. These two can be computed by the verifier, while
g1(t)
cannot, because it involves random evaluations at the polynomials
fi(X)
.

Hence the verifier is able to compute

g2(t), and the prover will compute
g1(t)
and send a proof of it's correctness.

The expressions are as following:

g1(t)=i=0m1rifi(t)tzi

g2(t)=i=0m1riyitzi

  1. Let
    tH(r,D)

We note that

g1(X)=i=0m1rifi(X)Xzi. However, we specify it as
i=0m1rifi(X)tzi
because
g1(t)
is also able to prove for an opening, hence the verifier is able to compute the commitment for it.

Thereby, we finally boil down to 2 IPA proofs. One for

g1(X) at
t
. We call this
π
. And the other one for
g(X)
at
t
. We call this
ρ
.

Hence, the prover now computes

y=g1(t), and the proof consists of
D,(π,y),ρ
.

However, this is still the variant where we haven't yet aggregated the proofs.

Verifier

The Verifier ultimately wants to verify that

D is the commitment to the polynomial
g(x)
, hence he computes
r
and
t
.

Then the verifier also computes

g2(t), by themselves.

However, the verifier cannot assert to the fact that

g1(t) is the correct computation by the prover. The verifier has to separately build
[g1(X)]
and then re-check it with
g1(t)
.

The verifier proceeds with computing

[g1(X)]. The verifier as I said, is able to compute this by themselves, to cross check it with
g1(t)
using the ipa_verify() function, the reference Go implementation, using (
[g1(X)]
,
g1(t)
,
π
) params.

As

g(t)=g1(t)g2(t), now that since
g1(t)
was verified to be correct and
g2(t)
was computed by the verifier, we can be sure that
g(t)
is correct.

Verifying
g(x)
at
t

We now call ipa_verify() passing (

D=[g(X)],
g(t)
,
ρ
) as params.

Now we have 2 IPA proofs, 1 commitment and 1 scalar.

Now we are left with aggregation to 1 final IPA proof.

Aggregating

Prover's side

Let

qH(t,[g1(X)])

The prover no longer computes an IPA proof for

g1(X) and
g(X)
instead they combine them using
q
.

g3(X)=g1(X)+qg(X)

Now we form an IPA Proof for

g3(X) at
t
. Lets call this
σ
.

The prover still computes

y=g1(t)

The proof consists of

D,σ,y

Verifier's side

In the previous step, the verifier called

[g1(X)] ,
g1(t)
with
π
, we delay this verification and instead compute:

  • [g3(X)]=[g1(X)]+q[g(X)]
  • g3(t)=g1(t)+qg(t)

We now call ipa_verify() using (

[g3(X)],
g3(t)
,
σ
).

This strategy finally boils down the proof to 1 IPA proof, 1 commitment and 1 scalar.