Abstract
Currently resource logic circuits like the transfer authorization circuit take a single witness and output the corresponding resource logic instance. This RFC proposes to instead make resource logic circuits take a vector of witnesses as inputs and output a corresponding equinumerous vector of resource logic instances. This will not reduce proving times, but it will reduce the number of logic proofs that have to be rolled up by aggregators. The example code here is done in Noir, but the main point might apply to the RISC Zero resource logic circuits.
Motivation
What resource logic circuits do today
A resource logic instance takes a single witness as a private input and outputs a corresponding resource logic instance:
fn main(witness: TransferAuthWitness) -> pub Field {
witness._constrain().digest()
}
The inefficiencies this creates
A transaction that consumes 4 resources of the same logic (e.g. USDC) and creates 4 resource of that same logic will require 8 resource logic proofs. This means that 8 resource logic proofs and a single compliance proof now need to be rolled up into a single proof. The more the proofs that need to be rolled up, the higher the proving time.
New vectorized resource logic circuit
The following change makes the resource logic circuit receive a vector/array of transfer authorization witnesses and output an equinumerous vector/array of resource logic instances.
global BATCH_SIZE: u32 = 4;
fn main(witness: [TransferAuthWitness; BATCH_SIZE]) -> pub [Field; BATCH_SIZE] {
witness.map(|x| x._constrain().digest())
}
Note that the original circuit was essentially multiplied by BATCH_SIZE. Moreover, the processing of each witness in the vector/array is completely independent of the processing of other witnesses. Also for Noir, probably a u32 indicating how many array slots are being used might also be needed.
Impact on total proving time for rollups
Instead of transactions containing as many resource logic proofs as there are consumed resources and created resources, transactions will now only contain as many proofs as there are distinct resource logics used in the transaction. For example, if a transaction only uses USDC resources, it will need only two proofs: one compliance proof and one resource logic proof. And for RISC Zero VM, this statement is true no matter how many resources are created or consumed.
So if the average transaction consumes 2 resources and creates 2 resources of the same logic, then instead of rolling up 5 proofs, only 2 proofs need to be aggregated. In the UltraHonk system, this would probably reduce the time spent aggregating proofs by a factor of 2.5x. All this being said, I do not know the shape of the average ARM transaction.
Impact on memory usage
Proving larger resource logic circuits is likely to use more memory. How problematic this is likely depends on the current memory usage of singleton resource logics.