Input-uniqueness check in CircuitAPI
is ignored
Description
The CircuitAPI
offers the function AssertInputsAreUnique
, which, according to its documentation, will ensure that every item of input data is unique so that no duplicates occur:
// AssertInputsAreUnique Asserts that all input data (Transaction, Receipt,
// StorageSlot) are different from each other
func (api *CircuitAPI) AssertInputsAreUnique() {
api.checkInputUniqueness = 1
}
However, api.checkInputUniqueness
is never used; the relevant code in the Define
function for HostCircuit
in sdk/host_circuit.go is commented out:
func (c *HostCircuit) Define(gapi frontend.API) error {
// ...
//assertInputUniqueness(gapi, c.Input.InputCommitments, api.checkInputUniqueness)
// ...
}
Accordingly, uniqueness of inputs is not actually ensured.
Impact
Users may use AssertInputsAreUnique
and then rely in their logic on the inputs being unique. This not actually being enforced by the circuit can then make users' circuits unsound.
For example, an application circuit may compute a weighted sum of the balances of an account for various accepted tokens, in order to compute their total holdings at a particular time. Such a circuit may use AssertInputsAreUnique
to ensure that attackers cannot inflate their supposed total holdings by using a single balance multiple times in the sum. Due to the discussed issue, this would be ineffective, and incorrect sums could be proven by the attacker.
Recommendations
We recommend to implement the uniqueness check in the HostCircuit
. Alternatively, remove the AssertInputsAreUnique
function from the CircuitAPI
.
Remediation
This issue has been acknowledged by Brevis, and a fix was implemented in commit 78b7d992↗.