GKR-LogUp: additional required API changes
plafer opened this issue · comments
The API changes in #271 to support GKR-LogUp were insufficient. As described in #257, GKR-LogUp relies on 2 auxiliary columns l
(the Lagrange kernel) and s
. As of #271, the prover currently doesn't have enough information to build the s
column, and the Air doesn't have enough information to evaluate the s
constraints.
GKR-LogUp auxiliary columns recap
The GKR circuit proof leaves the following claims to be proven by the Air: FinalOpeningClaim.openings
field.
To prove these
This expression can be rearranged:
Notice that this is an inner product between
- The
$l$ column stores the Lagrange kernel. That is, the value at row$x$ is$\mathrm{eq}(x, r)$ (where$x$ is the bit decomposition of the row index), and$r$ is the above mentioned Lagrange kernel randomness. - The
$s$ column is a running sum where row$x$ stores the inner product from row$0$ to row$x$ . Specifically,$$s(x) = s(x-1) + l(x) \sum_{i=0}^{m-1} \lambda_i f_i(x)$$
The constraints for
where
where
Required API changes
There are currently 2 issues with the current API.
- the prover is currently missing access to the
$\lambda_i$ values to build the aux trace, while - the Air is currently missing access to both the
$\lambda_i$ values and the$\tilde{f_i}(r)$ openings to evaluate the constraints.
Below are my suggestions on how to concretely achieve this (specific naming choices subject to change).
Define a new type GkrRandElements
as
struct GkrRandElements<E> {
lagrange: LagrangeRandElements,
lambdas: Vec<E>
}
Consequently, AuxRandElements
is modified to include this new type:
struct AuxRandElements<E> {
rand_elements: Vec<E>,
gkr: Option<GkrRandElements<E>>,
}
Then, Prover::build_aux_trace(main_trace, aux_rand_elements)
now has all the information it needs to build the auxiliary trace, solving issue 1.
Then, Prover::generate_gkr_proof()
now returns GkrRandElements
instead of only LagrangeKernelRandElements
. Consequently, Prover::generate_gkr_proof()
the prover will also need to commit to commit to openings GkrVerifier::verify()
also needs to return GkrRandElements
.
As for the changes in Air
, I suggest we add 2 methods analogous to Air::evaluate_aux_transition()
and Air::get_aux_assertions()
, that are only called when a GkrProof
is present, and pass in the
Note that unlike the Lagrange kernel constraints, the constraints for the s
column can be defined outside of winterfell, as they only require the typical EvaluationFrame
.
Thank you! The issue and the PR make sense and as I mentioned in the PR review, we can merge it after a couple of minor comments are addressed. I am wondering, however, if we should try to do a bigger refactoring around this as I think some of the assumptions we made initially, may not make as much sense now.
First, we assumed that the Lagrange Kernel (lk
) column and the s
column would be built by the user (i.e., outside of Winterfell). It now seems like lk
column and maybe s
column as well can be handled internally by Winterfell.
Second, we currently treat GKR and LK as two separate things. For example, we can set lagrange_kernel_aux_column_idx
in the AirContext
without specifying GkrProof
and GkrVerifier
associated types.
Addressing the first one should be relatively simple:
- Instead
AirContext::lagrange_kernel_aux_column_idx
we could have something likeAirContext::enable_gkr
which would be a boolean flag. - When
enable_gkr
is set to true, the prover would first make a call toself.build_aux_trace
(as it does now), and then would buildlk
ands
columns and append them to theaux_trace
. In a way,Prover::build_aux_trace()
would go back to being responsible for building aux traces only for user-defined aux columns. - One the constraint side,
enable_gkr
flag would also automatically enablelk
ands
column constraint evaluation. Forlk
column this is what we do already, and one open question for me is whether we can do the same for thes
column (seems like so - but want to confirm).
For the second point, my thinking is not as clear yet. But a few preliminary thoughts:
- It may be good to get rid of
Air::GkrVerifier
associated type in favor of addingAir::verify_gkr_proof()
function. This function would be called by the verifier wheneverAirContext::enable_gkr
is set to true. - I also wonder if it may be possible to replace
Air::verify_gkr_proof()
with something more basic that is useful for both the prover and the verifier. Ideally, the user would specify something likeGkrCircuit
and then the prover would be able to generate theGkrProof
for it and the verifier would know how to verify this proof.
I agree. It no longer makes sense to have a "Lagrange kernel"-centric API.
First, we assumed that the Lagrange Kernel (lk) column and the s column would be built by the user (i.e., outside of Winterfell). It now seems like lk column and maybe s column as well can be handled internally by Winterfell.
+++. The algorithm to generate these columns is always the same, so best handled internally rather than copy/pasted by users.
One the constraint side, enable_gkr flag would also automatically enable lk and s column constraint evaluation. For lk column this is what we do already, and one open question for me is whether we can do the same for the s column (seems like so - but want to confirm).
Certainly.
For the second point, my thinking is not as clear yet. But a few preliminary thoughts:
I agree with the general idea in this subsection. I believe this is what you're describing already, but I would see winterfell handling as much of LogUp-GKR as possible (i.e. define GkrProof
struct, as much of the circuit as possible, etc). The user only needs to define the input layer of the LogUp-GKR circuit (best way to do that is TBD); the rest can be handled internally. We already provide some machinery for the Lagrange kernel and "s" columns, but these have little use without the entire LogUp-GKR circuit proving & verifying (so we might as well provide that too).
Closed by #287