@0xpolygonid/js-sdk
Version:
SDK to work with Polygon ID
412 lines (353 loc) • 13 kB
text/typescript
import { Id, Claim } from '@iden3/js-iden3-core';
import { Signature } from '@iden3/js-crypto';
import { Query, ValueProof, CircuitError, ClaimWithSigProof, TreeState, GISTProof } from './models';
import { Hash, Proof } from '@iden3/js-merkletree';
import {
BaseConfig,
bigIntArrayToStringArray,
existenceToInt,
getNodeAuxValue,
IStateInfoPubSignals,
prepareCircuitArrayValues,
prepareSiblingsStr,
StatesInfo
} from './common';
import { byteDecoder, byteEncoder } from '../utils';
/**
* AtomicQuerySigV2OnChainInputs ZK private inputs for credentialAtomicQuerySig.circom
*
* @public
* @class AtomicQuerySigV2OnChainInputs
* @extends {BaseConfig}
*/
export class AtomicQuerySigV2OnChainInputs extends BaseConfig {
requestID!: bigint;
// auth
id!: Id;
profileNonce!: bigint;
claimSubjectProfileNonce!: bigint;
// claim issued for user
claim!: ClaimWithSigProof;
skipClaimRevocationCheck!: boolean;
authClaim!: Claim;
authClaimIncMtp!: Proof;
authClaimNonRevMtp!: Proof;
treeState!: TreeState;
gistProof!: GISTProof;
signature!: Signature;
challenge!: bigint;
// query
query!: Query;
currentTimeStamp!: number;
/**
* Validate inputs
*
*
*/
validate(): void {
if (!this.requestID) {
throw new Error(CircuitError.EmptyRequestID);
}
if (!this.claim.nonRevProof?.proof) {
throw new Error(CircuitError.EmptyClaimNonRevProof);
}
if (!this.claim.signatureProof?.issuerAuthIncProof.proof) {
throw new Error(CircuitError.EmptyIssuerAuthClaimProof);
}
if (!this.claim.signatureProof.issuerAuthNonRevProof.proof) {
throw new Error(CircuitError.EmptyIssuerAuthClaimNonRevProof);
}
if (!this.claim.signatureProof.signature) {
throw new Error(CircuitError.EmptyClaimSignature);
}
if (!this.query?.values) {
throw new Error(CircuitError.EmptyQueryValue);
}
if (!this.authClaimIncMtp) {
throw new Error(CircuitError.EmptyAuthClaimProof);
}
if (!this.authClaimNonRevMtp) {
throw new Error(CircuitError.EmptyAuthClaimNonRevProof);
}
if (!this.gistProof.proof) {
throw new Error(CircuitError.EmptyGISTProof);
}
if (!this.signature) {
throw new Error(CircuitError.EmptyChallengeSignature);
}
if (this.challenge === null || this.challenge === undefined) {
throw new Error(CircuitError.EmptyChallenge);
}
}
/**
* marshal inputs
*
* @returns Uint8Array
*/
inputsMarshal(): Uint8Array {
this.validate();
if (this.query?.valueProof) {
this.query.validate();
this.query.valueProof.validate();
}
const valueProof = this.query?.valueProof ?? new ValueProof();
const treeState = this.skipClaimRevocationCheck
? this.claim.signatureProof?.issuerAuthNonRevProof.treeState
: this.claim.nonRevProof?.treeState;
const s: Partial<AtomicQuerySigV2OnChainCircuitInputs> = {
requestID: this.requestID.toString(),
userGenesisID: this.id.bigInt().toString(),
profileNonce: this.profileNonce.toString(),
claimSubjectProfileNonce: this.claimSubjectProfileNonce?.toString(),
issuerID: this.claim.issuerID?.bigInt().toString(),
issuerClaim: this.claim.claim?.marshalJson(),
issuerClaimNonRevClaimsTreeRoot: treeState?.claimsRoot?.bigInt().toString(),
issuerClaimNonRevRevTreeRoot: treeState?.revocationRoot?.bigInt().toString(),
issuerClaimNonRevRootsTreeRoot: treeState?.rootOfRoots?.bigInt().toString(),
issuerClaimNonRevState: treeState?.state?.bigInt().toString(),
issuerClaimNonRevMtp:
this.claim.nonRevProof?.proof &&
prepareSiblingsStr(this.claim.nonRevProof.proof, this.getMTLevel()),
issuerClaimSignatureR8x:
this.claim.signatureProof && this.claim.signatureProof.signature.R8[0].toString(),
issuerClaimSignatureR8y: this.claim.signatureProof?.signature.R8[1].toString(),
issuerClaimSignatureS: this.claim.signatureProof?.signature.S.toString(),
issuerAuthClaim: this.claim.signatureProof?.issuerAuthClaim?.marshalJson(),
issuerAuthClaimMtp:
this.claim.signatureProof?.issuerAuthIncProof?.proof &&
prepareSiblingsStr(this.claim.signatureProof.issuerAuthIncProof.proof, this.getMTLevel()),
issuerAuthClaimsTreeRoot: this.claim.signatureProof?.issuerAuthIncProof?.treeState?.claimsRoot
?.bigInt()
.toString(),
issuerAuthRevTreeRoot:
this.claim.signatureProof?.issuerAuthIncProof?.treeState?.revocationRoot
?.bigInt()
.toString(),
issuerAuthRootsTreeRoot: this.claim.signatureProof?.issuerAuthIncProof?.treeState?.rootOfRoots
?.bigInt()
.toString(),
issuerAuthClaimNonRevMtp:
this.claim.signatureProof?.issuerAuthNonRevProof?.proof &&
prepareSiblingsStr(
this.claim.signatureProof.issuerAuthNonRevProof.proof,
this.getMTLevel()
),
claimSchema: this.claim.claim?.getSchemaHash().bigInt().toString(),
claimPathMtp: prepareSiblingsStr(valueProof.mtp, this.getMTLevelsClaim()),
claimPathValue: valueProof.value.toString(),
operator: this.query.operator,
timestamp: this.currentTimeStamp,
// value in this path in merklized json-ld document
slotIndex: this.query?.slotIndex,
isRevocationChecked: 1,
authClaim: this.authClaim.marshalJson(),
authClaimIncMtp:
this.authClaimIncMtp && prepareSiblingsStr(this.authClaimIncMtp, this.getMTLevel()),
authClaimNonRevMtp:
this.authClaimNonRevMtp && prepareSiblingsStr(this.authClaimNonRevMtp, this.getMTLevel()),
challenge: this.challenge?.toString(),
challengeSignatureR8x: this.signature.R8[0].toString(),
challengeSignatureR8y: this.signature.R8[1].toString(),
challengeSignatureS: this.signature.S.toString(),
userClaimsTreeRoot: this.treeState.claimsRoot?.string(),
userRevTreeRoot: this.treeState.revocationRoot?.string(),
userRootsTreeRoot: this.treeState.rootOfRoots?.string(),
userState: this.treeState.state?.string(),
gistRoot: this.gistProof.root.string(),
gistMtp: this.gistProof && prepareSiblingsStr(this.gistProof.proof, this.getMTLevelOnChain())
};
if (this.skipClaimRevocationCheck) {
s.isRevocationChecked = 0;
}
const nodeAuxNonRev = getNodeAuxValue(this.claim.nonRevProof?.proof);
s.issuerClaimNonRevMtpAuxHi = nodeAuxNonRev?.key.bigInt().toString();
s.issuerClaimNonRevMtpAuxHv = nodeAuxNonRev?.value.bigInt().toString();
s.issuerClaimNonRevMtpNoAux = nodeAuxNonRev?.noAux;
const nodeAuxIssuerAuthNonRev = getNodeAuxValue(
this.claim.signatureProof?.issuerAuthNonRevProof.proof
);
s.issuerAuthClaimNonRevMtpAuxHi = nodeAuxIssuerAuthNonRev?.key.bigInt().toString();
s.issuerAuthClaimNonRevMtpAuxHv = nodeAuxIssuerAuthNonRev?.value.bigInt().toString();
s.issuerAuthClaimNonRevMtpNoAux = nodeAuxIssuerAuthNonRev?.noAux;
s.claimPathNotExists = existenceToInt(valueProof.mtp.existence);
const nodAuxJSONLD = getNodeAuxValue(valueProof.mtp);
s.claimPathMtpNoAux = nodAuxJSONLD.noAux;
s.claimPathMtpAuxHi = nodAuxJSONLD.key.bigInt().toString();
s.claimPathMtpAuxHv = nodAuxJSONLD.value.bigInt().toString();
s.claimPathKey = valueProof.path.toString();
const values = prepareCircuitArrayValues(this.query.values, this.getValueArrSize());
s.value = bigIntArrayToStringArray(values);
const nodeAuxAuth = getNodeAuxValue(this.authClaimNonRevMtp);
s.authClaimNonRevMtpAuxHi = nodeAuxAuth.key.string();
s.authClaimNonRevMtpAuxHv = nodeAuxAuth.value.string();
s.authClaimNonRevMtpNoAux = nodeAuxAuth.noAux;
const globalNodeAux = getNodeAuxValue(this.gistProof.proof);
s.gistMtpAuxHi = globalNodeAux.key.string();
s.gistMtpAuxHv = globalNodeAux.value.string();
s.gistMtpNoAux = globalNodeAux.noAux;
return byteEncoder.encode(JSON.stringify(s));
}
}
/**
* AtomicQuerySigV2OnChainCircuitInputs type represents credentialAtomicQuerySig.circom private inputs required by prover
*
* @public
* @class AtomicQuerySigV2OnChainCircuitInputs
*/
export class AtomicQuerySigV2OnChainCircuitInputs {
requestID!: string;
// user data
userGenesisID!: string;
profileNonce!: string;
claimSubjectProfileNonce!: string;
issuerID!: string;
// Claim
issuerClaim!: string[];
issuerClaimNonRevClaimsTreeRoot!: string;
issuerClaimNonRevRevTreeRoot!: string;
issuerClaimNonRevRootsTreeRoot!: string;
issuerClaimNonRevState!: string;
issuerClaimNonRevMtp!: string[];
issuerClaimNonRevMtpAuxHi!: string;
issuerClaimNonRevMtpAuxHv!: string;
issuerClaimNonRevMtpNoAux!: string;
claimSchema!: string;
issuerClaimSignatureR8x!: string;
issuerClaimSignatureR8y!: string;
issuerClaimSignatureS!: string;
issuerAuthClaim!: string[];
issuerAuthClaimMtp!: string[];
issuerAuthClaimNonRevMtp!: string[];
issuerAuthClaimNonRevMtpAuxHi!: string;
issuerAuthClaimNonRevMtpAuxHv!: string;
issuerAuthClaimNonRevMtpNoAux!: string;
issuerAuthClaimsTreeRoot!: string;
issuerAuthRevTreeRoot!: string;
issuerAuthRootsTreeRoot!: string;
isRevocationChecked!: number;
// Query
// JSON path
claimPathNotExists!: number; // 0 for inclusion, 1 for non-inclusion
claimPathMtp!: string[];
claimPathMtpNoAux!: string; // 1 if aux node is empty, 0 if non-empty or for inclusion proofs
claimPathMtpAuxHi!: string; // 0 for inclusion proof
claimPathMtpAuxHv!: string; // 0 for inclusion proof
claimPathKey!: string; // hash of path in merklized json-ld document
claimPathValue!: string; // value in this path in merklized json-ld document
operator!: number;
slotIndex!: number;
timestamp!: number;
value!: string[];
// AuthClaim proof of inclusion
authClaim!: string[];
authClaimIncMtp!: string[];
// AuthClaim non revocation proof
authClaimNonRevMtp!: string[];
authClaimNonRevMtpAuxHi!: string;
authClaimNonRevMtpAuxHv!: string;
authClaimNonRevMtpNoAux!: string;
challenge!: string;
challengeSignatureR8x!: string;
challengeSignatureR8y!: string;
challengeSignatureS!: string;
// User State
userClaimsTreeRoot!: string;
userRevTreeRoot!: string;
userRootsTreeRoot!: string;
userState!: string;
// Global on-cain state
gistRoot!: string;
gistMtp!: string[];
gistMtpAuxHi!: string;
gistMtpAuxHv!: string;
gistMtpNoAux!: string;
}
/**
*
* public signals
* @public
* @class AtomicQuerySigV2OnChainPubSignals
* @extends {BaseConfig}
*/
export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig implements IStateInfoPubSignals {
requestID!: bigint;
userID!: Id;
issuerID!: Id;
issuerAuthState!: Hash;
issuerClaimNonRevState!: Hash;
timestamp!: number;
merklized!: number;
isRevocationChecked!: number; // 0 revocation not check, // 1 for check revocation
circuitQueryHash!: bigint;
challenge!: bigint;
gistRoot!: Hash;
//
/**
*
* // PubSignalsUnmarshal unmarshal credentialAtomicQuerySig.circom public signals
* @param {Uint8Array} data
* @returns AtomicQuerySigV2PubSignals
*/
pubSignalsUnmarshal(data: Uint8Array): AtomicQuerySigV2OnChainPubSignals {
// expected order:
// merklized
// userID
// circuitQueryHash
// issuerAuthState
// requestID
// challenge
// gistRoot
// issuerID
// isRevocationChecked
// issuerClaimNonRevState
// timestamp
// claimPathNotExists
// claimPathKey
const sVals: string[] = JSON.parse(byteDecoder.decode(data));
let fieldIdx = 0;
// -- merklized
this.merklized = parseInt(sVals[fieldIdx]);
fieldIdx++;
// - userID
this.userID = Id.fromBigInt(BigInt(sVals[fieldIdx]));
fieldIdx++;
// - circuitQueryHash
this.circuitQueryHash = BigInt(sVals[fieldIdx]);
fieldIdx++;
// - issuerAuthState
this.issuerAuthState = Hash.fromString(sVals[fieldIdx]);
fieldIdx++;
// - requestID
this.requestID = BigInt(sVals[fieldIdx]);
fieldIdx++;
// - challenge
this.challenge = BigInt(sVals[fieldIdx]);
fieldIdx++;
// - gistRoot
this.gistRoot = Hash.fromString(sVals[fieldIdx]);
fieldIdx++;
// - issuerID
this.issuerID = Id.fromBigInt(BigInt(sVals[fieldIdx]));
fieldIdx++;
// - isRevocationChecked
this.isRevocationChecked = parseInt(sVals[fieldIdx]);
fieldIdx++;
// - issuerClaimNonRevState
this.issuerClaimNonRevState = Hash.fromString(sVals[fieldIdx]);
fieldIdx++;
// - timestamp
this.timestamp = parseInt(sVals[fieldIdx]);
fieldIdx++;
return this;
}
/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
getStatesInfo(): StatesInfo {
return {
states: [
{ id: this.issuerID, state: this.issuerAuthState },
{ id: this.issuerID, state: this.issuerClaimNonRevState }
],
gists: [{ id: this.userID, root: this.gistRoot }]
};
}
}