Sources:
Read-only memory
The problem they tried to solve is to force an untrusted memory to prove it worked correctly, with very low space requirements of the verifier.
The verifier maintains two sets, which can be compressed and updated incrementally via permutation-invariant fingerprinting (see Permutation Check via Product Check):
- Read Set: The tuples returned by the prover
- Write Set: written to memory
Then, the verifier behaves as follows:
- At the beginning of the execution, they write for each address the tuple (or some other initial value)
- Each read returning is followed by a write of
- At the end of the execution, the verifier reads all addresses
If and only if the prover is honest, the read and write multi-sets will be equal.
Application: Indexed Lookup
Source: Unlocking the lookup singularity with Lasso
Suppose we have:
- A multi-linear extension of some table (i.e., read-only memory)
- A multi-linear extension of addresses
- A multi-linear extension of values
We want to show that:
where is the function that maps a field element to its bit representation.
We can show this is the case by simulating the offline memory verifier in a SNARK.
Specifically, the prover commits to two polynomials, and , containing the counts returned by the offline memory prover for the “normal” and final read operations.
The memory operations were performed correctly if where:
where is also a multi-linear polynomial:
The two multi-sets can be shown to be equal using the Permutation Check via Product Check! In particular, the grand product can be computed using a layered arithmetic circuit of depth and proven using GKR.
PIL Sketch
Comparison to LogUp (see LogUp & cq):
- The multiplicity with which elements are sent to the bus (the first argument of
bus_send
andbus_receive
) is always 1. - As a consequence, the bus argument does not need to support multiplicities and can be simply a Permutation Check via Product Check. This is cheaper than the fractional sum-check needed in LogUp.
- On the other hand, LogUp commits to a strict subset of columns: It does not need the
time_step
column. Also, in the case of non-indexed lookups (simply stating thatmain::value
is a subset oftable::value
), theaddress
columns are not needed.
Read-write memory
The original paper actually describes a read-write memory which is slightly more complex:
- As described above, all memory cells are initialized with some value at time step
- For each memory write of value to address at time :
- The prover provides and
- The verifier asserts that
- The tuple is added to the read set
- The tuple is added to the write set
- A memory read works the same, but with