From cb9722cc9a3eb88ad91763e572460d03235ca442 Mon Sep 17 00:00:00 2001 From: 0xturboblitz Date: Thu, 19 Sep 2024 09:45:31 -0700 Subject: [PATCH] add amplitude back --- app/ios/Podfile.lock | 2 +- app/src/stores/userStore.ts | 4 +- app/src/utils/cameraScanner.ts | 3 + app/src/utils/nfcScanner.ts | 140 ++++++++++++++++++++------------- app/src/utils/prover.ts | 37 +++++---- app/src/utils/zkeyDownload.ts | 4 +- 6 files changed, 117 insertions(+), 73 deletions(-) diff --git a/app/ios/Podfile.lock b/app/ios/Podfile.lock index cb71fbff..aa6bcb8d 100644 --- a/app/ios/Podfile.lock +++ b/app/ios/Podfile.lock @@ -659,6 +659,6 @@ SPEC CHECKSUMS: SwiftyTesseract: 1f3d96668ae92dc2208d9842c8a59bea9fad2cbb Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce -PODFILE CHECKSUM: d3a7fe796373a959164d78cc6caacf51cb9dee87 +PODFILE CHECKSUM: 9cb8f5a5b9cf92f86866e2c805998e51596330d5 COCOAPODS: 1.15.2 diff --git a/app/src/stores/userStore.ts b/app/src/stores/userStore.ts index 9c09885d..e1d75b0f 100644 --- a/app/src/stores/userStore.ts +++ b/app/src/stores/userStore.ts @@ -6,7 +6,6 @@ import { } from '@env'; import { PassportData, Proof } from '../../../common/src/utils/types'; import * as Keychain from 'react-native-keychain'; -import * as amplitude from '@amplitude/analytics-react-native'; import { loadPassportData, loadSecret, loadSecretOrCreateIt, storePassportData } from '../utils/keychain'; import { generateDscSecret } from '../../../common/src/utils/csca'; import { genMockPassportData } from '../../../common/src/utils/genMockPassportData'; @@ -111,8 +110,7 @@ const useUserStore = create((set, get) => ({ const alreadyStoredPassportData = await loadPassportData(); if (alreadyStoredPassportData) { - console.log("passportData is already stored, this should never happen in prod") - console.log("replacing it with the new one") + console.log("a passportData is already stored, replacing it with the new one") } await storePassportData(passportData) diff --git a/app/src/utils/cameraScanner.ts b/app/src/utils/cameraScanner.ts index 6f6a5cd6..33e02da3 100644 --- a/app/src/utils/cameraScanner.ts +++ b/app/src/utils/cameraScanner.ts @@ -28,6 +28,7 @@ export const startCameraScan = async () => { }) } catch (e) { console.error(e); + amplitude.track('camera_scan_error', { error: e }); } } else { NativeModules.CameraActivityModule.startCameraActivity() @@ -50,10 +51,12 @@ export const startCameraScan = async () => { }) } catch (error: any) { console.error('Invalid MRZ format:', error.message); + amplitude.track('invalid_mrz_format', { error: error.message }); } }) .catch((error: any) => { console.error('Camera Activity Error:', error); + amplitude.track('camera_scan_error', { error: error.message }); }); } }; \ No newline at end of file diff --git a/app/src/utils/nfcScanner.ts b/app/src/utils/nfcScanner.ts index 39e4dd5c..66461f89 100644 --- a/app/src/utils/nfcScanner.ts +++ b/app/src/utils/nfcScanner.ts @@ -27,6 +27,7 @@ export const scan = async (setModalProofStep: (modalProofStep: number) => void) ); if (!check.success) { + amplitude.track('inputs_invalid', { error: check.message }); toast.show("Unvailable", { message: check.message, customData: { @@ -54,7 +55,6 @@ const scanAndroid = async (setModalProofStep: (modalProofStep: number) => void) const { toast, setNfcSheetIsOpen } = useNavigationStore.getState(); setNfcSheetIsOpen(true); - try { const response = await PassportReader.scan({ documentNumber: passportNumber, @@ -63,19 +63,18 @@ const scanAndroid = async (setModalProofStep: (modalProofStep: number) => void) }); console.log('scanned'); setNfcSheetIsOpen(false); - //amplitude.track('NFC scan successful'); + amplitude.track('nfc_scan_successful'); handleResponseAndroid(response, setModalProofStep); } catch (e: any) { console.log('error during scan:', e); setNfcSheetIsOpen(false); - //amplitude.track('NFC scan unsuccessful', { error: JSON.stringify(e) }); + amplitude.track('nfc_scan_unsuccessful', { error: e.message }); toast.show('Error', { message: e.message, customData: { type: "error", }, }) - } }; @@ -87,6 +86,10 @@ const scanIOS = async (setModalProofStep: (modalProofStep: number) => void) => { } = useUserStore.getState() const { toast } = useNavigationStore.getState(); + console.log('passportNumber', passportNumber); + console.log('dateOfBirth', dateOfBirth); + console.log('dateOfExpiry', dateOfExpiry); + try { const response = await NativeModules.PassportReader.scanPassport( passportNumber, @@ -95,10 +98,10 @@ const scanIOS = async (setModalProofStep: (modalProofStep: number) => void) => { ); console.log('scanned'); handleResponseIOS(response, setModalProofStep); - //amplitude.track('NFC scan successful'); + amplitude.track('nfc_scan_successful'); } catch (e: any) { console.log('error during scan:', e); - //amplitude.track(`NFC scan unsuccessful, error ${e.message}`); + amplitude.track('nfc_scan_unsuccessful', { error: e.message }); if (!e.message.includes("UserCanceled")) { toast.show('Failed to read passport', { message: e.message, @@ -118,41 +121,52 @@ const handleResponseIOS = async ( const parsed = JSON.parse(response); - const eContentBase64 = parsed.eContentBase64; // this is what we call concatenatedDataHashes in android world - const signedAttributes = parsed.signedAttributes; // this is what we call eContent in android world - const mrz = parsed.passportMRZ; - const signatureBase64 = parsed.signatureBase64; - console.log('dataGroupsPresent', parsed.dataGroupsPresent) - console.log('placeOfBirth', parsed.placeOfBirth) - console.log('activeAuthenticationPassed', parsed.activeAuthenticationPassed) - console.log('isPACESupported', parsed.isPACESupported) - console.log('isChipAuthenticationSupported', parsed.isChipAuthenticationSupported) - console.log('residenceAddress', parsed.residenceAddress) - console.log('passportPhoto', parsed.passportPhoto.substring(0, 100) + '...') - console.log('encapsulatedContentDigestAlgorithm', parsed.encapsulatedContentDigestAlgorithm) - console.log('parsed.documentSigningCertificate', parsed.documentSigningCertificate) - const pem = JSON.parse(parsed.documentSigningCertificate).PEM.replace(/\n/g, ''); + const eContentBase64 = parsed?.eContentBase64; // this is what we call concatenatedDataHashes in android world + const signedAttributes = parsed?.signedAttributes; // this is what we call eContent in android world + const mrz = parsed?.passportMRZ; + const signatureBase64 = parsed?.signatureBase64; + console.log('dataGroupsPresent', parsed?.dataGroupsPresent) + console.log('placeOfBirth', parsed?.placeOfBirth) + console.log('activeAuthenticationPassed', parsed?.activeAuthenticationPassed) + console.log('isPACESupported', parsed?.isPACESupported) + console.log('isChipAuthenticationSupported', parsed?.isChipAuthenticationSupported) + console.log('residenceAddress', parsed?.residenceAddress) + console.log('passportPhoto', parsed?.passportPhoto.substring(0, 100) + '...') + console.log('encapsulatedContentDigestAlgorithm', parsed?.encapsulatedContentDigestAlgorithm) + console.log('documentSigningCertificate', parsed?.documentSigningCertificate) + const pem = JSON.parse(parsed?.documentSigningCertificate).PEM.replace(/\n/g, ''); console.log('pem', pem) + const eContentArray = Array.from(Buffer.from(signedAttributes, 'base64')); + const signedEContentArray = eContentArray.map(byte => byte > 127 ? byte - 256 : byte); + + const concatenatedDataHashesArray = Array.from(Buffer.from(eContentBase64, 'base64')); + const concatenatedDataHashesArraySigned = concatenatedDataHashesArray.map(byte => byte > 127 ? byte - 256 : byte); + + const encryptedDigestArray = Array.from(Buffer.from(signatureBase64, 'base64')).map(byte => byte > 127 ? byte - 256 : byte); + + amplitude.track('nfc_response_parsed', { + dataGroupsPresent: parsed?.dataGroupsPresent, + eContentLength: signedEContentArray?.length, + encryptedDigestLength: encryptedDigestArray?.length, + activeAuthenticationPassed: parsed?.activeAuthenticationPassed, + isPACESupported: parsed?.isPACESupported, + isChipAuthenticationSupported: parsed?.isChipAuthenticationSupported, + encapsulatedContentDigestAlgorithm: parsed?.encapsulatedContentDigestAlgorithm, + dsc: pem, + }); + + const passportData = { + mrz, + dsc: pem, + dataGroupHashes: concatenatedDataHashesArraySigned, + eContent: signedEContentArray, + encryptedDigest: encryptedDigestArray, + photoBase64: "data:image/jpeg;base64," + parsed.passportPhoto, + mockUser: false + }; + try { - const eContentArray = Array.from(Buffer.from(signedAttributes, 'base64')); - const signedEContentArray = eContentArray.map(byte => byte > 127 ? byte - 256 : byte); - - const concatenatedDataHashesArray = Array.from(Buffer.from(eContentBase64, 'base64')); - const concatenatedDataHashesArraySigned = concatenatedDataHashesArray.map(byte => byte > 127 ? byte - 256 : byte); - - const encryptedDigestArray = Array.from(Buffer.from(signatureBase64, 'base64')).map(byte => byte > 127 ? byte - 256 : byte); - - //amplitude.track('Sig alg before conversion: ' + signatureAlgorithm); - const passportData = { - mrz, - dsc: pem, - dataGroupHashes: concatenatedDataHashesArraySigned, - eContent: signedEContentArray, - encryptedDigest: encryptedDigestArray, - photoBase64: "data:image/jpeg;base64," + parsed.passportPhoto, - mockUser: false - }; useUserStore.getState().registerPassportData(passportData) const { signatureAlgorithm, hashFunction } = parseDSC(pem); const circuitName = getCircuitName("prove", signatureAlgorithm, hashFunction); @@ -160,9 +174,9 @@ const handleResponseIOS = async ( useNavigationStore.getState().setSelectedTab("next"); } catch (e: any) { console.log('error during parsing:', e); - //amplitude.track('Signature algorithm unsupported (ecdsa not parsed)', { error: JSON.stringify(e) }); + amplitude.track('error_parsing_nfc_response', { error: e.message }); toast.show('Error', { - message: "Your signature algorithm is not supported at that time. Please try again later.", + message: e.message, customData: { type: "error", }, @@ -174,6 +188,8 @@ const handleResponseAndroid = async ( response: any, setModalProofStep: (modalProofStep: number) => void ) => { + const { toast } = useNavigationStore.getState(); + const { mrz, eContent, @@ -188,8 +204,6 @@ const handleResponseAndroid = async ( documentSigningCertificate } = response; - //amplitude.track('Sig alg before conversion: ' + signatureAlgorithm); - const pem = "-----BEGIN CERTIFICATE-----" + documentSigningCertificate + "-----END CERTIFICATE-----" const passportData: PassportData = { mrz: mrz.replace(/\n/g, ''), @@ -200,18 +214,17 @@ const handleResponseAndroid = async ( photoBase64: photo.base64, mockUser: false }; - //amplitude.track('Sig alg after conversion: ' + passportData.signatureAlgorithm); console.log('passportData', JSON.stringify({ ...passportData, photoBase64: passportData.photoBase64.substring(0, 100) + '...' }, null, 2)); - console.log('mrz', passportData.mrz); - console.log('dataGroupHashes', passportData.dataGroupHashes); - console.log('eContent', passportData.eContent); - console.log('encryptedDigest', passportData.encryptedDigest); - console.log("photoBase64", passportData.photoBase64.substring(0, 100) + '...') + console.log('mrz', passportData?.mrz); + console.log('dataGroupHashes', passportData?.dataGroupHashes); + console.log('eContent', passportData?.eContent); + console.log('encryptedDigest', passportData?.encryptedDigest); + console.log("photoBase64", passportData?.photoBase64.substring(0, 100) + '...') console.log("digestAlgorithm", digestAlgorithm) console.log("signerInfoDigestAlgorithm", signerInfoDigestAlgorithm) console.log("digestEncryptionAlgorithm", digestEncryptionAlgorithm) @@ -219,10 +232,31 @@ const handleResponseAndroid = async ( console.log("unicodeVersion", unicodeVersion) console.log("encapContent", encapContent) console.log("documentSigningCertificate", documentSigningCertificate) - useUserStore.getState().registerPassportData(passportData) - const { signatureAlgorithm, hashFunction } = parseDSC(pem); - const circuitName = getCircuitName("prove", signatureAlgorithm, hashFunction); - downloadZkey(circuitName as any); - useNavigationStore.getState().setSelectedTab("next"); + amplitude.track('nfc_response_parsed', { + dataGroupHashesLength: passportData?.dataGroupHashes?.length, + eContentLength: passportData?.eContent?.length, + encryptedDigestLength: passportData?.encryptedDigest?.length, + digestAlgorithm: digestAlgorithm, + signerInfoDigestAlgorithm: signerInfoDigestAlgorithm, + digestEncryptionAlgorithm: digestEncryptionAlgorithm, + dsc: pem, + }); + + try { + useUserStore.getState().registerPassportData(passportData) + const { signatureAlgorithm, hashFunction } = parseDSC(pem); + const circuitName = getCircuitName("prove", signatureAlgorithm, hashFunction); + downloadZkey(circuitName as any); + useNavigationStore.getState().setSelectedTab("next"); + } catch (e: any) { + console.log('error during parsing:', e); + amplitude.track('error_parsing_nfc_response', { error: e.message }); + toast.show('Error', { + message: e.message, + customData: { + type: "error", + }, + }) + } }; diff --git a/app/src/utils/prover.ts b/app/src/utils/prover.ts index 4a55abbe..0b6901e1 100644 --- a/app/src/utils/prover.ts +++ b/app/src/utils/prover.ts @@ -1,28 +1,30 @@ import { NativeModules, Platform } from 'react-native'; import { parseProofAndroid } from './utils'; import RNFS from 'react-native-fs'; +import * as amplitude from '@amplitude/analytics-react-native'; export const generateProof = async ( circuit: string, inputs: any, ) => { - try { - console.log('launching generateProof function'); - console.log('inputs in prover.ts', inputs); - console.log('circuit', circuit); + console.log('launching generateProof function'); + console.log('inputs in prover.ts', inputs); + console.log('circuit', circuit); - const zkey_path = `${RNFS.DocumentDirectoryPath}/${circuit}.zkey` - // Example: "/data/user/0/com.proofofpassportapp/files/register_sha256WithRSAEncryption_65537.zkey" on android - const dat_path = `${RNFS.DocumentDirectoryPath}/${circuit}.dat` + const zkey_path = `${RNFS.DocumentDirectoryPath}/${circuit}.zkey` + // Example: "/data/user/0/com.proofofpassportapp/files/register_sha256WithRSAEncryption_65537.zkey" on android + const dat_path = `${RNFS.DocumentDirectoryPath}/${circuit}.dat` - const witness_calculator = circuit; + const witness_calculator = circuit; - if (!zkey_path || !witness_calculator || !dat_path) { - throw new Error('Required parameters are missing'); - } - console.log('zkey_path', zkey_path); - console.log('witness_calculator', witness_calculator); - console.log('dat_path', dat_path); + if (!zkey_path || !witness_calculator || !dat_path) { + throw new Error('Required parameters are missing'); + } + console.log('zkey_path', zkey_path); + console.log('witness_calculator', witness_calculator); + console.log('dat_path', dat_path); + + try { const response = await NativeModules.Prover.runProveAction( zkey_path, witness_calculator, @@ -47,6 +49,13 @@ export const generateProof = async ( } } catch (err: any) { console.log('err', err); + amplitude.track('error_generating_proof', { + error: err.message, + circuit: circuit, + zkey_path: zkey_path, + witness_calculator: witness_calculator, + dat_path: dat_path, + }); throw new Error(err); } }; diff --git a/app/src/utils/zkeyDownload.ts b/app/src/utils/zkeyDownload.ts index 353c4a32..fd660000 100644 --- a/app/src/utils/zkeyDownload.ts +++ b/app/src/utils/zkeyDownload.ts @@ -58,7 +58,7 @@ export async function downloadZkey( const downloadRequired = await isDownloadRequired(circuit, isZkeyDownloading); if (!downloadRequired) { console.log(`zkey and dat for ${circuit} already downloaded`) - //amplitude.track(`zkey for ${circuit} already downloaded`); + amplitude.track('zkey_already_downloaded', { circuit: circuit }); return; } @@ -117,7 +117,7 @@ export async function fetchZkeyAndDat( circuit: CircuitName, ) { console.log(`fetching zkey and dat for ${circuit} ...`) - //amplitude.track(`fetching zkey and dat for ${circuit} ...`); + amplitude.track('fetching_zkey_and_dat', { circuit: circuit }); const { isZkeyDownloading,