Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prove name is not in Ofac List #139

Merged
merged 46 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ef62088
Parse ofac
ashpect Jun 27, 2024
334df4c
Generate ofac circuit inputs
ashpect Jun 27, 2024
3ea0532
Merge branch 'dev' of github.com:zk-passport/proof-of-passport into dev
ashpect Jun 27, 2024
a95f2f4
merkle_tree for ofac data
ashpect Jun 27, 2024
aba3ebe
registry lockfiles
ashpect Jun 27, 2024
a232f04
passport tree
ashpect Jun 27, 2024
9652562
write circuits and tests
ashpect Jun 27, 2024
560a1d7
fix circuit
ashpect Jun 28, 2024
9181368
update jsons
ashpect Jun 29, 2024
7825719
fix circuit, testsPassed
ashpect Jun 29, 2024
d4559ab
use isEqual
ashpect Jul 1, 2024
55a0433
rewrote everything with smt
ashpect Jul 5, 2024
23fb450
neat tricks in circuits
ashpect Jul 5, 2024
dc57ed0
optimise script for names and dob
ashpect Jul 10, 2024
23440e2
add support for 3 levels
ashpect Jul 10, 2024
d8e9d41
update dob smt tree
ashpect Jul 11, 2024
3965154
better path
ashpect Jul 11, 2024
9c66e33
change name leaf logic
ashpect Jul 11, 2024
337e6a3
Merge branch 'dev' of github.com:ashpect/proof-of-passport into dev
ashpect Jul 11, 2024
140fd4b
Add validation and refactoring
ashpect Jul 12, 2024
d5f571c
code enhacements and etc.
ashpect Jul 17, 2024
23a3dd0
ofac refactor
ashpect Jul 21, 2024
8ac7f8a
export and import for smt's
ashpect Jul 21, 2024
dd3c494
COMPLETE REFACTORING OF CIRCUITS
ashpect Jul 22, 2024
fa11c31
update outputs, mockdata in ofac lists as well
ashpect Jul 22, 2024
14c743f
show inputs
ashpect Jul 22, 2024
c6543b6
input generation, almost died debugging names
ashpect Jul 22, 2024
ceaa9a8
cleanup
ashpect Jul 22, 2024
d6ec67f
merge dev fork with dev origin
ashpect Jul 22, 2024
98195ea
small update
ashpect Jul 22, 2024
2b236b9
cleanup
ashpect Jul 22, 2024
3056b01
update paths for mock data
ashpect Jul 22, 2024
d76f38e
unnecessary imports
ashpect Jul 22, 2024
0f63c97
fix linting to pass tests
ashpect Jul 22, 2024
2d40b64
add more edge cases tests
ashpect Jul 25, 2024
2babb2d
finally fixed the bug
ashpect Jul 25, 2024
48c45ef
add tests for edge cases
ashpect Jul 28, 2024
62de12d
Merge branch 'dev' of github.com:zk-passport/proof-of-passport into dev
ashpect Jul 28, 2024
affece9
linting
ashpect Jul 28, 2024
63db509
Merge branch 'dev' of github.com:zk-passport/proof-of-passport into dev
ashpect Aug 1, 2024
0780492
fix lint
ashpect Aug 1, 2024
096bad1
Update circuits to calculate path internally
ashpect Aug 5, 2024
80897a8
update ofac circuits tests
ashpect Aug 5, 2024
04a52e6
fix lint
ashpect Aug 5, 2024
760b34d
remove common components
ashpect Aug 7, 2024
384c535
Merge branch 'dev' of github.com:zk-passport/proof-of-passport into dev
ashpect Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading