Merge pull request #395 from selfxyz/feat/mock-passport

add staging proving flow
This commit is contained in:
turnoffthiscomputer
2025-03-09 14:24:17 -04:00
committed by GitHub
12 changed files with 411 additions and 354 deletions

View File

@@ -3,12 +3,11 @@ import { TouchableOpacity } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useNavigation } from '@react-navigation/native';
import { ChevronDown, Cpu, Minus, Plus, X } from '@tamagui/lucide-icons';
import { ChevronDown, Minus, Plus, X } from '@tamagui/lucide-icons';
import { flag } from 'country-emoji';
import getCountryISO2 from 'country-iso-3-to-2';
import {
Button,
Fieldset,
ScrollView,
Separator,
Sheet,
@@ -21,7 +20,13 @@ import {
import { countryCodes } from '../../../common/src/constants/constants';
import { genMockPassportData } from '../../../common/src/utils/passports/genMockPassportData';
import { usePassport } from '../stores/passportDataProvider';
import { initPassportDataParsing } from '../../../common/src/utils/passports/passport';
import ButtonsContainer from '../components/ButtonsContainer';
import { PrimaryButton } from '../components/buttons/PrimaryButton';
import { SecondaryButton } from '../components/buttons/SecondaryButton';
import { BodyText } from '../components/typography/BodyText';
import { Title } from '../components/typography/Title';
import { storePassportData } from '../stores/passportDataProvider';
import { borderColor, separatorColor, textBlack, white } from '../utils/colors';
import { buttonTap, selectionChange } from '../utils/haptic';
@@ -42,8 +47,6 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
date.toISOString().slice(8, 10)
).toString();
};
const { setData } = usePassport();
const [selectedCountry, setSelectedCountry] = useState('USA');
const [selectedAlgorithm, setSelectedAlgorithm] = useState('rsa sha256');
const [isCountrySheetOpen, setCountrySheetOpen] = useState(false);
@@ -60,9 +63,20 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
};
const signatureAlgorithmToStrictSignatureAlgorithm = {
'rsa sha256': 'rsa_sha256_65537_4096',
'rsa sha1': 'rsa_sha1_65537_2048',
'rsapss sha256': 'rsapss_sha256_65537_2048',
'rsa sha256': ['sha256', 'sha256', 'rsa_sha256_65537_4096'],
'rsa sha1': ['sha256', 'sha256', 'rsa_sha1_65537_2048'],
'rsapss sha256': ['sha256', 'sha256', 'rsapss_sha256_65537_2048'],
'sha256 brainpoolP256r1': [
'sha256',
'sha256',
'ecdsa_sha384_brainpoolP256r1_256',
],
'sha384 brainpoolP384r1': [
'sha384',
'sha384',
'ecdsa_sha384_brainpoolP384r1_384',
],
'sha384 secp384r1': ['sha384', 'sha384', 'ecdsa_sha384_secp384r1_384'],
} as const;
const handleGenerate = useCallback(async () => {
@@ -73,15 +87,18 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
.replace(/[^a-z0-9]/gi, '')
.toUpperCase();
await new Promise(resolve =>
setTimeout(() => {
setTimeout(async () => {
let mockPassportData;
const [hashFunction1, hashFunction2, signatureAlgorithm] =
signatureAlgorithmToStrictSignatureAlgorithm[
selectedAlgorithm as keyof typeof signatureAlgorithmToStrictSignatureAlgorithm
];
if (isInOfacList) {
mockPassportData = genMockPassportData(
'sha1',
'sha256',
signatureAlgorithmToStrictSignatureAlgorithm[
selectedAlgorithm as keyof typeof signatureAlgorithmToStrictSignatureAlgorithm
],
hashFunction1,
hashFunction2,
signatureAlgorithm,
selectedCountry as keyof typeof countryCodes,
// We disregard the age to stick with Arcangel's birth date
'541007',
@@ -92,19 +109,17 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
);
} else {
mockPassportData = genMockPassportData(
'sha1',
'sha256',
signatureAlgorithmToStrictSignatureAlgorithm[
selectedAlgorithm as keyof typeof signatureAlgorithmToStrictSignatureAlgorithm
],
hashFunction1,
hashFunction2,
signatureAlgorithm,
selectedCountry as keyof typeof countryCodes,
castDate(-age),
castDate(expiryYears),
randomPassportNumber,
);
}
setData(mockPassportData);
mockPassportData = initPassportDataParsing(mockPassportData);
await storePassportData(mockPassportData);
resolve(null);
}, 0),
);
@@ -117,172 +132,144 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
const { top, bottom } = useSafeAreaInsets();
return (
<>
<YStack
f={1}
gap="$4"
px="$4"
backgroundColor={white}
paddingTop={top}
paddingBottom={bottom}
>
<Text my="$9" textAlign="center" fontSize="$9" color={textBlack}>
Generate passport data
</Text>
<XStack ai="center">
<Text f={1} fontSize="$5">
Encryption
</Text>
<Button
onPress={() => {
buttonTap();
setAlgorithmSheetOpen(true);
}}
p="$2"
px="$3"
bg="white"
borderColor={borderColor}
borderWidth={1}
borderRadius="$4"
>
<XStack ai="center" gap="$2">
<Text fontSize="$4">{selectedAlgorithm}</Text>
<ChevronDown size={20} />
</XStack>
</Button>
</XStack>
<XStack ai="center">
<Text f={1} fontSize="$5">
Nationality
</Text>
<Button
onPress={() => {
buttonTap();
setCountrySheetOpen(true);
}}
p="$2"
px="$3"
bg="white"
borderColor={borderColor}
borderWidth={1}
borderRadius="$4"
>
<XStack ai="center" gap="$2">
<Text fontSize="$4">
{countryCodes[selectedCountry as keyof typeof countryCodes]}{' '}
{flag(getCountryISO2(selectedCountry))}
</Text>
<ChevronDown size={20} />
</XStack>
</Button>
</XStack>
<YStack f={1} bg={white} pt={top} pb={bottom}>
<ScrollView showsVerticalScrollIndicator={false}>
<YStack px="$4" pb="$4" gap="$5">
<YStack ai="center" mb={'$10'}>
<Title>Generate Passport Data</Title>
<BodyText textAlign="center">
Configure the passport data parameters below
</BodyText>
</YStack>
<Fieldset mt="$2" gap="$2" horizontal>
<Text
color={textBlack}
width={160}
justifyContent="flex-end"
fontSize="$5"
>
Age (🎂)
</Text>
<XStack f={1} />
<Button
h="$3.5"
w="$3.5"
bg="white"
jc="center"
borderColor={borderColor}
borderWidth={1}
borderRadius="$10"
onPress={() => {
buttonTap();
setAge(age - 1);
}}
disabled={age <= 0 || isInOfacList}
>
<Minus />
</Button>
<Text textAlign="center" w="$6" color={textBlack} fontSize="$5">
{isInOfacList ? 71 : age} yo
</Text>
<Button
h="$3.5"
w="$3.5"
bg="white"
jc="center"
borderColor={borderColor}
borderWidth={1}
borderRadius="$10"
onPress={() => {
buttonTap();
setAge(age + 1);
}}
disabled={isInOfacList}
>
<Plus />
</Button>
</Fieldset>
<Fieldset gap="$2" horizontal>
<Text
color={textBlack}
width={160}
justifyContent="flex-end"
fontSize="$5"
>
Passport expires in
</Text>
<XStack f={1} />
<Button
h="$3.5"
w="$3.5"
bg="white"
jc="center"
borderColor={borderColor}
borderWidth={1}
borderRadius="$10"
onPress={() => {
buttonTap();
setExpiryYears(expiryYears - 1);
}}
disabled={expiryYears <= 0}
>
<Minus />
</Button>
<Text textAlign="center" w="$6" color={textBlack} fontSize="$5">
{expiryYears} years
</Text>
<Button
h="$3.5"
w="$3.5"
bg="white"
jc="center"
borderColor={borderColor}
borderWidth={1}
borderRadius="$10"
onPress={() => {
buttonTap();
setExpiryYears(expiryYears + 1);
}}
>
<Plus />
</Button>
</Fieldset>
<YStack>
<Fieldset mt="$2" gap="$2" horizontal>
<Text
color={textBlack}
width={160}
justifyContent="flex-end"
fontSize="$5"
<XStack ai="center" jc="space-between">
<BodyText>Encryption</BodyText>
<Button
onPress={() => {
buttonTap();
setAlgorithmSheetOpen(true);
}}
p="$2"
px="$3"
bg="white"
borderColor={borderColor}
borderWidth={1}
borderRadius="$4"
>
Is in OFAC list
</Text>
<XStack f={1} />
<XStack ai="center" gap="$2">
<Text fontSize="$4">{selectedAlgorithm}</Text>
<ChevronDown size={20} />
</XStack>
</Button>
</XStack>
<XStack ai="center" jc="space-between">
<BodyText>Nationality</BodyText>
<Button
onPress={() => {
buttonTap();
setCountrySheetOpen(true);
}}
p="$2"
px="$3"
bg="white"
borderColor={borderColor}
borderWidth={1}
borderRadius="$4"
>
<XStack ai="center" gap="$2">
<Text fontSize="$4">
{countryCodes[selectedCountry as keyof typeof countryCodes]}{' '}
{flag(getCountryISO2(selectedCountry))}
</Text>
<ChevronDown size={20} />
</XStack>
</Button>
</XStack>
<XStack ai="center" jc="space-between">
<BodyText>Age (🎂)</BodyText>
<XStack ai="center" gap="$2">
<Button
h="$3.5"
w="$3.5"
bg="white"
jc="center"
borderColor={borderColor}
borderWidth={1}
borderRadius="$10"
onPress={() => {
buttonTap();
setAge(age - 1);
}}
disabled={age <= 0 || isInOfacList}
>
<Minus />
</Button>
<Text textAlign="center" w="$6" color={textBlack} fontSize="$5">
{isInOfacList ? 71 : age} yo
</Text>
<Button
h="$3.5"
w="$3.5"
bg="white"
jc="center"
borderColor={borderColor}
borderWidth={1}
borderRadius="$10"
onPress={() => {
buttonTap();
setAge(age + 1);
}}
disabled={isInOfacList}
>
<Plus />
</Button>
</XStack>
</XStack>
<XStack ai="center" jc="space-between">
<BodyText>Passport expires in</BodyText>
<XStack ai="center" gap="$2">
<Button
h="$3.5"
w="$3.5"
bg="white"
jc="center"
borderColor={borderColor}
borderWidth={1}
borderRadius="$10"
onPress={() => {
buttonTap();
setExpiryYears(expiryYears - 1);
}}
disabled={expiryYears <= 0}
>
<Minus />
</Button>
<Text textAlign="center" w="$6" color={textBlack} fontSize="$5">
{expiryYears} years
</Text>
<Button
h="$3.5"
w="$3.5"
bg="white"
jc="center"
borderColor={borderColor}
borderWidth={1}
borderRadius="$10"
onPress={() => {
buttonTap();
setExpiryYears(expiryYears + 1);
}}
>
<Plus />
</Button>
</XStack>
</XStack>
<XStack ai="center" jc="space-between">
<BodyText>In OFAC list</BodyText>
<Switch
size="$3.5"
checked={isInOfacList}
@@ -294,31 +281,32 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
>
<Switch.Thumb animation="quick" bc="white" />
</Switch>
</Fieldset>
<Text
mt="$2"
color="$red10"
justifyContent="flex-end"
fontSize="$3"
style={{ opacity: isInOfacList ? 1 : 0 }}
>
OFAC list is a list of people who are suspected of being involved in
terrorism or other illegal activities.
</Text>
</YStack>
</XStack>
<YStack f={1} />
<YStack>
<Text mb="$2" textAlign="center" fontSize="$4" color={textBlack}>
These passport data are only for testing purposes.
</Text>
<Button onPress={handleGenerate} disabled={isGenerating}>
{isGenerating ? <Spinner /> : <Cpu color={textBlack} />} Generate
passport data
</Button>
{isInOfacList && (
<Text color="$red10" fontSize="$3">
OFAC list is a list of people who are suspected of being involved
in terrorism or other illegal activities.
</Text>
)}
</YStack>
</ScrollView>
<YStack px="$4" pb="$4">
<ButtonsContainer>
<PrimaryButton onPress={handleGenerate} disabled={isGenerating}>
{isGenerating ? (
<Spinner color="white" size="small" />
) : (
'Generate Passport Data'
)}
</PrimaryButton>
<SecondaryButton onPress={() => navigation.goBack()}>
Cancel
</SecondaryButton>
</ButtonsContainer>
</YStack>
<Sheet
modal
open={isCountrySheetOpen}
@@ -399,7 +387,14 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
</XStack>
<Separator borderColor={separatorColor} mb="$4" />
<ScrollView showsVerticalScrollIndicator={false}>
{['rsa sha256', 'rsa sha1', 'rsapss sha256'].map(algorithm => (
{[
'rsa sha256',
'rsa sha1',
'rsapss sha256',
'sha256 brainpoolP256r1',
'sha384 brainpoolP384r1',
'sha384 secp384r1',
].map(algorithm => (
<TouchableOpacity
key={algorithm}
onPress={() => {
@@ -417,7 +412,7 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
</YStack>
</Sheet.Frame>
</Sheet>
</>
</YStack>
);
};

View File

@@ -67,12 +67,11 @@ const routes = [
// get the actual type of the routes so we can use in the onMenuPress function so it
// doesnt worry about us linking to screens with required props which we dont want to go to anyway
type RouteLinks = (typeof routes)[number][2];
type RouteLinks = (typeof routes)[number][2] | (typeof DEBUG_MENU)[number][2];
const DEBUG_MENU: [React.FC<SvgProps>, string, RouteOption] = [
Bug as React.FC<SvgProps>,
'Debug menu',
'DevSettings',
const DEBUG_MENU: [React.FC<SvgProps>, string, RouteOption][] = [
[Data as React.FC<SvgProps>, 'Gen Mock Passport Data', 'CreateMock'],
[Bug as React.FC<SvgProps>, 'Debug menu', 'DevSettings'],
];
const social = [
@@ -123,7 +122,7 @@ const SettingsScreen: React.FC<SettingsScreenProps> = ({}) => {
const navigation = useNavigation();
const screenRoutes = useMemo(() => {
return isDevMode ? [...routes, DEBUG_MENU] : routes;
return isDevMode ? [...routes, ...DEBUG_MENU] : routes;
}, [isDevMode]);
const twoFingerTap = Gesture.Tap()
@@ -175,7 +174,7 @@ ${deviceInfo.map(([k, v]) => `${k}=${v}`).join('; ')}
break;
default:
navigation.navigate(menuRoute);
navigation.navigate(menuRoute as any);
break;
}
};

View File

@@ -89,7 +89,8 @@ const handleResponseIOS = (response: any) => {
signedAttr: signedEContentArray,
encryptedDigest: encryptedDigestArray,
parsed: false,
};
documentType: 'passport',
} as PassportData;
};
const handleResponseAndroid = (response: any) => {
@@ -131,5 +132,6 @@ const handleResponseAndroid = (response: any) => {
eContent: JSON.parse(encapContent),
signedAttr: JSON.parse(eContent),
encryptedDigest: JSON.parse(encryptedDigest),
documentType: 'passport',
} as PassportData;
};

View File

@@ -0,0 +1,131 @@
import { LeanIMT } from '@openpassport/zk-kit-lean-imt';
import { SMT } from '@openpassport/zk-kit-smt';
import { poseidon2 } from 'poseidon-lite';
import nameAndDobSMTData from '../../../../common/ofacdata/outputs/nameAndDobSMT.json';
import nameAndYobSMTData from '../../../../common/ofacdata/outputs/nameAndYobSMT.json';
import passportNoAndNationalitySMTData from '../../../../common/ofacdata/outputs/passportNoAndNationalitySMT.json';
import {
DEFAULT_MAJORITY,
PASSPORT_ATTESTATION_ID,
attributeToPosition,
} from '../../../../common/src/constants/constants';
import { EndpointType, SelfApp } from '../../../../common/src/utils/appType';
import { getCircuitNameFromPassportData } from '../../../../common/src/utils/circuits/circuitsName';
import {
generateCircuitInputsDSC,
generateCircuitInputsRegister,
generateCircuitInputsVCandDisclose,
} from '../../../../common/src/utils/circuits/generateInputs';
import {
getCSCATree,
getCommitmentTree,
getDSCTree,
} from '../../../../common/src/utils/trees';
import { PassportData } from '../../../../common/src/utils/types';
export async function generateTeeInputsRegister(
secret: string,
passportData: PassportData,
endpointType: EndpointType,
) {
const serialized_dsc_tree = await getDSCTree(endpointType);
const inputs = generateCircuitInputsRegister(
secret,
passportData,
serialized_dsc_tree,
);
const circuitName = getCircuitNameFromPassportData(passportData, 'register');
if (circuitName == null) {
throw new Error('Circuit name is null');
}
return { inputs, circuitName };
}
export async function generateTeeInputsDsc(
passportData: PassportData,
endpointType: EndpointType,
) {
const serialized_csca_tree = await getCSCATree(endpointType);
const inputs = generateCircuitInputsDSC(
passportData.dsc,
serialized_csca_tree,
);
const circuitName = getCircuitNameFromPassportData(passportData, 'dsc');
if (circuitName == null) {
throw new Error('Circuit name is null');
}
return { inputs, circuitName };
}
export async function generateTeeInputsVCAndDisclose(
secret: string,
passportData: PassportData,
selfApp: SelfApp,
) {
const { scope, userId, disclosures } = selfApp;
const selector_dg1 = Array(88).fill('0');
Object.entries(disclosures).forEach(([attribute, reveal]) => {
if (['ofac', 'excludedCountries', 'minimumAge'].includes(attribute)) {
return;
}
if (reveal) {
const [start, end] =
attributeToPosition[attribute as keyof typeof attributeToPosition];
selector_dg1.fill('1', start, end + 1);
}
});
const majority = disclosures.minimumAge
? disclosures.minimumAge.toString()
: DEFAULT_MAJORITY;
const selector_older_than = disclosures.minimumAge ? '1' : '0';
const selector_ofac = disclosures.ofac ? 1 : 0;
const { passportNoAndNationalitySMT, nameAndDobSMT, nameAndYobSMT } =
await getOfacSMTs();
const serialized_tree = await getCommitmentTree();
const tree = LeanIMT.import((a, b) => poseidon2([a, b]), serialized_tree);
console.log('tree', tree);
// const commitment = generateCommitment(
// secret,
// PASSPORT_ATTESTATION_ID,
// passportData,
// );
// tree.insert(BigInt(commitment));
// Uncomment to add artificially the commitment to the tree
const inputs = generateCircuitInputsVCandDisclose(
secret,
PASSPORT_ATTESTATION_ID,
passportData,
scope,
selector_dg1,
selector_older_than,
tree,
majority,
passportNoAndNationalitySMT,
nameAndDobSMT,
nameAndYobSMT,
selector_ofac,
disclosures.excludedCountries ?? [],
userId,
);
return { inputs, circuitName: 'vc_and_disclose' };
}
/*** DISCLOSURE ***/
async function getOfacSMTs() {
// TODO: get the SMT from an endpoint
const passportNoAndNationalitySMT = new SMT(poseidon2, true);
passportNoAndNationalitySMT.import(passportNoAndNationalitySMTData);
const nameAndDobSMT = new SMT(poseidon2, true);
nameAndDobSMT.import(nameAndDobSMTData);
const nameAndYobSMT = new SMT(poseidon2, true);
nameAndYobSMT.import(nameAndYobSMTData);
return { passportNoAndNationalitySMT, nameAndDobSMT, nameAndYobSMT };
}

View File

@@ -1,55 +1,31 @@
import { LeanIMT } from '@openpassport/zk-kit-lean-imt';
import { SMT } from '@openpassport/zk-kit-smt';
import { poseidon2 } from 'poseidon-lite';
import nameAndDobSMTData from '../../../../common/ofacdata/outputs/nameAndDobSMT.json';
import nameAndYobSMTData from '../../../../common/ofacdata/outputs/nameAndYobSMT.json';
import passportNoAndNationalitySMTData from '../../../../common/ofacdata/outputs/passportNoAndNationalitySMT.json';
import {
API_URL,
DEFAULT_MAJORITY,
PASSPORT_ATTESTATION_ID,
WS_RPC_URL_VC_AND_DISCLOSE,
attributeToPosition,
} from '../../../../common/src/constants/constants';
import { SelfApp } from '../../../../common/src/utils/appType';
import { EndpointType, SelfApp } from '../../../../common/src/utils/appType';
import { getCircuitNameFromPassportData } from '../../../../common/src/utils/circuits/circuitsName';
import {
generateCircuitInputsDSC,
generateCircuitInputsRegister,
generateCircuitInputsVCandDisclose,
} from '../../../../common/src/utils/circuits/generateInputs';
import {
generateCommitment,
generateNullifier,
} from '../../../../common/src/utils/passports/passport';
import {
getCSCATree,
getCommitmentTree,
getDSCTree,
getLeafDscTree,
} from '../../../../common/src/utils/trees';
import { PassportData } from '../../../../common/src/utils/types';
import { ProofStatusEnum } from '../../stores/proofProvider';
import {
generateTeeInputsDsc,
generateTeeInputsRegister,
generateTeeInputsVCAndDisclose,
} from './inputs';
import { sendPayload } from './tee';
async function generateTeeInputsRegister(
secret: string,
passportData: PassportData,
) {
const serialized_dsc_tree = await getDSCTree();
const inputs = generateCircuitInputsRegister(
secret,
passportData,
serialized_dsc_tree,
);
const circuitName = getCircuitNameFromPassportData(passportData, 'register');
if (circuitName == null) {
throw new Error('Circuit name is null');
}
return { inputs, circuitName };
}
export type PassportSupportStatus =
| 'passport_metadata_missing'
| 'csca_not_found'
@@ -99,18 +75,20 @@ export async function sendRegisterPayload(
passportData: PassportData,
secret: string,
circuitDNSMapping: Record<string, string>,
endpointType: EndpointType,
) {
const { inputs, circuitName } = await generateTeeInputsRegister(
secret,
passportData,
endpointType,
);
await sendPayload(
inputs,
'register',
circuitName,
'https',
endpointType,
'https://self.xyz',
circuitDNSMapping[circuitName],
(circuitDNSMapping as any).REGISTER[circuitName],
undefined,
{
updateGlobalOnSuccess: true,
@@ -120,23 +98,11 @@ export async function sendRegisterPayload(
);
}
async function generateTeeInputsDsc(passportData: PassportData) {
const serialized_csca_tree = await getCSCATree();
const inputs = generateCircuitInputsDSC(
passportData.dsc,
serialized_csca_tree,
);
const circuitName = getCircuitNameFromPassportData(passportData, 'dsc');
if (circuitName == null) {
throw new Error('Circuit name is null');
}
return { inputs, circuitName };
}
async function checkIdPassportDscIsInTree(
passportData: PassportData,
dscTree: string,
circuitDNSMapping: Record<string, string>,
endpointType: EndpointType,
): Promise<boolean> {
const hashFunction = (a: any, b: any) => poseidon2([a, b]);
const tree = LeanIMT.import(hashFunction, dscTree);
@@ -148,7 +114,11 @@ async function checkIdPassportDscIsInTree(
const index = tree.indexOf(BigInt(leaf));
if (index === -1) {
console.log('DSC is not found in the tree, sending DSC payload');
const dscStatus = await sendDscPayload(passportData, circuitDNSMapping);
const dscStatus = await sendDscPayload(
passportData,
circuitDNSMapping,
endpointType,
);
if (dscStatus !== ProofStatusEnum.SUCCESS) {
console.log('DSC proof failed');
return false;
@@ -168,6 +138,7 @@ async function checkIdPassportDscIsInTree(
export async function sendDscPayload(
passportData: PassportData,
circuitDNSMapping: Record<string, string>,
endpointType: EndpointType,
): Promise<ProofStatusEnum | false> {
if (!passportData) {
return false;
@@ -177,93 +148,24 @@ export async function sendDscPayload(
// console.log('Passport not supported');
// return false;
// }
const { inputs, circuitName } = await generateTeeInputsDsc(passportData);
console.log('circuitName', circuitName);
const { inputs, circuitName } = await generateTeeInputsDsc(
passportData,
endpointType,
);
const dscStatus = await sendPayload(
inputs,
'dsc',
circuitName,
'https',
endpointType,
'https://self.xyz',
circuitDNSMapping[circuitName],
(circuitDNSMapping.DSC as any)[circuitName],
undefined,
{ updateGlobalOnSuccess: false },
);
return dscStatus;
}
/*** DISCLOSURE ***/
async function getOfacSMTs() {
// TODO: get the SMT from an endpoint
const passportNoAndNationalitySMT = new SMT(poseidon2, true);
passportNoAndNationalitySMT.import(passportNoAndNationalitySMTData);
const nameAndDobSMT = new SMT(poseidon2, true);
nameAndDobSMT.import(nameAndDobSMTData);
const nameAndYobSMT = new SMT(poseidon2, true);
nameAndYobSMT.import(nameAndYobSMTData);
return { passportNoAndNationalitySMT, nameAndDobSMT, nameAndYobSMT };
}
async function generateTeeInputsVCAndDisclose(
secret: string,
passportData: PassportData,
selfApp: SelfApp,
) {
const { scope, userId, disclosures } = selfApp;
const selector_dg1 = Array(88).fill('0');
Object.entries(disclosures).forEach(([attribute, reveal]) => {
if (['ofac', 'excludedCountries', 'minimumAge'].includes(attribute)) {
return;
}
if (reveal) {
const [start, end] =
attributeToPosition[attribute as keyof typeof attributeToPosition];
selector_dg1.fill('1', start, end + 1);
}
});
const majority = disclosures.minimumAge
? disclosures.minimumAge.toString()
: DEFAULT_MAJORITY;
const selector_older_than = disclosures.minimumAge ? '1' : '0';
const selector_ofac = disclosures.ofac ? 1 : 0;
const { passportNoAndNationalitySMT, nameAndDobSMT, nameAndYobSMT } =
await getOfacSMTs();
const serialized_tree = await getCommitmentTree();
const tree = LeanIMT.import((a, b) => poseidon2([a, b]), serialized_tree);
console.log('tree', tree);
// const commitment = generateCommitment(
// secret,
// PASSPORT_ATTESTATION_ID,
// passportData,
// );
// tree.insert(BigInt(commitment));
// Uncomment to add artificially the commitment to the tree
const inputs = generateCircuitInputsVCandDisclose(
secret,
PASSPORT_ATTESTATION_ID,
passportData,
scope,
selector_dg1,
selector_older_than,
tree,
majority,
passportNoAndNationalitySMT,
nameAndDobSMT,
nameAndYobSMT,
selector_ofac,
disclosures.excludedCountries ?? [],
userId,
);
return { inputs, circuitName: 'vc_and_disclose' };
}
export async function sendVcAndDisclosePayload(
secret: string,
passportData: PassportData | null,
@@ -331,20 +233,30 @@ export async function registerPassport(
secret: string,
) {
// First get the mapping, then use it for the check
const endpointType =
passportData.documentType && passportData.documentType === 'mock_passport'
? 'staging_celo'
: 'celo';
const [circuitDNSMapping, dscTree] = await Promise.all([
getCircuitDNSMapping(),
getDSCTree(),
getDSCTree(endpointType),
]);
console.log('circuitDNSMapping', circuitDNSMapping);
const dscOk = await checkIdPassportDscIsInTree(
passportData,
dscTree,
circuitDNSMapping,
endpointType,
);
if (!dscOk) {
return;
}
await sendRegisterPayload(passportData, secret, circuitDNSMapping);
await sendRegisterPayload(
passportData,
secret,
circuitDNSMapping,
endpointType,
);
}
export async function getDeployedCircuits() {

View File

@@ -6,6 +6,7 @@ import { v4 } from 'uuid';
import {
CIRCUIT_TYPES,
WS_DB_RELAYER,
WS_DB_RELAYER_STAGING,
} from '../../../../common/src/constants/constants';
import { EndpointType } from '../../../../common/src/utils/appType';
import {
@@ -168,7 +169,7 @@ export async function sendPayload(
console.log('Received UUID:', receivedUuid);
console.log(result);
if (!socket) {
socket = io(WS_DB_RELAYER, {
socket = io(getWSDbRelayerUrl(endpointType), {
path: '/',
transports: ['websocket'],
});
@@ -259,6 +260,7 @@ export type TEEPayloadDisclose = {
export type TEEPayload = {
type: 'register' | 'dsc';
onchain: true;
endpointType: string;
circuit: {
name: string;
inputs: string;
@@ -287,6 +289,7 @@ export function getPayload(
const payload: TEEPayload = {
type: circuit as 'register' | 'dsc',
onchain: true,
endpointType: endpointType,
circuit: {
name: circuitName,
inputs: JSON.stringify(inputs),
@@ -295,3 +298,9 @@ export function getPayload(
return payload;
}
}
function getWSDbRelayerUrl(endpointType: EndpointType) {
return endpointType === 'celo' || endpointType === 'https'
? WS_DB_RELAYER
: WS_DB_RELAYER_STAGING;
}