AztecProtocol / aztec-packages

Apache License 2.0
173 stars 177 forks source link

Use #[no_predicates] when computing contract calls #7729

Open nventuro opened 1 month ago

nventuro commented 1 month ago

A very common pattern is to conditionally call self in order to recursively perform a task, e.g. consume more notes if needed. A naive way to do this would be to do e.g.:

if need_to_recurse {
  Contract::at(self.address).function(params).call()
}

This unfortunately results in a large gate count blowup due to the computation of the contract interaction being predicated. I noticed upwards of 10k extra gates compared to the alternative:

let recursive_call = Contract::at(self.address).function(params);
if need_to_recurse {
  recursive_call.call()
}

This unfortunately is quite unintuitive, and makes it very easy for developers to accidentally write very large circuits. We should apply the #[no_predicates] attribute to the macro-generated functions that are used to create these interfaces, and test that we get the expected gate count reduction.

nventuro commented 1 month ago

The token.transfer function introduced in https://github.com/AztecProtocol/aztec-packages/pull/7730 should see a gate count reduction of ~10k gates if this is properly done.

nventuro commented 1 month ago

This currently causes compilation issues if introduced at the code autogenerated by the macros, likely due to some implementation detail of how no_predicates is implemented, considering it's an internal hack and not really meant to be relied on yet by language users. @vezenovm is looking into an alternative implementation that might solve this.