pragma circom 2.1.8;
template exp(){
signal output out1;
signal output out2;
out1 <-- 3 ** p;
//out1: expected 1F_p
//out1: actual 3F_p
out2 <-- 3 ** (p + 0);
//out2: expected 1F_p
//out2: actual 1F_p
}
component main = exp();
I came across a discrepancy in how the Circom compiler handles the prime p during compile-time evaluation.
According to the findings, the compiler fails to apply modular reduction to the prime p immediately during compilation, whereas expressions like p+0 are correctly reduced. This leads to inconsistent results when p is used as an exponent or in similar operations.
- We have a signal
out1 calculated using a function of p (e.g., $3^p$).
- We have a signal
out2 calculated using a function of p+0 (e.g., $3^{(p+0)}$).
In the scalar field $\mathbb{F}_p$, the value $p$ should be equivalent to $0$ (since $p \equiv 0 \pmod p$).
Therefore, an operation like $3^p$ (interpreted modulo $p$ in the exponent context for field elements) should conceptually be treated as $3^0$.
out1 (using p directly): The compiler does not reduce p to 0. It computes $3^p$. By Fermat's Little Theorem, $3^p \equiv 3 \pmod p$. The result is 3.
out2 (using p+0): The expression p+0 undergoes modular reduction after numerical evaluation. It becomes 0. The computation becomes $3^0$. The result is 1.
Both out1 and out2 should yield the same result. The prime p should be treated as 0 in $\mathbb{F}_p$ arithmetic during compilation, just as p+0 is. The expected result for both is 1.
Actual Behavior
-
out1 evaluates to 3 (Derived from $3^p$).
-
out2 evaluates to 1 (Derived from $3^0$).
I came across a discrepancy in how the Circom compiler handles the prime
pduring compile-time evaluation.According to the findings, the compiler fails to apply modular reduction to the prime
pimmediately during compilation, whereas expressions likep+0are correctly reduced. This leads to inconsistent results whenpis used as an exponent or in similar operations.out1calculated using a function ofp(e.g.,out2calculated using a function ofp+0(e.g.,In the scalar field$\mathbb{F}_p$ , the value $p$ should be equivalent to $0$ (since $p \equiv 0 \pmod p$ ).$3^p$ (interpreted modulo $p$ in the exponent context for field elements) should conceptually be treated as $3^0$ .
Therefore, an operation like
out1(usingpdirectly): The compiler does not reducepto0. It computes3.out2(usingp+0): The expressionp+0undergoes modular reduction after numerical evaluation. It becomes0. The computation becomes1.Both$\mathbb{F}_p$ arithmetic during compilation, just as
out1andout2should yield the same result. The primepshould be treated as0inp+0is. The expected result for both is1.Actual Behavior
out1evaluates to3(Derived fromout2evaluates to1(Derived from