Preprocessed Trace
This section and the following sections are intended for developers who have completed the First Breath of AIR section or are already familiar with the workflow of creating an AIR. If you have not gone through the previous section, we recommend doing so first as the following sections gloss over a lot of boilerplate code.For those of you who have completed the First Breath of AIR tutorial, you should now be familiar with the concept of a trace as a table of integers that are filled in by the prover (we will now refer to this as the original trace). In addition to the original trace, S-two also has a concept of a preprocessed trace, which is a table whose values are fixed and therefore cannot be arbitrarily chosen by the prover. In other words, these are columns whose values are known in advance of creating a proof and essentially agreed upon by both the prover and the verifier. One of the use cases of the preprocessed trace is as a selector for different constraints. Remember that in an AIR, the same constraints are applied to every row of the trace? If we go back to the spreadsheet analogy, this means that we can’t create a spreadsheet that runs different computations for different rows. To get around this, note that if we multiply a constraint with a “selector” that is zero, the constraint will be trivially satisfied. Building on this, we can create a selector column of 0s and 1s, and multiply the constraint with the selector column. For example, let’s say we want to create a constraint that runs different computations for the first 2 rows and the next 2 rows. We can do this by creating a selector column that has value 0 for the first 2 rows and 1 for the next 2 rows and combining it with the constraints as follows:

IsFirst column, where the value is 1 for the first row and 0 for all other rows.
Boilerplate code is omitted for brevity. Please refer to the full example code for the full implementation.
IsFirstColumn struct that will be used as a preprocessed trace. We will use the gen_column() function to generate a CircleEvaluation struct that is 1 for the first row and 0 for all other rows. The id() function is needed to identify this column when evaluating the constraints.
is_first_id field to retrieve the row value of the IsFirstColumn struct. Then, we compose two constraints using the IsFirstColumn row value as a selector and adding them together.
If you’re unfamiliar with how max_constraint_log_degree_bound(&self) should be implemented, please refer to this note.
FrameworkComponent using the TestEval struct and then prove and verify the component.