We define the following type of expressions:
Constant values: only a constant value is allowed.
Linear expression: an expression where only addition is used. These expressions can also be written in short using multiplication of variables by constants. For instance, the expression
2*x + 3*y + 2 is linear, as it is equivalent to
x + x + y + y + y + 2.
Quadratic expression: it is obtained by allowing a multiplication between two linear expressions and an addition of a linear expression:
A*B + C, where
C are linear expressions. For instance, the expression
(2*x + 3*y + 2) * (x+y) + 6*x + y – 2 is quadratic.
Non-quadratic expressions: any arithmetic expression which is not of the previous kind.
When designing a circuit, programmers must define explicitly the constraints that define their arithmetic circuit. All constraints must be quadratic expressions of the form
A*B + C = 0, where
C are linear combinations of signals. For example:
( 3*a - 2*b ) * ( -5*a + 8 ) + ( 7*a - 7*c ) = 0 is a valid constraint for the signals
c. Note that in this case we are taking the following linear combinations:
A = 3*a - 2*b
B = -5*a + 8
C = 7*a - 7*c
3*a^2 - 7 = 0 is also a valid constraint for the variable
a, since it is equivalent to the expression
( 3*a ) * ( a ) - 7 = 0, that uses the linear combinations:
A = 3*a
B = a
C = - 7
( 6*a^2 - c ) * ( b - 7 ) + 9 = 0 is not a valid constraint, since the first term
A = 6*a^2 - b is not a linear combination of signals (because it has the quadratic term
( a - 1 ) * ( b*c + 6 ) + c = 0 is not a valid constraint, since the second term
B = b*c + 6 is not a linear combination of signals (because it has the quadratic term
👉 In some cases, the circom compiler may apply minor transformations to the constraints defined in the circuit in order to meet the format
A*B + C = 0. The transformations are only the following ones:
Move from one side of the equality to the other.
For example, the constraint
a*b = 7 would be transformed into
a*b - 7 = 0.
Multiplication (or divisions) by constants.
For example, the constraint
6*a - 6*b = 0 would be transformed into
a - b = 0.
Constraints are imposed with the operator
===, as in the following examples:
a*(a-1) === 0;(3*a)*(b-3) + 5 === 0;
The constraints added in the code are included as
assert statements in the witness code generation.
A constraint can be defined together with a signal assignment using the operators
==>. With the operator
<== the signal being assigned must be on the left hand side of the operator and with
==> , the signal must be on the right hand side. See the following example:
out <== 1 - a*b;
This line of code does two things at the same time:
On one side, it forces the constraint
out = 1 - a*b. Note that the constraint has the right form
A*B + C = 0 . Following the notation above, we are taking
A = a,
B = b and
C = out - 1.
On the other side, it assigns to the signal
out the result of the operation
1 - a*b.