mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
Feat/sumsub (#1654)
* fix: circuits and contracts * feat: add reverse ofac logic * feat: add onlyRole modifiers to functions * style: replace onlyOwner reference in comment code to role-based access * test: unskip and update governance tests for access control * test: fix PCR0 setup in kyc test --------- Co-authored-by: Evi Nova <tranquil_flow@protonmail.com>
This commit is contained in:
52
common/src/utils/kyc/build_kyc_ofac_smt.ts
Normal file
52
common/src/utils/kyc/build_kyc_ofac_smt.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
// import * as fs from 'fs';
|
||||
// import { fileURLToPath } from 'url';
|
||||
// import { dirname, join } from 'path';
|
||||
|
||||
// import { buildKycSMT } from '../trees.js';
|
||||
|
||||
// async function build_kyc_ofac_smt() {
|
||||
// let startTime = performance.now();
|
||||
// const __filename = fileURLToPath(import.meta.url);
|
||||
// const __dirname = dirname(__filename);
|
||||
// const baseInputPath = __dirname;
|
||||
// const baseOutputPath = join(__dirname, '../../../../circuits/tests/consts/ofac/');
|
||||
|
||||
// const names = JSON.parse(fs.readFileSync(join(baseInputPath, 'names.json'), 'utf-8'));
|
||||
|
||||
// // -----KYC DATA-----
|
||||
// console.log(`Reading data from ${baseInputPath}`);
|
||||
|
||||
// // -----KYC DATA-----
|
||||
// console.log('\nBuilding KYC SMTs...');
|
||||
// const nameAndDobKycTree = buildKycSMT(names, 'name_and_dob');
|
||||
// const nameAndYobKycTree = buildKycSMT(names, 'name_and_yob');
|
||||
|
||||
// console.log('\n--- Results ---');
|
||||
// console.log(
|
||||
// `KYC - Name & DOB Tree: Processed ${nameAndDobKycTree[0]}/${names.length} entries in ${nameAndDobKycTree[1].toFixed(2)} ms`
|
||||
// );
|
||||
// console.log(
|
||||
// `KYC - Name & YOB Tree: Processed ${nameAndYobKycTree[0]}/${names.length} entries in ${nameAndYobKycTree[1].toFixed(2)} ms`
|
||||
// );
|
||||
// console.log('Total Time:', (performance.now() - startTime).toFixed(2), 'ms');
|
||||
|
||||
// console.log(`\nExporting SMTs to ${baseOutputPath}...`);
|
||||
// const nameAndDobKycOfacJSON = nameAndDobKycTree[2].export();
|
||||
// const nameAndYobKycOfacJSON = nameAndYobKycTree[2].export();
|
||||
|
||||
// fs.writeFileSync(
|
||||
// `${baseOutputPath}nameAndDobKycSMT.json`,
|
||||
// JSON.stringify(nameAndDobKycOfacJSON)
|
||||
// );
|
||||
// fs.writeFileSync(
|
||||
// `${baseOutputPath}nameAndYobKycSMT.json`,
|
||||
// JSON.stringify(nameAndYobKycOfacJSON)
|
||||
// );
|
||||
|
||||
// console.log('✅ SMT export complete.');
|
||||
// }
|
||||
|
||||
// build_kyc_ofac_smt().catch((error) => {
|
||||
// console.error('Error building KYC OFAC SMTs:', error);
|
||||
// process.exit(1);
|
||||
// });
|
||||
@@ -5,7 +5,7 @@ export const KYC_ID_TYPE_INDEX = KYC_COUNTRY_INDEX + KYC_COUNTRY_LENGTH;
|
||||
export const KYC_ID_TYPE_LENGTH = 27;
|
||||
|
||||
export const KYC_ID_NUMBER_INDEX = KYC_ID_TYPE_INDEX + KYC_ID_TYPE_LENGTH;
|
||||
export const KYC_ID_NUMBER_LENGTH = 32; // Updated: max(20, 32) = 32
|
||||
export const KYC_ID_NUMBER_LENGTH = 32;
|
||||
|
||||
export const KYC_ISSUANCE_DATE_INDEX = KYC_ID_NUMBER_INDEX + KYC_ID_NUMBER_LENGTH;
|
||||
export const KYC_ISSUANCE_DATE_LENGTH = 8;
|
||||
@@ -25,11 +25,8 @@ export const KYC_PHOTO_HASH_LENGTH = 32;
|
||||
export const KYC_PHONE_NUMBER_INDEX = KYC_PHOTO_HASH_INDEX + KYC_PHOTO_HASH_LENGTH;
|
||||
export const KYC_PHONE_NUMBER_LENGTH = 12;
|
||||
|
||||
export const KYC_DOCUMENT_INDEX = KYC_PHONE_NUMBER_INDEX + KYC_PHONE_NUMBER_LENGTH;
|
||||
export const KYC_DOCUMENT_LENGTH = 32; // Updated: max(2, 32) = 32
|
||||
|
||||
export const KYC_GENDER_INDEX = KYC_DOCUMENT_INDEX + KYC_DOCUMENT_LENGTH;
|
||||
export const KYC_GENDER_LENGTH = 6;
|
||||
export const KYC_GENDER_INDEX = KYC_PHONE_NUMBER_INDEX + KYC_PHONE_NUMBER_LENGTH;
|
||||
export const KYC_GENDER_LENGTH = 1;
|
||||
|
||||
export const KYC_ADDRESS_INDEX = KYC_GENDER_INDEX + KYC_GENDER_LENGTH;
|
||||
export const KYC_ADDRESS_LENGTH = 100;
|
||||
@@ -49,8 +46,7 @@ export const KYC_FIELD_LENGTHS = {
|
||||
DOB: KYC_DOB_LENGTH, // 8
|
||||
PHOTO_HASH: KYC_PHOTO_HASH_LENGTH, // 32
|
||||
PHONE_NUMBER: KYC_PHONE_NUMBER_LENGTH, // 12
|
||||
DOCUMENT: KYC_DOCUMENT_LENGTH, // 32 (updated)
|
||||
GENDER: KYC_GENDER_LENGTH, // 6
|
||||
GENDER: KYC_GENDER_LENGTH, // 1
|
||||
ADDRESS: KYC_ADDRESS_LENGTH, // 100
|
||||
} as const;
|
||||
|
||||
@@ -67,8 +63,7 @@ export const KYC_REVEAL_DATA_INDICES = {
|
||||
DOB: KYC_FULL_NAME_INDEX + KYC_FULL_NAME_LENGTH, // 142 (updated)
|
||||
PHOTO_HASH: KYC_DOB_INDEX + KYC_DOB_LENGTH, // 150 (updated)
|
||||
PHONE_NUMBER: KYC_PHOTO_HASH_INDEX + KYC_PHOTO_HASH_LENGTH, // 182 (updated)
|
||||
DOCUMENT: KYC_PHONE_NUMBER_INDEX + KYC_PHONE_NUMBER_LENGTH, // 194 (updated)
|
||||
GENDER: KYC_DOCUMENT_INDEX + KYC_DOCUMENT_LENGTH, // 226 (updated)
|
||||
GENDER: KYC_PHONE_NUMBER_INDEX + KYC_PHONE_NUMBER_LENGTH, // 194 (updated)
|
||||
ADDRESS: KYC_GENDER_INDEX + KYC_GENDER_LENGTH, // 232 (updated)
|
||||
} as const;
|
||||
|
||||
@@ -106,14 +101,10 @@ export const KYC_SELECTOR_BITS = {
|
||||
{ length: KYC_PHONE_NUMBER_LENGTH },
|
||||
(_, i) => i + KYC_PHOTO_HASH_INDEX + KYC_PHOTO_HASH_LENGTH
|
||||
) as number[], // 182-193 (updated)
|
||||
DOCUMENT: Array.from(
|
||||
{ length: KYC_DOCUMENT_LENGTH },
|
||||
(_, i) => i + KYC_PHONE_NUMBER_INDEX + KYC_PHONE_NUMBER_LENGTH
|
||||
) as number[], // 194-225 (updated)
|
||||
GENDER: Array.from(
|
||||
{ length: KYC_GENDER_LENGTH },
|
||||
(_, i) => i + KYC_DOCUMENT_INDEX + KYC_DOCUMENT_LENGTH
|
||||
) as number[], // 226-231 (updated)
|
||||
(_, i) => i + KYC_PHONE_NUMBER_INDEX + KYC_PHONE_NUMBER_LENGTH
|
||||
) as number[], // 194-194 (updated)
|
||||
ADDRESS: Array.from(
|
||||
{ length: KYC_ADDRESS_LENGTH },
|
||||
(_, i) => i + KYC_GENDER_INDEX + KYC_GENDER_LENGTH
|
||||
|
||||
@@ -25,8 +25,7 @@ export const OFAC_DUMMY_INPUT: KycData = {
|
||||
dob: '19481210',
|
||||
photoHash: '1234567890',
|
||||
phoneNumber: '1234567890',
|
||||
document: 'ID',
|
||||
gender: 'Male',
|
||||
gender: 'M',
|
||||
address: '1234567890',
|
||||
user_identifier: '1234567890',
|
||||
current_date: '20250101',
|
||||
@@ -44,8 +43,7 @@ export const NON_OFAC_DUMMY_INPUT: KycData = {
|
||||
dob: '19900101',
|
||||
photoHash: '1234567890',
|
||||
phoneNumber: '1234567890',
|
||||
document: 'ID',
|
||||
gender: 'Male',
|
||||
gender: 'M',
|
||||
address: '1234567890',
|
||||
user_identifier: '1234567890',
|
||||
current_date: '20250101',
|
||||
@@ -124,9 +122,16 @@ export const generateKycDiscloseInput = (
|
||||
forbiddenCountriesList?: string[],
|
||||
minimumAge?: number,
|
||||
updateTree?: boolean,
|
||||
secret: string = '1234'
|
||||
secret: string = '1234',
|
||||
reverse?: boolean
|
||||
) => {
|
||||
const data = ofac_input ? OFAC_DUMMY_INPUT : NON_OFAC_DUMMY_INPUT;
|
||||
let data = ofac_input ? OFAC_DUMMY_INPUT : NON_OFAC_DUMMY_INPUT;
|
||||
if (reverse) {
|
||||
data = {
|
||||
...data,
|
||||
fullName: data.fullName.split(' ').reverse().join(' '),
|
||||
};
|
||||
}
|
||||
const serializedData = serializeKycData(data).padEnd(KYC_MAX_LENGTH, '\0');
|
||||
const msgPadded = Array.from(serializedData, (x) => x.charCodeAt(0));
|
||||
const commitment = poseidon2([secret, packBytesAndPoseidon(msgPadded)]);
|
||||
|
||||
@@ -11,7 +11,6 @@ export type KycData = {
|
||||
dob: string;
|
||||
photoHash: string;
|
||||
phoneNumber: string;
|
||||
document: string;
|
||||
gender: string;
|
||||
address: string;
|
||||
user_identifier: string;
|
||||
@@ -32,7 +31,6 @@ export const serializeKycData = (kycData: KycData) => {
|
||||
serializedData += kycData.dob.padEnd(constants.KYC_DOB_LENGTH, '\0');
|
||||
serializedData += kycData.photoHash.padEnd(constants.KYC_PHOTO_HASH_LENGTH, '\0');
|
||||
serializedData += kycData.phoneNumber.padEnd(constants.KYC_PHONE_NUMBER_LENGTH, '\0');
|
||||
serializedData += kycData.document.padEnd(constants.KYC_DOCUMENT_LENGTH, '\0');
|
||||
serializedData += kycData.gender.padEnd(constants.KYC_GENDER_LENGTH, '\0');
|
||||
serializedData += kycData.address.padEnd(constants.KYC_ADDRESS_LENGTH, '\0');
|
||||
|
||||
|
||||
@@ -723,20 +723,29 @@ export function buildKycSMT(field: any[], treetype: string): [number, number, SM
|
||||
console.log(`Processing ${providerName}`, treetype, 'number', i, 'out of', field.length);
|
||||
}
|
||||
|
||||
let leaf = BigInt(0);
|
||||
let leafs = [BigInt(0), BigInt(0)];
|
||||
if (treetype == 'name_and_dob') {
|
||||
leaf = processNameAndDobKyc(entry, i);
|
||||
leafs[0] = processNameAndDobKyc(entry, i, false);
|
||||
leafs[1] = processNameAndDobKyc(entry, i, true);
|
||||
} else if (treetype == 'name_and_yob') {
|
||||
leaf = processNameAndYobKyc(entry, i);
|
||||
leafs[0] = processNameAndYobKyc(entry, i, false);
|
||||
leafs[1] = processNameAndYobKyc(entry, i, true);
|
||||
}
|
||||
|
||||
if (leaf == BigInt(0) || tree.createProof(leaf).membership) {
|
||||
if (leafs[0] == BigInt(0) || tree.createProof(leafs[0]).membership) {
|
||||
console.log('This entry already exists in the tree, skipping...');
|
||||
continue;
|
||||
} else if (leafs[1] == BigInt(0) || tree.createProof(leafs[1]).membership) {
|
||||
console.log('This entry already exists in the tree, skipping...');
|
||||
continue;
|
||||
}
|
||||
|
||||
tree.add(leafs[0], BigInt(1));
|
||||
count += 1;
|
||||
tree.add(leaf, BigInt(1));
|
||||
if (leafs[0] != leafs[1]) {
|
||||
tree.add(leafs[1], BigInt(1));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Total ${providerName}`, treetype, 'parsed are : ', count, ' over ', field.length);
|
||||
@@ -744,7 +753,7 @@ export function buildKycSMT(field: any[], treetype: string): [number, number, SM
|
||||
return [count, performance.now() - startTime, tree];
|
||||
}
|
||||
|
||||
const processNameAndDobKyc = (entry: any, i: number): bigint => {
|
||||
const processNameAndDobKyc = (entry: any, i: number, reverse: boolean): bigint => {
|
||||
const firstName = entry.First_Name;
|
||||
const lastName = entry.Last_Name;
|
||||
const day = entry.day;
|
||||
@@ -756,7 +765,7 @@ const processNameAndDobKyc = (entry: any, i: number): bigint => {
|
||||
return BigInt(0);
|
||||
}
|
||||
|
||||
const nameHash = processNameKyc(firstName, lastName, i);
|
||||
const nameHash = processNameKyc(firstName, lastName, i, reverse);
|
||||
const dobHash = processDobKyc(day, month, year, i);
|
||||
|
||||
return generateSmallKey(poseidon2([dobHash, nameHash]));
|
||||
@@ -773,7 +782,7 @@ export const getNameDobLeafKyc = (name: string, dob: string) => {
|
||||
return generateSmallKey(poseidon2([dobHash, nameHash]));
|
||||
};
|
||||
|
||||
const processNameKyc = (firstName: string, lastName: string, i: number): bigint => {
|
||||
const processNameKyc = (firstName: string, lastName: string, i: number, reverse: boolean): bigint => {
|
||||
const namePaddingLength = 64;
|
||||
|
||||
firstName = firstName.replace(/'/g, '');
|
||||
@@ -783,8 +792,8 @@ const processNameKyc = (firstName: string, lastName: string, i: number): bigint
|
||||
lastName = lastName.replace(/[- ]/g, '<');
|
||||
lastName = lastName.replace(/\./g, '');
|
||||
|
||||
//TODO: check if smile id does first name and last name || last name and first name
|
||||
const nameArr = (lastName + ' ' + firstName)
|
||||
let nameStr = reverse ? (lastName + ' ' + firstName) : (firstName + ' ' + lastName);
|
||||
const nameArr = nameStr
|
||||
.padEnd(namePaddingLength, '\0')
|
||||
.split('')
|
||||
.map((char) => char.charCodeAt(0));
|
||||
@@ -825,7 +834,7 @@ export const getNameYobLeafKyc = (name: string, yob: string) => {
|
||||
return generateSmallKey(poseidon2([yearHash, nameHash]));
|
||||
};
|
||||
|
||||
const processNameAndYobKyc = (entry: any, i: number): bigint => {
|
||||
const processNameAndYobKyc = (entry: any, i: number, reverse: boolean): bigint => {
|
||||
const firstName = entry.First_Name;
|
||||
const lastName = entry.Last_Name;
|
||||
const year = entry.year;
|
||||
@@ -834,7 +843,7 @@ const processNameAndYobKyc = (entry: any, i: number): bigint => {
|
||||
return BigInt(0);
|
||||
}
|
||||
|
||||
const nameHash = processNameKyc(firstName, lastName, i);
|
||||
const nameHash = processNameKyc(firstName, lastName, i, reverse);
|
||||
const yearHash = processYearKyc(year, i);
|
||||
return generateSmallKey(poseidon2([yearHash, nameHash]));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user