Using UPA in your ZK app
Last updated
Last updated
NEBRA Labs
In a typical ZK app:
The client makes requests of the app contract. Each request contains public inputsPIs
along with a proof that those public inputs were valid.
The app contract calls a verify
function that checks whether a request's (PIs, proof)
pair is valid or not. If the request was valid, then the app contract executes the corresponding business logic.
In a UPA-integrated ZK app, the UPA contract takes over the responsibility of proof verification. The client now makes a AppRequest
in two stages.
First, they submit (PIs, Proof)
to the UPA contract. If the proof is valid, then after some time the PIs
are marked as verified in the UPA contract.
Second, they make an AppRequest(PIs)
. The app contract checks whether PIs
has been marked as verified on the UPA contract. If so, the app goes on to execute the request.
The client saves gas because UPA verifies batches of proofs rather than individual proofs.
The UPA contract verifies batches of proofs as follows.
The UPA contract receives a submit(PIs, Proof)
call.
An off-chain proof aggregator adds the (PIs, Proof)
pair to a batch. Then it produces a ZK proof aggregatedProof
that all of the (PIs, proof)
pairs in that batch are valid. It then sends the aggregatedProof
to the UPA contract.
The UPA contract only needs to verify a single proof: aggregatedProof
. If correct, then the contract marks all of the proofs in the corresponding batch as valid.