mirror of
https://github.com/0xPARC/zk-bug-tracker.git
synced 2026-01-08 21:38:06 -05:00
Updated section related to arithmetic overflows
This commit is contained in:
32
README.md
32
README.md
@@ -820,31 +820,41 @@ This can cause unintended consequences if there are no checks preventing these p
|
||||
|
||||
**Attack Scenario**
|
||||
|
||||
For example, let’s assume there is a circuit that outputs a user’s new balance as the public output:
|
||||
For example, consider the following circuit that computes a user’s new balance:
|
||||
|
||||
```jsx
|
||||
template getNewBalance() {
|
||||
signal currBal;
|
||||
signal withdrawAmt;
|
||||
signal output newBal;
|
||||
signal currentBalance;
|
||||
signal withdrawAmount;
|
||||
signal output newBalance;
|
||||
|
||||
newBal <== currBal - withdrawAmt;
|
||||
newBalance <== currentBalance - withdrawAmount;
|
||||
}
|
||||
```
|
||||
|
||||
If a user inputs a currBal < withdrawAmt, the newBal output will underflow and will be an extremely large number close to p. This is clearly not what is intended by the circuit.
|
||||
If a user inputs a `withdrawAmount` that is greater than their `currentBalance`, the `newBalance` output will underflow and will be an extremely large number close to `p`. This is clearly not what was intended by the circuit writer.
|
||||
|
||||
**Preventative Techniques**
|
||||
**The fix**
|
||||
|
||||
Adding range checks via the circomlib/comparators library can ensure the numbers we are working with are not within bounds of causing over/under flows:
|
||||
We can use the `LessThan` and `Num2Bits` templates defined by Circomlib to ensure the values we are working with are within the correct bounds, and will not cause overflows or underflows:
|
||||
|
||||
```jsx
|
||||
component lt = LessThan(252);
|
||||
lt.in[0] = withdrawAmt;
|
||||
lt.in[1] = currBal;
|
||||
# Ensure that both values are positive.
|
||||
component n2b1 = Num2Bits(64);
|
||||
n2b1.in <== withdrawAmount;
|
||||
|
||||
component n2b2 = Num2Bits(64);
|
||||
n2b2.in <== currentBalance;
|
||||
|
||||
# Ensure that withdrawAmount <= currentBalance.
|
||||
component lt = LessThan(64);
|
||||
lt.in[0] = withdrawAmount;
|
||||
lt.in[1] = currentBalance + 1;
|
||||
lt.out === 1;
|
||||
```
|
||||
|
||||
Here, `Num2Bits(n)` is used as a range check to ensure that the input lies in the interval `[0, 2^n)`. In particular, if `n` is small enough this ensures that the input is positive. If we forgot these range checks a malicious user could input a `withdrawAmount` equal to `p - 1`. This would satisfy the constraints defined by `LessThan` as long as the current balance is non-negative since `p - 1 = -1 < currentBalance`.
|
||||
|
||||
## <a name="mismatching-bit-lengths">4. Mismatching Bit Lengths</a>
|
||||
|
||||
Many of CircomLib’s circuits take in an expected number of bits. In order for their constraints and output to be accurate, the input parameters need to be constrained to that maximum number of bits outside of the CircomLib circuit. For example, the *LessThan* circuit expects *n* number of bits.
|
||||
|
||||
Reference in New Issue
Block a user