mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
Merge branch 'dev' into feat/npm-package
This commit is contained in:
@@ -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) {
|
||||
@@ -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);
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
"asn1.js": "^5.4.1",
|
||||
"asn1js": "^3.0.5",
|
||||
"axios": "^1.7.2",
|
||||
"buffer": "^6.0.3",
|
||||
"chai": "^4.3.8",
|
||||
"elliptic": "^6.5.5",
|
||||
"fs": "^0.0.1-security",
|
||||
@@ -35,4 +36,4 @@
|
||||
"@types/node-forge": "^1.3.10",
|
||||
"prettier": "^3.3.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
export function buildSMT(field: any[], treetype: string): [number, number, SMT] {
|
||||
let count = 0
|
||||
let startTime = performance.now();
|
||||
|
||||
for (let i = 0; i < field.length; i++) {
|
||||
const entry = field[i]
|
||||
const hash2 = (childNodes: ChildNodes) => (childNodes.length === 2 ? poseidon2(childNodes) : poseidon3(childNodes))
|
||||
const tree = new SMT(hash2, true)
|
||||
|
||||
if (i !== 0) {
|
||||
console.log('Processing', treetype,'number', i, "out of", field.length);
|
||||
}
|
||||
for (let i = 0; i < field.length; i++) {
|
||||
const entry = field[i]
|
||||
|
||||
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))
|
||||
}
|
||||
if (i !== 0) {
|
||||
console.log('Processing', treetype, 'number', i, "out of", field.length);
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
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;
|
||||
if (leaf == BigInt(0) || tree.createProof(leaf).membership) {
|
||||
console.log("This entry already exists in the tree, skipping...")
|
||||
continue
|
||||
}
|
||||
|
||||
fs.writeFileSync(finalPath, jsonString, 'utf8');
|
||||
}
|
||||
|
||||
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;
|
||||
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 += '<'
|
||||
}
|
||||
@@ -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, '');
|
||||
@@ -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",
|
||||
@@ -160,14 +126,14 @@ 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)
|
||||
@@ -175,7 +141,7 @@ function processCountry(country1 : string, country2 : string, i : number){
|
||||
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
|
||||
@@ -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
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -232,4 +198,3 @@ export function getDobLeaf(dobMrz : (bigint|number)[], i? : number): bigint {
|
||||
console.log('err : Dob', err, i, dobMrz)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ export class OpenPassportVerifier extends AttestationVerifier {
|
||||
return this;
|
||||
}
|
||||
|
||||
setDevMode(devMode: boolean): this {
|
||||
this.devMode = devMode;
|
||||
allowMockPassports(): this {
|
||||
this.devMode = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,54 +18,54 @@ const handleWebSocketMessage =
|
||||
openPassportVerifier: OpenPassportVerifier,
|
||||
onSuccess: (proof: OpenPassportAttestation) => void
|
||||
) =>
|
||||
async (data) => {
|
||||
console.log('received mobile status:', data.status);
|
||||
switch (data.status) {
|
||||
case 'mobile_connected':
|
||||
setProofStep(QRcodeSteps.MOBILE_CONNECTED);
|
||||
break;
|
||||
case 'mobile_disconnected':
|
||||
setProofStep(QRcodeSteps.WAITING_FOR_MOBILE);
|
||||
break;
|
||||
case 'proof_generation_started':
|
||||
setProofStep(QRcodeSteps.PROOF_GENERATION_STARTED);
|
||||
break;
|
||||
case 'proof_generated':
|
||||
setProofStep(QRcodeSteps.PROOF_GENERATED);
|
||||
break;
|
||||
case 'proof_generation_failed':
|
||||
setProofVerified(false);
|
||||
setProofStep(QRcodeSteps.PROOF_VERIFIED);
|
||||
console.log('Proof generation failed');
|
||||
break;
|
||||
}
|
||||
async (data) => {
|
||||
console.log('received mobile status:', data.status);
|
||||
switch (data.status) {
|
||||
case 'mobile_connected':
|
||||
setProofStep(QRcodeSteps.MOBILE_CONNECTED);
|
||||
break;
|
||||
case 'mobile_disconnected':
|
||||
setProofStep(QRcodeSteps.WAITING_FOR_MOBILE);
|
||||
break;
|
||||
case 'proof_generation_started':
|
||||
setProofStep(QRcodeSteps.PROOF_GENERATION_STARTED);
|
||||
break;
|
||||
case 'proof_generated':
|
||||
setProofStep(QRcodeSteps.PROOF_GENERATED);
|
||||
break;
|
||||
case 'proof_generation_failed':
|
||||
setProofVerified(false);
|
||||
setProofStep(QRcodeSteps.PROOF_VERIFIED);
|
||||
console.log('Proof generation failed');
|
||||
break;
|
||||
}
|
||||
|
||||
if (data.proof) {
|
||||
console.log(data.proof);
|
||||
try {
|
||||
const local_proofVerified = await openPassportVerifier.verify(data.proof);
|
||||
setProofVerified(local_proofVerified.valid);
|
||||
setProofStep(QRcodeSteps.PROOF_VERIFIED);
|
||||
setTimeout(() => {
|
||||
if (data.proof) {
|
||||
console.log(data.proof);
|
||||
try {
|
||||
const local_proofVerified = await openPassportVerifier.verify(data.proof);
|
||||
setProofVerified(local_proofVerified.valid);
|
||||
setProofStep(QRcodeSteps.PROOF_VERIFIED);
|
||||
setTimeout(() => {
|
||||
newSocket.emit('proof_verified', {
|
||||
sessionId,
|
||||
proofVerified: local_proofVerified.toString(),
|
||||
});
|
||||
if (local_proofVerified) {
|
||||
onSuccess(data.proof);
|
||||
}
|
||||
}, 1500); // wait for animation to finish before sending the proof to mobile
|
||||
} catch (error) {
|
||||
console.error('Error verifying proof:', error);
|
||||
setProofVerified(false);
|
||||
setProofStep(QRcodeSteps.PROOF_VERIFIED);
|
||||
newSocket.emit('proof_verified', {
|
||||
sessionId,
|
||||
proofVerified: local_proofVerified.toString(),
|
||||
proofVerified: JSON.stringify({ valid: false, error: error.message }),
|
||||
});
|
||||
if (local_proofVerified) {
|
||||
onSuccess(data.proof);
|
||||
}
|
||||
}, 1500); // wait for animation to finish before sending the proof to mobile
|
||||
} catch (error) {
|
||||
console.error('Error verifying proof:', error);
|
||||
setProofVerified(false);
|
||||
setProofStep(QRcodeSteps.PROOF_VERIFIED);
|
||||
newSocket.emit('proof_verified', {
|
||||
sessionId,
|
||||
proofVerified: { valid: false, error: error.message },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export function initWebSocket(
|
||||
websocketUrl: string,
|
||||
|
||||
@@ -7,9 +7,9 @@ export default function Prove() {
|
||||
const userId = uuidv4();
|
||||
const scope = 'scope';
|
||||
|
||||
const openPassportVerifier = new OpenPassportVerifier('prove_onchain', scope)
|
||||
.setNationality('France')
|
||||
const openPassportVerifier = new OpenPassportVerifier('prove_offchain', scope)
|
||||
.excludeCountries('Finland', 'Norway')
|
||||
.allowMockPassports()
|
||||
.setMinimumAge(12);
|
||||
return (
|
||||
<div className="h-screen w-full bg-white flex flex-col items-center justify-center gap-4">
|
||||
|
||||
Reference in New Issue
Block a user