Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/zk-passport/openpassport int…
Browse files Browse the repository at this point in the history
…o dev
  • Loading branch information
remicolin committed Aug 16, 2024
2 parents 7b22c77 + 8598d67 commit 40a7ddf
Show file tree
Hide file tree
Showing 32 changed files with 101,535 additions and 71 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
contracts/contracts/RegisterASCII.txt
sdk/.env
.DS_Store
dist
**/node_modules
**/node_modules/
Expand Down
24 changes: 3 additions & 21 deletions circuits/circuits/disclose/disclose.circom
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ include "@zk-email/circuits/utils/bytes.circom";
include "../utils/isOlderThan.circom";
include "../utils/isValid.circom";
include "binary-merkle-root.circom";
include "../utils/validatePassport.circom";

template Disclose(nLevels) {
signal input secret;
Expand All @@ -27,27 +28,8 @@ template Disclose(nLevels) {
signal output nullifier; // Poseidon(secret, scope)
signal output revealedData_packed[3];

// Compute the commitment
component poseidon_hasher = Poseidon(6);
poseidon_hasher.inputs[0] <== secret;
poseidon_hasher.inputs[1] <== attestation_id;
poseidon_hasher.inputs[2] <== pubkey_leaf;
signal mrz_packed[3] <== PackBytes(93)(mrz);
for (var i = 0; i < 3; i++) {
poseidon_hasher.inputs[i + 3] <== mrz_packed[i];
}

// Verify commitment inclusion
signal computedRoot <== BinaryMerkleRoot(nLevels)(poseidon_hasher.out, merkletree_size, path, siblings);
merkle_root === computedRoot;

// Verify validity of the passport
component isValid = IsValid();
isValid.currDate <== current_date;
for (var i = 0; i < 6; i++) {
isValid.validityDateASCII[i] <== mrz[70 + i];
}
1 === isValid.out;
// Validate Passport
ValidatePassport(nLevels)(secret, attestation_id, pubkey_leaf, mrz, merkle_root, merkletree_size, path, siblings, current_date);

// Disclose optional data
component isOlderThan = IsOlderThan();
Expand Down
59 changes: 59 additions & 0 deletions circuits/circuits/ofac/ofac_nameDob_verifier.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
pragma circom 2.1.5;

include "circomlib/circuits/poseidon.circom";
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/bitify.circom";
include "binary-merkle-root.circom";
include "../utils/getCommonLength.circom";
include "../utils/validatePassport.circom";
include "../utils/smt.circom";

template ProveNameDobNotInOfac(nLevels) {
signal input secret;
signal input attestation_id;
signal input pubkey_leaf;
signal input mrz[93];
signal input merkle_root;
signal input merkletree_size;
signal input path[nLevels];
signal input siblings[nLevels];
signal input current_date[6];

signal input closest_leaf;
signal input smt_root;
signal input smt_siblings[256];
signal output proofLevel;

// Validate passport
ValidatePassport(nLevels)(secret, attestation_id, pubkey_leaf, mrz, merkle_root, merkletree_size, path, siblings, current_date);

// Name Hash
component poseidon_hasher[3];
for (var j = 0; j < 3; j++) {
poseidon_hasher[j] = Poseidon(13);
for (var i = 0; i < 13; i++) {
poseidon_hasher[j].inputs[i] <== mrz[10 + 13 * j + i];
}
}
signal name_hash <== Poseidon(3)([poseidon_hasher[0].out, poseidon_hasher[1].out, poseidon_hasher[2].out]);

// Dob hash
component pos_dob = Poseidon(6);
for(var i = 0; i < 6; i++) {
pos_dob.inputs[i] <== mrz[62 + i];
}

// NameDob hash
signal name_dob_hash <== Poseidon(2)([pos_dob.out, name_hash]);
signal smtleaf_hash <== Poseidon(3)([name_dob_hash, 1,1]);

// SMT Verification
signal closestleaf <== SMTVerify(256)(name_dob_hash, 1, closest_leaf, smt_root, smt_siblings);

signal proofType <== IsEqual()([closestleaf,smtleaf_hash]);
proofType === 0; // Uncomment this line to make circuit handle both membership and non-membership proof and returns the type of proof (0 for non-membership, 1 for membership)

proofLevel <== 2;
}

component main { public [ merkle_root,smt_root ] } = ProveNameDobNotInOfac(16);
52 changes: 52 additions & 0 deletions circuits/circuits/ofac/ofac_name_verifier.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
pragma circom 2.1.5;

include "circomlib/circuits/poseidon.circom";
include "circomlib/circuits/comparators.circom";
include "binary-merkle-root.circom";
include "../utils/getCommonLength.circom";
include "../utils/validatePassport.circom";
include "../utils/smt.circom";

template ProveNameNotInOfac(nLevels) {
signal input secret;
signal input attestation_id;
signal input pubkey_leaf;
signal input mrz[93];
signal input merkle_root;
signal input merkletree_size;
signal input path[nLevels];
signal input siblings[nLevels];
signal input current_date[6];

signal input closest_leaf;
signal input smt_root;
signal input smt_siblings[256];
signal output proofType;
signal output proofLevel;

// Validate passport
ValidatePassport(nLevels)(secret, attestation_id, pubkey_leaf, mrz, merkle_root, merkletree_size, path, siblings, current_date);

// Name Hash
component poseidon_hasher[3];
for (var j = 0; j < 3; j++) {
poseidon_hasher[j] = Poseidon(13);
for (var i = 0; i < 13; i++) {
poseidon_hasher[j].inputs[i] <== mrz[10 + 13 * j + i];
}
}

signal name_hash <== Poseidon(3)([poseidon_hasher[0].out, poseidon_hasher[1].out, poseidon_hasher[2].out]);
signal smtleaf_hash <== Poseidon(3)([name_hash, 1,1]);

// SMT Verification
signal closestleaf <== SMTVerify(256)(name_hash, 1, closest_leaf, smt_root, smt_siblings);

proofType <== IsEqual()([closestleaf,smtleaf_hash]);
proofType === 0; // Uncomment this line to make circuit handle both membership and non-membership proof and returns the type of proof (0 for non-membership, 1 for membership)

proofLevel <== 1;

}

component main { public [ merkle_root,smt_root ] } = ProveNameNotInOfac(16);
48 changes: 48 additions & 0 deletions circuits/circuits/ofac/ofac_passportNo_verifier.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
pragma circom 2.1.5;

include "circomlib/circuits/poseidon.circom";
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/bitify.circom";
include "@zk-email/circuits/utils/array.circom";
include "binary-merkle-root.circom";
include "../utils/getCommonLength.circom";
include "../utils/validatePassport.circom";
include "../utils/smt.circom";

template ProvePassportNotInOfac(nLevels) {
signal input secret;
signal input attestation_id;
signal input pubkey_leaf;
signal input mrz[93];
signal input merkle_root;
signal input merkletree_size;
signal input path[nLevels];
signal input siblings[nLevels];
signal input current_date[6];

signal input closest_leaf;
signal input smt_root;
signal input smt_siblings[256];
signal output proofLevel;

// Validate passport
ValidatePassport(nLevels)(secret, attestation_id, pubkey_leaf, mrz, merkle_root, merkletree_size, path, siblings, current_date);

// PassportNo Hash
component poseidon_hasher = Poseidon(9);
for (var i = 0; i < 9; i++) {
poseidon_hasher.inputs[i] <== mrz[49 + i];
}
signal smtleaf_hash <== Poseidon(3)([poseidon_hasher.out, 1,1]);

// SMT Verification
signal closestleaf <== SMTVerify(256)(poseidon_hasher.out, 1, closest_leaf, smt_root, smt_siblings);

// If leaf given = leaf calulated ; then membership proof
signal proofType <== IsEqual()([closestleaf,smtleaf_hash]); // 1 for membership proof, 0 for non-membership proof
proofType === 0; // Uncomment this line to make circuit handle both membership and non-membership proof (0 for non-membership, 1 for membership)

proofLevel <== 3;
}

component main { public [ merkle_root,smt_root ] } = ProvePassportNotInOfac(16);
67 changes: 67 additions & 0 deletions circuits/circuits/utils/getCommonLength.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
pragma circom 2.1.5;

include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/bitify.circom";

// Computes the first n common bits of the hashes
template CommonBitsLengthFromEnd() {

signal input bits1[256];
signal input bits2[256];
signal output out;

component iseq[256];
signal pop[256];

pop[255] <== IsEqual()([bits1[255], bits2[255]]);

for (var i = 254; i >= 0; i--) {
var temp = bits2[i] - bits1[i];
iseq[i] = IsEqual();
bits1[i] ==> iseq[i].in[0];
bits2[i] ==> iseq[i].in[1];
pop[i] <== iseq[i].out*pop[i+1];
}

var added = 0;
for(var i = 0; i<256;i++){
added += pop[i];
}

added ==> out;

}

// Computes length of an array when array is padded with 0;s from end and the last element after which padding starts is not 0, 0's might come in between.
template SiblingsLength() {
signal input siblings[256];
signal output length;

// Siblings can be like (1,2,3,0,0,4,5,0,0...all 0 till 256[the padded 0 ones])
// We need to get the length , i.e 7 in this case
var foo[256];
for(var i = 0; i<256; i++){
foo[i] = 0;
}
foo[255] = siblings[255];
for(var i = 256-2; i>=0; i--){
foo[i] = siblings[i] + foo[i+1];
}

// convert to (15,14,12,9,9,9,5,0,0,0..), this takes out the middle 0's
var total = 0;
signal pop[256];
component iszero[256];

for(var i = 0; i<256; i++){
iszero[i] = IsZero();
foo[i] ==> iszero[i].in;
pop[i] <== iszero[i].out;
}

for(var i = 0; i<256; i++){
total += pop[i];
}

256-total ==> length;
}
46 changes: 46 additions & 0 deletions circuits/circuits/utils/smt.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
pragma circom 2.1.5;

include "circomlib/circuits/poseidon.circom";
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/bitify.circom";
include "@zk-email/circuits/utils/array.circom";
include "binary-merkle-root.circom";
include "getCommonLength.circom";

template SMTVerify(nLength) {
signal input key;
signal input value;
signal input closest_key; // key itself if checking for inclusion
signal input root;
signal input siblings[nLength];
signal output closestleaf;

// Calculate depth of the smt tree
signal depth <== SiblingsLength()(siblings);

// Calulate the path needed
signal path[nLength];
signal path_in_bits_reversed[nLength] <== Num2Bits(256)(key);
var path_in_bits[nLength];

for (var i = 0; i < nLength; i++) {
path_in_bits[i] = path_in_bits_reversed[nLength-1-i];
}

// Shift the path to the left by depth to make it compatible for BinaryMerkleRoot function
component ct1 = VarShiftLeft(nLength,nLength);
ct1.in <== path_in_bits;
ct1.shift <== (nLength-depth);
path <== ct1.out;

// Closest_key to Closest_leaf
signal closest_hash <== Poseidon(3)([closest_key, value,1]);
signal isClosestZero <== IsEqual()([closest_key,0]);
signal closest <== IsEqual()([isClosestZero,0]); // Because zk-kit/smt stores a 0 leaf as itself and not as Hash(0,value,1)
closestleaf <== closest_hash * closest;

// Verification
signal computedRoot <== BinaryMerkleRoot(nLength)(closestleaf, depth, path, siblings);
computedRoot === root;

}
43 changes: 43 additions & 0 deletions circuits/circuits/utils/validatePassport.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
pragma circom 2.1.5;

include "circomlib/circuits/poseidon.circom";
include "@zk-email/circuits/utils/bytes.circom";
include "isOlderThan.circom";
include "isValid.circom";
include "binary-merkle-root.circom";

template ValidatePassport(nLevels) {
signal input secret;
signal input attestation_id;
signal input pubkey_leaf;
signal input mrz[93];

signal input merkle_root;
signal input merkletree_size;
signal input path[nLevels];
signal input siblings[nLevels];
signal input current_date[6];

// Compute the commitment
component poseidon_hasher = Poseidon(6);
poseidon_hasher.inputs[0] <== secret;
poseidon_hasher.inputs[1] <== attestation_id;
poseidon_hasher.inputs[2] <== pubkey_leaf;
signal mrz_packed[3] <== PackBytes(93)(mrz);
for (var i = 0; i < 3; i++) {
poseidon_hasher.inputs[i + 3] <== mrz_packed[i];
}

// Verify commitment inclusion
signal computedRoot <== BinaryMerkleRoot(nLevels)(poseidon_hasher.out, merkletree_size, path, siblings);
merkle_root === computedRoot;

// Verify validity of the passport
component isValid = IsValid();
isValid.currDate <== current_date;
for (var i = 0; i < 6; i++) {
isValid.validityDateASCII[i] <== mrz[70 + i];
}

1 === isValid.out;
}
1 change: 1 addition & 0 deletions circuits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"lint": "prettier --check ."
},
"dependencies": {
"@ashpect/smt": "https://github.com/ashpect/smt#main",
"@noble/curves": "^1.4.2",
"@types/chai-as-promised": "^7.1.6",
"@types/node": "^20.11.19",
Expand Down
Loading

0 comments on commit 40a7ddf

Please sign in to comment.