Verify addition of 2-byte numbers
The aim in this section is to design a program (and its corresponding PIL code) to verify addition of two integers each of a size fitting in exactly 2 bytes. Any input to the addition program is considered invalid if it is not an integer in the range [0, 65535].Naive execution trace
Of course, there are many ways in which such a program can be arithmetized. We are going to use a method based on inclusion arguments. The overall idea is to reduce -byte additions to -byte additions. Specifically, the program consists of two input polynomials and where each introduces a single byte (equivalently, an integer in the range [0, 255]) in each row, starting with the less significant byte, for each operand of the sum. Hence, a new addition is checked in every second row. The output of the addition between -byte words can’t be stored in a single column that only accepts words of -byte, since an overflow may occur. The result of the addition is split into two columns; and . Each column accepts only -byte words, thereby storing the complete result so that a correct addition between bytes can be defined as: The below table shows an example of a valid execution trace for this program. Note that the final sum of each pair of -byte numbers, in the above table, is composed of the last value and the last two values, from the most significant to the least significant (going from left to right). For example, . Similarly, . Observe that is not satisfied in row 4, because the value raised in the third row must be added to the -byte addition at row 4. The problem with this design is that there’s no direct way to introduce the previous value of in the PIL code.Adding an extra polynomial
There is a need to introduce another polynomial, call it , which contains a shifted version of the value in the polynomial. More specifically, we add the following constraint to ensure that is correctly defined: There is another snag here. According to , the previous value could affect two different 2-byte additions. That is, two non-related operations should not be linked via carries. A selector polynomial can be used to separate values of from one addition to another. We use as previously used. for every odd row index, and otherwise. The execution trace is now adjusted as follows, Following this logic, we can now derive the final (and accurate) constraint: The PIL code can now be written as follows:Addition of n-byte numbers
Similarly to the Multiplier example of the previous sections, it is worth mentioning that by changing only the polynomial (and not the PIL itself), it is possible to arithmetize the program in such a way that generic -byte additions can be verified. In such cases, for the first rows of each operation, and in the -th row of the operation. Up to this point, one can think that the constraint in restricts sound representation of the program. However, since we are working over a finite field, it is not. For example, the following execution trace is valid, as it satisfies all the constraints, but does not correspond to a valid computation: The above table gives a concrete example of how to work around any restrictions of the current program. Nonetheless, the introduction of more bytes in either column does not break the intention of this program, which was designed to only deal with byte-sized columns. It is strictly necessary to enforce that all the evaluations of committed polynomials be correct. An inclusion argument is used for this purpose.Inclusion argument
Given two vectors, and , it is said that, In other words, if one thinks of and as multisets and reduce them to sets (by removing the multiplicity), then is contained in if is a subset of . See this document for more details on multisets and Plookup. A protocol is an inclusion argument if the protocol can be used by to prove to that one vector is contained in another vector. In the PIL context, the implemented inclusion argument is the same as the method provided in [GW20], also discussed here. Other “alternative” method exists such as PlonkUp. An inclusion argument is invoked in PIL with the "" keyword. Specifically, given two columns and , we can declare an inclusion argument between them using the syntax , where and do not necessarily need to be defined in different programs. For instance, the PIL code for a program called , with an inclusion argument is as follows.