Conditional Logic
In provable code, we can't use the JavaScript if
statement. For a constraint system to be valid, it must follow the exact
same path every time it's executed. In traditional programming, what an if
statement does is evaluate an expression, then
jump to one of two different code paths. This behavior can't be copied, but what is possible within provable codes is
setting a variable based on the outcome of an expression. The trick is that both sides of the expression will always be
evaluated.
Invalid Example
For a simple example of the kind of conditional logic that won't work, see:
// INVALID - DO NOT COPY
let n_heads = Field(0);
for (let i = 0; i < 5; i++) {
const x = Field.random();
Provable.if(
x.isEven(),
(n_heads = n_heads.add(1)),
(n_heads = n_heads.add(0))
);
}
// n_heads is ALWAYS 5
The reason this code is invalid is that every iteration, we evaluate the true side, then the false side. So we always
add 1
, then 0
to the number of heads flipped. The result will always evaluate to the number of flips.
Valid Example
Instead, write conditional logic like this:
let n_heads = Field(0);
for (let i = 0; i < 5; i++) {
const x = Field.random();
const flip = Provable.if(x.isEven(), Field(1), Field(0));
n_heads = n_heads.add(flip);
}
This code will work correctly because we assign the result of the expression to a variable, and there are no other side effects caused by evaluating both sides.
Valid Example Using a Function
It is valid to execute code in both sides of the condition, as long as you understand the implications! In general, a function that returns a value and has no side effects is good to use in this case.
function oneMoreThan(x: Field) {
return x.add(1);
}
let n_heads = Field(0);
for (let i = 0; i < 5; i++) {
const x = Field.random();
const new_n_heads = Provable.if(x.isEven(), oneMoreThan(n_heads), n_heads);
n_heads = new_n_heads;
}