Signal Aliasing Remediation
How to fix redundant equality constraints that create aliases without adding security.
Signal Aliasing Remediation
Overview
Related Detector: Signal Aliasing
Signal aliasing occurs when two signals are constrained to be equal (a === b) but neither signal is independently constrained. The equality ensures consistency between the two values, but if both are unconstrained, the prover can set them to any field element. The fix is to ensure at least one side of every equality constraint is independently bound to a meaningful value.
Recommended Fix
Before (Vulnerable)
template UnsafeProcessor() {
signal input x;
signal temp;
signal output out;
temp <-- complexComputation(x);
out === temp; // Alias: out equals temp, but temp is unconstrained
}
After (Fixed — Constrain the Source Signal)
template SafeProcessor() {
signal input x;
signal temp;
signal output out;
temp <-- complexComputation(x);
temp * temp === x; // Independent constraint on temp (e.g., sqrt)
out <== temp; // out now inherits the constraint
}
After (Fixed — Replace Alias with Direct Constraint)
template SafeProcessor() {
signal input x;
signal output out;
out <-- complexComputation(x);
out * out === x; // Directly constrain out, no alias needed
}
Alternative Mitigations
1. Eliminate the Intermediate Signal
If the intermediate signal exists only as a computation step, remove it and constrain the output directly:
// Before: unnecessary alias
signal temp;
temp <-- a / b;
result === temp;
// After: direct constraint
result <-- a / b;
result * b === a; // Direct constraint on result
2. Use Component Outputs Directly
Instead of aliasing a component output to a local signal, use the component output directly in downstream constraints:
component hash = Poseidon(2);
hash.inputs[0] <== a;
hash.inputs[1] <== b;
// Use hash.out directly instead of aliasing to a local signal
expectedHash === hash.out;
Common Mistakes
Assuming equality is a constraint: a === b is a constraint, but it only ensures a == b. If neither a nor b is independently bound, the constraint is satisfied for any value the prover chooses.
Chaining aliases: If a === b and b === c and none are independently constrained, you have three unconstrained signals that must be equal. This is equivalent to one unconstrained signal — no security is added by the chain.
Confusing assignment with constraint: a <== b is shorthand for a <-- b; a === b. If b is unconstrained, this still creates an unconstrained alias. The <== operator does not add constraint strength beyond what === provides.