During verification, the verifier must compute a product of f terms that depends on index decomposition. This ends up being quite inefficient.
As noted in #16, it's possible to replace standard index decomposition with a Gray code design. This is beneficial since successive indexes will differ only in a single digit. This means that successive products of f terms can be computed with only two multiplications, one of which is the inverse of a scalar element of f. We can further take advantage of the curve library's scalar batch inversion functionality to efficiently compute all such inverses at once.
This PR adds this functionality. It introduces a new GrayIterator that iteratively identifies digit changes between successive index decompositions, and modifies the prover and verifier to account for the change.
During verification, the verifier must compute a product of
f
terms that depends on index decomposition. This ends up being quite inefficient.As noted in #16, it's possible to replace standard index decomposition with a Gray code design. This is beneficial since successive indexes will differ only in a single digit. This means that successive products of
f
terms can be computed with only two multiplications, one of which is the inverse of a scalar element off
. We can further take advantage of the curve library's scalar batch inversion functionality to efficiently compute all such inverses at once.This PR adds this functionality. It introduces a new
GrayIterator
that iteratively identifies digit changes between successive index decompositions, and modifies the prover and verifier to account for the change.Closes #16.