More efficient remainder verification in FRI
Al-Kindi-0 opened this issue · comments
Currently, the last step in FRI verification is https://github.com/novifinancial/winterfell/blob/e43b75d365e03a71288ede25a6c2c9d9dc021a4d/fri/src/verifier/mod.rs#L307-L319
This is inefficient in, at least, two ways:
- The commitment to the remainder is a Merkle tree. This is inefficient because we don't really use the property of vector-commitment that a Merkle tree provides in the above implementation and we can in fact get away with the weaker notion of set-commitment, provided the set is composed of elements of the form
(position,remainder[position])
. - Combined with the previous point, the verifier can, instead of checking that
remainder[position] == evaluation
, just compute the set commitment to(position,evaluations[position])
and then check that the two set-commitments are equal. This assumes that the queries at the initial layer are drawn in such a way so as the last folded positions span the range[0, remainder.len() - 1]
. I assume this is already implemented in Winterfell but I haven't checked.
As for the set-commitment, a sequential hash of remainder[i]
for
I think the first part will definitely work. The second part will also kind of work, but I doubt savings would be more than about 500 bytes in most cases.
The reason for the second part is that we still need to send most of the remainder. We can skip only positions which we get from folding. For example, if the remainder size is 128 elements, and and the proof contains 30 queries, then the best we could hope for is that 30 of 128 elements can be skipped. If we are in a 128-bit field, these 30 skipped elements would result in proof size reduction of 30 * 16 = 480 bytes.
The first point of this was addressed in #128
There is actually another optimization we can do which makes the second point here irrelevant. Specifically, instead of sending the actual codeword for the remainder (which we then need to interpolate into a polynomial in coefficient form), we can just send the polynomial in coefficient form. Then, the verifier would evaluate the polynomial and make sure the resulting evaluations match the commitment.
Depending on the blowup factor, this could result in signifiant savings (i.e.,g 1KB or more).
Yes, but I think that this is exactly the optimization I mentioned at the start of issue 0xPolygonMiden/miden-vm#568 . Then, as mentioned there, the iNTT check becomes unnecessary as one can just evaluate at
Actually, an NTT on the verifier side might make sense for remainder polynomials of large degree.