Lookups allow us to check whether a particular witness value is an element of some set.
Such a check can be done using
PLONK(opens new window)
too but it’s much more expensive.
Imagine we have a witness
x
and we would like to prove that
x∈{0,1,2,3,4}.
We could write a custom gate,
x(x−1)(x−2)(x−3)(x−4)=0,
using PLONK, but this becomes inefficient when the set is big (the bigger the degree of the
gate, the slower the protocol).
Let’s see an example.
As usual, we are in the field
Fp
and we have the multiplicative subgroup
H={1,w,w2,...,wn−1}ofFp.
We also have the polynomial
ZH(x),
for which it holds:
ZH(x)=0forx∈H
We’ve observed how the prover can prove, for example, that for each
x∈H:
But let’s pretend that
S
is huge and it’s totally inefficient to use the standard PLONK approach.
The technique presented here is the
halo2(opens new window)
lookup variant, not the original
plookup(opens new window).
And we extend
S
with duplicates to be of the same length as
A1
and then permute it
to have the same values as
A1
at the positions where the value in
A1
changes. Let’s denote it by
S1:
At positions denoted by "...", it can be any value from
S.
The prover needs to prove that either
A1[i]=S1[i]
or
A1[i]=A1[i−1]
holds.
This way, the prover proves that elements in
A1
are only elements from
S.
Let’s say we have polynomials
A′
and
S′
such that:
A′(ωi)=A1[i]
S′(ωi)=S1[i]
So, the prover needs to prove:
(A′(x)−S′(x))(A′(x)−A′(ω−1x))=0
for
x∈H.
This is done by dividing by the vanishing polynomial and opening the commitment
as discussed last time.
If the prover then proves that
A1
is the permutation of
A
and that
S1
is the permutation of
S,
the prover is done.
This can be achieved using the same approach (grand product) as for the
permutation arguments. The grand product in this case
would contain the elements: