Incomplete constant check
Description
The function is_constant
is implemented as follows:
bool is_constant() const { return prime_basis_limb.witness_index == IS_CONSTANT; }
It only checks whether the prime limb is constant, but no check is done on the binary limbs. This causes issues in some of the functions using this if one were to call them with a bigfield
element that has a nonconstant binary limb but constant prime limb. There is a constructor that can be used to construct such bigfield
, so this situation can occur with the current implementation of the bigfield
component.
For example, in reduction_check
, there would be a problem if only the prime limb is constant, as it will replace the current bigfield
element with one that is constant, with a value taken from the binary limbs, even if they are not constant.
In the self_reduce
function, there is already a comment about handling the situation where some limbs are constant and others are not, which may be in reference to the issue under discussion:
template <typename Builder, typename T> void bigfield<Builder, T>::self_reduce() const
{
// Warning: this assumes we have run circuit construction at least once in debug mode where large non reduced
// constants are disallowed via ASSERT
if (is_constant()) {
return;
}
// TODO: handle situation where some limbs are constant and others are not constant
const auto [quotient_value, remainder_value] = get_value().divmod(target_basis.modulus);
Impact
This problem leads to a completeness issue. One concrete example where a user might construct a bigfield
with a constant prime limb and not-constant binary limbs might be if the user wants to have a value modulo that is either or . Then, the prime limb would always be , so it could be constant. In that case, running the circuit to generate the proving key would bake in one particular value as a constant, so proving the circuit with the other choice would later fail.
Recommendations
There are two options. If bigfield
elements in which some, but not all, limbs are constant should be supported, then the is_constant
function should only return true
if all five limbs are constant. If this is not to be supported, then the constructors should ensure that if the prime limb is constant, then the binary limbs are constant as well.
Remediation
This issue has been acknowledged by Aztec, and a fix was implemented in commit 3fdd8022↗. The remediation includes a check in the constructors to ensure that if the prime limb is constant or any binary limbs is constant then all other limbs must be constant.