Skip to content

Add section on AIRs to composition polynomial#34

Merged
varunthakore merged 3 commits into
mainfrom
varun/airs
Oct 15, 2025
Merged

Add section on AIRs to composition polynomial#34
varunthakore merged 3 commits into
mainfrom
varun/airs

Conversation

@varunthakore

Copy link
Copy Markdown
Contributor

No description provided.


Consider an AIR composed of two components with trace tables: $\mathscr{T}_0$ and $\mathscr{T}_1$. The component table $\mathscr{T}_0$ is defined over the trace domain $D_{n_0}$, which is a [canonic coset](../circle-group.md#canonic-coset) of size $N_0 = 2^{n_0}$. Similarly, component table $\mathscr{T}_1$ is defined over the trace domain $D_{n_1}$ of size $N_1 = 2^{n_1}$.

The prover interpolates the trace polynomials for each component and then evaluates the trace polynomials over an evaluation domain that is a blowup factor $B = 2^\beta$ times larger than the trace domain. Thus, the evaluation domain for component table $\mathscr{T}_0$ is $D_{n_0 + \beta}$ of size $2^{n_0 + \beta}$. Similarly, the evaluation domain for component table $\mathscr{T}_1$ is $D_{n_1 + \beta}$ of size $2^{n_1 + \beta}$. Both interpolation and evaluation use [circle FFT](../circle-fft/index.md). The prover then commits to the evaluations of trace polynomials from all components using a single [Merkle tree](../vcs/index.md).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

is this correct? traces from different components are committed separately, no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The execution trace which contains all the component tables of different sizes is committed in a single Merkle tree. This is an advantage of the Merkle tree construction used in Stwo where the internal nodes can also have values.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Consider this example: https://github.com/starkware-libs/stwo/blob/411d8c6a0142912d75fb38a5f28a767ef9dfb350/crates/examples/src/state_machine/mod.rs#L59-L74

The execution trace corresponding to both the opcodes i.e. op0 and op1 is committed using a single Merkle tree.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ah yes you're right 😅 Please ignore

Comment thread src/how-it-works/air/overview.md Outdated

As shown in an earlier section (refer to [Components](../../air-development/components/index.md)), Stwo represents the trace using multiple tables where each table is referred to as a _component_. An AIR in Stwo is a collection of multiple components. Components can interact with one another, and the consistency of these interactions is verified using [_logUp_](https://eprint.iacr.org/2022/1530.pdf).

For example, in the [hash function example](../../air-development/components/index.md#hash-function-example), the scheduling component and computing component interact with each other: the computing component looks up inputs from the scheduling component, and the scheduling component looks up outputs from the computing component. The consistency of this interaction is then verified by adding logUp constraints to each component.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this may have been from an earlier version, but now it's been changed to the scheduling component looking up the pair (input, output) from the computing component (or computing to scheduling component). It was changed because looking up the inputs and outputs separately can lead to a soundness issue (there's an example added in the linked section). Sorry if there was any confusion about this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, updated this paragraph.

Comment thread src/how-it-works/air/overview.md Outdated

Finally, the prover computes the cross-domain composition polynomial as
$$
q = \gamma^{e_0} \cdot q_0 + \gamma^{e_1} \cdot q_1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think randomness is used when combining the composition polynomials over multiple domains. (accumulate function, which is called here and defined here) We just use it for combining the constraints.

Instead, it would be nice to add an explanation that we expand all composition polynomials to the largest degree composition polynomial domain.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Instead, it would be nice to add an explanation that we expand all composition polynomials to the largest degree composition polynomial domain.

Just read to the end and saw that this is mentioned in the last section 😅 But I still think it would be nice to have an explanation here.

@varunthakore varunthakore Oct 8, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The implementation linked here is for the finalize() function called on the accumulator. But before calling the finalize() function, we evaluate the quotient for each component over their respective evaluation domain and then append those evaluations to the accumulator.

Finally, the finalize() function will combine all the evaluations of the quotients of all the components and then output a single composition quotient polynomial.

https://github.com/zksecurity/stwo/blob/26c65203535a467526d332412f84a9351c0df703/crates/stwo/src/prover/air/component_prover.rs#L61

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This also matches the description in the Stwo whitepaper.

Comment thread src/how-it-works/air/overview.md Outdated

Both component tables define computation constraints and lookup constraints for their specific component. The component constraints are proven table-wise, each with its separate domain quotient, which are then combined into a single cross-domain composition polynomial.

The verifier sends $\gamma \in \mathsf{QM31}$ to the prover, which is used to compute the random linear combination of all constraints on component $\mathscr{T}_0$ to obtain the component-level composition polynomial $p_0$. Similarly, the prover uses powers of $\gamma$ to compute the component-level composition polynomial $p_1$ for component $\mathscr{T}_1$.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think the explanation here is a little confusing. How about mentioning that we reuse the same \gamma to combine all constraints over all component tables? Also, adding an equation illustrating how we use the powers of \gamma over constraints would be nice.

Comment thread src/how-it-works/air/components.md Outdated

The following are some important functions implemented for the `Components` struct.

1. `composition_log_degree_bound`: This function determines the log of the degree of the composition polynomial.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It looks like the first line is shifted to the right because of the tab in L22?
image

Comment thread src/how-it-works/air/components.md Outdated
```
From the perspective of the prover (and verifier), when they need to open the composition polynomial at a specific point sent by the verifier (for example, an out-of-domain point), they require additional polynomial evaluations to verify the constraints.

The composition polynomial combines many component-level constraint quotients. Each constraint involves relationships between multiple cells in the execution trace, potentially at different rows/offsets.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should "multiple cells" be "multiple columns"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I am referring to constraints between multiple cells using preprocessed selectors. I have omitted these details simplicity.

Comment thread src/how-it-works/air/components.md Outdated

The function body operates as follows. First, an `evaluation_accumulator` is instantiated. Then, for each component, the evaluation of the component-level quotient is added to the `evaluation_accumulator`. For the [example AIR containing two components](./overview.md#air-to-composition-polynomial), this adds the evaluations of component-level quotients $q_0$ and $q_1$ at the input `point` to the `evaluation_accumulator`. Finally, the `finalize()` function is called on the `evaluation_accumulator`, which outputs the random linear combination evaluated at the input `point`.
$$
q = \gamma^{e_0} \cdot q_0 + \gamma^{e_1} \cdot q_1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Again, I don't think random linear combination is used here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added a note on the previous comment.

@mellowcroc mellowcroc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM 👍

Comment thread src/how-it-works/air/overview.md Outdated
$$
q = \gamma^{e_0} \cdot q_0 + \gamma^{e_1} \cdot q_1
$$
where $e_0, e_1$ are powers of $\gamma$ that have not been used earlier.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I guess e_0 and e_1 are not necessarily powers that have not been used earlier since they are set to e_0=gamma^0, e_1=gamma^{num_of_constraints_in_p_0}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated the section.

@varunthakore
varunthakore merged commit 4e6504f into main Oct 15, 2025
1 check passed
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

Successfully merging this pull request may close these issues.

2 participants