Skip to content

Conversation

@Al-Kindi-0
Copy link
Contributor

@Al-Kindi-0 Al-Kindi-0 commented May 2, 2025

This leads to a simplification of the code and has a also a simplifying effect on recursive verification.

Note: Ran some benchmarks and it seems that there is no noticeable performance changes.

Copy link

@adr1anh adr1anh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just left very minor nits.

/// - Assume each column value is an evaluation of a trace polynomial T_i(x).
/// - Assume each column value is an evaluation of a polynomial T_i(x), either trace or
/// constraint composition polynomial.
/// - For each T_i(x) compute T'_i(x) = (T_i(x) - T_i(z)) / (x - z) and
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it doesn't make much sense to optimize the verifier here, but we could compute this more efficiently like the recursive verifier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it but it seemed like a non-negligible amount of work for a marginal improvement in our current context.
We can come back to it if we need to optimize the verifier for whatever reason, if you agree.

@Al-Kindi-0 Al-Kindi-0 force-pushed the al-open-quotient-at-gz branch from cc90089 to a636005 Compare May 21, 2025 14:49
@adr1anh
Copy link

adr1anh commented May 21, 2025

LGTM (but can't approve)

Copy link
Contributor

@plafer plafer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Left a nit


// --- merge polynomials of the composition polynomial trace ------------------------------
i = 0;
for poly in quotient_polys.into_columns() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of re-using i, I would use .into_columns().into_iter().enumerate() (as i is not needed in subsequent loops)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, changed it now

@Al-Kindi-0 Al-Kindi-0 force-pushed the al-open-quotient-at-gz branch from a636005 to 1db592b Compare May 23, 2025 05:45
Copy link
Collaborator

@irakliyk irakliyk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you! I left a few small comments inline. Also, I'd like to clarify a couple of points:

My understanding is that we went from:

$$ Y(x) = \sum_{i=0}^k{( \alpha_i \cdot (\frac{T_i(x) - T_i(z)}{x - z} + \frac{T_i(x) - T_i(z \cdot g)}{x - z \cdot g}) )} + \sum_{j=0}^m{\beta_j \cdot \frac{H_j(x) - H_j(z)}{x - z}} $$

Where $T_i(x)$ are trace columns and $H_i(x)$ are constraint evaluation columns.

To something like:

$$ Y(x) = \sum_{i=0}^{k+m}{( \alpha_i \cdot (\frac{T_i(x) - T_i(z)}{x - z} + \frac{T_i(x) - T_i(z \cdot g)}{x - z \cdot g}) )} $$

Where the first $k$ columns of $T_i(x)$ are trace columns and the remaining $m$ columns are the constraint evaluation columns.

Is this correct? If so, this seems like a bit more work (we also need to merge the evaluations at $g \cdot z$ for constraint composition columns, but I guess the expression is more uniform and so this simplifies things a bit - right?

Another thing that wasn't clear to me: for constraint evaluations at $z$ we have a check that they match evaluating constraints against the trace frame. But we don't have any such check for constraint evaluation at $z \cdot g$ (at least as far as I could tell). What prevents a malicious prover from putting some arbitrary data in there? Basically, how does the verifier check that constraint evaluations at $z \cdot g$ included in the QuotientOodFrame are actual evaluations rather than some arbitrary data.

Comment on lines 295 to 299
pub struct QuotientOodFrame<E: FieldElement> {
current_row: Vec<E>,
next_row: Vec<E>,
num_quotients: usize,
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to have num_quotients as a separate filed here? Isn't basically the same as current_row.len()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, it is not needed. Removed now

@Al-Kindi-0
Copy link
Contributor Author

Is this correct? If so, this seems like a bit more work (we also need to merge the evaluations at g ⋅ z for constraint composition columns, but I guess the expression is more uniform and so this simplifies things a bit - right?

Actually, if I am not missing something, this should be, algorithmically at least, better for the prover than before as we have removed the synthetic divisions, one per constraint composition polynomial, and just kept the original two divisions that were used for the trace columns, one for z and one for gz.
In practice, the difference is probably not noticeable and I haven't observed it on the benchmarks I ran (Lamport as it is the example with largest constraint degree).

Another thing that wasn't clear to me: for constraint evaluations at z we have a check that they match evaluating constraints against the trace frame. But we don't have any such check for constraint evaluation at z ⋅ g (at least as far as I could tell). What prevents a malicious prover from putting some arbitrary data in there? Basically, how does the verifier check that constraint evaluations at z ⋅ g included in the QuotientOodFrame are actual evaluations rather than some arbitrary data.

There are, at least, two points I believe:

  1. The prover usually provides the minimal number of openings necessary for the verifier to run the constraints evaluation check, but providing more does not hurt, at least plain soundness.
  2. The fact that the new opened values are part of the DEEP polynomial gives us that, if the DEEP polynomial passes the FRI check, then the opening is a legit opening, with high probability. So the prover cannot send any value or else FRI would not pass.

@irakliyk
Copy link
Collaborator

irakliyk commented May 26, 2025

Actually, if I am not missing something, this should be, algorithmically at least, better for the prover than before as we have removed the synthetic divisions, one per constraint composition polynomial, and just kept the original two divisions that were used for the trace columns, one for z and one for gz.
In practice, the difference is probably not noticeable and I haven't observed it on the benchmarks I ran (Lamport as it is the example with largest constraint degree).

Makes sense!

There are, at least, two points I believe:

  1. The prover usually provides the minimal number of openings necessary for the verifier to run the constraints evaluation check, but providing more does not hurt, at least plain soundness.
  2. The fact that the new opened values are part of the DEEP polynomial gives us that, if the DEEP polynomial passes the FRI check, then the opening is a legit opening, with high probability. So the prover cannot send any value or else FRI would not pass.

Yes, makes sense that FRI guarantees that openings at $g \cdot z$ are for polynomials with the right degree bounds. But would it also guarantee that these openings are for evaluations of constraint polynomials? Basically, could the prover pick some random polynomials of the right degree, evaluate them at $g \cdot z$, and then send openings of these polynomials? Or maybe it doesn't matter?

It has also been a while since I thought about how this works - so, could be missing something simple.

@Al-Kindi-0
Copy link
Contributor Author

Yes, makes sense that FRI guarantees that openings at g ⋅ z are for polynomials with the right degree bounds. But would it also guarantee that these openings are for evaluations of constraint polynomials? Basically, could the prover pick some random polynomials of the right degree, evaluate them at g ⋅ z , and then send openings of these polynomials? Or maybe it doesn't matter?

It has to be the same polynomial that was opened at z and committed to in the constraint composition polynomials trace as the expression appearing in the DEEP poly is
$$\left(\frac{h_i(x) - h_i(z)}{x - z} + \frac{h_i(x) - h_i(gz)}{x - gz}\right)$$
were $h_i$ is one of the constraint composition polynomials.
So in other words, FRI passing tells us that the degrees of the "alleged polynomials" committed to in the constraints composition polys trace are low and that they open at the provided values in the OOD frame at both z and gz

@irakliyk
Copy link
Collaborator

It has to be the same polynomial that was opened at z and committed to in the constraint composition polynomials trace > as the expression appearing in the DEEP poly is
$$\left(\frac{h_i(x) - h_i(z)}{x - z} + \frac{h_i(x) - h_i(gz)}{x - gz}\right)$$
were $h_i$ is one of the constraint composition polynomials.
So in other words, FRI passing tells us that the degrees of the "alleged polynomials" committed to in the constraints composition polys trace are low and that they open at the provided values in the OOD frame at both z and gz

Ah yes - makes sense! Thank you for explaining!

@Al-Kindi-0
Copy link
Contributor Author

Hopefully all feedback is addressed now :)

Copy link
Collaborator

@irakliyk irakliyk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks good! Thank you!

@irakliyk irakliyk merged commit 74246b2 into facebook:main May 27, 2025
8 checks passed
@Al-Kindi-0 Al-Kindi-0 deleted the al-open-quotient-at-gz branch May 27, 2025 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants