Description
The underlying circuit library supports arbitrary number of inputs and outputs, but the top-level circuit must have a fixed size. The fixed size is due to the fact that a ZKP circuit design must not have different steps of computation dependent on the input values. Having variable sized arrays is not possible as a result, because that would cause the circuit runtime to perform different computations dependent on the number of elements in the arrays.
At the moment all top level circuits (in the /zkp/circuits
folder) for fungible tokens use 2-sized arrays for both inputs and outputs. Either array can have a 0-valued UTXO so that transactions with either single input or single output can be supported.
With the above, the following combinations of transactions can be supported:
- 2 inputs, 2 outputs
- 1 input, 2 outputs (the 2nd element in the inputs array is set to
0
) - 2 inputs, 1 output (the 2nd element in the outputs array is set to
0
) - 1 input, 1 output (2nd element in the inputs and outputs array are set to
0
)
If we want to support larger sized inputs and outputs, we need the following layers to be updated:
- top level circuits, plus the corresponding proving keys, verification keys (optional if verification is only performed by the Solidity verifier code) and the solidity verifier
- solidity tokens implementations
Having a larger sized inputs and outputs means that, when not all input elements are used, meaning they are set to 0
, all computations are still carried out as if they were non-zero elements, yet the results are not compared with the public inputs. This effectively multiplies the cost of the proof generation, although verification time is still constant thanks to SNARK.
The most efficient way from the runtime point of view is having the exact sized inputs. However this means for every circuit, we need many copies of derived artifacts: verifier contracts, unit tests, etc. Maintenance will be a big headache.