This proof function is used to implement the proof of payment authorization flow.
The proof functions for the proof of payment flow are in ozki-toolkit repo:
zkp/proof-functions/ProvePayPalSubscriptionMain.circom
This is the wrapper function which simply instantiates the ProvePayPalSubscription component.
zkp/circuits/ProvePayPalSubscription.circom
This is the actual proof function.
The ProvePayPalSubscriptionMain.circom codes are listed below.
pragma circom 2.0.0;
include "../circuits/ProvePayPalSubscription.circom";
component main = ProvePayPalSubscription(48, (48+4+4)*8, 8);
The ProvePayPalSubscription.circom code are listed below. The key points to note in this function are:
This function takes 5 input parameters: sigR8, sigS, ts, payment_subs_id, pa.
Input parameter 'ts' (for timestamp) is always required for OZKi proof function.
Because this proof function an implementation for the OZKi signed proof, the signature parameters (sigR8, and SigS) are required. Also note that the first thing the proof function does is to check the digital signature using the oracle public key.
Input parameter payment_subs_id and pa (for payment age) are the custom input parameters.
Output parameter timestamp is always required for OZKi proof function.
Output parameter constraintStatus is custom output parameter.
pragma circom 3.0.0;include "comparators.circom";include "isbufferequal.circom";include "eddsa.circom";include "bitify.circom";template ProvePayPalSubscription(length, eddsaLength, bitsize) {// input signals:// ozki: sigR8, sigS, and ts: required, name sensitive, order insensitive signal input sigR8[256]; // required input signal input sigS[256]; // required input signal input ts[4]; // required input signal input payment_subs_id[length]; // custom input signal input pa[4]; // custom input// output signals:// ozki: timeStamp, and constraintStatus: required, name insensitive, order sensitive signal output timestamp; // required output signal output constraintStatus; // required output// custom output may follow here// local varsvarPAYPAL_SUBSCRIPTION_PERIOD=365; // 1 yearvarPAYPAL_SUBSCRIPTION_ID_LENGTH=26; // subs id is fixed at 26 chars// The expected Paypal's subscription id (P-1BF08962SE3742350MKRYCVQ)varPAYPAL_SUBSCRIPTION_ID[PAYPAL_SUBSCRIPTION_ID_LENGTH] = [ 80,45,49,66,70,48,56,57,54,50,83,69,51,55,52,50,51,53,48,77,75,82,89,67,86,81 ];// The oracle's digital signature verification keyvarORACLE_DSAVER_KEY[256] = [0,0,1,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1,1,0,1,1,1,1,0,1,1,0,0,1,0,1,0,1,1,0,1,0,0,1,1,1,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,1,1,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,1,1,0,1,1,1,0,0,1,1,1,1,0,1,0,1,0,0,1,1,0,0,0,0,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,0,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,0,1,0,0,0,0,1,1,0,1,0,1,1,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,1,1,1,1,0,1,1,1,0,0,0,0,1,1,1,1,0,0,1];var status =1;var msg[56];var msgBits[eddsaLength];var expected_subs_id[length];var tmstamp = ts[0] + ts[1]*256+ ts[2]*256*256+ ts[3]*256*256*256;var payment_age = pa[0] + pa[1]*256+ pa[2]*256*256+ pa[3]*256*256*256;// circom components component isSubsIdEqual =IsBufferEqual(length); component isAgeGood =LessEqThan(32); component eddsaSignature =EdDSAVerifier(eddsaLength); component bits[56];// serialize inputs into 'msg' varfor (var i =0; i <48; i++) { msg[i] = payment_subs_id[i]; }for (var i =0; i <4; i++) { msg[48+i] = pa[i]; // payment age msg[52+i] = ts[i]; // timestamp }// convert msg into msgBitsfor (var i =0; i <56; i++) {//log(i); bits[i] =Num2Bits(bitsize); bits[i].in <== msg[i];for (var j =0; j < bitsize; j++) {//log(i*bitsize+j); msgBits[i*bitsize + j] = bits[i].out[j]; } }//// Verify the signature//for (var i =0; i <256; i++) {eddsaSignature.A[i] <==ORACLE_DSAVER_KEY[i];eddsaSignature.R8[i] <== sigR8[i];eddsaSignature.S[i] <== sigS[i]; }for (var i =0; i < eddsaLength; i++) {eddsaSignature.msg[i] <== msgBits[i]; }// eddsaSignature will error out right here if the sig ver fails//// verify payment_age// payment age has to be equal or less than the expected age//isAgeGood.in[0] <== payment_age;isAgeGood.in[1] <==PAYPAL_SUBSCRIPTION_PERIOD;isAgeGood.out ===1; status = status *isAgeGood.out;//// verify payment_subs_id// the payment's subscription id must match the expected one//for (var i =0; i <PAYPAL_SUBSCRIPTION_ID_LENGTH; i++) { expected_subs_id[i] =PAYPAL_SUBSCRIPTION_ID[i]; }for (var i =PAYPAL_SUBSCRIPTION_ID_LENGTH; i < length; i++) { expected_subs_id[i] =32; }for (var i =0; i < length; i++) {isSubsIdEqual.buffer1[i] <== payment_subs_id[i];isSubsIdEqual.buffer2[i] <== expected_subs_id[i]; }isSubsIdEqual.out ===1; status = status *isSubsIdEqual.out; timestamp <== tmstamp; constraintStatus <== status;}