-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #115 from iden3/feature/linked-proof-pocs
Linked proof PoCs
- Loading branch information
Showing
5 changed files
with
292 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
pragma circom 2.1.1; | ||
|
||
include "../../../node_modules/circomlib/circuits/comparators.circom"; | ||
include "query.circom"; | ||
include "modifiers.circom"; | ||
include "../utils/claimUtils.circom"; | ||
|
||
template ProcessQueryWithModifiers(claimLevels, valueArraySize){ | ||
signal input enabled; | ||
signal input claimPathNotExists; // 0 for inclusion, 1 for non-inclusion | ||
signal input claimPathMtp[claimLevels]; | ||
signal input claimPathMtpNoAux; // 1 if aux node is empty, 0 if non-empty or for inclusion proofs | ||
signal input claimPathMtpAuxHi; // 0 for inclusion proof | ||
signal input claimPathMtpAuxHv; // 0 for inclusion proof | ||
signal input claimPathKey; // hash of path in merklized json-ld document | ||
signal input claimPathValue; // value in this path in merklized json-ld document | ||
signal input slotIndex; | ||
signal input operator; | ||
signal input value[valueArraySize]; | ||
|
||
signal input issuerClaim[8]; | ||
signal input merklized; | ||
signal input merklizedRoot; | ||
|
||
// Modifier/Computation Operator output ($sd) | ||
signal output operatorOutput; | ||
|
||
signal smtEnabled <== AND()(enabled, merklized); | ||
|
||
// check path/in node exists in merkletree specified by jsonldRoot | ||
SMTVerifier(claimLevels)( | ||
enabled <== smtEnabled, // if merklize flag 0 or enabled 0 skip MTP verification | ||
fnc <== claimPathNotExists, // inclusion | ||
root <== merklizedRoot, | ||
siblings <== claimPathMtp, | ||
oldKey <== claimPathMtpAuxHi, | ||
oldValue <== claimPathMtpAuxHv, | ||
isOld0 <== claimPathMtpNoAux, | ||
key <== claimPathKey, | ||
value <== claimPathValue | ||
); // 9585 constraints | ||
|
||
// select value from claim by slot index (0-7) | ||
signal slotValue <== getValueByIndex()(issuerClaim, slotIndex); | ||
|
||
// select value for query verification, | ||
// if claim is merklized merklizeFlag = `1|2`, take claimPathValue | ||
// if not merklized merklizeFlag = `0`, take value from selected slot | ||
signal fieldValue <== Mux1()( | ||
[slotValue, claimPathValue], | ||
merklized | ||
); | ||
|
||
///////////////////////////////////////////////////////////////// | ||
// Query Operator Processing | ||
///////////////////////////////////////////////////////////////// | ||
|
||
// verify query | ||
// 1756 constraints (Query+LessThan+ForceEqualIfEnabled) | ||
signal querySatisfied <== Query(valueArraySize)( | ||
in <== fieldValue, | ||
value <== value, | ||
operator <== operator | ||
); | ||
|
||
signal isQueryOp <== LessThan(5)([operator, 16]); | ||
signal querySatisfiedEnabled <== AND()(enabled, isQueryOp); | ||
ForceEqualIfEnabled()( | ||
querySatisfiedEnabled, | ||
[querySatisfied, 1] | ||
); | ||
|
||
///////////////////////////////////////////////////////////////// | ||
// Modifier/Computation Operators Processing | ||
///////////////////////////////////////////////////////////////// | ||
|
||
// selective disclosure | ||
// no need to calc anything, fieldValue is just passed as an output | ||
|
||
///////////////////////////////////////////////////////////////// | ||
// Modifier Operator Validation & Output Preparation | ||
///////////////////////////////////////////////////////////////// | ||
|
||
// output value only if modifier operation was selected | ||
operatorOutput <== modifierValidatorOutputSelector()( | ||
operator <== operator, | ||
modifierOutputs <== [ | ||
fieldValue, // 16 - selective disclosure (16-16 = index 0) | ||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 17-31 - not used | ||
] | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
pragma circom 2.1.5; | ||
|
||
include "../../node_modules/circomlib/circuits/comparators.circom"; | ||
include "../lib/query/processQueryWithModifiers.circom"; | ||
include "../lib/linked/linkId.circom"; | ||
include "../lib/utils/claimUtils.circom"; | ||
include "../lib/utils/safeOne.circom"; | ||
include "../lib/utils/spongeHash.circom"; | ||
|
||
// This circuit processes multiple query requests at once for a given claim using linked proof | ||
template LinkedMultiQuery(N, claimLevels, valueArraySize) { | ||
|
||
// linked proof signals | ||
signal input linkNonce; | ||
signal input issuerClaim[8]; | ||
|
||
// query signals | ||
signal input enabled[N]; // 1 if query non-empty, 0 to skip query check | ||
signal input claimSchema; | ||
signal input claimPathNotExists[N]; // 0 for inclusion, 1 for non-inclusion | ||
signal input claimPathMtp[N][claimLevels]; | ||
signal input claimPathMtpNoAux[N]; // 1 if aux node is empty, 0 if non-empty or for inclusion proofs | ||
signal input claimPathMtpAuxHi[N]; // 0 for inclusion proof | ||
signal input claimPathMtpAuxHv[N]; // 0 for inclusion proof | ||
signal input claimPathKey[N]; // hash of path in merklized json-ld document | ||
signal input claimPathValue[N]; // value in this path in merklized json-ld document | ||
signal input slotIndex[N]; | ||
signal input operator[N]; | ||
signal input value[N][valueArraySize]; | ||
|
||
// Outputs | ||
signal output linkID; | ||
signal output merklized; | ||
signal output operatorOutput[N]; | ||
signal output circuitQueryHash[N]; | ||
|
||
///////////////////////////////////////////////////////////////// | ||
// General verifications | ||
///////////////////////////////////////////////////////////////// | ||
|
||
// get safe one values to be used in ForceEqualIfEnabled | ||
signal one <== SafeOne()(linkNonce); // 7 constraints | ||
|
||
// get claim header | ||
component issuerClaimHeader = getClaimHeader(); // 300 constraints | ||
issuerClaimHeader.claim <== issuerClaim; | ||
|
||
// get merklized flag & root | ||
component merklize = getClaimMerklizeRoot(); | ||
merklize.claim <== issuerClaim; | ||
merklize.claimFlags <== issuerClaimHeader.claimFlags; | ||
|
||
merklized <== merklize.flag; | ||
|
||
// Verify issuerClaim schema | ||
verifyCredentialSchema()(one, issuerClaimHeader.schema, claimSchema); // 3 constraints | ||
|
||
signal valueHash[N]; | ||
signal queryHash[N]; | ||
|
||
signal issuerClaimHash, issuerClaimHi, issuerClaimHv; | ||
(issuerClaimHash, issuerClaimHi, issuerClaimHv) <== getClaimHash()(issuerClaim); // 834 constraints | ||
//////////////////////////////////////////////////////////////////////// | ||
// calculate linkID | ||
//////////////////////////////////////////////////////////////////////// | ||
linkID <== LinkID()(issuerClaimHash, linkNonce); // 243 constraints | ||
|
||
///////////////////////////////////////////////////////////////// | ||
// Query Processing Loop | ||
///////////////////////////////////////////////////////////////// | ||
for (var i=0; i<N; i++) { | ||
|
||
// output value only if modifier operation was selected | ||
operatorOutput[i] <== ProcessQueryWithModifiers(claimLevels, valueArraySize)( | ||
enabled[i], | ||
claimPathNotExists[i], | ||
claimPathMtp[i], | ||
claimPathMtpNoAux[i], | ||
claimPathMtpAuxHi[i], | ||
claimPathMtpAuxHv[i], | ||
claimPathKey[i], | ||
claimPathValue[i], | ||
slotIndex[i], | ||
operator[i], | ||
value[i], | ||
issuerClaim, | ||
merklized, | ||
merklize.out | ||
); | ||
|
||
///////////////////////////////////////////////////////////////// | ||
// Calculate query hash | ||
///////////////////////////////////////////////////////////////// | ||
// 4950 constraints (SpongeHash+Poseidon) | ||
valueHash[i] <== SpongeHash(valueArraySize, 6)(value[i]); // 6 - max size of poseidon hash available on-chain | ||
queryHash[i] <== Poseidon(6)([ | ||
claimSchema, | ||
slotIndex[i], | ||
operator[i], | ||
claimPathKey[i], | ||
claimPathNotExists[i], | ||
valueHash[i] | ||
]); | ||
|
||
circuitQueryHash[i] <== Mux1()([0, queryHash[i]], enabled[i]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
pragma circom 2.1.5; | ||
|
||
include "../../node_modules/circomlib/circuits/comparators.circom"; | ||
include "../lib/linked/linkId.circom"; | ||
include "../lib/utils/nullify.circom"; | ||
include "../lib/utils/safeOne.circom"; | ||
include "../lib/utils/claimUtils.circom"; | ||
|
||
// This circuit generates nullifier for a given claim using linked proof | ||
template LinkedNullifier(){ | ||
|
||
// linked proof signals | ||
signal input linkNonce; | ||
signal input issuerClaim[8]; | ||
|
||
// nullifier signals | ||
signal input userGenesisID; | ||
signal input claimSubjectProfileNonce; | ||
signal input claimSchema; | ||
signal input verifierID; | ||
signal input nullifierSessionID; | ||
|
||
signal output nullifier; | ||
signal output linkID; | ||
|
||
// get safe one values to be used in ForceEqualIfEnabled | ||
signal one <== SafeOne()(userGenesisID); // 7 constraints | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
// verify nullifier signals | ||
//////////////////////////////////////////////////////////////////////// | ||
|
||
component issuerClaimHeader = getClaimHeader(); // 300 constraints | ||
issuerClaimHeader.claim <== issuerClaim; | ||
|
||
// Verify issuerClaim schema | ||
verifyCredentialSchema()(one, issuerClaimHeader.schema, claimSchema); // 3 constraints | ||
|
||
// Check issuerClaim is issued to provided identity | ||
verifyCredentialSubjectProfile()( | ||
one, | ||
issuerClaim, | ||
issuerClaimHeader.claimFlags, | ||
userGenesisID, | ||
claimSubjectProfileNonce | ||
); // 1236 constraints | ||
|
||
signal issuerClaimHash, issuerClaimHi, issuerClaimHv; | ||
(issuerClaimHash, issuerClaimHi, issuerClaimHv) <== getClaimHash()(issuerClaim); // 834 constraints | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
// calculate linkID | ||
//////////////////////////////////////////////////////////////////////// | ||
linkID <== LinkID()(issuerClaimHash, linkNonce); // 243 constraints | ||
|
||
signal linkIDisNotZero <== NOT()(IsZero()(linkID)); | ||
ForceEqualIfEnabled()(one, [linkIDisNotZero, one]); | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
// calculate nullifier | ||
//////////////////////////////////////////////////////////////////////// | ||
nullifier <== Nullify()( | ||
userGenesisID, | ||
claimSubjectProfileNonce, | ||
claimSchema, | ||
verifierID, | ||
nullifierSessionID | ||
); // 330 constraints | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pragma circom 2.1.1; | ||
|
||
include "linked/multiQuery.circom"; | ||
|
||
component main {public [enabled]} = LinkedMultiQuery(10, 32, 64); // 164791 constraints |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters