Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How eval_at_tau works? #86

Open
qy3u opened this issue May 23, 2022 · 0 comments
Open

How eval_at_tau works? #86

qy3u opened this issue May 23, 2022 · 0 comments

Comments

@qy3u
Copy link

qy3u commented May 23, 2022

I'm sorry to ask this question because this question does not involve the correctness of the code, but is purely a question of my own understanding. After inquiring some information, I did not get a suitable answer, so I think I can only ask the question in here it is.

I don't quite understand how the eval_of_tau function in generator works.

Here is the eval_at_tau function:

fn eval_at_tau<S: PrimeField>(
powers_of_tau: &[Scalar<S>],
p: &[(S, usize)],
) -> S {
let mut acc = S::zero();
for &(ref coeff, index) in p {
let mut n = powers_of_tau[index].0;
n.mul_assign(coeff);
acc.add_assign(&n);
}
acc
}

Its second parameter is the QAP polynomial stored in point-valued form:

// QAP polynomials
at: &[Vec<(E::Fr, usize)>],
bt: &[Vec<(E::Fr, usize)>],
ct: &[Vec<(E::Fr, usize)>],

It's first parameter is powers_of_tau, but this powers_of_tau confuses me. In the front, this variable is exactly what it says, it is the powers of tau

// Compute powers of tau
{
let powers_of_tau = powers_of_tau.as_mut();
worker.scope(powers_of_tau.len(), |scope, chunk| {
for (i, powers_of_tau) in powers_of_tau.chunks_mut(chunk).enumerate() {
scope.spawn(move |_scope| {
let mut current_tau_power = tau.pow_vartime(&[(i * chunk) as u64]);
for p in powers_of_tau {
p.0 = current_tau_power;
current_tau_power.mul_assign(&tau);
}
});
}
});
}

But before actually using it, make the following transformation:

// Use inverse FFT to convert powers of tau to Lagrange coefficients
powers_of_tau.ifft(&worker);

So as I understand it, from here on powers_of_tau becomes the coefficients (a0, a1, ..an) of the polynomial f(x) such that
A polynomial of the form f(x) = a0 + a1 * x + a2 * x^2 .... an * x^n
Satisfy:
f(ω0) = tau^0
f(ω1) = tau^1
....

In this case, according to the implementation of the eval_at_tau function

let mut acc = S::zero();
for &(ref coeff, index) in p {
let mut n = powers_of_tau[index].0;
n.mul_assign(coeff);
acc.add_assign(&n);
}

How can this be the value of a QAP polynomial at tau?

Because powers_of_tau has been ifft transformed before, so
powers_of_tau[index].0 here should be the indexth coefficient of f(x). What is the significance of multiplying this coefficient with coeff?

I guess based on the comments, here is the equivalent to the point value form of QAP by doing Lagrangian interpolation, the formula:

$$ L(x) = \sum _{j=0}^{k} {y}_j * {l}_j(x) $$

Then coeff is equivalent to $$ {y}_j $$

Then the jth item of powers_of_tau is equal to the l_j(x) corresponding to y_j?

Is this guess correct? Is there any formula to prove that they are indeed equal? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant