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 fix-android
  • Loading branch information
remicolin committed Oct 21, 2024
2 parents 7bfd0b6 + fda3917 commit db1d702
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 219 deletions.
5 changes: 2 additions & 3 deletions app/src/screens/ProveScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ const ProveScreen: React.FC<ProveScreenProps> = ({ setSheetRegisterIsOpen }) =>
});

newSocket.on('proof_verification_result', (result) => {
console.log('Proof verification result:', result);
setProofVerificationResult(JSON.parse(result));
console.log("result", result);
if (JSON.parse(result).valid) {
Expand Down Expand Up @@ -143,7 +142,7 @@ const ProveScreen: React.FC<ProveScreenProps> = ({ setSheetRegisterIsOpen }) =>

socket.emit('proof_generation_start', { sessionId: selectedApp.sessionId });


console.log("selectedApp.mode", selectedApp.mode);
switch (selectedApp.mode) {
case 'vc_and_disclose':
const inputs_disclose = await generateCircuitInputsInApp(passportData, selectedApp);
Expand Down Expand Up @@ -196,7 +195,7 @@ const ProveScreen: React.FC<ProveScreenProps> = ({ setSheetRegisterIsOpen }) =>
socket.emit('proof_generated', { sessionId: selectedApp.sessionId, proof: attestation });
break;
case 'prove_offchain':
const inputs_prove = generateCircuitInputsInApp(passportData, selectedApp);
const inputs_prove = await generateCircuitInputsInApp(passportData, selectedApp);
const proof_prove = await generateProof(
circuitName,
inputs_prove,
Expand Down
26 changes: 17 additions & 9 deletions app/src/screens/WrongProofScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,24 @@ const WrongProofScreen: React.FC = () => {
<Text ml="$1" fontSize={34} color={textBlack}>
<Text style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>Oops</Text>, the proof is not valid.
</Text>
<Text ml="$2" mt="$3" fontSize="$8" color={textBlack}>
Some of the <Text >conditions</Text> have not been satisfied:
</Text>
<YStack ml="$4" mt="$5">
{failedConditions.map((condition, index) => (
<Text key={index} fontSize="$7" color={textBlack} >
· <Text key={index} style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>{condition}</Text>
{(proofVerificationResult as any).error ? (
<Text ml="$2" mt="$3" fontSize="$8" color={textBlack}>
Error: {(proofVerificationResult as any).error}
</Text>
) : (
<>
<Text ml="$2" mt="$3" fontSize="$8" color={textBlack}>
Some of the <Text >conditions</Text> have not been satisfied:
</Text>
))}
</YStack>
<YStack ml="$4" mt="$5">
{failedConditions.map((condition, index) => (
<Text key={index} fontSize="$7" color={textBlack} >
· <Text key={index} style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>{condition}</Text>
</Text>
))}
</YStack>
</>
)}
<Text ml="$2" mt="$8" fontSize="$7" color={textBlack} style={{ opacity: 0.7 }}>
<Text style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>Check again</Text> your eligibility, if you are sure to be eligible to this verification please contact OpenPassport support.
</Text>
Expand Down
12 changes: 6 additions & 6 deletions app/src/utils/generateInputsInApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export const generateCircuitInputsInApp = async (
const selector_dg1 = revealBitmapFromAttributes(disclosureOptions);
const selector_older_than = disclosureOptions.minimumAge.enabled ? 1 : 0;
const selector_ofac = disclosureOptions.ofac ? 1 : 0;

return generateCircuitInputsProve(
const forbidden_countries_list = disclosureOptions.excludedCountries.value.map(country => getCountryCode(country));
const inputs = generateCircuitInputsProve(
selector_mode,
secret,
dscSecret as string,
Expand All @@ -37,11 +37,11 @@ export const generateCircuitInputsInApp = async (
disclosureOptions.minimumAge.value ?? DEFAULT_MAJORITY,
smt,
selector_ofac,
disclosureOptions.excludedCountries.value.map(country => getCountryCode(country)),
forbidden_countries_list,
app.userId,
app.userIdType
);
break;
return inputs;
case "register":
const selector_dg1_zero = new Array(88).fill(0);
const selector_older_than_zero = 0;
Expand Down Expand Up @@ -70,8 +70,8 @@ export const generateCircuitInputsInApp = async (
const selector_dg1_disclose = revealBitmapFromAttributes(disclosureOptionsDisclose);
const selector_older_than_disclose = disclosureOptionsDisclose.minimumAge.enabled ? 1 : 0;
const selector_ofac_disclose = disclosureOptionsDisclose.ofac ? 1 : 0;
const forbidden_countries_list = disclosureOptionsDisclose.excludedCountries.value.map(country => getCountryCode(country))
return generateCircuitInputsDisclose(secret, PASSPORT_ATTESTATION_ID, passportData, app.scope, selector_dg1_disclose, selector_older_than_disclose, tree, disclosureOptionsDisclose.minimumAge.value ?? DEFAULT_MAJORITY, smt, selector_ofac_disclose, forbidden_countries_list, app.userId)
const forbidden_countries_list_disclose = disclosureOptionsDisclose.excludedCountries.value.map(country => getCountryCode(country))
return generateCircuitInputsDisclose(secret, PASSPORT_ATTESTATION_ID, passportData, app.scope, selector_dg1_disclose, selector_older_than_disclose, tree, disclosureOptionsDisclose.minimumAge.value ?? DEFAULT_MAJORITY, smt, selector_ofac_disclose, forbidden_countries_list_disclose, app.userId)
}

}
143 changes: 54 additions & 89 deletions common/src/utils/smtTree.ts
Original file line number Diff line number Diff line change
@@ -1,90 +1,56 @@
import { poseidon9, poseidon3, poseidon2, poseidon6, poseidon13 } from "poseidon-lite"
import { hash, stringToAsciiBigIntArray } from "./utils";
import { ChildNodes,SMT } from "@ashpect/smt";
import fs from 'fs';
import path from 'path';
import { stringToAsciiBigIntArray } from "./utils";
import { ChildNodes, SMT } from "@ashpect/smt"

// SMT trees for 3 levels :
// 1. Passport tree : level 3 (Absolute Match)
// 2. Names and dob combo tree : level 2 (High Probability Match)
// 3. Names tree : level 1 (Partial Match)

export function buildSMT(field :any[], treetype:string): [number, number, SMT]{
let count = 0
let startTime = performance.now();

const hash2 = (childNodes: ChildNodes) => (childNodes.length === 2 ? poseidon2(childNodes) : poseidon3(childNodes))
const tree = new SMT(hash2, true)

for (let i = 0; i < field.length; i++) {
const entry = field[i]

if (i !== 0) {
console.log('Processing', treetype,'number', i, "out of", field.length);
}

let leaf = BigInt(0)
if (treetype == "passport") {
leaf = processPassport(entry.Pass_No, i)
} else if (treetype == "name_dob") {
leaf = processNameDob(entry, i)
} else if (treetype == "name"){
leaf = processName(entry.First_Name, entry.Last_Name, i)
} else if (treetype == "country"){
const keys = Object.keys(entry);
leaf = processCountry(keys[0],entry[keys[0]],i)
}

if( leaf==BigInt(0) || tree.createProof(leaf).membership){
console.log("This entry already exists in the tree, skipping...")
continue
}

count += 1
tree.add(leaf,BigInt(1))
}

console.log("Total",treetype ,"paresed are : ",count ," over ",field.length )
console.log(treetype, 'tree built in', performance.now() - startTime, 'ms')
return [count, performance.now() - startTime, tree]
}
export function buildSMT(field: any[], treetype: string): [number, number, SMT] {
let count = 0
let startTime = performance.now();

export function exportSMTToJsonFile(count: number, time: number, smt: SMT, outputPath?: string) {
const serializedSMT = smt.export();
const data = {
count: count,
time: time,
smt: serializedSMT
};
const jsonString = JSON.stringify(data, null, 2);
const defaultPath = path.join(process.cwd(), 'smt.json');
const finalPath = outputPath ? path.resolve(process.cwd(), outputPath) : defaultPath;
const hash2 = (childNodes: ChildNodes) => (childNodes.length === 2 ? poseidon2(childNodes) : poseidon3(childNodes))
const tree = new SMT(hash2, true)

fs.writeFileSync(finalPath, jsonString, 'utf8');
}
for (let i = 0; i < field.length; i++) {
const entry = field[i]

export function importSMTFromJsonFile(filePath?: string): SMT | null {
try {
const jsonString = fs.readFileSync(path.resolve(process.cwd(), filePath), 'utf8');

const data = JSON.parse(jsonString);

const hash2 = (childNodes: ChildNodes) => (childNodes.length === 2 ? poseidon2(childNodes) : poseidon3(childNodes));
const smt = new SMT(hash2, true);
smt.import(data.smt);

console.log('Successfully imported SMT from JSON file');
return smt;
} catch (error) {
console.error('Failed to import SMT from JSON file:', error);
return null;
if (i !== 0) {
console.log('Processing', treetype, 'number', i, "out of", field.length);
}

let leaf = BigInt(0)
if (treetype == "passport") {
leaf = processPassport(entry.Pass_No, i)
} else if (treetype == "name_dob") {
leaf = processNameDob(entry, i)
} else if (treetype == "name") {
leaf = processName(entry.First_Name, entry.Last_Name, i)
} else if (treetype == "country") {
const keys = Object.keys(entry);
leaf = processCountry(keys[0], entry[keys[0]], i)
}

if (leaf == BigInt(0) || tree.createProof(leaf).membership) {
console.log("This entry already exists in the tree, skipping...")
continue
}

count += 1
tree.add(leaf, BigInt(1))
}

console.log("Total", treetype, "paresed are : ", count, " over ", field.length)
console.log(treetype, 'tree built in', performance.now() - startTime, 'ms')
return [count, performance.now() - startTime, tree]
}

function processPassport(passno : string, index: number): bigint {
function processPassport(passno: string, index: number): bigint {
if (passno.length > 9) {
console.log('passport length is greater than 9:', index, passno)
} else if (passno.length < 9){
} else if (passno.length < 9) {
while (passno.length != 9) {
passno += '<'
}
Expand All @@ -104,17 +70,17 @@ function processNameDob(entry: any, i: number): bigint {
const day = entry.day
const month = entry.month
const year = entry.year
if(day == null || month == null || year == null){
if (day == null || month == null || year == null) {
console.log('dob is null', i, entry)
return BigInt(0)
}
const nameHash = processName(firstName,lastName,i)
const dobHash = processDob(day, month, year,i)
const nameHash = processName(firstName, lastName, i)
const dobHash = processDob(day, month, year, i)
const leaf = poseidon2([dobHash, nameHash])
return leaf
}

function processName(firstName:string, lastName:string, i: number ): bigint {
function processName(firstName: string, lastName: string, i: number): bigint {
// LASTNAME<<FIRSTNAME<MIDDLENAME<<<... (6-44)
firstName = firstName.replace(/'/g, '');
firstName = firstName.replace(/\./g, '');
Expand All @@ -139,7 +105,7 @@ function processName(firstName:string, lastName:string, i: number ): bigint {
return getNameLeaf(nameArr, i)
}

function processDob(day: string, month: string, year: string, i : number): bigint {
function processDob(day: string, month: string, year: string, i: number): bigint {
// YYMMDD
const monthMap: { [key: string]: string } = {
jan: "01",
Expand All @@ -160,22 +126,22 @@ function processDob(day: string, month: string, year: string, i : number): bigin
year = year.slice(-2);
const dob = year + month + day;
let arr = stringToAsciiBigIntArray(dob);
return getDobLeaf(arr,i)
return getDobLeaf(arr, i)
}

function processCountry(country1 : string, country2 : string, i : number){
function processCountry(country1: string, country2: string, i: number) {
let arr = stringToAsciiBigIntArray(country1)
let arr2 = stringToAsciiBigIntArray(country2)

const leaf = getCountryLeaf(arr,arr2,i)
const leaf = getCountryLeaf(arr, arr2, i)
if (!leaf) {
console.log('Error creating leaf value', i, country1, country2)
return BigInt(0)
}
return leaf
}

export function getCountryLeaf(country_by: (bigint|number)[], country_to: (bigint|number)[], i?: number): bigint{
export function getCountryLeaf(country_by: (bigint | number)[], country_to: (bigint | number)[], i?: number): bigint {
if (country_by.length !== 3 || country_to.length !== 3) {
console.log('parsed passport length is not 3:', i, country_to, country_by)
return
Expand All @@ -184,11 +150,11 @@ export function getCountryLeaf(country_by: (bigint|number)[], country_to: (bigin
const country = country_by.concat(country_to)
return poseidon6(country)
} catch (err) {
console.log('err : sanc_country hash', err, i, country_by,country_to)
console.log('err : sanc_country hash', err, i, country_by, country_to)
}
}

export function getPassportNumberLeaf(passport: (bigint|number)[], i?: number): bigint {
export function getPassportNumberLeaf(passport: (bigint | number)[], i?: number): bigint {
if (passport.length !== 9) {
console.log('parsed passport length is not 9:', i, passport)
return
Expand All @@ -200,17 +166,17 @@ export function getPassportNumberLeaf(passport: (bigint|number)[], i?: number):
}
}

export function getNameDobLeaf(nameMrz : (bigint|number)[], dobMrz : (bigint|number)[], i? : number): bigint {
export function getNameDobLeaf(nameMrz: (bigint | number)[], dobMrz: (bigint | number)[], i?: number): bigint {
return poseidon2([getDobLeaf(dobMrz), getNameLeaf(nameMrz)])
}

export function getNameLeaf(nameMrz : (bigint|number)[] , i? : number ) : bigint {
export function getNameLeaf(nameMrz: (bigint | number)[], i?: number): bigint {
let middleChunks: bigint[] = [];
let chunks: (number|bigint)[][] = [];
let chunks: (number | bigint)[][] = [];

chunks.push(nameMrz.slice(0, 13), nameMrz.slice(13, 26), nameMrz.slice(26, 39)); // 39/3 for posedion to digest

for(const chunk of chunks){
for (const chunk of chunks) {
middleChunks.push(poseidon13(chunk))
}

Expand All @@ -221,7 +187,7 @@ export function getNameLeaf(nameMrz : (bigint|number)[] , i? : number ) : bigint
}
}

export function getDobLeaf(dobMrz : (bigint|number)[], i? : number): bigint {
export function getDobLeaf(dobMrz: (bigint | number)[], i?: number): bigint {
if (dobMrz.length !== 6) {
console.log('parsed dob length is not 9:', i, dobMrz)
return
Expand All @@ -232,4 +198,3 @@ export function getDobLeaf(dobMrz : (bigint|number)[], i? : number): bigint {
console.log('err : Dob', err, i, dobMrz)
}
}

Loading

0 comments on commit db1d702

Please sign in to comment.