Merge pull request #161 from zk-passport/new-ux

New ux
This commit is contained in:
turnoffthiscomputer
2024-08-07 11:46:52 +02:00
committed by GitHub
114 changed files with 10355 additions and 2274 deletions

View File

@@ -53,8 +53,4 @@ jobs:
- name: Run Tests
working-directory: ./circuits
run: yarn test
- name: Run Tests
working-directory: ./circuits
run: yarn test
run: yarn test

View File

@@ -9,28 +9,36 @@ import useNavigationStore from './src/stores/navigationStore';
import { AMPLITUDE_KEY } from '@env';
import * as amplitude from '@amplitude/analytics-react-native';
import useUserStore from './src/stores/userStore';
import { bgWhite } from './src/utils/colors';
global.Buffer = Buffer;
function App(): JSX.Element {
const toast = useToastController();
const setToast = useNavigationStore((state) => state.setToast);
const initUserStore = useUserStore((state) => state.initUserStore);
const setSelectedTab = useNavigationStore((state) => state.setSelectedTab);
useEffect(() => {
initUserStore();
}, [initUserStore]);
useEffect(() => {
setToast(toast);
}, [toast, setToast]);
useEffect(() => {
setSelectedTab('splash');
}, [setSelectedTab]);
useEffect(() => {
if (AMPLITUDE_KEY) {
amplitude.init(AMPLITUDE_KEY);
}
initUserStore();
//initUserStore();
}, []);
// TODO: when passportData already stored, retrieve and jump to main screen
return (
<YStack f={1} bc="#161616" h="100%" w="100%">
<YStack f={1} bc={bgWhite} h="100%" w="100%">
<YStack h="100%" w="100%">
<MainScreen />
</YStack>

View File

@@ -140,6 +140,8 @@ dependencies {
implementation project(':passportreader')
implementation 'org.jmrtd:jmrtd:0.7.18'
implementation 'com.github.blikoon:QRCodeScanner:0.1.2'
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.squareup.okhttp3', module:'okhttp'

View File

@@ -13,6 +13,7 @@ import io.tradle.nfc.RNPassportReaderPackage;
import java.util.List;
import com.proofofpassport.prover.ProverPackage;
import com.rnfs.RNFSPackage;
import com.proofofpassport.QRCodeScannerPackage;
public class MainApplication extends Application implements ReactApplication {
@@ -32,6 +33,7 @@ public class MainApplication extends Application implements ReactApplication {
// Add the custom package here
packages.add(new CameraActivityPackage());
packages.add(new ProverPackage());
packages.add(new QRCodeScannerPackage());
return packages;
}

View File

@@ -0,0 +1,93 @@
package com.proofofpassport;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.BaseActivityEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.blikoon.qrcodescanner.QrCodeActivity;
import android.Manifest;
public class QRCodeScannerModule extends ReactContextBaseJavaModule {
private static final int REQUEST_CODE_QR_SCAN = 101;
private static final int PERMISSION_REQUEST_CAMERA = 1;
private Promise scanPromise;
private final ActivityEventListener activityEventListener = new BaseActivityEventListener() {
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_QR_SCAN) {
if (scanPromise != null) {
if (resultCode == Activity.RESULT_OK) {
String result = data.getStringExtra("com.blikoon.qrcodescanner.got_qr_scan_relult");
scanPromise.resolve(result);
} else {
scanPromise.reject("SCAN_FAILED", "QR Code scanning failed or was cancelled");
}
scanPromise = null;
}
}
}
};
QRCodeScannerModule(ReactApplicationContext reactContext) {
super(reactContext);
reactContext.addActivityEventListener(activityEventListener);
}
@NonNull
@Override
public String getName() {
return "QRCodeScanner";
}
@ReactMethod
public void scanQRCode(Promise promise) {
Activity currentActivity = getCurrentActivity();
if (currentActivity == null) {
promise.reject("ACTIVITY_DOES_NOT_EXIST", "Activity doesn't exist");
return;
}
scanPromise = promise;
if (ContextCompat.checkSelfPermission(currentActivity, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(currentActivity,
new String[]{Manifest.permission.CAMERA},
PERMISSION_REQUEST_CAMERA);
} else {
startQRScanner(currentActivity);
}
}
private void startQRScanner(Activity activity) {
Intent intent = new Intent(activity, QrCodeActivity.class);
activity.startActivityForResult(intent, REQUEST_CODE_QR_SCAN);
}
// Add this method to handle permission result
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CAMERA) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Activity currentActivity = getCurrentActivity();
if (currentActivity != null) {
startQRScanner(currentActivity);
}
} else {
if (scanPromise != null) {
scanPromise.reject("PERMISSION_DENIED", "Camera permission was denied");
scanPromise = null;
}
}
}
}
}

View File

@@ -0,0 +1,24 @@
package com.proofofpassport;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class QRCodeScannerPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new QRCodeScannerModule(reactContext));
return modules;
}
}

View File

@@ -4,6 +4,11 @@
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
<item name="android:statusBarColor">#F5F5F5</item>
<item name="android:navigationBarColor">#F5F5F5</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowLightNavigationBar">true</item>
<item name="android:windowBackground">#F5F5F5</item>
</style>
</resources>
</resources>

View File

@@ -1,11 +1,11 @@
{
"Deploy_Registry#Formatter": "0x15cAe49aFFD6C9f918BC454A255C05997A74F960",
"Deploy_Registry#PoseidonT3": "0xdfAC8e1AECc55C4c8B8eC55D666A5a5BB8fbAE5c",
"Deploy_Registry#Registry": "0xBabF700EdE592Aa69e14B5BAE1859ee4164C3323",
"Deploy_Registry#Verifier_disclose": "0x36BDB37Ab78feB585B782A734C07D04C4c5A66B4",
"Deploy_Registry#Verifier_dsc_4096": "0x97c7D14A52e1576dADf8a7CCDf92a246aeb0C493",
"Deploy_Registry#Verifier_register_sha1WithRSAEncryption_65537": "0x8392b122Bcbf1eF99dFf1b183C5D4939EDf699A2",
"Deploy_Registry#Verifier_register_sha256WithRSAEncryption_65537": "0x2f5505803a3FCa5322A70A6471C91C34545AEa5D",
"Deploy_Registry#ProofOfPassportRegister": "0xEd7495516a957dD7d378d8A78846646461cFF25f",
"Deploy_Registry#SBT": "0x601Fd54FD11C5E77DE84d877e55B829aff20f0A6"
"Deploy_Registry#Formatter": "0xD73395ad7391a3285d2e2a2259031ED6Eb753a2c",
"Deploy_Registry#PoseidonT3": "0xbc16D1BD4Be33Cff388Bcbd61285b08BDCdeb86C",
"Deploy_Registry#Registry": "0xe2778F3b0302359d947531C2E668b46cFbE97206",
"Deploy_Registry#Verifier_disclose": "0xE2e39e0b823c1290788303094cb75B474899EAf6",
"Deploy_Registry#Verifier_dsc_sha256_rsa_4096": "0xFD3AFBb0E0565cc28E99d9e11629c4c20e1e517D",
"Deploy_Registry#Verifier_register_sha1WithRSAEncryption_65537": "0x434547E86530A583137c9990ffb87682F0d5ca48",
"Deploy_Registry#Verifier_register_sha256WithRSAEncryption_65537": "0xDc5e3E81b4b3bC22f79C3a90dbb57EBB9aEdAAfF",
"Deploy_Registry#ProofOfPassportRegister": "0x3F346FFdC5d583e4126AF01A02Ac5b9CdB3f1909",
"Deploy_Registry#SBT": "0x33f41D706587a7AC6c2061B1893e6eb29615822B"
}

41
app/ios/LottieView.swift Normal file
View File

@@ -0,0 +1,41 @@
//
// LottieView.swift
// FreedomTools
//
// Created by Ivan Lele on 27.02.2024.
//
import Lottie
import SwiftUI
struct LottieView: UIViewRepresentable {
var animationFileName: String
let loopMode: LottieLoopMode
func updateUIView(_ uiView: UIViewType, context: Context) {}
func makeUIView(context: Context) -> some UIView {
let view = UIView(frame: .zero)
let animationView = LottieAnimationView(name: animationFileName)
animationView.loopMode = loopMode
animationView.contentMode = .scaleAspectFit
animationView.play()
animationView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(animationView)
NSLayoutConstraint.activate([
animationView.widthAnchor.constraint(equalTo: view.widthAnchor),
animationView.heightAnchor.constraint(equalTo: view.heightAnchor)
])
return view
}
}
#Preview {
LottieView(animationFileName: "passport", loopMode: .loop)
.frame(width: 300)
}

View File

@@ -28,6 +28,8 @@ class MRZScannerModule: NSObject, RCTBridgeModule {
var hostingController: UIHostingController<ScannerWithInstructions>? = nil
var scannerView = QKMRZScannerViewRepresentable()
let lottieView = LottieView(animationFileName: "passport", loopMode: .loop)
scannerView.onScanResult = { scanResult in
let resultDict: [String: Any] = [
"documentNumber": scanResult.documentNumber,
@@ -41,7 +43,7 @@ class MRZScannerModule: NSObject, RCTBridgeModule {
}
// Wrap the scanner view and instruction text in a new SwiftUI view
let scannerWithInstructions = ScannerWithInstructions(scannerView: scannerView)
let scannerWithInstructions = ScannerWithInstructions(scannerView: scannerView, lottieView: lottieView)
hostingController = UIHostingController(rootView: scannerWithInstructions)
rootViewController.present(hostingController!, animated: true, completion: nil)
}
@@ -55,14 +57,29 @@ class MRZScannerModule: NSObject, RCTBridgeModule {
// Define a new SwiftUI view that includes the scanner and instruction text
struct ScannerWithInstructions: View {
var scannerView: QKMRZScannerViewRepresentable
var lottieView: LottieView
var body: some View {
VStack {
scannerView
Text("Avoid glare or reflections during scanning.")
.font(.title3)
.padding()
.multilineTextAlignment(.center)
ZStack {
Color.white.ignoresSafeArea() // This creates a white background for the entire view
VStack {
ZStack {
scannerView
.mask {
RoundedRectangle(cornerRadius: 15)
.frame(width: 370, height: 270)
}
lottieView.frame(width: 360, height: 230)
}
.frame(height: 320)
Text("Hold your passport on a flat surface while scanning")
.font(.custom("Inter-Regular", size: 20))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.frame(width: 300)
.padding()
}
}
}
}
}

View File

@@ -41,6 +41,8 @@ target 'ProofOfPassport' do
pod 'NFCPassportReader', git: 'https://github.com/0xturboblitz/NFCPassportReader.git', commit: '310ecb519655d9ed8b1afc5eb490b2f51a4d3595'
pod 'QKMRZScanner'
pod 'RNFS', :path => '../node_modules/react-native-fs'
pod 'lottie-ios'
pod 'SwiftQRScanner', :git => 'https://github.com/vinodiOS/SwiftQRScanner'
use_react_native!(
:path => config[:reactNativePath],
@@ -79,4 +81,4 @@ target 'ProofOfPassport' do
)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
end
end
end

View File

@@ -13,6 +13,7 @@ PODS:
- ReactCommon/turbomodule/core (= 0.72.3)
- fmt (6.2.1)
- glog (0.3.5)
- lottie-ios (4.5.0)
- NFCPassportReader (2.0.3):
- OpenSSL-Universal (= 1.1.1100)
- OpenSSL-Universal (1.1.1100)
@@ -291,10 +292,14 @@ PODS:
- React-jsinspector (0.72.3)
- React-logger (0.72.3):
- glog
- react-native-date-picker (5.0.4):
- React-Core
- react-native-get-random-values (1.11.0):
- React-Core
- react-native-netinfo (11.3.1):
- React-Core
- react-native-nfc-manager (3.15.1):
- React-Core
- React-NativeModulesApple (0.72.3):
- React-callinvoker
- React-Core
@@ -419,6 +424,7 @@ PODS:
- SSZipArchive (~> 2.2)
- SocketRocket (0.6.1)
- SSZipArchive (2.4.3)
- SwiftQRScanner (1.1.6)
- SwiftyTesseract (3.1.3)
- Yoga (1.14.0)
@@ -429,6 +435,7 @@ DEPENDENCIES:
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- lottie-ios
- NFCPassportReader (from `https://github.com/0xturboblitz/NFCPassportReader.git`, commit `310ecb519655d9ed8b1afc5eb490b2f51a4d3595`)
- QKMRZScanner
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
@@ -447,8 +454,10 @@ DEPENDENCIES:
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- react-native-date-picker (from `../node_modules/react-native-date-picker`)
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-nfc-manager (from `../node_modules/react-native-nfc-manager`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
@@ -472,11 +481,13 @@ DEPENDENCIES:
- RNKeychain (from `../node_modules/react-native-keychain`)
- RNSVG (from `../node_modules/react-native-svg`)
- RNZipArchive (from `../node_modules/react-native-zip-archive`)
- SwiftQRScanner (from `https://github.com/vinodiOS/SwiftQRScanner`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
trunk:
- fmt
- lottie-ios
- OpenSSL-Universal
- QKMRZParser
- QKMRZScanner
@@ -530,10 +541,14 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
React-logger:
:path: "../node_modules/react-native/ReactCommon/logger"
react-native-date-picker:
:path: "../node_modules/react-native-date-picker"
react-native-get-random-values:
:path: "../node_modules/react-native-get-random-values"
react-native-netinfo:
:path: "../node_modules/@react-native-community/netinfo"
react-native-nfc-manager:
:path: "../node_modules/react-native-nfc-manager"
React-NativeModulesApple:
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios"
React-perflogger:
@@ -580,6 +595,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-svg"
RNZipArchive:
:path: "../node_modules/react-native-zip-archive"
SwiftQRScanner:
:git: https://github.com/vinodiOS/SwiftQRScanner
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
@@ -587,6 +604,9 @@ CHECKOUT OPTIONS:
NFCPassportReader:
:commit: 310ecb519655d9ed8b1afc5eb490b2f51a4d3595
:git: https://github.com/0xturboblitz/NFCPassportReader.git
SwiftQRScanner:
:commit: fddcabcb431cd6110cea0394660082661dbafa7e
:git: https://github.com/vinodiOS/SwiftQRScanner
SPEC CHECKSUMS:
amplitude-react-native: 43098dfcfe1dcd6f0e9426017258ba79289d7a21
@@ -596,6 +616,7 @@ SPEC CHECKSUMS:
FBReactNativeSpec: c6bd9e179757b3c0ecf815864fae8032377903ef
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
lottie-ios: a881093fab623c467d3bce374367755c272bdd59
NFCPassportReader: a160b80e3df3b5325c13902f90405f5eef7520b3
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
QKMRZParser: 6b419b6f07d6bff6b50429b97de10846dc902c29
@@ -609,15 +630,17 @@ SPEC CHECKSUMS:
React-Core: 8293312ad137ea82fd2c29deb163dbc24aa4e00e
React-CoreModules: 32fab1d62416849a3b6dac6feff9d54e5ddc2d1e
React-cxxreact: 55d0f7cb6b4cc09ba9190797f1da87182d1a2fb6
React-debug: 7e61555c8158126c6cd98c3154381ad3821aaaca
React-debug: 2aafa5b6cea5ab76043c20d72663aa0204e49020
React-jsc: 0db8e8cc2074d979c37ffa7b8d7c914833960497
React-jsi: 58677ff4848ceb6aeb9118fe03448a843ea5e16a
React-jsiexecutor: 2c15ba1bace70177492368d5180b564f165870fd
React-jsinspector: b511447170f561157547bc0bef3f169663860be7
React-logger: c5b527272d5f22eaa09bb3c3a690fee8f237ae95
react-native-date-picker: 6891317e850deae5b53d51355226e07a495aba61
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
react-native-netinfo: bdb108d340cdb41875c9ced535977cac6d2ff321
React-NativeModulesApple: 0438665fc7473be6edc496e823e6ea0b0537b46c
react-native-nfc-manager: 3134770f9afcb586c0ae859e747fda3106ec1f76
React-NativeModulesApple: 1d8e4abb2fc6d80bdd13dcf128ee548804eb4a24
React-perflogger: 6bd153e776e6beed54c56b0847e1220a3ff92ba5
React-RCTActionSheet: c0b62af44e610e69d9a2049a682f5dba4e9dff17
React-RCTAnimation: fe7005136b58f58871cab2f70732343b6e330d30
@@ -631,9 +654,9 @@ SPEC CHECKSUMS:
React-RCTVibration: ea3a68a49873a54ced927c90923fc6932baf344a
React-rncore: 9672a017af4a7da7495d911f0b690cbcae9dd18d
React-runtimeexecutor: 369ae9bb3f83b65201c0c8f7d50b72280b5a1dbc
React-runtimescheduler: ec1066a4f2d1152eb1bc3fb61d69376b3bc0dde0
React-utils: d55ba834beb39f01b0b470ae43478c0a3a024abe
ReactCommon: 68e3a815fbb69af3bb4196e04c6ae7abb306e7a8
React-runtimescheduler: 053752ab29d2747602f81c76d1bd7ede9412ef69
React-utils: d3799712bc7003f1ad6501a37189384bf87c25f1
ReactCommon: e639ff94ef1db3d9dd184decec9b02a6fbcc638e
RNCAsyncStorage: 826b603ae9c0f88b5ac4e956801f755109fa4d5c
RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
@@ -642,9 +665,10 @@ SPEC CHECKSUMS:
RNZipArchive: ef9451b849c45a29509bf44e65b788829ab07801
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
SwiftQRScanner: e85a25f9b843e9231dab89a96e441472fe54a724
SwiftyTesseract: 1f3d96668ae92dc2208d9842c8a59bea9fad2cbb
Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce
PODFILE CHECKSUM: 2e0fb25883367cd333873ac29cbb9f28ba88c30f
PODFILE CHECKSUM: ed2a230fe418418ecb7e6525cb769af59fc9dae2
COCOAPODS: 1.15.2

View File

@@ -26,7 +26,12 @@
165E76BD2B8DC4A00000FA90 /* MRZScannerModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165E76BC2B8DC4A00000FA90 /* MRZScannerModule.swift */; };
165E76BF2B8DC53A0000FA90 /* MRZScannerModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 165E76BE2B8DC53A0000FA90 /* MRZScannerModule.m */; };
165E76C32B8DC8370000FA90 /* ScannerHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165E76C22B8DC8370000FA90 /* ScannerHostingController.swift */; };
1686F0DC2C500F3800841CDE /* QRScannerBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1686F0DB2C500F3800841CDE /* QRScannerBridge.swift */; };
1686F0DE2C500F4F00841CDE /* QRScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1686F0DD2C500F4F00841CDE /* QRScannerViewController.swift */; };
1686F0E02C500FBD00841CDE /* QRScannerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 1686F0DF2C500FBD00841CDE /* QRScannerBridge.m */; };
16E0838A2C4E7AF100CE8DB2 /* LottieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16E083892C4E7AF100CE8DB2 /* LottieView.swift */; };
16E6646E2B8D292500FDD6A0 /* QKMRZScannerViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16E6646D2B8D292500FDD6A0 /* QKMRZScannerViewRepresentable.swift */; };
16E884A52C5BD764003B7125 /* passport.json in Resources */ = {isa = PBXBuildFile; fileRef = 16E884A42C5BD764003B7125 /* passport.json */; };
1BA25F26C91C45F697D55099 /* Inter-ExtraLight.otf in Resources */ = {isa = PBXBuildFile; fileRef = 568162F4DC4B4CDC8B341853 /* Inter-ExtraLight.otf */; };
1D2A11340C7041909B820A90 /* Inter-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = D20EA8C94F544E14AB58E6EB /* Inter-ExtraBold.otf */; };
2CD45EA0A0A94063935CE7D3 /* Inter-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = DF4EC58B331A46F098343757 /* Inter-Regular.otf */; };
@@ -90,7 +95,12 @@
165E76BC2B8DC4A00000FA90 /* MRZScannerModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MRZScannerModule.swift; sourceTree = "<group>"; };
165E76BE2B8DC53A0000FA90 /* MRZScannerModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MRZScannerModule.m; sourceTree = "<group>"; };
165E76C22B8DC8370000FA90 /* ScannerHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScannerHostingController.swift; sourceTree = "<group>"; };
1686F0DB2C500F3800841CDE /* QRScannerBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScannerBridge.swift; sourceTree = "<group>"; };
1686F0DD2C500F4F00841CDE /* QRScannerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScannerViewController.swift; sourceTree = "<group>"; };
1686F0DF2C500FBD00841CDE /* QRScannerBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QRScannerBridge.m; sourceTree = "<group>"; };
16E083892C4E7AF100CE8DB2 /* LottieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LottieView.swift; sourceTree = "<group>"; };
16E6646D2B8D292500FDD6A0 /* QKMRZScannerViewRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QKMRZScannerViewRepresentable.swift; sourceTree = "<group>"; };
16E884A42C5BD764003B7125 /* passport.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = passport.json; sourceTree = "<group>"; };
1CA9D245CD5A439D88F01D4F /* Inter-ThinItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-ThinItalic.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-ThinItalic.otf"; sourceTree = "<group>"; };
22FDF2ADA5789E09558ADB4E /* Pods-ProofOfPassport-ProofOfPassportTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ProofOfPassport-ProofOfPassportTests.release.xcconfig"; path = "Target Support Files/Pods-ProofOfPassport-ProofOfPassportTests/Pods-ProofOfPassport-ProofOfPassportTests.release.xcconfig"; sourceTree = "<group>"; };
2B01EC4981C171CA304E6D2B /* Pods-ProofOfPassport.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ProofOfPassport.release.xcconfig"; path = "Target Support Files/Pods-ProofOfPassport/Pods-ProofOfPassport.release.xcconfig"; sourceTree = "<group>"; };
@@ -156,6 +166,7 @@
13B07FAE1A68108700A75B9A /* ProofOfPassport */ = {
isa = PBXGroup;
children = (
16E884A42C5BD764003B7125 /* passport.json */,
05EDEDC42B52D25D00AA51AD /* Prover.m */,
05EDEDC52B52D25D00AA51AD /* Prover.swift */,
905B700A2A72A5E900AFA232 /* masterList.pem */,
@@ -173,9 +184,13 @@
905B70032A72767800AFA232 /* ProofOfPassport-Bridging-Header.h */,
165E76C22B8DC8370000FA90 /* ScannerHostingController.swift */,
905B70062A72774000AFA232 /* PassportReader.m */,
16E083892C4E7AF100CE8DB2 /* LottieView.swift */,
165E76BC2B8DC4A00000FA90 /* MRZScannerModule.swift */,
165E76BE2B8DC53A0000FA90 /* MRZScannerModule.m */,
16E6646D2B8D292500FDD6A0 /* QKMRZScannerViewRepresentable.swift */,
1686F0DB2C500F3800841CDE /* QRScannerBridge.swift */,
1686F0DF2C500FBD00841CDE /* QRScannerBridge.m */,
1686F0DD2C500F4F00841CDE /* QRScannerViewController.swift */,
);
name = ProofOfPassport;
sourceTree = "<group>";
@@ -383,6 +398,7 @@
37AF1D1302824FFC83B6D1D2 /* Inter-ThinItalic.otf in Resources */,
CC99B59A281C4B6497C14141 /* Luciole-Bold-Italic.ttf in Resources */,
05E2174E2E7E48EB80B9C8D8 /* Luciole-Bold.ttf in Resources */,
16E884A52C5BD764003B7125 /* passport.json in Resources */,
6959CC40713D4D42AA56850D /* Luciole-Regular-Italic.ttf in Resources */,
E4E0715B819049EFACAF2AEE /* Luciole-Regular.ttf in Resources */,
98D6CE33FC02453794D8DB08 /* slkscr.ttf in Resources */,
@@ -523,7 +539,10 @@
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
1686F0DE2C500F4F00841CDE /* QRScannerViewController.swift in Sources */,
1686F0E02C500FBD00841CDE /* QRScannerBridge.m in Sources */,
05EDEDC72B52D25D00AA51AD /* Prover.swift in Sources */,
1686F0DC2C500F3800841CDE /* QRScannerBridge.swift in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
905B70072A72774000AFA232 /* PassportReader.m in Sources */,
16E6646E2B8D292500FDD6A0 /* QKMRZScannerViewRepresentable.swift in Sources */,
@@ -531,6 +550,7 @@
905B70052A72767900AFA232 /* PassportReader.swift in Sources */,
165E76C32B8DC8370000FA90 /* ScannerHostingController.swift in Sources */,
05EDEDC62B52D25D00AA51AD /* Prover.m in Sources */,
16E0838A2C4E7AF100CE8DB2 /* LottieView.swift in Sources */,
165E76BD2B8DC4A00000FA90 /* MRZScannerModule.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -609,7 +629,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 47;
DEVELOPMENT_TEAM = 5B29R5LYHQ;
DEVELOPMENT_TEAM = X53ZR86F22;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -708,6 +728,7 @@
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = ProofOfPassport/Info.plist;
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Needed only if you want to upload QRcodes";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -726,7 +747,7 @@
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = com.warroom.proofofpassport;
PRODUCT_BUNDLE_IDENTIFIER = "com.warroom.proofofpassport-dev";
PRODUCT_NAME = ProofOfPassport;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/ProofOfPassport-Bridging-Header.h";
@@ -744,7 +765,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ProofOfPassport/ProofOfPassport.entitlements;
CURRENT_PROJECT_VERSION = 47;
DEVELOPMENT_TEAM = 5B29R5LYHQ;
DEVELOPMENT_TEAM = X53ZR86F22;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion\"",
@@ -842,6 +863,8 @@
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = ProofOfPassport/Info.plist;
INFOPLIST_KEY_NSDocumentsFolderUsageDescription = "";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Needed only if you want to upload QRcodes";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -859,7 +882,7 @@
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = com.warroom.proofofpassport;
PRODUCT_BUNDLE_IDENTIFIER = "com.warroom.proofofpassport-dev";
PRODUCT_NAME = ProofOfPassport;
SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/ProofOfPassport-Bridging-Header.h";
SWIFT_VERSION = 5.0;

View File

@@ -1,6 +1,8 @@
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTBridge.h>
@implementation AppDelegate
@@ -23,4 +25,4 @@
#endif
}
@end
@end

View File

@@ -51,6 +51,8 @@
<string></string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to allow you to choose passport photos or save generated QR codes.</string>
<key>UIAppFonts</key>
<array>
<string>Inter-Black.otf</string>

File diff suppressed because one or more lines are too long

15
app/ios/QRScannerBridge.m Normal file
View File

@@ -0,0 +1,15 @@
//
// QRScannerBridge.m
// ProofOfPassport
//
// Created by Rémi Colin on 23/07/2024.
//
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(QRScannerBridge, NSObject)
RCT_EXTERN_METHOD(scanQRCode:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
@end

View File

@@ -0,0 +1,30 @@
//
// QRScannerBridge.swift
// ProofOfPassport
//
// Created by Rémi Colin on 23/07/2024.
//
import Foundation
import SwiftQRScanner
import React
@objc(QRScannerBridge)
class QRScannerBridge: NSObject {
@objc
static func requiresMainQueueSetup() -> Bool {
return false
}
@objc
func scanQRCode(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
DispatchQueue.main.async {
let rootViewController = UIApplication.shared.keyWindow?.rootViewController
let qrScannerViewController = QRScannerViewController()
qrScannerViewController.completionHandler = { result in
resolve(result)
}
rootViewController?.present(qrScannerViewController, animated: true, completion: nil)
}
}
}

View File

@@ -0,0 +1,45 @@
//
// QRScannerViewController.swift
// ProofOfPassport
//
// Created by Rémi Colin on 23/07/2024.
//
import Foundation
import UIKit
import SwiftQRScanner
class QRScannerViewController: UIViewController, QRScannerCodeDelegate {
var completionHandler: ((String) -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
var configuration = QRScannerConfiguration()
configuration.cameraImage = UIImage(named: "camera")
configuration.flashOnImage = UIImage(named: "flash-on")
configuration.galleryImage = UIImage(named: "photos")
let scanner = QRCodeScannerController(qrScannerConfiguration: configuration)
scanner.delegate = self
addChild(scanner)
view.addSubview(scanner.view)
scanner.view.frame = view.bounds
scanner.didMove(toParent: self)
}
func qrScanner(_ controller: UIViewController, didScanQRCodeWithResult result: String) {
completionHandler?(result)
dismiss(animated: true, completion: nil)
}
func qrScanner(_ controller: UIViewController, didFailWithError error: QRCodeError) {
print("QR Scanner Error: \(error.localizedDescription)")
dismiss(animated: true, completion: nil)
}
func qrScannerDidCancel(_ controller: UIViewController) {
dismiss(animated: true, completion: nil)
}
}

1134
app/ios/passport.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -14,15 +14,16 @@
"@amplitude/analytics-react-native": "^1.4.7",
"@babel/plugin-transform-private-methods": "^7.23.3",
"@ethersproject/shims": "^5.7.0",
"@proofofpassport/sdk": "^1.5.6",
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-native-community/clipboard": "^1.5.1",
"@react-native-community/netinfo": "^11.3.1",
"@tamagui/colors": "^1.94.3",
"@tamagui/config": "^1.94.3",
"@tamagui/core": "^1.94.3",
"@tamagui/lucide-icons": "^1.94.3",
"@tamagui/toast": "^1.94.3",
"@tamagui/types": "^1.94.3",
"@tamagui/colors": "^1.103.0",
"@tamagui/config": "^1.103.0",
"@tamagui/core": "^1.103.0",
"@tamagui/lucide-icons": "^1.103.0",
"@tamagui/toast": "^1.103.0",
"@tamagui/types": "^1.103.0",
"@zk-kit/imt": "https://gitpkg.now.sh/0xturboblitz/zk-kit/packages/imt?6d417675",
"axios": "^1.6.3",
"body-parser": "^1.20.2",
@@ -40,14 +41,18 @@
"react": "18.2.0",
"react-native": "0.72.3",
"react-native-canvas": "^0.1.39",
"react-native-date-picker": "^5.0.4",
"react-native-dialog": "^9.3.0",
"react-native-fs": "^2.20.0",
"react-native-get-random-values": "^1.11.0",
"react-native-keychain": "^8.2.0",
"react-native-nfc-manager": "^3.15.1",
"react-native-passport-reader": "^1.0.3",
"react-native-svg": "13.4.0",
"react-native-zip-archive": "^6.1.0",
"tamagui": "^1.94.3",
"react-spinners": "^0.14.1",
"socket.io-client": "^4.7.5",
"tamagui": "^1.103.0",
"zustand": "^4.5.2"
},
"devDependencies": {
@@ -76,4 +81,4 @@
"engines": {
"node": ">=16"
}
}
}

View File

@@ -1,4 +1,4 @@
import { AppType } from "../utils/appType";
import { AppType } from "../../../common/src/utils/appType";
import { Text, YStack } from 'tamagui';
import { Coins } from '@tamagui/lucide-icons';
import GITCOIN from '../images/gitcoin.png';

View File

@@ -1,4 +1,4 @@
import { AppType } from "../utils/appType";
import { AppType } from "../../../common/src/utils/appType";
import { Flame } from '@tamagui/lucide-icons';
import { Text, XStack, YStack } from 'tamagui';
import { generateProof } from "../utils/prover";
@@ -159,7 +159,7 @@ export const sbtApp: AppType = {
const end = Date.now();
console.log('Total proof time from frontend:', end - start);
amplitude.track('Proof generation successful, took ' + ((end - start) / 1000) + ' seconds');
//amplitude.track('Proof generation successful, took ' + ((end - start) / 1000) + ' seconds');
update({
proof: proof,
proofTime: end - start,
@@ -174,7 +174,7 @@ export const sbtApp: AppType = {
},
})
setStep(Steps.NEXT_SCREEN);
amplitude.track(error.message);
//amplitude.track(error.message);
}
},
@@ -269,7 +269,7 @@ export const sbtApp: AppType = {
console.log('Failed to parse blockchain error');
}
}
amplitude.track(error.message);
//amplitude.track(error.message);
}
}
}

View File

@@ -1,4 +1,4 @@
import { AppType } from "../utils/appType";
import { AppType } from "../../../common/src/utils/appType";
import { Text, YStack } from 'tamagui';
import { Ticket } from '@tamagui/lucide-icons';
import ZUPASS from '../images/zupass.png';

View File

@@ -0,0 +1,116 @@
import React, { useState } from 'react'
import { AnimatePresence } from '@tamagui/animate-presence'
import { ArrowLeft, ArrowRight, Nfc, ShieldCheck } from '@tamagui/lucide-icons'
import { Button, Image, XStack, YStack, styled, Text } from 'tamagui'
import { bgBlue, bgGreen, borderColor, textBlack, textColor1, textColor2 } from '../utils/colors'
import CustomButton from './CustomButton'
const GalleryItem = styled(YStack, {
zIndex: 1,
x: 0,
opacity: 1,
fullscreen: true,
variants: {
going: {
':number': (going) => ({
enterStyle: {
x: going > 0 ? 1000 : -1000,
opacity: 0,
},
exitStyle: {
zIndex: 0,
x: going < 0 ? 1000 : -1000,
opacity: 0,
},
}),
},
} as const,
})
const wrap = (min: number, max: number, v: number) => {
const rangeSize = max - min
return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min
}
interface CarouselProps {
images: string[];
height?: number;
onSlideChange?: (index: number) => void;
handleNfcScan?: () => void;
}
export function Carousel({ images, height = 300, onSlideChange, handleNfcScan }: CarouselProps) {
const [[page, going], setPage] = useState([0, 0])
const imageIndex = wrap(0, images.length, page)
const paginate = (going: number) => {
const newPage = page + going
setPage([newPage, going])
onSlideChange?.(newPage)
}
const isLastImage = imageIndex === images.length - 1
const slideTexts = [
{ header: "Follow this guide carefully", subtitle: "", acknowledgment: "I'm ready to start" },
{ header: "Remove your phone case", subtitle: "If your phone does not have a case, you can skip this step.", acknowledgment: "I have removed my phone case" },
{ header: "Open your passport to the last page", subtitle: "", acknowledgment: "I have opened my passport to the last page" },
{ header: "Put your phone on the passport", subtitle: "Press your phone against the last page of the passport as in the image.", acknowledgment: "I have placed my phone on the passport" },
{ header: "Start scanning", subtitle: "Press Start NFC Scan and follow the on-screen instructions.", acknowledgment: "Start scanning" },
]
const currentSlide = slideTexts[imageIndex] || { header: "No header", subtitle: "No subtitle for this slide", acknowledgment: "Continue" }
return (
<YStack f={1} >
<XStack
overflow="hidden"
backgroundColor="#000"
position="relative"
height={height}
alignItems="center"
borderRadius="$10"
mt="$5"
>
<AnimatePresence initial={false} custom={{ going }}>
<GalleryItem key={page} animation="medium" going={going}>
<Image source={{ uri: images[imageIndex] }} height={height} resizeMode="contain" />
</GalleryItem>
</AnimatePresence>
{imageIndex > 0 && (
<Button
icon={ArrowLeft}
size="$5"
position="absolute"
left="$4"
circular
elevate
onPress={() => paginate(-1)}
zi={100}
/>
)}
</XStack>
<YStack ml="$2">
<Text fontSize="$8" mt="$4" color={textBlack} textAlign='center'>{currentSlide.header}</Text>
<Text color={textBlack} fontSize="$5" mt="$2" textAlign='center' style={{ opacity: 0.7 }} fontStyle='italic'>{currentSlide.subtitle}</Text>
</YStack>
<XStack justifyContent='center' alignItems='center' gap="$1.5" position="absolute" style={{ bottom: 120, left: 0, right: 0 }}>
<ShieldCheck color={textBlack} size={14} />
<Text color={textBlack} fontSize="$4" >private and secured</Text>
</XStack>
<XStack f={1} />
<CustomButton
onPress={isLastImage ? () => handleNfcScan?.() : () => paginate(+1)}
text={currentSlide.acknowledgment}
Icon={isLastImage ? <Nfc /> : undefined}
blueVariant={!isLastImage}
/>
</YStack>
)
}

View File

@@ -0,0 +1,32 @@
import React from 'react';
import { Button, Text } from 'tamagui';
import { bgBlue, bgGreen, textBlack } from '../utils/colors';
import useNavigationStore from '../stores/navigationStore';
interface CustomButtonProps {
text: string;
onPress: () => void;
Icon?: React.ReactNode;
bgColor?: string;
h?: string;
isDisabled?: boolean;
disabledOnPress?: () => void;
blueVariant?: boolean;
}
const CustomButton: React.FC<CustomButtonProps> = ({ text, onPress, Icon, bgColor, h, isDisabled, disabledOnPress, blueVariant }) => {
const {
toast,
} = useNavigationStore();
return (
<Button bg={bgColor ? bgColor : blueVariant ? bgBlue : bgGreen} h={blueVariant ? "$8" : "$4.5"} borderRadius="$10" mx="$3" onPress={isDisabled ? disabledOnPress : onPress}>
{Icon && <Button.Icon>{Icon}</Button.Icon>}
<Text textAlign='center' fontSize={blueVariant ? "$6" : "$5"} fontWeight="bold" color={textBlack}>
{text}
</Text>
</Button>
);
};
export default CustomButton;

View File

@@ -0,0 +1,20 @@
import { XStack } from "tamagui";
import { textBlack } from "../utils/colors";
interface StepOneStepTwoProps {
variable: string;
step1: string;
step2: string;
}
const StepOneStepTwo = ({ variable, step1, step2 }: StepOneStepTwoProps) => {
const isVisible = variable === step1 || variable === step2;
return (
<XStack px="$4" mt="$4" gap="$3" style={{ opacity: isVisible ? 1 : 0 }}>
<XStack h="$0.25" f={1} bg={textBlack} borderRadius={100} style={{ opacity: variable === step1 ? 1 : 0.2 }} />
<XStack h="$0.25" f={1} bg={textBlack} borderRadius={100} style={{ opacity: variable === step2 ? 1 : 0.2 }} />
</XStack>
)
}
export default StepOneStepTwo;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

View File

@@ -0,0 +1,55 @@
import React from 'react';
import { ScrollView, YStack } from 'tamagui';
import AppCard from '../components/AppCard';
import { Steps } from '../utils/utils';
import useNavigationStore from '../stores/navigationStore';
import { AppType } from '../../../common/src/utils/appType';
import sbtApp from '../apps/sbt';
import zupassApp from '../apps/zupass';
import gitcoinApp from '../apps/gitcoin';
const AppScreen: React.FC = () => {
const {
selectedApp,
update
} = useNavigationStore();
const handleCardSelect = (app: AppType) => {
update({
selectedTab: "prove",
selectedApp: app,
step: Steps.APP_SELECTED,
})
};
// add new apps here
const cardsData = [
sbtApp,
zupassApp,
gitcoinApp
];
return (
<ScrollView f={1}>
<YStack my="$8" gap="$5" px="$5" jc="center" alignItems='center'>
{
cardsData.map(app => (
<AppCard
key={app.id}
title={app.title}
description={app.description}
id={app.id}
onTouchStart={() => handleCardSelect(app)}
selected={selectedApp && selectedApp.id === app.id ? true : false}
selectable={app.selectable}
icon={app.icon}
tags={app.tags}
/>
))
}
</YStack>
</ScrollView>
);
}
export default AppScreen;

View File

@@ -1,19 +1,41 @@
import React from 'react';
import { ScrollView, YStack } from 'tamagui';
import { ScrollView, Text, YStack } from 'tamagui';
import AppCard from '../components/AppCard';
import { Steps } from '../utils/utils';
import useNavigationStore from '../stores/navigationStore';
import { AppType } from '../utils/appType';
import { AppType, createAppType } from '../../../common/src/utils/appType';
import sbtApp from '../apps/sbt';
import zupassApp from '../apps/zupass';
import gitcoinApp from '../apps/gitcoin';
import { XStack } from 'tamagui';
import CustomButton from '../components/CustomButton';
import { BadgeCheck, Binary, LayoutGrid, List, LockKeyhole, QrCode, ShieldCheck, Smartphone, UserPlus } from '@tamagui/lucide-icons';
import { bgBlue, bgGreen, separatorColor, textBlack } from '../utils/colors';
import { orange } from '@tamagui/colors';
import useUserStore from '../stores/userStore';
import { Platform } from 'react-native';
import { NativeModules } from 'react-native';
const AppScreen: React.FC = () => {
interface AppScreenProps {
setSheetAppListOpen: (value: boolean) => void;
setSheetRegisterIsOpen: (value: boolean) => void;
}
const AppScreen: React.FC<AppScreenProps> = ({ setSheetAppListOpen, setSheetRegisterIsOpen }) => {
const {
selectedApp,
update
setSelectedApp,
update,
selectedTab,
setSelectedTab,
toast
} = useNavigationStore();
const {
registered,
setRegistered
} = useUserStore();
const handleCardSelect = (app: AppType) => {
update({
selectedTab: "prove",
@@ -22,16 +44,163 @@ const AppScreen: React.FC = () => {
})
};
// add new apps here
const cardsData = [
sbtApp,
zupassApp,
gitcoinApp
];
const scanQRCode = () => {
if (Platform.OS === 'ios') {
if (NativeModules.QRScannerBridge && NativeModules.QRScannerBridge.scanQRCode) {
NativeModules.QRScannerBridge.scanQRCode()
.then((result: string) => {
handleQRCodeScan(result);
})
.catch((error: any) => {
console.error('QR Scanner Error:', error);
toast.show('Error', {
message: 'Failed to scan QR code',
type: 'error',
});
});
} else {
console.error('QR Scanner module not found for iOS');
toast.show('Error', {
message: 'QR Scanner not available',
type: 'error',
});
}
} else if (Platform.OS === 'android') {
if (NativeModules.QRCodeScanner && NativeModules.QRCodeScanner.scanQRCode) {
NativeModules.QRCodeScanner.scanQRCode()
.then((result: string) => {
handleQRCodeScan(result);
})
.catch((error: any) => {
console.error('QR Scanner Error:', error);
toast.show('Error', {
message: 'Failed to scan QR code',
type: 'error',
});
});
} else {
console.error('QR Scanner module not found for Android');
toast.show('Error', {
message: 'QR Scanner not available',
type: 'error',
});
}
}
};
const handleQRCodeScan = (result: string) => {
try {
console.log(result);
const app = createAppType(JSON.parse(result));
console.log(app);
setSelectedApp(app);
setSelectedTab("prove");
} catch (error) {
console.error('Error parsing QR code result:', error);
toast.show('Error', {
message: 'Invalid QR code format',
type: 'error',
});
}
};
return (
<ScrollView f={1}>
<YStack my="$8" gap="$5" px="$5" jc="center" alignItems='center'>
<YStack f={1} pb="$3" px="$3">
{/* <XStack h="$0.25" bg={separatorColor} mx="$0" /> */}
<ScrollView showsVerticalScrollIndicator={true} indicatorStyle="black">
<YStack >
<Text fontSize="$8" mt="$2" >Account</Text>
<XStack ml="$2" gap="$2" ai="center">
<Text fontSize="$5">status:</Text>
{registered ?
<XStack bg={bgGreen} px="$2.5" py="$2" borderRadius="$10">
<Text color={textBlack} fontSize="$4">registered</Text>
</XStack> :
<XStack bg={'#FFB897'} px="$2.5" py="$2" borderRadius="$10">
<Text color={textBlack} fontSize="$4">not registered</Text>
</XStack>}
</XStack>
{/* <XStack ml="$2" gap="$2" mt="$1">
<Text fontSize="$5">userID:</Text>
<Text color={textBlack} fontSize="$5">0x1234567890</Text>
</XStack> */}
</YStack>
<YStack>
<Text mt="$4" fontSize="$8" >How to use Proof of Passport?</Text>
<YStack>
<XStack mt="$3" px="$5" gap="$2" >
<QrCode size={50} color={textBlack} />
<YStack>
<Text fontSize="$5" mb="$1">Scan QR code</Text>
<XStack gap="$2"><Text fontSize="$3">1</Text><Text fontSize="$3" maxWidth={220}>Find the QR code on the page of the app that asks for proof of passport.</Text></XStack>
<XStack mt="$1" gap="$2"><Text fontSize="$3">2</Text><Text fontSize="$3" maxWidth={220}>Scan the QR code.</Text></XStack>
</YStack>
</XStack>
<XStack mt="$4" px="$5" gap="$2" >
<BadgeCheck size={50} color={textBlack} />
<YStack>
<Text fontSize="$5" mb="$1">Generate a Proof</Text>
<XStack gap="$2"><Text fontSize="$3">1</Text><Text fontSize="$3" maxWidth={220}>Generate a proof of the selected information.</Text></XStack>
<XStack mt="$1" gap="$2"><Text fontSize="$3">2</Text><Text fontSize="$3" maxWidth={220}>Share the proof with the application.</Text></XStack>
</YStack>
</XStack>
</YStack>
</YStack>
<YStack mb="$4">
<Text mt="$5" fontSize="$8" >How does it works?</Text>
<YStack>
<XStack mt="$3" px="$5" gap="$2" >
<Binary size={50} color={textBlack} />
<YStack>
<Text fontSize="$5" mb="$1">Strong cryptography</Text>
<XStack gap="$2"><Text fontSize="$3">·</Text><Text fontSize="$3" maxWidth={220}>Proof of Passport uses ZK technologies which allows you to prove a statement without revealing why it's true.</Text></XStack>
<XStack gap="$2"><Text fontSize="$3">·</Text><Text fontSize="$3" maxWidth={220}>You are always anonymous</Text></XStack>
</YStack>
</XStack>
<XStack mt="$3" px="$5" gap="$2" >
<Smartphone size={50} color={textBlack} />
<YStack>
<Text fontSize="$5" mb="$1">Serverless</Text>
<XStack gap="$2"><Text fontSize="$3">·</Text><Text fontSize="$3" maxWidth={220}>Proof of Passport will never receive your data and will never know who you are.</Text></XStack>
<XStack gap="$2"><Text fontSize="$3">·</Text><Text fontSize="$3" maxWidth={220}>Everything is achieved on your device, even the camera and NFC scanning.</Text></XStack>
</YStack>
</XStack>
</YStack>
</YStack>
</ScrollView>
<XStack f={1} minHeight="$1" />
<YStack gap="$2.5">
<CustomButton
text="Scan QR Code"
onPress={() => {
if (registered) {
scanQRCode();
} else {
setSheetRegisterIsOpen(true);
}
}}
Icon={<QrCode size={18} color={textBlack} />}
/>
<CustomButton bgColor='white' text="Open app list" onPress={
registered ?
() => setSheetAppListOpen(true)
:
() => setSheetRegisterIsOpen(true)} Icon={<List size={18} color={textBlack} />} />
</YStack>
{/* <YStack my="$8" gap="$5" px="$5" jc="center" alignItems='center'>
{
cardsData.map(app => (
<AppCard
@@ -47,9 +216,9 @@ const AppScreen: React.FC = () => {
/>
))
}
</YStack>
</ScrollView>
</YStack> */}
</YStack>
);
}
export default AppScreen;
export default AppScreen;

View File

@@ -1,9 +1,10 @@
import React from 'react';
import { YStack, Button, Image, Text } from 'tamagui';
import { Camera, SquarePen } from '@tamagui/lucide-icons';
import { bgColor, borderColor, textColor1, textColor2 } from '../utils/colors';
import { YStack, Button, Image, Text, ScrollView, XStack, Separator } from 'tamagui';
import { Camera, ShieldCheck, SquarePen, X } from '@tamagui/lucide-icons';
import { bgColor, bgGreen, borderColor, componentBgColor, componentBgColor2, separatorColor, textBlack, textColor1, textColor2 } from '../utils/colors';
import SCANHelp from '../images/scan_help.png'
import { startCameraScan } from '../utils/cameraScanner';
import CustomButton from '../components/CustomButton';
interface CameraScreenProps {
sheetIsOpen: boolean
@@ -11,30 +12,31 @@ interface CameraScreenProps {
}
const CameraScreen: React.FC<CameraScreenProps> = ({ sheetIsOpen, setSheetIsOpen }) => {
return (
<YStack f={1} p="$3">
<YStack f={1} jc="center">
<Image borderRadius="$5"
<YStack f={1} mt="$16">
<Text ml="$1" fontSize={34} color={textBlack}><Text style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>Scan</Text> or type your passport ID</Text>
<Text ml="$2" mt="$8" fontSize="$8" color={textBlack}>Open your passport on the <Text style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>main page</Text> to scan it.</Text>
<Text ml="$2" mt="$2" fontSize="$8" color={textBlack} style={{ opacity: 0.7 }}>Your data never leaves your device.</Text>
<XStack f={1} />
<XStack justifyContent='center' alignItems='center' gap="$1.5">
<ShieldCheck color={textBlack} size={14} />
<Text color={textBlack} fontSize="$4">private and secured</Text>
</XStack>
</YStack>
{/* <Image borderRadius="$5"
w="full"
h="$13"
source={{ uri: SCANHelp }}
/>
<YStack gap="$0.5" mt="$3.5">
<Text mt="$1" color={textColor1}>Use your camera to scan the main page of your passport.</Text>
<Text fontSize="$2" color={textColor2} mt="$2">You can also enter those data manually.</Text>
<Text fontSize="$2" style={{ fontStyle: 'italic' }} color={textColor2}>The app does not take a picture of your passport, it only reads some fields.</Text>
</YStack>
/> */}
<YStack gap="$2.5" mt="$5" >
<CustomButton text="Open Camera" onPress={startCameraScan} Icon={<Camera color={textBlack} size={24} />} />
<CustomButton bgColor='#ffff' text="Manual Input" onPress={() => setSheetIsOpen(true)} Icon={<SquarePen color={textBlack} size={24} />} />
</YStack>
<YStack gap="$2" mb="$6">
<Button borderWidth={1.3} borderColor={borderColor} borderRadius="$10" bg="#3185FC" onPress={startCameraScan}><Camera color={textColor1} /></Button>
<Button bg={textColor2} borderColor={borderColor} borderRadius="$10" onPress={() => setSheetIsOpen(true)}><SquarePen /></Button>
</YStack>
</YStack >
</YStack>
);
};
export default CameraScreen;
export default CameraScreen;

View File

@@ -4,9 +4,9 @@ import forge from 'node-forge';
import Dialog from "react-native-dialog";
import { ethers } from 'ethers';
// import ressources
import { YStack, XStack, Text, Button, Tabs, Sheet, Label, Fieldset, Input, Switch, H2, Image, useWindowDimensions, H4, H3 } from 'tamagui'
import { HelpCircle, IterationCw, VenetianMask, Cog, CheckCircle2, ChevronLeft, Share, Eraser } from '@tamagui/lucide-icons';
import X from '../images/x.png'
import { YStack, XStack, Text, Button, Tabs, Sheet, Label, Fieldset, Input, Switch, H2, Image, useWindowDimensions, H4, H3, Separator } from 'tamagui'
import { HelpCircle, IterationCw, VenetianMask, Cog, CheckCircle2, ChevronLeft, Share, Eraser, CalendarSearch, Cross, X, UserPlus, Wifi } from '@tamagui/lucide-icons';
import Xlogo from '../images/x.png'
import Telegram from '../images/telegram.png'
import Github from '../images/github.png'
import Internet from "../images/internet.png"
@@ -17,7 +17,7 @@ import { ToastMessage } from '../components/ToastMessage';
import useUserStore from '../stores/userStore';
import useNavigationStore from '../stores/navigationStore';
// import utils
import { bgColor, blueColorLight, borderColor, componentBgColor, textColor1, textColor2 } from '../utils/colors';
import { bgColor, bgGreen, bgWhite, blueColorLight, borderColor, componentBgColor, componentBgColor2, separatorColor, textBlack, textColor1, textColor2 } from '../utils/colors';
import { ModalProofSteps, Steps } from '../utils/utils';
import { scan } from '../utils/nfcScanner';
import { CircuitName, fetchZkey } from '../utils/zkeyDownload';
@@ -40,6 +40,13 @@ import AppScreen from './AppScreen';
import { RPC_URL, SignatureAlgorithm } from '../../../common/src/constants/constants';
import { mock_csca_sha256_rsa_4096, mock_dsc_sha256_rsa_4096 } from '../../../common/src/constants/mockCertificates';
import DatePicker from 'react-native-date-picker'
import StartScreen from './StartScreen';
import CustomButton from '../components/CustomButton';
import StepOneStepTwo from '../components/StepOneStepTwo';
import SplashScreen from './SplashScreen';
import ValidProofScreen from './ValidProofScreen';
import WrongProofScreen from './WrongProofScreen';
const MainScreen: React.FC = () => {
const [NFCScanIsOpen, setNFCScanIsOpen] = useState(false);
@@ -49,7 +56,14 @@ const MainScreen: React.FC = () => {
const [dialogDeleteSecretIsOpen, setDialogDeleteSecretIsOpen] = useState(false);
const [HelpIsOpen, setHelpIsOpen] = useState(false);
const [sheetIsOpen, setSheetIsOpen] = useState(false);
const [sheetAppListOpen, setSheetAppListOpen] = useState(false);
const [sheetRegisterIsOpen, setSheetRegisterIsOpen] = useState(false);
const [modalProofStep, setModalProofStep] = useState(0);
const [dateOfBirthDatePicker, setDateOfBirthDatePicker] = useState<Date | null>(null)
const [dateOfExpiryDatePicker, setDateOfExpiryDatePicker] = useState<Date | null>(null)
const [dateOfBirthDatePickerIsOpen, setDateOfBirthDatePickerIsOpen] = useState(false)
const [dateOfExpiryDatePickerIsOpen, setDateOfExpiryDatePickerIsOpen] = useState(false)
const [isFormComplete, setIsFormComplete] = useState(false);
const {
passportNumber,
@@ -73,16 +87,18 @@ const MainScreen: React.FC = () => {
step,
setStep,
selectedTab,
setSelectedTab,
hideData,
toast,
showRegistrationErrorSheet,
registrationErrorMessage,
nfcSheetIsOpen,
setNfcSheetIsOpen,
} = useNavigationStore();
const handleRestart = () => {
updateNavigationStore({
selectedTab: "scan",
selectedApp: null,
selectedTab: "start",
step: Steps.MRZ_SCAN,
})
deleteMrzFields();
@@ -120,7 +136,6 @@ const MainScreen: React.FC = () => {
useUserStore.getState().setDscSecret(secret);
}
const inputs_csca = getCSCAInputs(
secret,
dscCert,
@@ -136,12 +151,19 @@ const MainScreen: React.FC = () => {
toast.show("Using mock passport data!", { type: "info" })
}
const castDate = (date: Date) => {
return (date.toISOString().slice(2, 4) + date.toISOString().slice(5, 7) + date.toISOString().slice(8, 10)).toString();
}
const decrementStep = () => {
if (selectedTab === "nfc") {
setStep(Steps.MRZ_SCAN);
if (selectedTab === "scan") {
setSelectedTab("start");
}
else if (selectedTab === "nfc") {
setSelectedTab("scan");
}
else if (selectedTab === "next") {
setStep(Steps.MRZ_SCAN_COMPLETED);
setSelectedTab("nfc");
}
else if (selectedTab === "register") {
setStep(Steps.NEXT_SCREEN);
@@ -196,6 +218,7 @@ const MainScreen: React.FC = () => {
throw new Error("Transaction failed");
}
setRegistered(true);
setSelectedTab("app");
setStep(Steps.REGISTERED);
toast.show('✅', {
message: "Registered",
@@ -210,88 +233,117 @@ const MainScreen: React.FC = () => {
}
}, [modalProofStep]);
useEffect(() => {
if (passportNumber?.length === 9 && (dateOfBirth?.length === 6 && dateOfExpiry?.length === 6)) {
setStep(Steps.MRZ_SCAN_COMPLETED);
}
setIsFormComplete(passportNumber?.length === 9 && dateOfBirth?.length === 6 && dateOfExpiry?.length === 6);
}, [passportNumber, dateOfBirth, dateOfExpiry]);
useEffect(() => {
if (registered && step < Steps.REGISTERED) {
setStep(Steps.REGISTERED);
}
}, [registered]);
// useEffect(() => {
// if (registered && step < Steps.REGISTERED) {
// setStep(Steps.REGISTERED);
// }
// }, [registered]);
useEffect(() => {
let timeoutId: ReturnType<typeof setTimeout>;
if (step == Steps.MRZ_SCAN) {
updateNavigationStore({
selectedTab: "scan",
})
timeoutId = setTimeout(() => {
setNFCScanIsOpen(false);
}, 0);
}
else if (step == Steps.MRZ_SCAN_COMPLETED) {
updateNavigationStore({
selectedTab: "nfc",
})
timeoutId = setTimeout(() => {
setNFCScanIsOpen(false);
}, 0);
}
else if (step == Steps.NEXT_SCREEN) {
// Set the timeout and store its ID
timeoutId = setTimeout(() => {
setNFCScanIsOpen(false);
}, 700);
}
else if (step == Steps.PROOF_GENERATED) {
updateNavigationStore({
selectedTab: "mint",
})
}
if (step == Steps.NEXT_SCREEN) {
updateNavigationStore({
selectedTab: "next",
})
}
if (step == Steps.REGISTER) {
updateNavigationStore({
selectedTab: "register",
})
}
if (step == Steps.REGISTERED) {
updateNavigationStore({
selectedTab: "app",
})
}
return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
};
}, [step]);
// useEffect(() => {
// let timeoutId: ReturnType<typeof setTimeout>;
// if (step == Steps.START) {
// updateNavigationStore({
// selectedTab: "start",
// })
// }
// if (step == Steps.MRZ_SCAN) {
// updateNavigationStore({
// selectedTab: "scan",
// })
// timeoutId = setTimeout(() => {
// setNFCScanIsOpen(false);
// }, 0);
// }
// else if (step == Steps.MRZ_SCAN_COMPLETED) {
// updateNavigationStore({
// selectedTab: "nfc",
// })
// timeoutId = setTimeout(() => {
// setNFCScanIsOpen(false);
// }, 0);
// }
// else if (step == Steps.NEXT_SCREEN) {
// // Set the timeout and store its ID
// timeoutId = setTimeout(() => {
// setNFCScanIsOpen(false);
// }, 700);
// }
// else if (step == Steps.PROOF_GENERATED) {
// updateNavigationStore({
// selectedTab: "mint",
// })
// }
// if (step == Steps.NEXT_SCREEN) {
// updateNavigationStore({
// selectedTab: "next",
// })
// }
// if (step == Steps.REGISTER) {
// updateNavigationStore({
// selectedTab: "register",
// })
// }
// if (step == Steps.REGISTERED) {
// updateNavigationStore({
// selectedTab: "app",
// })
// }
// return () => {
// if (timeoutId) {
// clearTimeout(timeoutId);
// }
// };
// }, [step]);
const { height } = useWindowDimensions();
return (
<>
<YStack f={1} bc="#161616" mt={Platform.OS === 'ios' ? "$8" : "$0"} >
<YStack f={1}>
<ToastViewport portalToRoot flexDirection="column-reverse" top={85} right={0} left={0} />
<ToastMessage />
<YStack f={1} mt={Platform.OS === 'ios' ? "$8" : "$0"} mb={Platform.OS === 'ios' ? "$4" : "$2"}>
<YStack >
<XStack jc="space-between" ai="center" px="$3">
<Button p="$2" py="$3" unstyled onPress={decrementStep}><ChevronLeft color={(selectedTab === "scan") ? "transparent" : "#a0a0a0"} /></Button>
<StepOneStepTwo variable={selectedTab} step1="scan" step2="nfc" />
{selectedTab !== ("app") && selectedTab !== ("splash") && <XStack onPress={() => setSelectedTab("app")} px="$4" py="$2" mt="$3" alignSelf='flex-end'><X size={28} color={textBlack} /></XStack>}
{selectedTab === "app" &&
<XStack px="$4" py="$2" mt="$0" ai="center">
<Text fontSize="$9" >Proof of Passport</Text>
<XStack f={1} />
<Text fontSize="$6" color="#a0a0a0">
{selectedTab === "scan" ? "Scan" : (selectedTab === "app" ? "Apps" : "Prove")}
</Text>
<XStack>
<Button p="$2" py="$3" unstyled onPress={() => setSettingsIsOpen(true)}><Cog color="#a0a0a0" /></Button>
<Button p="$2" py="$3" unstyled onPress={() => setHelpIsOpen(true)}><HelpCircle color="#a0a0a0" /></Button>
<XStack onPress={() => setHelpIsOpen(true)}><HelpCircle size={28} color={textBlack} /></XStack>
<XStack p="$2" onPress={() => setSettingsIsOpen(true)}><Cog size={24} color={textBlack} /></XStack>
</XStack>
</XStack>
<Sheet open={NFCScanIsOpen} onOpenChange={setNFCScanIsOpen} dismissOnSnapToBottom modal dismissOnOverlayPress={false} disableDrag animation="medium" snapPoints={[35]}>
}
{/* {selectedTab !== "start" && selectedTab !== "scan" && selectedTab !== "nfc" && selectedTab !== "next" && selectedTab !== "register" && (
<YStack>
<XStack jc="space-between" ai="center" px="$3">
<Button p="$2" py="$3" unstyled onPress={decrementStep}><ChevronLeft color={(selectedTab === "start") ? "transparent" : "#a0a0a0"} /></Button>
<Text fontSize="$6" color="#a0a0a0">
{selectedTab === "scan" ? "Scan" : (selectedTab === "app" ? "Apps" : "Prove")}
</Text>
<XStack>
<Button p="$2" py="$3" unstyled onPress={() => setSettingsIsOpen(true)}><Cog color="#a0a0a0" /></Button>
<Button p="$2" py="$3" unstyled onPress={() => setHelpIsOpen(true)}><HelpCircle color="#a0a0a0" /></Button>
</XStack>
</XStack>
<Separator borderColor={separatorColor} />
</YStack>
)} */}
<Sheet open={nfcSheetIsOpen} onOpenChange={setNfcSheetIsOpen} dismissOnSnapToBottom modal dismissOnOverlayPress={false} disableDrag animation="medium" snapPoints={[35]}>
<Sheet.Overlay />
<Sheet.Frame>
<YStack gap="$5" f={1} pt="$3">
@@ -421,6 +473,16 @@ const MainScreen: React.FC = () => {
<Eraser color={textColor2} />
</Button>
</Fieldset>
<Fieldset gap="$4" mt="$1" horizontal>
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="skip" >
registered = (!registered)
</Label>
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={() => setRegistered(!registered)}>
<UserPlus color={textColor2} />
</Button>
</Fieldset>
</>
)}
@@ -436,85 +498,91 @@ const MainScreen: React.FC = () => {
</Sheet.Frame>
</Sheet>
<Sheet open={HelpIsOpen} onOpenChange={setHelpIsOpen} dismissOnSnapToBottom modal animation="medium" snapPoints={[88]}>
<Sheet open={HelpIsOpen} onOpenChange={setHelpIsOpen} dismissOnSnapToBottom modal animation="medium" snapPoints={[76]}>
<Sheet.Overlay />
<Sheet.Frame bg={bgColor} borderRadius="$9">
<YStack px="$3" pb="$5" flex={1} >
<XStack ml="$2" mt="$3" gap="$2">
<H2 color={textColor1}>Help</H2>
<HelpCircle color={textColor1} mt="$1" alignSelf='center' size="$2" />
<XStack justifyContent="flex-end" f={1} mt="$2" mr="$2" gap="$5">
<Pressable onPress={() => Linking.openURL('https://proofofpassport.com')}>
<Image
source={{ uri: Internet, width: 24, height: 24 }}
/>
</Pressable>
<Pressable onPress={() => Linking.openURL('https://t.me/proofofpassport')}>
<Image
source={{ uri: Telegram, width: 24, height: 24 }}
/>
</Pressable>
<Pressable onPress={() => Linking.openURL('https://x.com/proofofpassport')}>
<Image
source={{ uri: X, width: 24, height: 24 }}
/>
</Pressable>
<Pressable onPress={() => Linking.openURL('https://github.com/zk-passport/proof-of-passport')}>
<Image
tintColor={textColor1}
source={{ uri: Github, width: 24, height: 24 }}
/>
</Pressable>
<Sheet.Frame bg={bgWhite} borderTopLeftRadius="$9" borderTopRightRadius="$9" pt="$2" pb="$3">
<YStack p="$4" f={1} gap="$3">
<XStack>
<Text fontSize="$8" mb="$2">Help 💁</Text>
<XStack f={1} />
<XStack onPress={() => setHelpIsOpen(false)} p="$2">
<X color={borderColor} size="$1.5" mr="$2" />
</XStack>
</XStack>
<YStack flex={1} mt="$3" jc="space-evenly">
<YStack >
<H3 color={textColor1}>Security and Privacy</H3>
<Text color={textColor2} ml="$2" mt="$1">Proof of Passport uses zero-knowledge cryptography to allow you to prove facts about yourself like humanity, nationality or age without disclosing sensitive information.</Text>
<Separator borderColor={separatorColor} />
<YStack flex={1} jc="space-between">
{/* <YStack >
<H3 color={textBlack}>Security and Privacy</H3>
<Text color={textBlack} ml="$2" mt="$1">Proof of Passport uses zero-knowledge cryptography to allow you to prove facts about yourself like humanity, nationality or age without disclosing sensitive information.</Text>
</YStack>
<YStack >
<H3 color={textColor1}>About ZK Proofs</H3>
<Text color={textColor2} ml="$2" mt="$1">Zero-knowledge proofs rely on mathematical magic tricks to show the validity of some computation without revealing of all its inputs. In our case, the proof shows the passport has not been forged, but allows you to hide sensitive data.</Text>
</YStack>
<H3 color={textBlack}>About ZK Proofs</H3>
<Text color={textBlack} ml="$2" mt="$1">Zero-knowledge proofs rely on mathematical magic tricks to show the validity of some computation without revealing of all its inputs. In our case, the proof shows the passport has not been forged, but allows you to hide sensitive data.</Text>
</YStack> */}
<YStack gap="$1">
<H3 color={textColor1}>FAQ</H3>
<H3 color={textBlack}>FAQ</H3>
<YStack ml="$1">
<H4 color={textColor1}>Troubleshoot NFC scanning</H4>
<Text color={textColor2} ml="$2" >Refer to <Text onPress={() => Linking.openURL('https://zk-passport.github.io/posts/how-to-scan-your-passport-using-nfc/')} color={blueColorLight} style={{ textDecorationLine: 'underline', fontStyle: 'italic' }}>this tutorial</Text> on how to scan your passport using NFC.</Text>
</YStack>
<YStack ml="$1">
<H4 color={textColor1}>My camera is down</H4>
<Text color={textColor2} ml="$2">Go to settings and turn on the broken camera option.</Text>
</YStack>
<YStack ml="$1">
<H4 color={textColor1}>My passport is not supported</H4>
<Text color={textColor2} ml="$2">Please contact us on Telegram, or if you have programming skills, you can easily <Text onPress={() => Linking.openURL('https://t.me/proofofpassport')} color={blueColorLight} style={{ textDecorationLine: 'underline', fontStyle: 'italic' }}>contribute</Text> to the project by adding your signature algorithm.</Text>
<H4 color={textBlack}>My passport is not supported</H4>
<Text color={textBlack} ml="$2">Please contact us on Telegram, or if you have programming skills, you can easily <Text onPress={() => Linking.openURL('https://t.me/proofofpassport')} color={blueColorLight} style={{ textDecorationLine: 'underline', fontStyle: 'italic' }}>contribute</Text> to the project by adding your signature algorithm.</Text>
</YStack>
</YStack>
</YStack>
{/* <Button mt="$3" bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" alignSelf='center' w="80%" onPress={() => setHelpIsOpen(false)}>
<Text color={textColor1} w="80%" textAlign='center' fow="bold">Close</Text>
</Button> */}
<XStack justifyContent="center" mb="$2" gap="$5" mt="$8">
<Pressable onPress={() => Linking.openURL('https://proofofpassport.com')}>
<Image
source={{ uri: Internet, width: 24, height: 24 }}
/>
</Pressable>
<Pressable onPress={() => Linking.openURL('https://t.me/proofofpassport')}>
<Image
source={{ uri: Telegram, width: 24, height: 24 }}
/>
</Pressable>
<Pressable onPress={() => Linking.openURL('https://x.com/proofofpassport')}>
<Image
source={{ uri: Xlogo, width: 24, height: 24 }}
/>
</Pressable>
<Pressable onPress={() => Linking.openURL('https://github.com/zk-passport/proof-of-passport')}>
<Image
tintColor={textBlack}
source={{ uri: Github, width: 24, height: 24 }}
/>
</Pressable>
</XStack>
</YStack>
</Sheet.Frame>
</Sheet>
<Sheet open={sheetIsOpen} onOpenChange={setSheetIsOpen} dismissOnSnapToBottom modal animation="medium" snapPoints={[80]}>
<Sheet open={sheetIsOpen} onOpenChange={setSheetIsOpen} dismissOnSnapToBottom modal animation="medium" snapPoints={[44]} moveOnKeyboardChange>
<Sheet.Overlay />
<Sheet.Frame bg={bgColor} borderRadius="$9" pt="$2">
<Sheet.Frame bg={bgWhite} borderTopLeftRadius="$9" borderTopRightRadius="$9" pt="$2" pb="$3">
<YStack p="$4" f={1} gap="$3">
<Text fontSize="$6" mb="$4" color={textColor1}>Enter your the information manually</Text>
<Fieldset gap="$4" horizontal>
<Text color={textColor1} width={160} justifyContent="flex-end" fontSize="$4">
<XStack>
<Text fontSize="$8" mb="$">Manual input </Text>
<XStack f={1} />
<XStack onPress={() => setSheetIsOpen(false)} p="$2">
<X color={borderColor} size="$1.5" mr="$2" />
</XStack>
</XStack>
<Separator borderColor={separatorColor} />
<Fieldset gap="$4" horizontal mt="$2">
<Text color={textBlack} width={160} justifyContent="flex-end" fontSize="$5">
Passport Number
</Text>
<Input
bg={componentBgColor}
color={textColor1}
bg={bgWhite}
color={textBlack}
h="$3.5"
borderColor={passportNumber?.length === 9 ? "green" : "unset"}
borderColor={passportNumber?.length === 9 ? bgGreen : textBlack}
flex={1}
id="passportnumber"
onChangeText={(text) => {
@@ -524,42 +592,165 @@ const MainScreen: React.FC = () => {
keyboardType="default"
/>
</Fieldset>
<Fieldset gap="$4" horizontal>
<Text color={textColor1} width={160} justifyContent="flex-end" fontSize="$4">
Date of birth (yymmdd)
<Text color={textBlack} width={160} justifyContent="flex-end" fontSize="$5">
Date of birth
</Text>
<Input
bg={componentBgColor}
color={textColor1}
h="$3.5"
borderColor={dateOfBirth?.length === 6 ? "green" : "unset"}
flex={1}
id="dateofbirth"
onChangeText={(text) => {
update({ dateOfBirth: text })
<Text color={textBlack} f={1}>
{dateOfBirthDatePicker ? dateOfBirthDatePicker.toISOString().slice(0, 10) : ''}
</Text>
<Button bg={bgGreen} onPress={() => setDateOfBirthDatePickerIsOpen(true)}
borderRadius={"$10"}
>
<CalendarSearch />
</Button>
<DatePicker
modal
mode='date'
open={dateOfBirthDatePickerIsOpen}
date={dateOfBirthDatePicker || new Date()}
onConfirm={(date) => {
setDateOfBirthDatePickerIsOpen(false)
setDateOfBirthDatePicker(date)
update({ dateOfBirth: castDate(date) })
}}
onCancel={() => {
setDateOfBirthDatePickerIsOpen(false)
}}
value={dateOfBirth}
keyboardType={Platform.OS === "ios" ? "default" : "number-pad"}
/>
</Fieldset>
<Fieldset gap="$4" horizontal>
<Text color={textColor1} width={160} justifyContent="flex-end" fontSize="$4">
Date of expiry (yymmdd)
<Text color={textBlack} width={160} justifyContent="flex-end" fontSize="$5">
Date of expiry
</Text>
<Input
bg={componentBgColor}
color={textColor1}
h="$3.5"
borderColor={dateOfExpiry?.length === 6 ? "green" : "unset"}
flex={1}
id="dateofexpiry"
onChangeText={(text) => {
update({ dateOfExpiry: text })
<Text color={textBlack} f={1}>
{dateOfExpiryDatePicker ? dateOfExpiryDatePicker.toISOString().slice(0, 10) : ''}
</Text>
<Button bg={bgGreen} onPress={() => setDateOfExpiryDatePickerIsOpen(true)}
borderRadius="$10"
>
<CalendarSearch />
</Button>
<DatePicker
modal
mode='date'
open={dateOfExpiryDatePickerIsOpen}
date={dateOfExpiryDatePicker || new Date()}
onConfirm={(date) => {
setDateOfExpiryDatePickerIsOpen(false)
setDateOfExpiryDatePicker(date)
update({ dateOfExpiry: castDate(date) })
}}
onCancel={() => {
setDateOfExpiryDatePickerIsOpen(false)
}}
value={dateOfExpiry}
keyboardType={Platform.OS === "ios" ? "default" : "number-pad"}
/>
</Fieldset>
<XStack f={1} />
<YStack gap="$2">
<CustomButton
text="Submit"
onPress={() => {
setSelectedTab("nfc");
setSheetIsOpen(false);
}}
bgColor={isFormComplete ? bgGreen : separatorColor}
isDisabled={!isFormComplete}
disabledOnPress={() => toast.show('✍️', {
message: "Please fill in all fields.",
customData: {
type: "info",
},
})}
/>
</YStack>
</YStack>
</Sheet.Frame>
</Sheet>
<Sheet open={sheetAppListOpen} onOpenChange={setSheetAppListOpen} dismissOnSnapToBottom modal animation="medium" snapPoints={[35]}>
<Sheet.Overlay />
<Sheet.Frame bg={bgWhite} borderTopLeftRadius="$9" borderTopRightRadius="$9" pt="$2" mb="$3">
<YStack p="$4" f={1} gap="$3">
<XStack>
<Text fontSize="$8" mb="$2">Applications</Text>
<XStack f={1} />
<XStack onPress={() => setSheetAppListOpen(false)} p="$2">
<X color={borderColor} size="$1.5" mr="$2" />
</XStack>
</XStack>
<Separator borderColor={separatorColor} />
<XStack f={1} />
<YStack gap="$2">
<CustomButton
text="Zupass"
onPress={() => toast.show('😖', {
message: "Work in progress",
customData: {
type: "info",
},
})}
/>
<CustomButton
text="Gitcoin passport"
onPress={() => toast.show('😖', {
message: "Work in progress",
customData: {
type: "info",
},
})}
/>
<CustomButton
text="SBT"
onPress={() => toast.show('😖', {
message: "Work in progress",
customData: {
type: "info",
},
})}
/>
</YStack>
<XStack f={1} />
</YStack>
</Sheet.Frame>
</Sheet>
<Sheet open={sheetRegisterIsOpen} onOpenChange={setSheetRegisterIsOpen} dismissOnSnapToBottom modal animation="medium" snapPoints={[35]}>
<Sheet.Overlay />
<Sheet.Frame bg={bgWhite} borderTopLeftRadius="$9" borderTopRightRadius="$9" pt="$2" >
<YStack p="$4" f={1} gap="$3">
<XStack>
<Text fontSize="$8" mb="$2">👋 Not registered yet?</Text>
<XStack f={1} />
<XStack onPress={() => setSheetRegisterIsOpen(false)} p="$2">
<X color={borderColor} size="$1.5" mr="$2" />
</XStack>
</XStack>
<Separator borderColor={separatorColor} />
<YStack gap="$2">
<Text fontSize="$7" color={textBlack}>Registering to Proof of Passport does not leak anything about your personal information.</Text>
<Text fontSize="$6" onPress={() => Linking.openURL('https://zk-passport.github.io/posts/how-to-scan-your-passport-using-nfc/')} color={blueColorLight} style={{ textDecorationLine: 'underline', fontStyle: 'italic' }}>Learn more.</Text>
</YStack>
<XStack f={1} />
<YStack gap="$2">
<CustomButton
text="Register"
Icon={<UserPlus color={textBlack} />}
onPress={() => {
setSheetRegisterIsOpen(false);
setSelectedTab("start");
}}
/>
</YStack>
<XStack f={1} />
</YStack>
</Sheet.Frame>
</Sheet>
@@ -574,33 +765,43 @@ const MainScreen: React.FC = () => {
dismissOnSnapToBottom modal animation="medium" snapPoints={[80]}
>
<Sheet.Overlay />
<Sheet.Frame bg={bgColor} borderRadius="$9" pt="$2">
<YStack p="$4" f={1} gap="$3">
<H2 textAlign='center' mb="$6" color={textColor1}>Passport unsupported</H2>
<Text fontSize="$6" mb="$4" color={textColor1}>Unfortunately, your passport is currently not supported. Details:</Text>
<Text fontSize="$6" mb="$4" textAlign="center" color="#a0a0a0">{registrationErrorMessage} </Text>
<Sheet.Frame bg={bgWhite} borderRadius="$9" pt="$2">
<YStack p="$4" f={1} gap="$3" pb="$6">
<YStack jc="flex-start" >
<Text fontSize="$9" textAlign='left' mb="$2" color={textBlack}>Sorry, an error has occurred</Text>
</YStack>
<Text fontSize="$6" mb="$4" color={textColor1}>To help us add support for it, please consider contributing its data!</Text>
<Fieldset gap="$4" mt="$1" horizontal>
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="restart">
Contribute
</Label>
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={() => setDialogContributeIsOpen(true)}>
<Share color={textColor1} />
</Button>
</Fieldset>
<Text fontSize="$7">Error details:</Text>
<Text fontSize="$6" mb="$2" textAlign="center" color="#a0a0a0">{registrationErrorMessage} </Text>
<Separator borderColor={separatorColor} />
<Text mt="$4" fontSize="$6" mb="$4" color={textBlack}>Unfortunately, your passport is currently not supported.</Text>
<Text fontSize="$6" mb="$4" color={textBlack}>To help us add support for it, please consider contributing its data!</Text>
<XStack f={1} />
<CustomButton
text="Contribute"
onPress={() => setDialogContributeIsOpen(true)}
Icon={<Share />}
/>
</YStack>
</Sheet.Frame>
</Sheet>
<XStack bc="#343434" h={1.2} />
</YStack>
<Tabs f={1} orientation="horizontal" flexDirection="column" defaultValue={"scan"}
<Tabs f={1} orientation="horizontal" flexDirection="column" defaultValue={"splash"}
value={selectedTab}
onValueChange={(value) => updateNavigationStore({ selectedTab: value })}
>
<ToastViewport flexDirection="column-reverse" top={15} right={0} left={0} />
<ToastMessage />
<Tabs.Content value="splash" f={1}>
<SplashScreen
/>
</Tabs.Content>
<Tabs.Content value="start" f={1}>
<StartScreen
/>
</Tabs.Content>
<Tabs.Content value="scan" f={1}>
<CameraScreen
sheetIsOpen={sheetIsOpen}
@@ -619,15 +820,27 @@ const MainScreen: React.FC = () => {
<RegisterScreen />
</Tabs.Content>
<Tabs.Content value="app" f={1}>
<AppScreen />
<AppScreen
setSheetAppListOpen={setSheetAppListOpen}
setSheetRegisterIsOpen={setSheetRegisterIsOpen}
/>
</Tabs.Content>
<Tabs.Content value="prove" f={1}>
<ProveScreen />
<ProveScreen
setSheetRegisterIsOpen={setSheetRegisterIsOpen}
/>
</Tabs.Content>
<Tabs.Content value="mint" f={1}>
<SendProofScreen />
</Tabs.Content>
<Tabs.Content value="valid" f={1}>
<ValidProofScreen />
</Tabs.Content>
<Tabs.Content value="wrong" f={1}>
<WrongProofScreen />
</Tabs.Content>
</Tabs>
</YStack>
<Modal visible={showWarningModal.show} animationType="slide" transparent={true}>
<YStack bc="#161616" p={20} ai="center" jc="center" position="absolute" top={0} bottom={0} left={0} right={0}>
@@ -656,7 +869,7 @@ const MainScreen: React.FC = () => {
</YStack>
</YStack>
</Modal>
</>
</YStack >
);
};

View File

@@ -1,20 +1,22 @@
import React from 'react';
import { YStack, XStack, Text, Button, Image, useWindowDimensions, Fieldset } from 'tamagui';
import { Info } from '@tamagui/lucide-icons';
import { ArrowRight, Info } from '@tamagui/lucide-icons';
import { getFirstName, maskString } from '../../utils/utils';
import { attributeToPosition } from '../../../common/src/constants/constants';
import USER from '../images/user.png'
import { borderColor, componentBgColor, textColor1, textColor2 } from '../utils/colors';
import { bgGreen, borderColor, componentBgColor, textBlack, textColor1, textColor2 } from '../utils/colors';
import { Platform } from 'react-native';
import { formatAttribute, Steps } from '../utils/utils';
import useUserStore from '../stores/userStore';
import useNavigationStore from '../stores/navigationStore';
import CustomButton from '../components/CustomButton';
const NextScreen: React.FC = () => {
const {
hideData,
setStep,
setSelectedTab
} = useNavigationStore()
@@ -32,8 +34,8 @@ const NextScreen: React.FC = () => {
const { height } = useWindowDimensions();
return (
<YStack px="$4" f={1} mb={Platform.OS === 'ios' ? "$5" : "$0"}>
<YStack flex={1} mx="$2" gap="$2">
<YStack p="$3" f={1} mb={Platform.OS === 'ios' ? "$5" : "$0"}>
<YStack flex={1} mx="$2" gap="$2" mt="$2">
<YStack alignSelf='center' my="$3">
{hideData
? <Image
@@ -54,17 +56,19 @@ const NextScreen: React.FC = () => {
/>
}
</YStack>
<Text color={textColor1} fontSize="$5" fontWeight="bold">
<Text color={textBlack} fontSize="$8" mt="$8" >
Hi{" "}
{
hideData
? maskString(getFirstName(passportData.mrz))
: getFirstName(passportData.mrz)
}
<Text color={textBlack} fontSize="$8" style={{
textDecorationLine: "underline", textDecorationColor: bgGreen
}}>{
hideData
? maskString(getFirstName(passportData.mrz))
: getFirstName(passportData.mrz)
}</Text>
{" "}👋
</Text>
<YStack gap="$2.5" mt="$2" ml="$2">
<YStack gap="$2" mt="$4" >
{Object.keys(disclosureOptions).map((key) => {
const key_ = key;
const indexes = attributeToPosition[key_ as keyof typeof attributeToPosition];
@@ -74,11 +78,15 @@ const NextScreen: React.FC = () => {
return (
<Fieldset horizontal key={key} gap="$3" alignItems='center'>
<Text color={textColor2} w="$10" justifyContent="flex-end" >
<Text color={textBlack} w="$10" justifyContent="flex-end" fontSize="$5" style={{
opacity: 0.7
}}>
{keyFormatted}:
</Text>
<Text
color={textColor1}
color={textBlack}
fontSize="$5"
>
{hideData ? maskString(mrzAttributeFormatted) : mrzAttributeFormatted}
</Text>
@@ -89,20 +97,15 @@ const NextScreen: React.FC = () => {
</YStack>
<YStack f={1} />
<XStack mt="$6" bg={componentBgColor} borderRadius={100} borderWidth={1} borderColor={borderColor} py="$2.5" px="$3">
<Info alignSelf='center' size={24} color={textColor1} />
<Text ml="$3" pr="$6" fontSize="$3" color={textColor1}>Your information will remain confidential and will not be used or shared without your explicit consent.</Text>
<XStack bg="#ffff" borderRadius={100} py="$2.5" px="$3">
<Info alignSelf='center' size={24} color={textBlack} />
<Text ml="$3" pr="$6" fontSize="$3" color={textBlack}>Your information will remain confidential and will not be used or shared without your explicit consent.</Text>
</XStack>
<Button
mt="$8"
alignSelf='center'
onPress={() => setStep(Steps.REGISTER)}
borderWidth={1.3} borderColor={borderColor} borderRadius="$10" bg="#3185FC"
mb="$6"
w="100%"
>
<Text color="white" fontSize="$5">Next</Text>
</Button>
<YStack f={1} />
<CustomButton onPress={() => setSelectedTab("register")} text="Next" Icon={<ArrowRight color={textBlack} />} />
</YStack >
</YStack >
);

View File

@@ -1,57 +1,100 @@
import React from 'react';
import { YStack, Text, XStack, Button, Image } from 'tamagui';
import { Nfc } from '@tamagui/lucide-icons';
import { blueColorDark, blueColorLight, borderColor, componentBgColor2, greenColorDark, greenColorLight, redColorDark, redColorLight, textColor1, textColor2 } from '../utils/colors';
import NFCHelp from '../images/nfc_help.png'
import React, { useState } from 'react';
import { YStack, Text, XStack, Button, ScrollView } from 'tamagui';
import { Nfc, X } from '@tamagui/lucide-icons';
import { bgGreen, borderColor, textBlack, textColor1 } from '../utils/colors';
import { Carousel } from '../components/Carousel';
import US_PASSPORT from '../images/us-passport.png'
import REMOVE_CASE from '../images/remove_case.png'
import US_PASSPORT_LASTPAGE from '../images/passport_lastpage_graybg.png'
import US_PASSPORT_LASTPAGE_IOS from '../images/passport_lastpage_iphone.png'
import US_PASSPORT_LASTPAGE_ANDROID from '../images/passport_lastpage_android.png'
import PHONE_SCANBUTTON from "../images/phone_scanbutton.png"
import Dialog from "react-native-dialog";
import NfcManager from 'react-native-nfc-manager';
import { Platform, Linking, Dimensions } from 'react-native';
interface NfcScreenProps {
handleNFCScan: () => void;
}
const NfcScreen: React.FC<NfcScreenProps> = ({ handleNFCScan }) => {
const [isLastSlideReached, setIsLastSlideReached] = useState(false);
const [dialogVisible, setDialogVisible] = useState(false);
const [dialogMessage, setDialogMessage] = useState('');
const [isNfcSupported, setIsNfcSupported] = useState(true);
const carouselImages = [US_PASSPORT, REMOVE_CASE, US_PASSPORT_LASTPAGE, Platform.OS === 'ios' ? US_PASSPORT_LASTPAGE_IOS : US_PASSPORT_LASTPAGE_ANDROID, PHONE_SCANBUTTON,];
const windowHeight = Dimensions.get('window').height;
const handleSlideChange = (index: number) => {
if (index === carouselImages.length - 1) {
setIsLastSlideReached(true);
}
};
const openNfcSettings = () => {
if (Platform.OS === 'ios') {
Linking.openURL('App-Prefs:root=General&path=About');
} else {
Linking.sendIntent('android.settings.NFC_SETTINGS');
}
setDialogVisible(false);
};
const checkNfcSupport = async () => {
const isSupported = await NfcManager.isSupported();
if (isSupported) {
const isEnabled = await NfcManager.isEnabled();
if (!isEnabled) {
setDialogMessage('NFC is not enabled. Would you like to enable it in settings?');
setDialogVisible(true);
setIsNfcSupported(true);
return false;
}
return true;
} else {
setDialogMessage("Sorry, your device doesn't seem to have an NFC reader.");
setDialogVisible(true);
setIsNfcSupported(false);
return false;
}
};
const handleNfcScan = async () => {
const nfcSupported = await checkNfcSupport();
if (nfcSupported) {
handleNFCScan();
}
};
return (
<YStack f={1} p="$3">
<Image borderRadius="$5" alignSelf='center'
w="$12"
h="$14"
source={{ uri: NFCHelp }}
/>
<YStack f={1} gap="$2">
<YStack mt="$2">
<Text fontSize="$7" fow="bold" mt="$1" color={textColor1}>Scan the NFC chip in your passport.</Text>
<Text fontSize="$6" color={textColor1} mt="$2">How do I find and scan the NFC chip?</Text>
<YStack ml="$3" gap="$2" mt="$1" >
<XStack gap="$1">
<Text fontSize="$4" color={textColor2}>1.</Text>
<Text fontSize="$4" color={textColor2}>Close your passport and hold the middle of the back cover of your passport to the top of the phoneThe passport should touch the phone.</Text>
<ScrollView flex={1} contentContainerStyle={{ flexGrow: 1 }}>
<YStack f={1} p="$3" >
{/* <Text fontSize="$8" fow="bold" mt="$1.5" mb="$3" color={textColor1} textAlign='center'>Verify your passport using NFC</Text> */}
<Text fontSize="$9" mt="$0" color={textBlack} mb="$4" ml="$2">Verify your passport using <Text fontSize="$9" color={textBlack} style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>NFC</Text></Text>
<Carousel
images={carouselImages}
height={300}
onSlideChange={handleSlideChange}
handleNfcScan={handleNfcScan}
/>
<Dialog.Container visible={dialogVisible}>
<Dialog.Title>NFC Status</Dialog.Title>
<Dialog.Description>
{dialogMessage}
</Dialog.Description>
{isNfcSupported ? (
<XStack>
<XStack f={1} />
<Dialog.Button label="Open Settings" onPress={openNfcSettings} />
</XStack>
<XStack gap="$1">
<Text fontSize="$4" color={textColor2}>2.</Text>
<Text fontSize="$4" color={textColor2}>If that does not work, try using the front cover of your passport.</Text>
</XStack>
<XStack gap="$1">
<Text fontSize="$4" color={textColor2}>3.</Text>
<Text fontSize="$4" color={textColor2}>Move your phone slowly up and down until scanning starts.</Text>
</XStack>
<XStack gap="$1">
<Text fontSize="$4" color={textColor2}>4.</Text>
<Text fontSize="$4" color={textColor2}>Hold your device still when scanning starts.</Text>
</XStack>
</YStack>
</YStack>
) : (
<Dialog.Button label="OK" onPress={() => setDialogVisible(false)} />
)}
</Dialog.Container>
</YStack>
<YStack gap="$2" mb="$6">
<Button borderWidth={1.3} borderColor={borderColor} borderRadius="$10" bg="#3185FC" onPress={handleNFCScan}><Nfc color={textColor1} /></Button>
</YStack>
</YStack >
</ScrollView>
);
};
export default NfcScreen;
export default NfcScreen;

View File

@@ -0,0 +1,31 @@
import React from 'react';
import { YStack, Button, Image, Text, styled } from 'tamagui';
import { Camera, SquarePen, UserPlus } from '@tamagui/lucide-icons';
import { bgColor, borderColor, textBlack, textColor1, textColor2 } from '../utils/colors';
import { Steps } from "../utils/utils";
import CustomButton from '../components/CustomButton';
const NoSkipCarousel: React.FC = () => {
const textStyle = styled(Text, {
fontSize: 20,
fontWeight: 'bold',
color: textBlack,
});
return (
<YStack f={1} p="$3" bg="white">
<YStack f={1} jc="center">
<YStack gap="$0.5" mt="$3.5">
<Text fontSize="$9" mt="$1" >Lorem ipsum doflor siat amet</Text>
<Text fontSize="$2" mt="$2" color={textBlack}>Lorem ipsum dolor sit amet</Text>
</YStack>
</YStack>
<CustomButton text="Let's start" onPress={() => {
console.log("Let's start");
}} />
</YStack >
);
};
export default NoSkipCarousel;

View File

@@ -1,46 +1,177 @@
import React, { useState, useEffect } from 'react';
import { YStack, XStack, Text, Checkbox, Input, Button, Spinner, Image, useWindowDimensions, ScrollView } from 'tamagui';
import { Check, Plus, Minus, PenTool } from '@tamagui/lucide-icons';
import { getFirstName, maskString } from '../../utils/utils';
import { attributeToPosition } from '../../../common/src/constants/constants';
import { YStack, XStack, Text, Input, Button, Spinner, Image, useWindowDimensions, ScrollView, Fieldset } from 'tamagui';
import { Check, CheckCircle, CheckCircle2, Share, } from '@tamagui/lucide-icons';
import { attributeToPosition, DEFAULT_MAJORITY, } from '../../../common/src/constants/constants';
import USER from '../images/user.png'
import { borderColor, componentBgColor, componentBgColor2, textColor1, textColor2 } from '../utils/colors';
import { bgGreen, borderColor, componentBgColor, componentBgColor2, separatorColor, textBlack, textColor1, textColor2 } from '../utils/colors';
import { ethers } from 'ethers';
import { Platform } from 'react-native';
import { formatAttribute, Steps } from '../utils/utils';
import { downloadZkey } from '../utils/zkeyDownload';
import useUserStore from '../stores/userStore';
import useNavigationStore from '../stores/navigationStore';
import { AppType } from '../utils/appType';
import { AppType } from '../../../common/src/utils/appType';
import useSbtStore from '../stores/sbtStore';
import CustomButton from '../components/CustomButton';
import { generateCircuitInputsDisclose } from '../../../common/src/utils/generateInputs';
import { PASSPORT_ATTESTATION_ID } from '../../../common/src/constants/constants';
import axios from 'axios';
import { stringToNumber } from '../../../common/src/utils/utils';
import { revealBitmapFromAttributes } from '../../../common/src/utils/revealBitmap';
import { getTreeFromTracker } from '../../../common/src/utils/pubkeyTree';
import { generateProof } from '../utils/prover';
import io, { Socket } from 'socket.io-client';
export const appStoreMapping = {
'soulbound': useSbtStore,
// Add more app ID to store mappings as needed
};
interface ProveScreenProps {
setSheetRegisterIsOpen: (value: boolean) => void;
}
const ProveScreen: React.FC = () => {
const ProveScreen: React.FC<ProveScreenProps> = ({ setSheetRegisterIsOpen }) => {
const [generatingProof, setGeneratingProof] = useState(false);
const selectedApp = useNavigationStore(state => state.selectedApp) as AppType;
const {
hideData,
isZkeyDownloading,
step,
toast,
setSelectedTab
} = useNavigationStore()
const {
fields,
handleProve,
circuit,
} = selectedApp
secret,
setProofVerificationResult
} = useUserStore()
const useAppStore = appStoreMapping[selectedApp.id as keyof typeof appStoreMapping]
const [proofStatus, setProofStatus] = useState<string>('');
const {
address,
majority,
disclosure,
update
} = useAppStore();
const [socket, setSocket] = useState<Socket | null>(null);
const [isConnecting, setIsConnecting] = useState(false);
const waitForSocketConnection = (socket: Socket): Promise<void> => {
return new Promise((resolve) => {
if (socket.connected) {
resolve();
} else {
socket.once('connect', () => {
resolve();
});
}
});
};
useEffect(() => {
const newSocket = io('https://proofofpassport-merkle-tree.xyz', {
path: '/websocket',
transports: ['websocket'],
query: { sessionId: selectedApp.userId, clientType: 'mobile' }
});
newSocket.on('connect', () => {
console.log('Connected to WebSocket server');
});
newSocket.on('disconnect', () => {
console.log('Disconnected from WebSocket server');
});
newSocket.on('connect_error', (error) => {
console.error('Connection error:', error);
});
newSocket.on('proof_verification_result', (result) => {
console.log('Proof verification result:', result);
setProofVerificationResult(JSON.parse(result));
setProofStatus(`Proof verification result: ${result}`);
console.log("result", result);
setSelectedTab(JSON.parse(result).valid ? "valid" : "wrong");
});
setSocket(newSocket);
return () => {
newSocket.disconnect();
};
}, [selectedApp.userId]);
const handleProve = async () => {
try {
setIsConnecting(true);
setGeneratingProof(true);
if (!socket) {
throw new Error('Socket not initialized');
}
await waitForSocketConnection(socket);
setIsConnecting(false);
setProofStatus('Generating proof...');
socket.emit('proof_generation_start', { sessionId: selectedApp.userId });
const tree = await getTreeFromTracker();
const inputs = generateCircuitInputsDisclose(
secret,
PASSPORT_ATTESTATION_ID,
passportData,
tree as any,
(selectedApp.disclosureOptions && selectedApp.disclosureOptions.older_than) ? selectedApp.disclosureOptions.older_than : DEFAULT_MAJORITY,
revealBitmapFromAttributes(selectedApp.disclosureOptions as any),
selectedApp.scope,
stringToNumber(selectedApp.userId).toString()
);
console.log("inputs", inputs);
const localProof = await generateProof(
selectedApp.circuit,
inputs,
);
setProofStatus('Sending proof to verification...');
// console.log("localProof", localProof);
// Send the proof via WebSocket
const formattedLocalProof = {
proof: {
pi_a: [
localProof.proof.a[0],
localProof.proof.a[1],
"1"
],
pi_b: [
[localProof.proof.b[0][0], localProof.proof.b[0][1]],
[localProof.proof.b[1][0], localProof.proof.b[1][1]],
["1", "0"]
],
pi_c: [
localProof.proof.c[0],
localProof.proof.c[1],
"1"
],
protocol: "groth16",
curve: "bn128"
},
publicSignals: (localProof as any).pub_signals
};
// console.log("formattedLocalProof", formattedLocalProof);
socket.emit('proof_generated', { sessionId: selectedApp.userId, proof: formattedLocalProof });
// Wait for verification result
const verificationResult = await new Promise((resolve) => {
socket.once('proof_verification_result', resolve);
});
setProofStatus(`Proof verification result: ${(verificationResult)}`);
} catch (error) {
console.error('Error in handleProve:', error);
setProofStatus(`Error: ${error || 'An unknown error occurred'}`);
} finally {
setGeneratingProof(false);
setIsConnecting(false);
}
};
const {
registered,
@@ -49,213 +180,81 @@ const ProveScreen: React.FC = () => {
const handleDisclosureChange = (field: string) => {
const requiredOrOptional = selectedApp.disclosureOptions[field as keyof typeof selectedApp.disclosureOptions];
if (requiredOrOptional === 'required') {
return;
}
update({
disclosure: {
...disclosure,
[field]: !disclosure[field as keyof typeof disclosure]
}
});
};
const { height } = useWindowDimensions();
useEffect(() => {
// this already checks if downloading is required
downloadZkey(circuit);
}, [])
const disclosureFieldsToText = (key: string, value: string = "") => {
if (key === 'older_than') {
return `I am older than ${value} years old.`;
}
if (key === 'nationality') {
return `I have a valid passport from ${value}.`;
}
return '';
}
return (
<YStack px="$4" f={1} mb={Platform.OS === 'ios' ? "$5" : "$0"}>
<YStack flex={1} mx="$2" gap="$2">
<YStack alignSelf='center' my="$3">
{hideData
? <Image
w={height > 750 ? 150 : 100}
h={height > 750 ? 190 : 80}
borderRadius={height > 800 ? "$7" : "$6"}
source={{
uri: USER,
}}
/>
: <Image
w={height > 750 ? 150 : 110}
h={height > 750 ? 190 : 130}
borderRadius={height > 750 ? "$7" : "$6"}
source={{
uri: passportData.photoBase64 ?? USER,
}}
/>
}
</YStack>
<Text color={textColor1} fontSize="$5" fontWeight="bold" ml="$2" mb="$1">
Hi{" "}
{
hideData
? maskString(getFirstName(passportData.mrz))
: getFirstName(passportData.mrz)
}
{" "}👋
<YStack f={1} p="$3">
{Object.keys(selectedApp.disclosureOptions as any).length > 0 ? <YStack mt="$4">
<Text fontSize="$9">
<Text fow="bold" style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>{selectedApp.name}</Text> is requesting you to prove the following information.
</Text>
<Text mt="$3" fontSize="$8" color={textBlack} style={{ opacity: 0.9 }}>
{fields.map((Field, index) => (
<Field key={index} />
))}
No <Text style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>other</Text> information than the one selected below will be shared with {selectedApp.name}.
</Text>
</YStack> :
<Text fontSize="$9">
<Text fow="bold" style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>{selectedApp.name}</Text> is requesting you to prove you own a valid passport.
</Text>
}
<YStack f={1} >
<YStack bc="#1c1c1c" borderWidth={1.2} borderColor="#343434" borderRadius="$6">
<YStack p="$3">
<XStack gap="$4" ai="center">
<XStack p="$2" bc="#232323" borderWidth={1.2} borderColor="#343434" borderRadius="$3">
<PenTool color="#a0a0a0" />
</XStack>
<YStack gap="$1">
<XStack gap="$2">
<Text fontSize={16} fow="bold" color="#ededed">Disclose</Text>
</XStack>
<Text color="#a0a0a0">Select what to disclose</Text>
</YStack>
</XStack>
</YStack>
<YStack
gap="$2"
p="$3"
bc="#232323"
borderWidth={1.2}
borderLeftWidth={0}
borderRightWidth={0}
borderBottomWidth={0}
borderColor="#343434"
borderBottomLeftRadius="$6"
borderBottomRightRadius="$6"
>
<ScrollView h={height < 750 ? "$6" : ""} >
{selectedApp && Object.keys(selectedApp.disclosureOptions).map((key) => {
const key_ = key;
const indexes = attributeToPosition[key_ as keyof typeof attributeToPosition];
const keyFormatted = key_.replace(/_/g, ' ').split(' ').map((word: string) => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
const mrzAttribute = passportData.mrz.slice(indexes[0], indexes[1] + 1);
const mrzAttributeFormatted = formatAttribute(key_, mrzAttribute);
<YStack mt="$6">
{selectedApp && Object.keys(selectedApp.disclosureOptions as any).map((key) => {
const key_ = key;
const keyFormatted = key_.replace(/_/g, ' ').split(' ').map((word: string) => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
return (
<XStack key={key} mx="$2" gap="$3" alignItems='center'>
<XStack p="$2" onPress={() => handleDisclosureChange(key_)} >
<Checkbox
bg={componentBgColor}
borderColor={borderColor}
value={key}
checked={disclosure[key_ as keyof typeof disclosure]}
onCheckedChange={() => handleDisclosureChange(key_)}
aria-label={keyFormatted}
size="$6"
>
<Checkbox.Indicator >
<Check color={textColor1} />
</Checkbox.Indicator>
</Checkbox>
</XStack>
<Text color={textColor2} >{keyFormatted}: </Text>
{key_ === 'older_than' ? (
<XStack gap="$1.5" jc='center' ai='center'>
<XStack mr="$2">
<Text color={textColor1} w="$1" fontSize={16}>{majority}</Text>
<Text color={textColor1} fontSize={16}> yo</Text>
</XStack>
<Button
bg={componentBgColor}
borderColor={borderColor}
h="$2"
w="$3"
onPress={() => update({
majority: majority - 1
})}
>
<Minus color={textColor1} size={18} />
</Button>
<Button
bg={componentBgColor}
borderColor={borderColor}
h="$2"
w="$3"
onPress={() => update({
majority: majority + 1
})}
>
<Plus color={textColor1} size={18} />
</Button>
</XStack>
) : (
<Text
color={textColor1}
>
{hideData ? maskString(mrzAttributeFormatted) : mrzAttributeFormatted}
</Text>
)}
</XStack>
);
})}
</ScrollView >
</YStack >
</YStack >
</YStack >
<Button
disabled={isZkeyDownloading[selectedApp.circuit] || (address == ethers.ZeroAddress)}
borderWidth={1.3}
borderColor={borderColor}
borderRadius={100}
onPress={handleProve}
mt="$8"
backgroundColor={address == ethers.ZeroAddress ? "#cecece" : "#3185FC"}
alignSelf='center'
>
{!registered ? (
<XStack ai="center" gap="$1">
<Spinner />
<Text color={textColor1} fow="bold">
Registering identity...
return (
<XStack key={key} gap="$3" mb="$3" ml="$3" >
<CheckCircle size={16} mt="$1.5" />
<Text fontSize="$7" color={textBlack} w="85%">
{disclosureFieldsToText(key_, (selectedApp.disclosureOptions as any)[key_])}
</Text>
</XStack>
) : isZkeyDownloading[selectedApp.circuit] ? (
<XStack ai="center" gap="$1">
<Spinner />
<Text color={textColor1} fow="bold">
Downloading ZK proving key
</Text>
</XStack>
) : step === Steps.GENERATING_PROOF ? (
<XStack ai="center" gap="$1">
<Spinner />
<Text color={textColor2} marginLeft="$2" fow="bold">
Generating ZK proof
</Text>
</XStack>
) : address == ethers.ZeroAddress ? (
<Text color={textColor2} fow="bold">
Enter address
</Text>
) : (
<Text color={textColor1} fow="bold">
Generate ZK proof
</Text>
)}
</Button>
{
(height > 750) &&
<Text
fontSize={10}
color={step === Steps.GENERATING_PROOF ? "#a0a0a0" : "#161616"}
py="$2"
alignSelf='center'
>
This operation can take up to 1 mn, phone may freeze during this time
</Text>
}
</YStack >
);
})}
</YStack>
<XStack f={1} />
<CustomButton
Icon={isConnecting ? <Spinner /> : generatingProof ? <Spinner /> : <CheckCircle />}
isDisabled={isConnecting || generatingProof}
text={isConnecting ? "Connecting..." : generatingProof ? "Generating Proof..." : "Verify"}
onPress={registered ? handleProve : () => setSheetRegisterIsOpen(true)}
bgColor={isConnecting || generatingProof ? separatorColor : bgGreen}
disabledOnPress={() => toast.show('⏳', {
message: isConnecting ? "Connecting to server..." : "Proof is generating",
customData: {
type: "info",
},
})}
/>
{/* {proofStatus && (
<Text mt="$4" fontSize="$6" color={textBlack}>
{proofStatus}
</Text>
)} */}
</YStack >
);
};

View File

@@ -1,10 +1,11 @@
import React, { useState } from 'react';
import { YStack, XStack, Text, Button, Spinner } from 'tamagui';
import { LockKeyhole } from '@tamagui/lucide-icons';
import { borderColor, componentBgColor, componentBgColor2, textColor1, textColor2 } from '../utils/colors';
import { LockKeyhole, UserPlus } from '@tamagui/lucide-icons';
import { bgGreen, borderColor, componentBgColor, componentBgColor2, textBlack } from '../utils/colors';
import { Platform } from 'react-native';
import useUserStore from '../stores/userStore';
import useNavigationStore from '../stores/navigationStore';
import CustomButton from '../components/CustomButton';
const RegisterScreen: React.FC = () => {
@@ -16,6 +17,7 @@ const RegisterScreen: React.FC = () => {
const handleRegister = async () => {
setRegistering(true);
useUserStore.getState().registerCommitment();
setRegisterStep("Generating witness...");
setTimeout(() => {
setRegisterStep("Generating proof...");
@@ -29,23 +31,30 @@ const RegisterScreen: React.FC = () => {
}
return (
<YStack px="$4" f={1} mb={Platform.OS === 'ios' ? "$5" : "$0"}>
<YStack p="$3" f={1} mb={Platform.OS === 'ios' ? "$5" : "$0"}>
<YStack flex={1} mx="$2" gap="$2">
<Text mt="$12" color={textColor1} fontSize="$10" fontWeight="bold">
Register
</Text>
<Text mt="$6" fontSize="$6" color={textColor1}>Join Proof of Passport to start sharing your identity securely.</Text>
<Text mt="$1" fontSize="$4" color={textColor2}>Easily verify your nationality, humanity, or age and share only what you want to reveal.</Text>
<YStack f={1} />
<Text mt="$7" fontSize="$9" color={textBlack}>Join Proof of Passport to start sharing your identity<Text style={{
textDecorationLine: "underline", textDecorationColor: bgGreen
}}> securely. </Text></Text>
<Text mt="$0" color={textBlack} fontSize="$8">Easily verify your nationality, humanity, or age and share<Text style={{
textDecorationLine: "underline", textDecorationColor: bgGreen
}}> only </Text>what you want to reveal.</Text>
<XStack f={1} />
<XStack mt="$5" bg={componentBgColor} borderRadius={100} borderWidth={1} borderColor={borderColor} py="$2" px="$3">
<XStack bg={componentBgColor2} borderRadius={100} p="$2" >
<LockKeyhole alignSelf='center' size={24} color={textColor1} />
<XStack mt="$5" bg="white" borderRadius={100} mb="$12" py="$2.5" px="$3">
<XStack p="$2" >
<LockKeyhole alignSelf='center' size={24} color={textBlack} />
</XStack>
<Text alignSelf='center' ml="$3" pr="$5" fontSize="$3" color={textColor1}>Registration does not leak any personal information</Text>
<Text alignSelf='center' ml="$3" pr="$5" fontSize="$3" color={textBlack}>Registration does not leak any personal information</Text>
</XStack>
<Button
<CustomButton
isDisabled={isZkeyDownloading.register_sha256WithRSAEncryption_65537 || registering}
onPress={handleRegister}
text={isZkeyDownloading.register_sha256WithRSAEncryption_65537 ? "Downloading zkey..." : (registerStep || "Register")}
Icon={isZkeyDownloading.register_sha256WithRSAEncryption_65537 || registering ? <Spinner color={textBlack} /> : <UserPlus color={textBlack} />}
/>
{/* <Button
disabled={isZkeyDownloading.register_sha256WithRSAEncryption_65537}
mt="$8"
alignSelf='center'
@@ -56,11 +65,11 @@ const RegisterScreen: React.FC = () => {
>
<XStack gap="$3">
{(registering || isZkeyDownloading.register_sha256WithRSAEncryption_65537) && <Spinner color="white" size="small" />}
<Text color={textColor1} fontSize="$5" >
<Text color={textBlack} fontSize="$5" >
{isZkeyDownloading.register_sha256WithRSAEncryption_65537 ? "Downloading zkey..." : (registerStep || "Register")}
</Text>
</XStack>
</Button>
</Button> */}
</YStack >
</YStack >
);

View File

@@ -7,7 +7,7 @@ import ProofGrid from '../components/ProofGrid';
import { Platform } from 'react-native';
import { blueColor, borderColor, componentBgColor, textColor1, textColor2 } from '../utils/colors';
import useNavigationStore from '../stores/navigationStore';
import { AppType } from '../utils/appType';
import { AppType } from '../../../common/src/utils/appType';
import { appStoreMapping } from './ProveScreen';
const SendProofScreen: React.FC = () => {

View File

@@ -0,0 +1,31 @@
import React, { useEffect } from 'react';
import useUserStore from '../stores/userStore';
import useNavigationStore from '../stores/navigationStore';
import { YStack, Text, Spinner, XStack } from 'tamagui';
import { bgGreen, textBlack } from '../utils/colors';
const SplashScreen = () => {
const { userLoaded, registered } = useUserStore();
const { setSelectedTab } = useNavigationStore();
// once registered is retrieved from zustand, navigate to the appropriate screen
useEffect(() => {
if (userLoaded) {
if (registered) {
setSelectedTab('app');
} else {
setSelectedTab('start');
}
}
}, [userLoaded]);
return (
<YStack ai="center" f={1} gap="$8" mt="$18" mb="$8">
<Text fontSize="$9">Proof of Passport</Text>
<XStack f={1} />
<Spinner color={textBlack} />
</YStack>
);
};
export default SplashScreen;

View File

@@ -0,0 +1,44 @@
import React from 'react';
import { YStack, Button, Image, Text, styled } from 'tamagui';
import { ArrowRight, Camera, SquarePen, UserPlus } from '@tamagui/lucide-icons';
import { bgColor, bgGreen, borderColor, textBlack, textColor1, textColor2 } from '../utils/colors';
import { Steps } from "../utils/utils";
import CustomButton from '../components/CustomButton';
import useNavigationStore from '../stores/navigationStore';
const StartScreen: React.FC = () => {
const {
setStep,
step,
selectedTab,
setSelectedTab
} = useNavigationStore();
return (
<YStack f={1} p="$3">
<YStack f={1} mt="$12">
<YStack gap="$0.5" mb="$14">
<Text fontSize="$9" >Welcome to Proof of Passport 👋</Text>
<Text fontSize="$8" mt="$6" color={textBlack}>Proof of Passport allows you to scan your passport, and to prove your identity in a
<Text fontSize="$8" color={textBlack} style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}> secure </Text>way.
</Text>
<Text fontSize="$8" mt="$4" color={textBlack} style={{ opacity: 0.7 }}>You can for example prove that you are over 18 yo while staying fully
<Text fontSize="$8" color={textBlack} style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}> anonymous.</Text>
</Text>
</YStack>
</YStack>
<CustomButton Icon={<ArrowRight />} text="Let's start" onPress={() => {
setSelectedTab("scan");
}} />
{/* <Button onPress={() => {
setSelectedTab("register");
}}>
Register
</Button> */}
</YStack >
);
};
export default StartScreen;

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { YStack, Button, Image, Text, ScrollView, XStack, Separator } from 'tamagui';
import { Camera, ShieldCheck, SquarePen, X } from '@tamagui/lucide-icons';
import { bgColor, bgGreen, borderColor, componentBgColor, componentBgColor2, separatorColor, textBlack, textColor1, textColor2 } from '../utils/colors';
import SCANHelp from '../images/scan_help.png'
import { startCameraScan } from '../utils/cameraScanner';
import CustomButton from '../components/CustomButton';
const SuccessScreen: React.FC = () => {
return (
<YStack f={1} p="$3">
<YStack f={1} mt="$8">
<Text ml="$1" fontSize="$10" color={textBlack}><Text style={{ textDecorationLine: 'underline', textDecorationColor: bgGreen }}>Success</Text>, the proof has been verified</Text>
<XStack f={1} />
</YStack>
</YStack>
);
};
export default SuccessScreen;

View File

@@ -0,0 +1,59 @@
import React from 'react';
import { YStack, Text, XStack } from 'tamagui';
import { bgGreen, textBlack } from '../utils/colors';
import useUserStore from '../stores/userStore';
const WrongProofScreen: React.FC = () => {
const { proofVerificationResult } = useUserStore();
console.log('Raw proofVerificationResult:', JSON.stringify(proofVerificationResult));
const formatFieldName = (field: string) => {
return field.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
};
// Remove the parsing step
const parsedResult = proofVerificationResult;
const fieldsToCheck = [
'scope', 'merkle_root', 'attestation_id', 'current_date', 'issuing_state',
'name', 'passport_number', 'nationality', 'date_of_birth', 'gender',
'expiry_date', 'older_than', 'owner_of', 'proof'
];
const failedConditions = [];
for (const field of fieldsToCheck) {
console.log(`Checking field ${field}: ${JSON.stringify(parsedResult[field])}`);
if (parsedResult[field] === false) {
failedConditions.push(formatFieldName(field));
}
}
console.log('Failed conditions:', JSON.stringify(failedConditions));
return (
<YStack f={1} p="$3">
<YStack f={1} mt="$4" >
<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>
</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 Proof of Passport support.
</Text>
<XStack f={1} />
</YStack>
</YStack >
);
};
export default WrongProofScreen;

View File

@@ -2,7 +2,7 @@ import { create } from 'zustand'
import { IsZkeyDownloading, ShowWarningModalProps } from '../utils/zkeyDownload';
import { Steps } from '../utils/utils';
import { useToastController } from '@tamagui/toast';
import { AppType } from '../utils/appType';
import { AppType } from '../../../common/src/utils/appType';
interface NavigationState {
step: number
@@ -11,12 +11,16 @@ interface NavigationState {
hideData: boolean
toast: ReturnType<typeof useToastController>
selectedTab: string
setSelectedTab: (tab: string) => void
selectedApp: AppType | null
setSelectedApp: (app: AppType | null) => void
showRegistrationErrorSheet: boolean
registrationErrorMessage: string
setToast: (toast: ReturnType<typeof useToastController>) => void;
setStep: (step: number) => void
update: (patch: any) => void
nfcSheetIsOpen: boolean
setNfcSheetIsOpen: (isOpen: boolean) => void
}
const useNavigationStore = create<NavigationState>((set, get) => ({
@@ -41,8 +45,10 @@ const useNavigationStore = create<NavigationState>((set, get) => ({
selectedApp: null,
setToast: (toast) => set({ toast }),
setSelectedApp: (app) => set({ selectedApp: app }),
setStep: (step) => set({ step }),
setSelectedTab: (tab) => set({ selectedTab: tab }),
update: (patch) => {
set({
@@ -50,6 +56,8 @@ const useNavigationStore = create<NavigationState>((set, get) => ({
...patch,
});
},
nfcSheetIsOpen: false,
setNfcSheetIsOpen: (isOpen) => set({ nfcSheetIsOpen: isOpen }),
}))
export default useNavigationStore

View File

@@ -20,6 +20,8 @@ import { sendRegisterTransaction } from '../utils/transactions';
import { loadPassportData, loadSecret, loadSecretOrCreateIt, storePassportData } from '../utils/keychain';
import { ethers } from 'ethers';
import { isCommitmentRegistered } from '../utils/registration';
import { ProofOfPassportVerifierReport } from '@proofofpassport/sdk';
interface UserState {
passportNumber: string
@@ -32,6 +34,7 @@ interface UserState {
cscaProof: Proof | null
localProof: Proof | null
dscSecret: string | null
userLoaded: boolean
initUserStore: () => void
registerPassportData: (passportData: PassportData) => void
registerCommitment: (passportData?: PassportData) => void
@@ -42,9 +45,13 @@ interface UserState {
deleteMrzFields: () => void
setRegistered: (registered: boolean) => void
setDscSecret: (dscSecret: string) => void
setUserLoaded: (userLoaded: boolean) => void
proofVerificationResult: string,
setProofVerificationResult: (proofVerificationResult: string) => void
}
const useUserStore = create<UserState>((set, get) => ({
userLoaded: false,
passportNumber: DEFAULT_PNUMBER ?? "",
dateOfBirth: DEFAULT_DOB ?? "",
dateOfExpiry: DEFAULT_DOE ?? "",
@@ -61,7 +68,13 @@ const useUserStore = create<UserState>((set, get) => ({
setDscSecret: (dscSecret: string) => {
set({ dscSecret });
},
setUserLoaded: (userLoaded: boolean) => {
set({ userLoaded });
},
proofVerificationResult: "null",
setProofVerificationResult: (proofVerificationResult: string) => {
set({ proofVerificationResult });
},
// When user opens the app, checks presence of passportData
// - If passportData is not present, starts the onboarding flow
// - If passportData is present, then secret must be here too (they are always set together). Request the tree.
@@ -78,6 +91,9 @@ const useUserStore = create<UserState>((set, get) => ({
const passportData = await loadPassportData();
if (!passportData) {
console.log("No passport data found, starting onboarding flow")
set({
userLoaded: true,
});
return;
}
@@ -87,8 +103,10 @@ const useUserStore = create<UserState>((set, get) => ({
console.log("not registered but passport data found, skipping to nextScreen")
set({
passportData: JSON.parse(passportData),
userLoaded: true,
});
useNavigationStore.getState().setStep(Steps.NEXT_SCREEN);
// useNavigationStore.getState().setStep(Steps.NEXT_SCREEN);
return;
}
@@ -97,7 +115,8 @@ const useUserStore = create<UserState>((set, get) => ({
passportData: JSON.parse(passportData),
registered: true,
});
// useNavigationStore.getState().setStep(Steps.REGISTERED);
useNavigationStore.getState().setStep(Steps.REGISTERED);
set({ userLoaded: true });
},
// When reading passport for the first time:
@@ -116,6 +135,7 @@ const useUserStore = create<UserState>((set, get) => ({
},
registerCommitment: async (mockPassportData?: PassportData) => {
console.log("registerCommitment")
const {
toast,
setStep,
@@ -128,6 +148,7 @@ const useUserStore = create<UserState>((set, get) => ({
}
const isAlreadyRegistered = await isCommitmentRegistered(secret, passportData);
console.log("isAlreadyRegistered", isAlreadyRegistered)
if (isAlreadyRegistered) {
console.log("commitment is already registered")
toast.show('Identity already registered, skipping', {
@@ -160,7 +181,7 @@ const useUserStore = create<UserState>((set, get) => ({
);
amplitude.track(`Sig alg supported: ${passportData.signatureAlgorithm}`);
//amplitude.track(`Sig alg supported: ${passportData.signatureAlgorithm}`);
console.log("userStore - inputs - Object.keys(inputs).forEach((key) => {...")
Object.keys(inputs).forEach((key) => {
if (Array.isArray(inputs[key as keyof typeof inputs])) {
@@ -184,7 +205,7 @@ const useUserStore = create<UserState>((set, get) => ({
const end = Date.now();
console.log('Total proof time from frontend:', end - start);
amplitude.track('Proof generation successful, took ' + ((end - start) / 1000) + ' seconds');
//amplitude.track('Proof generation successful, took ' + ((end - start) / 1000) + ' seconds');
if ((get().cscaProof !== null) && (get().localProof !== null)) {
@@ -199,6 +220,7 @@ const useUserStore = create<UserState>((set, get) => ({
}
set({ registered: true });
setStep(Steps.REGISTERED);
useNavigationStore.getState().setSelectedTab("app");
toast.show('✅', {
message: "Registered",
customData: {
@@ -217,7 +239,7 @@ const useUserStore = create<UserState>((set, get) => ({
registrationErrorMessage: error.message,
})
setStep(Steps.NEXT_SCREEN);
amplitude.track(error.message);
//amplitude.track(error.message);
}
},

View File

@@ -1,44 +0,0 @@
import { CircuitName } from "./zkeyDownload";
type DisclosureOption = "required" | "optional";
type Disclosure = {
[key: string]: DisclosureOption;
};
export type AppType = {
id: string;
// AppScreen UI
title: string,
description: string,
background?: string,
colorOfTheText: string,
selectable: boolean,
icon: any,
tags: React.JSX.Element[]
// ProveScreen UI
name: string;
disclosureOptions: Disclosure | {};
beforeSendText1: string;
beforeSendText2: string;
sendButtonText: string;
sendingButtonText: string;
successTitle: string;
successText: string;
successComponent: () => React.JSX.Element;
finalButtonAction: () => void;
finalButtonText: string;
scope: string;
circuit: CircuitName; // circuit and witness calculator name
fields: React.FC[];
handleProve: () => void;
handleSendProof: () => void;
}

View File

@@ -5,7 +5,7 @@ import useUserStore from '../stores/userStore';
import useNavigationStore from '../stores/navigationStore';
export const startCameraScan = async () => {
const {toast, setStep} = useNavigationStore.getState();
const { toast, setSelectedTab } = useNavigationStore.getState();
if (Platform.OS === 'ios') {
try {
@@ -19,17 +19,15 @@ export const startCameraScan = async () => {
dateOfExpiry: formatDateToYYMMDD(result.expiryDate),
})
setStep(Steps.MRZ_SCAN_COMPLETED);
setSelectedTab("nfc");
toast.show("Scan successful", {
message: 'Nice to meet you!',
message: '',
customData: {
type: "success",
},
})
amplitude.track('Camera scan successful');
} catch (e) {
console.error(e);
amplitude.track('Camera scan unsuccessful');
}
} else {
NativeModules.CameraActivityModule.startCameraActivity()
@@ -43,22 +41,19 @@ export const startCameraScan = async () => {
dateOfExpiry: expiryDate,
})
setStep(Steps.MRZ_SCAN_COMPLETED);
amplitude.track('Camera scan successful');
setSelectedTab("nfc");
toast.show("Scan successful", {
message: 'Nice to meet you!',
message: '',
customData: {
type: "success",
},
})
})
} catch (error: any) {
console.error('Invalid MRZ format:', error.message);
amplitude.track('Camera scan unsuccessful');
}
})
.catch((error: any) => {
console.error('Camera Activity Error:', error);
amplitude.track('Camera scan unsuccessful');
});
}
};

View File

@@ -13,3 +13,8 @@ export const redColorDark = "#3c181a"
export const redColorLight = "#e5484d"
export const yellowColorDark = "#2d2200"
export const yellowColorLight = "#f5d90a"
export const bgWhite = "#F5F5F5"
export const textBlack = "#333333"
export const bgGreen = "#94FBAB"
export const bgBlue = "#69DFFF"
export const separatorColor = "#E0E0E0"

View File

@@ -22,7 +22,7 @@ export const scan = async (setModalProofStep: (modalProofStep: number) => void)
dateOfExpiry,
} = useUserStore.getState()
const { toast, setStep } = useNavigationStore.getState();
const { toast, setStep, nfcSheetIsOpen, setNfcSheetIsOpen } = useNavigationStore.getState();
const check = checkInputs(
passportNumber,
@@ -57,7 +57,9 @@ const scanAndroid = async (setModalProofStep: (modalProofStep: number) => void)
dateOfExpiry,
dscCertificate
} = useUserStore.getState()
const { toast, setStep } = useNavigationStore.getState();
const { toast, setNfcSheetIsOpen } = useNavigationStore.getState();
setNfcSheetIsOpen(true);
try {
const response = await PassportReader.scan({
@@ -66,12 +68,13 @@ const scanAndroid = async (setModalProofStep: (modalProofStep: number) => void)
dateOfExpiry: dateOfExpiry
});
console.log('scanned');
amplitude.track('NFC scan successful');
setNfcSheetIsOpen(false);
//amplitude.track('NFC scan successful');
handleResponseAndroid(response, setModalProofStep);
} catch (e: any) {
console.log('error during scan:', e);
setStep(Steps.MRZ_SCAN_COMPLETED);
amplitude.track('NFC scan unsuccessful', { error: JSON.stringify(e) });
setNfcSheetIsOpen(false);
//amplitude.track('NFC scan unsuccessful', { error: JSON.stringify(e) });
toast.show('Error', {
message: e.message,
customData: {
@@ -98,11 +101,11 @@ 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);
setStep(Steps.MRZ_SCAN_COMPLETED);
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,
@@ -155,7 +158,7 @@ const handleResponseIOS = async (
const encryptedDigestArray = Array.from(Buffer.from(signatureBase64, 'base64')).map(byte => byte > 127 ? byte - 256 : byte);
amplitude.track('Sig alg before conversion: ' + signatureAlgorithm);
//amplitude.track('Sig alg before conversion: ' + signatureAlgorithm);
console.log('signatureAlgorithm before conversion', signatureAlgorithm);
const passportData = {
mrz,
@@ -196,10 +199,11 @@ const handleResponseIOS = async (
sendCSCARequest(inputs_csca, setModalProofStep);
useNavigationStore.getState().setStep(Steps.NEXT_SCREEN);
useNavigationStore.getState().setSelectedTab("next");
} catch (e: any) {
console.log('error during parsing:', e);
useNavigationStore.getState().setStep(Steps.MRZ_SCAN_COMPLETED);
amplitude.track('Signature algorithm unsupported (ecdsa not parsed)', { error: JSON.stringify(e) });
//amplitude.track('Signature algorithm unsupported (ecdsa not parsed)', { error: JSON.stringify(e) });
toast.show('Error', {
message: "Your signature algorithm is not supported at that time. Please try again later.",
customData: {
@@ -231,7 +235,7 @@ const handleResponseAndroid = async (
documentSigningCertificate
} = response;
amplitude.track('Sig alg before conversion: ' + signatureAlgorithm);
//amplitude.track('Sig alg before conversion: ' + signatureAlgorithm);
const pem = "-----BEGIN CERTIFICATE-----" + documentSigningCertificate + "-----END CERTIFICATE-----"
@@ -255,7 +259,7 @@ const handleResponseAndroid = async (
encryptedDigest: JSON.parse(encryptedDigest),
photoBase64: photo.base64,
};
amplitude.track('Sig alg after conversion: ' + passportData.signatureAlgorithm);
//amplitude.track('Sig alg after conversion: ' + passportData.signatureAlgorithm);
console.log('passportData', JSON.stringify({
...passportData,
@@ -304,4 +308,5 @@ const handleResponseAndroid = async (
);
sendCSCARequest(inputs_csca, setModalProofStep);
useNavigationStore.getState().setStep(Steps.NEXT_SCREEN);
useNavigationStore.getState().setSelectedTab("next");
};

View File

@@ -8,7 +8,16 @@ import { formatMrz, packBytes } from "../../../common/src/utils/utils";
import { findIndexInTree } from "../../../common/src/utils/generateInputs";
export async function isCommitmentRegistered(secret: string, passportData: PassportData) {
const response = await axios.get(COMMITMENT_TREE_TRACKER_URL)
let response;
console.log(COMMITMENT_TREE_TRACKER_URL)
try {
response = await axios.get(COMMITMENT_TREE_TRACKER_URL);
} catch (error) {
console.error('Error fetching commitment tree:', error);
throw error; // rethrow the error after logging
}
console.log('response.data:', response.data);
const imt = new LeanIMT(
@@ -40,7 +49,7 @@ export async function isCommitmentRegistered(secret: string, passportData: Passp
try {
findIndexInTree(imt as any, commitment); // this will throw if not found
return true
} catch(err) {
} catch (err) {
return false;
}
}

View File

@@ -34,6 +34,7 @@ export function formatDateToYYMMDD(inputDate: string) {
}
export const Steps = {
START: 0,
MRZ_SCAN: 1,
MRZ_SCAN_COMPLETED: 2,
NFC_SCANNING: 3,

View File

@@ -43,7 +43,7 @@ export async function downloadZkey(
const downloadRequired = await isDownloadRequired(circuit, isZkeyDownloading);
if (!downloadRequired) {
console.log(`zkey for ${circuit} already downloaded`)
amplitude.track(`zkey for ${circuit} already downloaded`);
//amplitude.track(`zkey for ${circuit} already downloaded`);
return;
}
@@ -107,7 +107,7 @@ export async function fetchZkey(
circuit: CircuitName,
) {
console.log(`fetching zkey for ${circuit} ...`)
amplitude.track(`fetching zkey for ${circuit} ...`);
//amplitude.track(`fetching zkey for ${circuit} ...`);
const {
isZkeyDownloading,
@@ -171,7 +171,7 @@ export async function fetchZkey(
}
});
amplitude.track('zkey download succeeded, took ' + ((Date.now() - startTime) / 1000) + ' seconds');
//amplitude.track('zkey download succeeded, took ' + ((Date.now() - startTime) / 1000) + ' seconds');
const zipSize = await RNFS.stat(`${RNFS.DocumentDirectoryPath}/${circuit}.zkey.zip`);
console.log('zipSize:', zipSize.size);
@@ -202,7 +202,7 @@ export async function fetchZkey(
[circuit]: false,
}
});
amplitude.track('zkey download failed: ' + error.message);
//amplitude.track('zkey download failed: ' + error.message);
toast.show('Error', {
message: `Error: ${error.message}`,
customData: {

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,7 @@ describe('Disclose', function () {
const secret = BigInt(Math.floor(Math.random() * Math.pow(2, 254))).toString();
attestation_id = poseidon1([BigInt(Buffer.from(attestation_name).readUIntBE(0, 6))]).toString();
const majority = ['1', '8'];
const majority = '18';
const user_identifier = '0xE6E4b6a802F2e0aeE5676f6010e0AF5C9CDd0a50';
const bitmap = Array(90).fill('1');
const scope = poseidon1([BigInt(Buffer.from('VOTEEEEE').readUIntBE(0, 6))]).toString();

View File

@@ -64,6 +64,6 @@ describe('DSC chain certificate - SHA1 RSA', function () {
});
it('should compute the correct output', async () => {
const witness = await circuit.calculateWitness(inputs, true);
const witness = await circuit.calculateWitness(inputs.inputs, true);
});
});

View File

@@ -63,6 +63,6 @@ describe('DSC chain certificate - SHA256 RSA', function () {
});
it('should compute the correct output', async () => {
const witness = await circuit.calculateWitness(inputs, true);
const witness = await circuit.calculateWitness(inputs.inputs, true);
});
});

View File

@@ -94,6 +94,6 @@ describe('DSC chain certificate - SHA256 RSA-PSS', function () {
});
it('should compute the correct output', async () => {
const witness = await circuit.calculateWitness(inputs, true);
const witness = await circuit.calculateWitness(inputs.inputs, true);
});
});

View File

@@ -55,17 +55,17 @@ describe('RSA Verifier', function () {
expect(isVerified).to.be.true;
});
it('should extract and log certificate information', async () => {
const csca_inputs = getCSCAInputs('0', dscCert_forge, cscaCert_forge, n, k, n, k, 2048, true);
const tbsCertificateHashFormatted = getTBSHash(dscCert_forge, 'sha256', n, k);
// it('should extract and log certificate information', async () => {
// const csca_inputs = getCSCAInputs('0', dscCert_forge, cscaCert_forge, n, k, n, k, 2048, true);
// const tbsCertificateHashFormatted = getTBSHash(dscCert_forge, 'sha256', n, k);
const inputs = {
message: tbsCertificateHashFormatted,
signature: csca_inputs.dsc_signature,
modulus: csca_inputs.csca_modulus,
};
const witness = await circuit.calculateWitness(inputs, true);
});
// const inputs = {
// message: tbsCertificateHashFormatted,
// signature: csca_inputs.inputs.dsc_signature,
// modulus: csca_inputs.inputs.dsc_modulus,
// };
// const witness = await circuit.calculateWitness(inputs, true);
// });
});
describe('SHA-1 certificates', () => {

View File

@@ -56,17 +56,17 @@ describe('RSAPSS Verifier', function () {
expect(isVerified).to.be.true;
});
it('should extract and log certificate information', async () => {
const csca_inputs = getCSCAInputs('0', dscCert_forge, cscaCert_forge, n, k, n, k, 960, true);
// const tbsCertificateHashFormatted = getTBSHash(dscCert_forge, 'sha256', n, k);
// it('should extract and log certificate information', async () => {
// const csca_inputs = getCSCAInputs('0', dscCert_forge, cscaCert_forge, n, k, n, k, 960, true);
// // const tbsCertificateHashFormatted = getTBSHash(dscCert_forge, 'sha256', n, k);
const inputs = {
raw_message: csca_inputs.raw_dsc_cert,
raw_message_padded_bytes: csca_inputs.raw_dsc_cert_padded_bytes,
signature: csca_inputs.dsc_signature,
modulus: csca_inputs.csca_modulus,
};
//const witness = await circuit.calculateWitness(inputs, true);
});
// const inputs = {
// raw_message: csca_inputs.inputs.raw_dsc_cert,
// raw_message_padded_bytes: csca_inputs.inputs.raw_dsc_cert_padded_bytes,
// signature: csca_inputs.inputs.dsc_signature,
// modulus: csca_inputs.inputs.dsc_modulus,
// };
// /const witness = await circuit.calculateWitness(inputs, true);
// });
});
});

View File

@@ -3,6 +3,7 @@
"@babel/runtime": "^7.23.4",
"@zk-kit/imt": "https://gitpkg.now.sh/0xturboblitz/zk-kit/packages/imt?6d417675",
"@zk-kit/lean-imt": "^2.0.1",
"@zk-kit/utils": "^1.2.0",
"asn1.js": "^5.4.1",
"axios": "^1.7.2",
"elliptic": "^6.5.5",
@@ -20,4 +21,4 @@
"devDependencies": {
"@types/node-forge": "^1.3.10"
}
}
}

View File

@@ -1,6 +1,6 @@
export const RELAYER_URL = "https://0pw5u65m3a.execute-api.eu-north-1.amazonaws.com/api-stage/mint"
export const COMMITMENT_TREE_TRACKER_URL = "https://app.proofofpassport.com/apiv2/download-merkle-tree"
//export const COMMITMENT_TREE_TRACKER_URL = "https://app.proofofpassport.com/apiv2/download-merkle-tree"
export const COMMITMENT_TREE_TRACKER_URL = "https://proofofpassport-merkle-tree.xyz/api/download-merkle-tree"
export const PUBKEY_TREE_DEPTH = 16
export const CSCA_TREE_DEPTH = 12
export const COMMITMENT_TREE_DEPTH = 16
@@ -14,6 +14,7 @@ export const RPC_URL = "https://opt-mainnet.g.alchemy.com/v2/Mjj_SdklUaCdR6EPfVK
// we make it global here because passing it to generateCircuitInputsRegister caused trouble
export const DEVELOPMENT_MODE = true
export const DEFAULT_MAJORITY = "18"
export enum SignatureAlgorithm {
sha256WithRSAEncryption_65537 = 1,
@@ -28,6 +29,11 @@ export enum SignatureAlgorithm {
sha512WithRSAEncryption_65537 = 10
}
export const signatureOidToName = {
"1.2.840.113549.1.1.11": "sha256_rsa",
"1.2.840.113549.1.1.5": "sha1_rsa"
}
export const attributeToPosition = {
issuing_state: [2, 4],
name: [5, 43],
@@ -312,7 +318,7 @@ qzOBhID0Nxk4k9sW1uT6ocW1xp1SB2WotORssOKIAOLJM8IbPl6n/DkYNcfvyXI7
-----END RSA PUBLIC KEY-----`;
export const DEFAULT_RPC_URL = "https://mainnet.optimism.io";
export const REGISTER_CONTRACT_ADDRESS = "0xEd7495516a957dD7d378d8A78846646461cFF25f";
export const REGISTER_CONTRACT_ADDRESS = "0x3F346FFdC5d583e4126AF01A02Ac5b9CdB3f1909";
export const SBT_CONTRACT_ADDRESS = "0x601Fd54FD11C5E77DE84d877e55B829aff20f0A6";
/*** ABI ***/

View File

@@ -0,0 +1,159 @@
export const vkey_disclose = {
"protocol": "groth16",
"curve": "bn128",
"nPublic": 14,
"vk_alpha_1": [
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
"1"
],
"vk_beta_2": [
[
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
],
[
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
],
[
"1",
"0"
]
],
"vk_gamma_2": [
[
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
],
[
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
],
[
"1",
"0"
]
],
"vk_delta_2": [
[
"6942436740229168666595536581519256291593117600832247164924519038970269461046",
"17557865657217054151399710026819127874171362865266657132072043760282335721027"
],
[
"15629082942757783052734933529055204330846116501031658743204188522840567440030",
"866803245463331646327183913175583329159450203348438102150009828684148559895"
],
[
"1",
"0"
]
],
"vk_alphabeta_12": [
[
[
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
],
[
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
],
[
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
]
],
[
[
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
],
[
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
],
[
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
]
]
],
"IC": [
[
"10998553002727424987884583305349753345629818748955483305954960876370686844925",
"18369020735737057562107768810182682586161750799521907185011795199521493953276",
"1"
],
[
"3870156317905136354369536369223776179854927352937539086581682263147147725326",
"947908099816727525943796981035826395896386995128918341433720280874486019589",
"1"
],
[
"9619614659642762666110070745787072277198407288262286655564043642023793950605",
"1444870940646607538213811271690623291794427513321591343855928143309974143815",
"1"
],
[
"10290556281387838061211784545032614883237381276187632418810139452226710406378",
"12820288689147023950592422696432066467590193138126598372596214785570201388663",
"1"
],
[
"10044189939644279332588298610988772483187101321076758071894028734198440253205",
"15016612240779620571490237444430121691511928826472608688773111463692886510804",
"1"
],
[
"6158786594227478832634691320618082224218218524296943509099128649963428556955",
"2818896662082406397657145229256654653904841140122301210666395782176903475916",
"1"
],
[
"200295911748915977788397688942615122670319721182540082686195028815964792730",
"16374098866162622474777608838325780437892472095191094825634065695603492498672",
"1"
],
[
"1001933084599581827076405562561115761770358156189382784432273793509010836288",
"13618159500648302749264797924828312592779374840705268445533823753672345860949",
"1"
],
[
"12152127135355257668073159516593687751413730484411437719952408933610175077761",
"15590965974244077225547659000022179448961631917634079092877797469009672737373",
"1"
],
[
"14643873766083688335082369233094018379987105460165787549629338089338629672719",
"18976194036990056092890684065171543382286602242265347684324001010669281606450",
"1"
],
[
"4974359282562923295097396773583362835614429754286473873410152881834388935350",
"2615967425575591157936435871031665935046196308487298765704452331348089292330",
"1"
],
[
"16489750714044704248135942822786071904168862423655325973193848507501139487825",
"4644993658884496411511912365771411317040070112230395754480725062427812526601",
"1"
],
[
"11801682757910657983396995619983996921870874978799260563404809167285348391422",
"19228652101325919244735412842681375925619382430642205708320466729501949572254",
"1"
],
[
"4495248066509783309072792039672520701419947625749866524660708846549914823847",
"4585216314173588273427806971446529726371555267351812069737927114283850919560",
"1"
],
[
"18719866673490039760627957665040843673978402675108669037278157044178865894074",
"11183065716352601580915387671262116390467334689778841393328736869598818253587",
"1"
]
]
};

View File

@@ -0,0 +1,35 @@
export type CircuitName = "register_sha256WithRSAEncryption_65537" | "disclose";
//type DisclosureOption = "required" | "optional";
interface Disclosure {
[key: string]: string;
}
export interface AppType {
id?: string;
name: string;
scope: string;
callbackEndPoint?: string;
userId: string;
disclosureOptions: Disclosure;
circuit: string;
title?: string;
description?: string;
background?: string;
colorOfTheText?: string;
icon?: unknown;
}
export function createAppType(data: AppType): AppType {
return {
//id: data.id || "",
name: data.name,
scope: data.scope,
//callbackEndPoint: data.callbackEndPoint,
userId: data.userId,
disclosureOptions: data.disclosureOptions,
circuit: data.circuit || "disclose",
...data
};
}

View File

@@ -0,0 +1,5 @@
// import { LeanIMT } from "@zk-kit/lean-imt";
// import { poseidon2 } from "poseidon-lite";
// import axios from "axios";
// import { COMMITMENT_TREE_TRACKER_URL } from "../constants/constants";

View File

@@ -1,7 +1,7 @@
import { sha1Pad, sha256Pad } from "./shaPad";
import * as forge from "node-forge";
import { splitToWords } from "./utils";
import { CSCA_AKI_MODULUS, CSCA_TREE_DEPTH, MODAL_SERVER_ADDRESS } from "../constants/constants";
import { CSCA_AKI_MODULUS, CSCA_TREE_DEPTH, MODAL_SERVER_ADDRESS, signatureOidToName } from "../constants/constants";
import { poseidon16, poseidon2, poseidon4 } from "poseidon-lite";
import { IMT } from "@zk-kit/imt";
import serialized_csca_tree from "../../pubkeys/serialized_csca_tree.json"
@@ -131,17 +131,22 @@ export function getCSCAInputs(dscSecret: string, dscCertificate: any, cscaCertif
return {
"raw_dsc_cert": dsc_message_padded_formatted,
"raw_dsc_cert_padded_bytes": [dsc_messagePaddedLen_formatted],
"csca_modulus": csca_modulus_formatted,
"dsc_signature": dsc_signature_formatted,
"dsc_modulus": dsc_modulus_formatted,
"start_index": [startIndex_formatted],
"secret": [dscSecret],
"merkle_root": [BigInt(root).toString()],
"path": proof.pathIndices.map(index => index.toString()),
"siblings": proof.siblings.flat().map(sibling => sibling.toString())
"signature_algorithm": signatureOidToName[signatureAlgorithm],
"inputs":
{
"raw_dsc_cert": dsc_message_padded_formatted,
"raw_dsc_cert_padded_bytes": [dsc_messagePaddedLen_formatted],
"csca_modulus": csca_modulus_formatted,
"dsc_signature": dsc_signature_formatted,
"dsc_modulus": dsc_modulus_formatted,
"start_index": [startIndex_formatted],
"secret": [dscSecret],
"merkle_root": [BigInt(root).toString()],
"path": proof.pathIndices.map(index => index.toString()),
"siblings": proof.siblings.flat().map(sibling => sibling.toString())
}
}
}
export function derToBytes(derValue: string) {

View File

@@ -33,13 +33,13 @@ export function generateCircuitInputsRegister(
const { mrz, signatureAlgorithm, pubKey, dataGroupHashes, eContent, encryptedDigest } =
passportData;
const tree = getCSCAModulusMerkleTree();
// const tree = getCSCAModulusMerkleTree();
if (DEVELOPMENT_MODE) {
for (const mockPassportData of mocks) {
tree.insert(getLeaf(mockPassportData).toString());
}
}
// if (DEVELOPMENT_MODE) {
// for (const mockPassportData of mocks) {
// tree.insert(getLeaf(mockPassportData).toString());
// }
// }
if (
![
@@ -75,14 +75,14 @@ export function generateCircuitInputsRegister(
...pubKey,
}).toString();
const index = tree.indexOf(leaf);
// const index = tree.indexOf(leaf);
// console.log(`Index of pubkey in the registry: ${index}`);
if (index === -1) {
throw new Error('Your public key was not found in the registry');
}
// if (index === -1) {
// throw new Error('Your public key was not found in the registry');
// }
const proof = tree.createProof(index);
console.log('verifyProof', tree.verifyProof(proof));
// const proof = tree.createProof(index);
// console.log('verifyProof', tree.verifyProof(proof));
if (dataGroupHashes.length > MAX_DATAHASHES_LEN) {
console.error(
@@ -142,7 +142,7 @@ export function generateCircuitInputsDisclose(
attestation_id: string,
passportData: PassportData,
merkletree: LeanIMT,
majority: string[],
majority: string,
bitmap: string[],
scope: string,
user_identifier: string
@@ -174,6 +174,9 @@ export function generateCircuitInputsDisclose(
PUBKEY_TREE_DEPTH
);
// format majority to bigints
return {
secret: [secret],
attestation_id: [attestation_id],
@@ -184,9 +187,9 @@ export function generateCircuitInputsDisclose(
path: merkleProofIndices.map((index) => BigInt(index).toString()),
siblings: merkleProofSiblings.map((index) => BigInt(index).toString()),
bitmap: bitmap,
scope: [scope],
current_date: getCurrentDateYYMMDD().map((datePart) => BigInt(datePart).toString()),
majority: majority.map((char) => BigInt(char.charCodeAt(0)).toString()),
scope: [BigInt(scope).toString()],
current_date: getCurrentDateYYMMDD().map(datePart => BigInt(datePart).toString()),
majority: majority.split('').map(char => BigInt(char.charCodeAt(0)).toString()),
user_identifier: [user_identifier],
};
}

View File

@@ -1,9 +1,10 @@
import { SignatureAlgorithm, PUBKEY_TREE_DEPTH, COMMITMENT_TREE_TRACKER_URL } from "../constants/constants";
import { IMT, LeanIMT } from '@zk-kit/imt'
import { formatSigAlgNameForCircuit } from "./utils";
import { toStandardName } from "./formatNames";
import axios from "axios";
import { poseidon10, poseidon2, poseidon3, poseidon5, poseidon6, poseidon8 } from 'poseidon-lite';
import { SignatureAlgorithm, PUBKEY_TREE_DEPTH } from '../constants/constants';
import { IMT } from '@zk-kit/imt';
import { BigintToArray, hexToDecimal, splitToWords } from './utils';
import { formatSigAlgNameForCircuit } from './utils';
import { toStandardName } from './formatNames';
export function buildPubkeyTree(pubkeys: any[]) {
let leaves: bigint[] = [];
@@ -94,3 +95,13 @@ export function getLeaf(pubkey: any, i?: number): bigint {
}
}
}
export async function getTreeFromTracker(): Promise<LeanIMT> {
const response = await axios.get(COMMITMENT_TREE_TRACKER_URL)
const imt = new LeanIMT(
(a: bigint, b: bigint) => poseidon2([a, b]),
[]
);
imt.import(response.data)
return imt
}

View File

@@ -1,10 +1,10 @@
import { attributeToPosition } from "../constants/constants";
export function revealBitmapFromMapping(attributeToReveal: {[key: string]: boolean}): string[] {
export function revealBitmapFromMapping(attributeToReveal: { [key: string]: string }): string[] {
const reveal_bitmap = Array(90).fill('0');
Object.entries(attributeToReveal).forEach(([attribute, reveal]) => {
if (reveal) {
if (reveal !== "") {
const [start, end] = attributeToPosition[attribute as keyof typeof attributeToPosition];
reveal_bitmap.fill('1', start, end + 1);
}
@@ -12,6 +12,16 @@ export function revealBitmapFromMapping(attributeToReveal: {[key: string]: boole
return reveal_bitmap;
}
export function revealBitmapFromAttributes(attributeToReveal: { [key: string]: boolean }): string[] {
const reveal_bitmap = Array(90).fill('0');
Object.entries(attributeToReveal).forEach(([attribute, reveal]) => {
const [start, end] = attributeToPosition[attribute as keyof typeof attributeToPosition];
reveal_bitmap.fill('1', start, end + 1);
});
return reveal_bitmap;
}
export function unpackReveal(revealedData_packed: string[]): string[] {
const revealedData_packed_formatted = [
@@ -22,14 +32,14 @@ export function unpackReveal(revealedData_packed: string[]): string[] {
const bytesCount = [31, 31, 28]; // nb of bytes in each of the first three field elements
const bytesArray = revealedData_packed_formatted.flatMap((element: string, index: number) => {
const bytes = bytesCount[index];
const elementBigInt = BigInt(element);
const byteMask = BigInt(255); // 0xFF
const bytes = bytesCount[index];
const elementBigInt = BigInt(element);
const byteMask = BigInt(255); // 0xFF
const bytesOfElement = [...Array(bytes)].map((_, byteIndex) => {
return (elementBigInt >> (BigInt(byteIndex) * BigInt(8))) & byteMask;
});
return bytesOfElement;
const bytesOfElement = [...Array(bytes)].map((_, byteIndex) => {
return (elementBigInt >> (BigInt(byteIndex) * BigInt(8))) & byteMask;
});
return bytesOfElement;
});
return bytesArray.map((byte: bigint) => String.fromCharCode(Number(byte)));

View File

@@ -92,15 +92,11 @@ contract ProofOfPassportRegister is IRegister, Ownable {
if (bytes32(proof.attestation_id) != attestationId) {
revert("Register__InvalidAttestationId");
}
if (
!verifyProof(
proof,
proof_csca,
signature_algorithm,
signature_algorithm_csca
)
) {
revert("Register__InvalidProof");
if (!verifyProofRegister(proof, signature_algorithm)) {
revert("Register__InvalidProofRegister");
}
if (!verifyProofCSCA(proof_csca, signature_algorithm_csca)) {
revert("Register__InvalidProofCSCA");
}
if (
bytes32(proof.blinded_dsc_commitment) !=
@@ -120,14 +116,12 @@ contract ProofOfPassportRegister is IRegister, Ownable {
);
}
function verifyProof(
function verifyProofRegister(
RegisterProof calldata proof,
CSCAProof calldata proof_csca,
uint256 signature_algorithm,
uint256 signature_algorithm_csca
uint256 signature_algorithm
) public view override returns (bool) {
return
IVerifier(verifiers[signature_algorithm]).verifyProof(
bool register_proof_result = IVerifier(verifiers[signature_algorithm])
.verifyProof(
proof.a,
proof.b,
proof.c,
@@ -137,16 +131,23 @@ contract ProofOfPassportRegister is IRegister, Ownable {
uint(proof.commitment),
uint(proof.attestation_id)
]
) &&
IVerifierCSCA(cscaVerifier[signature_algorithm_csca]).verifyProof(
proof_csca.a,
proof_csca.b,
proof_csca.c,
[
uint(proof_csca.blinded_dsc_commitment),
uint(proof_csca.merkle_root)
]
);
return register_proof_result;
}
function verifyProofCSCA(
CSCAProof calldata proof,
uint256 signature_algorithm_csca
) public view override returns (bool) {
bool csca_proof_result = IVerifierCSCA(
cscaVerifier[signature_algorithm_csca]
).verifyProof(
proof.a,
proof.b,
proof.c,
[uint(proof.blinded_dsc_commitment), uint(proof.merkle_root)]
);
return csca_proof_result;
}
function _addCommitment(uint256 commitment) internal {

View File

@@ -37,10 +37,10 @@ contract Verifier_disclose {
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
uint256 constant deltax1 = 17557865657217054151399710026819127874171362865266657132072043760282335721027;
uint256 constant deltax2 = 6942436740229168666595536581519256291593117600832247164924519038970269461046;
uint256 constant deltay1 = 866803245463331646327183913175583329159450203348438102150009828684148559895;
uint256 constant deltay2 = 15629082942757783052734933529055204330846116501031658743204188522840567440030;
uint256 constant deltax1 = 15676203424747222008362998300678870836264175060817282396863626616184454326330;
uint256 constant deltax2 = 8595392371605829087851094594557910940660445712429027269022585227622642504554;
uint256 constant deltay1 = 12203872594051358924092008745444424746295079999395247253358361977634312297663;
uint256 constant deltay2 = 12761630983022770637435884556671821605356660389025801528165040076412407626174;
uint256 constant IC0x = 10998553002727424987884583305349753345629818748955483305954960876370686844925;

View File

@@ -37,26 +37,26 @@ contract Verifier_register_sha1WithRSAEncryption_65537 {
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
uint256 constant deltax1 = 13155179383413945275687042601864057745717821721437680053026365184572594484550;
uint256 constant deltax2 = 13419763754509431879614817407927849049139910459488314935101788246897460635978;
uint256 constant deltay1 = 21461827286215648586210619400681535578437522448486174192703397303023830118552;
uint256 constant deltay2 = 12737898342805752317935622271701172371990602062953535674427676773537602957073;
uint256 constant deltax1 = 18253612257067907544176772960107463272624812993732140062961899640928066456080;
uint256 constant deltax2 = 17318353882487500984282554464840296751913352404012464994030577338417525343971;
uint256 constant deltay1 = 721186767351735401414914095792921248540353988754079694804425043629944474130;
uint256 constant deltay2 = 8641160395086880158290557415208090358351831755246287088136583424620790058222;
uint256 constant IC0x = 19950267415749769872984420635469219689637916763338714397594201219209357028767;
uint256 constant IC0y = 11341752974833232963273183460328031645291254337522467099721253089381997536320;
uint256 constant IC0x = 1014191657240367827160282284111839866462582312274715702627427091205567946886;
uint256 constant IC0y = 20064777062727594410930852533508532096138075748869034434640217278789575366962;
uint256 constant IC1x = 11343271873447077701345513372787017979035448895799705910074152336406632103014;
uint256 constant IC1y = 15291140079645029904975407443517463786063189008869473596208133516803303710125;
uint256 constant IC1x = 8040733382730768800444374594157736147847832041657938614863886123469540225889;
uint256 constant IC1y = 15176962615443332259650291303258627816076442767778878415428831772797210231229;
uint256 constant IC2x = 6292918500439751291901422848995771412468846049104271000519437364662679332041;
uint256 constant IC2y = 1878279471168197263319180659589173388877997868101930670989411481503721284369;
uint256 constant IC2x = 11540868305335161307326358835675297677768222525355131845910993931594882318691;
uint256 constant IC2y = 2733531636908192599307790060017802843953773596015693191555967489792529852910;
uint256 constant IC3x = 19090924808474659577406284164688929291816288947267788776359044398392811107731;
uint256 constant IC3y = 13853769554127135937032588662814446560788563521681976738789630741456776650960;
uint256 constant IC3x = 4726489574882911673974820746815872571311765544934541335124510833035518984566;
uint256 constant IC3y = 9959433282395160106486758522716112395005767937241995683289413508988346901679;
uint256 constant IC4x = 10289494778834425299665842959201067528454414592551242737919429067761473110056;
uint256 constant IC4y = 10819880897088345060810729932987810005442991406854600436496172825722441835954;
uint256 constant IC4x = 2726107064980905793685456391217077600902590214827304503877626599879070362829;
uint256 constant IC4y = 20809786446816938445294209618344975739842207809116419224037622667595617959803;
// Memory data

View File

@@ -22,58 +22,87 @@ pragma solidity >=0.7.0 <0.9.0;
contract Verifier_register_sha256WithRSAEncryption_65537 {
// Scalar field size
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 constant r =
21888242871839275222246405745257275088548364400416034343698204186575808495617;
// Base field size
uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
uint256 constant q =
21888242871839275222246405745257275088696311157297823662689037894645226208583;
// Verification Key data
uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
uint256 constant deltax1 = 1037380972141538745399950553909330149820502317843211086553895175257817779372;
uint256 constant deltax2 = 1740815875839241540332417489268947801829496353730386086007108179404337117013;
uint256 constant deltay1 = 6307674282939481529797944800746136626548126296541382914082037305183098846296;
uint256 constant deltay2 = 20598922041836569438727926608870745752734230776330209767048604424081248826810;
uint256 constant alphax =
20491192805390485299153009773594534940189261866228447918068658471970481763042;
uint256 constant alphay =
9383485363053290200918347156157836566562967994039712273449902621266178545958;
uint256 constant betax1 =
4252822878758300859123897981450591353533073413197771768651442665752259397132;
uint256 constant betax2 =
6375614351688725206403948262868962793625744043794305715222011528459656738731;
uint256 constant betay1 =
21847035105528745403288232691147584728191162732299865338377159692350059136679;
uint256 constant betay2 =
10505242626370262277552901082094356697409835680220590971873171140371331206856;
uint256 constant gammax1 =
11559732032986387107991004021392285783925812861821192530917403151452391805634;
uint256 constant gammax2 =
10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 constant gammay1 =
4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 =
8495653923123431417604973247489272438418190587263600148770280649306958101930;
uint256 constant deltax1 =
1037380972141538745399950553909330149820502317843211086553895175257817779372;
uint256 constant deltax2 =
1740815875839241540332417489268947801829496353730386086007108179404337117013;
uint256 constant deltay1 =
6307674282939481529797944800746136626548126296541382914082037305183098846296;
uint256 constant deltay2 =
20598922041836569438727926608870745752734230776330209767048604424081248826810;
uint256 constant IC0x =
9720091360134047110754097159401493796660543288592018718226493514433640874991;
uint256 constant IC0y =
9816797761738028831499868308538515271427588347801916552504443254539173856438;
uint256 constant IC1x =
8321344198478472159116798038892978501539506318034192464536707151301617026931;
uint256 constant IC1y =
5162036085088930928154136912718425414931610304133625063308206440957516700168;
uint256 constant IC2x =
13177356501445995293332798335857864829950196156174960167346472326702069056696;
uint256 constant IC2y =
10123754129821780550611152311412848695235565741848206360569448620207136999663;
uint256 constant IC3x =
15800750648534882001293098141511862547516231817837268745140708055565406852893;
uint256 constant IC3y =
3111875870276149539313318494349104168321847784629653817811461001326987877496;
uint256 constant IC4x =
11374553600031801461260163829101393652119031120393018855112829004013226583739;
uint256 constant IC4y =
11948013189599962904927300285557649747124295332223275928752245757162896852086;
uint256 constant IC0x = 9720091360134047110754097159401493796660543288592018718226493514433640874991;
uint256 constant IC0y = 9816797761738028831499868308538515271427588347801916552504443254539173856438;
uint256 constant IC1x = 8321344198478472159116798038892978501539506318034192464536707151301617026931;
uint256 constant IC1y = 5162036085088930928154136912718425414931610304133625063308206440957516700168;
uint256 constant IC2x = 13177356501445995293332798335857864829950196156174960167346472326702069056696;
uint256 constant IC2y = 10123754129821780550611152311412848695235565741848206360569448620207136999663;
uint256 constant IC3x = 15800750648534882001293098141511862547516231817837268745140708055565406852893;
uint256 constant IC3y = 3111875870276149539313318494349104168321847784629653817811461001326987877496;
uint256 constant IC4x = 11374553600031801461260163829101393652119031120393018855112829004013226583739;
uint256 constant IC4y = 11948013189599962904927300285557649747124295332223275928752245757162896852086;
// Memory data
uint16 constant pVk = 0;
uint16 constant pPairing = 128;
uint16 constant pLastMem = 896;
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[4] calldata _pubSignals) public view returns (bool) {
function verifyProof(
uint[2] calldata _pA,
uint[2][2] calldata _pB,
uint[2] calldata _pC,
uint[4] calldata _pubSignals
) public view returns (bool) {
assembly {
function checkField(v) {
if iszero(lt(v, q)) {
if iszero(lt(v, r)) {
mstore(0, 0)
return(0, 0x20)
}
}
// G1 function to multiply a G1 value(x,y) to value in an address
function g1_mulAccC(pR, x, y, s) {
let success
@@ -108,19 +137,21 @@ contract Verifier_register_sha256WithRSAEncryption_65537 {
mstore(add(_pVk, 32), IC0y)
// Compute the linear combination vk_x
g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
// -A
mstore(_pPairing, calldataload(pA))
mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
mstore(
add(_pPairing, 32),
mod(sub(q, calldataload(add(pA, 32))), q)
)
// B
mstore(add(_pPairing, 64), calldataload(pB))
@@ -142,7 +173,6 @@ contract Verifier_register_sha256WithRSAEncryption_65537 {
mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
// gamma2
mstore(add(_pPairing, 448), gammax1)
mstore(add(_pPairing, 480), gammax2)
@@ -159,8 +189,14 @@ contract Verifier_register_sha256WithRSAEncryption_65537 {
mstore(add(_pPairing, 704), deltay1)
mstore(add(_pPairing, 736), deltay2)
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
let success := staticcall(
sub(gas(), 2000),
8,
_pPairing,
768,
_pPairing,
0x20
)
isOk := and(success, mload(_pPairing))
}
@@ -169,23 +205,22 @@ contract Verifier_register_sha256WithRSAEncryption_65537 {
mstore(0x40, add(pMem, pLastMem))
// Validate that all evaluations ∈ F
checkField(calldataload(add(_pubSignals, 0)))
checkField(calldataload(add(_pubSignals, 32)))
checkField(calldataload(add(_pubSignals, 64)))
checkField(calldataload(add(_pubSignals, 96)))
checkField(calldataload(add(_pubSignals, 128)))
// Validate all evaluations
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
mstore(0, isValid)
return(0, 0x20)
}
}
}
return(0, 0x20)
}
}
}

View File

@@ -0,0 +1,191 @@
// SPDX-License-Identifier: GPL-3.0
/*
Copyright 2021 0KIMS association.
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
snarkJS is a free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
snarkJS is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.7.0 <0.9.0;
contract Verifier_register_sha256WithRSAEncryption_65537 {
// Scalar field size
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
// Base field size
uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
// Verification Key data
uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
uint256 constant deltax1 = 15594951545396927133821323111112838246440151372486640584540136770576637393038;
uint256 constant deltax2 = 16646501228722464486042890930566300897412243452681656199619061425330163109294;
uint256 constant deltay1 = 7391847066598204603635570301223858822745255584907407139867164202959899110336;
uint256 constant deltay2 = 16818942323013965805725851186284589299702074465619454314061881957166689439913;
uint256 constant IC0x = 9720091360134047110754097159401493796660543288592018718226493514433640874991;
uint256 constant IC0y = 9816797761738028831499868308538515271427588347801916552504443254539173856438;
uint256 constant IC1x = 8321344198478472159116798038892978501539506318034192464536707151301617026931;
uint256 constant IC1y = 5162036085088930928154136912718425414931610304133625063308206440957516700168;
uint256 constant IC2x = 13177356501445995293332798335857864829950196156174960167346472326702069056696;
uint256 constant IC2y = 10123754129821780550611152311412848695235565741848206360569448620207136999663;
uint256 constant IC3x = 15800750648534882001293098141511862547516231817837268745140708055565406852893;
uint256 constant IC3y = 3111875870276149539313318494349104168321847784629653817811461001326987877496;
uint256 constant IC4x = 11374553600031801461260163829101393652119031120393018855112829004013226583739;
uint256 constant IC4y = 11948013189599962904927300285557649747124295332223275928752245757162896852086;
// Memory data
uint16 constant pVk = 0;
uint16 constant pPairing = 128;
uint16 constant pLastMem = 896;
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[4] calldata _pubSignals) public view returns (bool) {
assembly {
function checkField(v) {
if iszero(lt(v, q)) {
mstore(0, 0)
return(0, 0x20)
}
}
// G1 function to multiply a G1 value(x,y) to value in an address
function g1_mulAccC(pR, x, y, s) {
let success
let mIn := mload(0x40)
mstore(mIn, x)
mstore(add(mIn, 32), y)
mstore(add(mIn, 64), s)
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
if iszero(success) {
mstore(0, 0)
return(0, 0x20)
}
mstore(add(mIn, 64), mload(pR))
mstore(add(mIn, 96), mload(add(pR, 32)))
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
if iszero(success) {
mstore(0, 0)
return(0, 0x20)
}
}
function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
let _pPairing := add(pMem, pPairing)
let _pVk := add(pMem, pVk)
mstore(_pVk, IC0x)
mstore(add(_pVk, 32), IC0y)
// Compute the linear combination vk_x
g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
// -A
mstore(_pPairing, calldataload(pA))
mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
// B
mstore(add(_pPairing, 64), calldataload(pB))
mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
// alpha1
mstore(add(_pPairing, 192), alphax)
mstore(add(_pPairing, 224), alphay)
// beta2
mstore(add(_pPairing, 256), betax1)
mstore(add(_pPairing, 288), betax2)
mstore(add(_pPairing, 320), betay1)
mstore(add(_pPairing, 352), betay2)
// vk_x
mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
// gamma2
mstore(add(_pPairing, 448), gammax1)
mstore(add(_pPairing, 480), gammax2)
mstore(add(_pPairing, 512), gammay1)
mstore(add(_pPairing, 544), gammay2)
// C
mstore(add(_pPairing, 576), calldataload(pC))
mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
// delta2
mstore(add(_pPairing, 640), deltax1)
mstore(add(_pPairing, 672), deltax2)
mstore(add(_pPairing, 704), deltay1)
mstore(add(_pPairing, 736), deltay2)
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
isOk := and(success, mload(_pPairing))
}
let pMem := mload(0x40)
mstore(0x40, add(pMem, pLastMem))
// Validate that all evaluations ∈ F
checkField(calldataload(add(_pubSignals, 0)))
checkField(calldataload(add(_pubSignals, 32)))
checkField(calldataload(add(_pubSignals, 64)))
checkField(calldataload(add(_pubSignals, 96)))
checkField(calldataload(add(_pubSignals, 128)))
// Validate all evaluations
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
mstore(0, isValid)
return(0, 0x20)
}
}
}

View File

@@ -9,7 +9,9 @@ interface IRegister {
/// @notice Error thrown when the same nullifier is used more than once
error Register__YouAreUsingTheSameNullifierTwice();
/// @notice Error thrown when the proof provided is invalid
error Register__InvalidProof();
error Register__InvalidProofRegister();
/// @notice Error thrown when the proof provided is invalid
error Register__InvalidProofCSCA();
/// @notice Error thrown when the signature algorithm provided is invalid
error Register__InvalidSignatureAlgorithm();
/// @notice Error thrown when the verifier address is invalid
@@ -65,10 +67,16 @@ interface IRegister {
/// @notice Verifies a Register proof
/// @param proof The Register proof to verify
/// @return bool Returns true if the proof is valid, false otherwise
function verifyProof(
function verifyProofRegister(
RegisterProof calldata proof,
CSCAProof calldata proof_csca,
uint256 signature_algorithm,
uint256 signature_algorithm
) external view returns (bool);
/// @notice Verifies a Register proof
/// @param proof The Register proof to verify
/// @return bool Returns true if the proof is valid, false otherwise
function verifyProofCSCA(
CSCAProof calldata proof,
uint256 signature_algorithm_csca
) external view returns (bool);

View File

@@ -1,7 +1,6 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
import { formatRoot } from "../../../common/src/utils/utils";
import { generateCircuitInputsRegister } from "../../../common/src/utils/generateInputs";
import { mockPassportData_sha256WithRSAEncryption_65537 } from "../../../common/src/utils/mockPassportData";
import { countryCodes, k_csca, n_csca } from "../../../common/src/constants/constants";
import { getCSCAModulusMerkleTree } from "../../../common/src/utils/csca";
@@ -15,11 +14,11 @@ export default buildModule("Deploy_Registry", (m) => {
const register = m.contract("ProofOfPassportRegister", [registry], { libraries: { PoseidonT3: poseidonT3 } });
const Verifier_register_sha256WithRSAEncryption_65537 = m.contract("Verifier_register_sha256WithRSAEncryption_65537");
const Verifier_register_sha1WithRSAEncryption_65537 = m.contract("Verifier_register_sha1WithRSAEncryption_65537");
const Verifier_dsc_4096 = m.contract("Verifier_dsc_4096");
const Verifier_dsc_sha256_rsa_4096 = m.contract("Verifier_dsc_sha256_rsa_4096");
m.call(register, "addSignatureAlgorithm", [1, Verifier_register_sha256WithRSAEncryption_65537], { id: "a" });
m.call(register, "addSignatureAlgorithm", [3, Verifier_register_sha1WithRSAEncryption_65537], { id: "b" });
m.call(register, "addCSCAVerifier", [1, Verifier_dsc_4096], { id: "c" });
m.call(register, "addCSCAVerifier", [1, Verifier_dsc_sha256_rsa_4096], { id: "c" });
const verifier_disclose = m.contract("Verifier_disclose");
const sbt = m.contract("SBT", [verifier_disclose, formatter, register]);

View File

@@ -0,0 +1,15 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
import { getCSCAModulusMerkleTree } from "../../../../common/src/utils/csca";
import { formatRoot } from "../../../../common/src/utils/utils";
module.exports = buildModule("UpdateMerkleRoot", (m) => {
const registryAddress = "0xBabF700EdE592Aa69e14B5BAE1859ee4164C3323";
const deployedRocketInstance = m.contractAt("Registry", registryAddress);
console.log("Deployed registry instance", deployedRocketInstance);
const merkleRoot = formatRoot(getCSCAModulusMerkleTree().root);
console.log("Merkle root", merkleRoot);
m.call(deployedRocketInstance, "update", [merkleRoot]);
return { deployedRocketInstance };
});

View File

@@ -0,0 +1,15 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
import { getCSCAModulusMerkleTree } from "../../../../common/src/utils/csca";
import { formatRoot } from "../../../../common/src/utils/utils";
module.exports = buildModule("UpdateMerkleRoot", (m) => {
const registryAddress = "0xBabF700EdE592Aa69e14B5BAE1859ee4164C3323";
const deployedRocketInstance = m.contractAt("Registry", registryAddress);
console.log("Deployed registry instance", deployedRocketInstance);
const merkleRoot = formatRoot(getCSCAModulusMerkleTree().root);
console.log("Merkle root", merkleRoot);
m.call(deployedRocketInstance, "update", [merkleRoot]);
return { deployedRocketInstance };
});

View File

@@ -0,0 +1,15 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
import { getCSCAModulusMerkleTree } from "../../../../common/src/utils/csca";
import { formatRoot } from "../../../../common/src/utils/utils";
module.exports = buildModule("UpdateMerkleRoot", (m) => {
const registryAddress = "0xBabF700EdE592Aa69e14B5BAE1859ee4164C3323";
const deployedRocketInstance = m.contractAt("Registry", registryAddress);
console.log("Deployed registry instance", deployedRocketInstance);
const merkleRoot = formatRoot(getCSCAModulusMerkleTree().root);
console.log("Merkle root", merkleRoot);
m.call(deployedRocketInstance, "update", [merkleRoot]);
return { deployedRocketInstance };
});

View File

@@ -1,5 +1,10 @@
{
"name": "hardhat-project",
"scripts": {
"test": "npx hardhat test",
"deploy_all": "npx hardhat ignition deploy ignition/modules/Deploy_All.ts --network optimism --verify",
"compile": "npx hardhat compile"
},
"devDependencies": {
"@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
"@nomicfoundation/hardhat-ethers": "^3.0.5",
@@ -16,7 +21,7 @@
"@types/snarkjs": "^0.7.7",
"chai": "^4.4.1",
"ethers": "^6.12.1",
"hardhat": "^2.22.3",
"hardhat": "^2.22.6",
"hardhat-gas-reporter": "^1.0.10",
"solidity-coverage": "^0.8.12",
"ts-node": "^10.9.1",
@@ -42,4 +47,4 @@
"poseidon-solidity": "^0.0.5",
"snarkjs": "^0.7.1"
}
}
}

View File

@@ -1,7 +1,7 @@
import { expect, assert } from "chai";
import { ethers } from "hardhat";
// import { describe } from "mocha";
import { mockPassportData_sha256WithRSASSAPSS_65537, mockPassportData_sha1WithRSAEncryption_65537, mockPassportData_sha256WithRSAEncryption_65537 } from "../../common/src/utils/mockPassportData";
import { mockPassportData_sha256_rsa_65537, mockPassportData_sha1_rsa_65537, } from "../../common/src/constants/mockPassportData";
import { countryCodes, PASSPORT_ATTESTATION_ID, SignatureAlgorithm } from "../../common/src/constants/constants";
import { formatRoot } from "../../common/src/utils/utils";
import { groth16 } from 'snarkjs'
@@ -12,14 +12,11 @@ import fs from 'fs';
import { LeanIMT } from "@zk-kit/lean-imt";
import { poseidon2 } from "poseidon-lite";
import { Signer } from "ethers";
import { getCSCAInputs } from "../../common/src/utils/csca";
import { getCSCAInputs, getCSCAModulusMerkleTree } from "../../common/src/utils/csca";
import forge from "node-forge";
import { mock_csca_sha256_rsa_4096, mock_dsc_sha256_rsa_4096 } from '../../common/src/constants/mockCertificates';
import { mock_csca_sha256_rsa_4096, mock_dsc_sha256_rsa_4096, mock_dsc_sha1_rsa_4096, mock_csca_sha1_rsa_4096 } from '../../common/src/constants/mockCertificates';
//const mock_dsc_sha256_rsa_4096 = fs.readFileSync('../common/src/mock_certificates/sha256_rsa_4096/mock_dsc.pem', 'utf8');
//const mock_csca_sha256_rsa_4096 = fs.readFileSync('../common/src/mock_certificates/sha256_rsa_4096/mock_csca.pem', 'utf8');
type RegisterCircuitArtifacts = {
type CircuitArtifacts = {
[key: string]: {
wasm: string,
zkey: string,
@@ -35,18 +32,19 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
this.timeout(0);
let proof, publicSignals;
let proof_dsc
const register_circuits: RegisterCircuitArtifacts = {
const register_circuits: CircuitArtifacts = {
sha256WithRSAEncryption_65537: {
wasm: "../circuits/build/register_sha256WithRSAEncryption_65537_js/register_sha256WithRSAEncryption_65537.wasm",
zkey: "../circuits/build/register_sha256WithRSAEncryption_65537_final.zkey",
vkey: "../circuits/build/register_sha256WithRSAEncryption_65537_vkey.json"
},
// sha1WithRSAEncryption_65537: {
// wasm: "../circuits/build/register_sha1WithRSAEncryption_65537_js/register_sha1WithRSAEncryption_65537.wasm",
// zkey: "../circuits/build/register_sha1WithRSAEncryption_65537_final.zkey",
// vkey: "../circuits/build/register_sha1WithRSAEncryption_65537_vkey.json"
// },
sha1WithRSAEncryption_65537: {
wasm: "../circuits/build/register_sha1WithRSAEncryption_65537_js/register_sha1WithRSAEncryption_65537.wasm",
zkey: "../circuits/build/register_sha1WithRSAEncryption_65537_final.zkey",
vkey: "../circuits/build/register_sha1WithRSAEncryption_65537_vkey.json"
},
// sha256WithRSASSAPSS_65537: {
// wasm: "../circuits/build/register_sha256WithRSASSAPSS_65537_js/register_sha256WithRSASSAPSS_65537.wasm",
// zkey: "../circuits/build/register_sha256WithRSASSAPSS_65537_final.zkey",
@@ -54,29 +52,32 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
// }
}
const path_dsc_wasm = "../circuits/build/dsc_4096_js/dsc_4096.wasm";
const path_dsc_zkey = "../circuits/build/dsc_4096_final.zkey";
const path_dsc_vkey = "../circuits/build/dsc_4096_vkey.json";
const dsc_circuits: CircuitArtifacts = {
sha256WithRSAEncryption_65537: {
wasm: "../circuits/build/dsc_sha256_rsa_4096_js/dsc_sha256_rsa_4096.wasm",
zkey: "../circuits/build/dsc_sha256_rsa_4096_final.zkey",
vkey: "../circuits/build/dsc_sha256_rsa_4096_vkey.json"
},
sha1WithRSAEncryption_65537: {
wasm: "../circuits/build/dsc_sha1_rsa_4096_js/dsc_sha1_rsa_4096.wasm",
zkey: "../circuits/build/dsc_sha1_rsa_4096_final.zkey",
vkey: "../circuits/build/dsc_sha1_rsa_4096_vkey.json"
}
}
const path_disclose_wasm = "../circuits/build/disclose_js/disclose.wasm";
const path_disclose_zkey = "../circuits/build/disclose_final.zkey";
const path_disclose_vkey = "../circuits/build/disclose_vkey.json";
// Smart contracts
let Verifier_register: any, verifier_register: any, Registry: any, Formatter: any, Register: any, Verifier_disclose: any, SBT: any, PoseidonT3: any;
let Verifier_dsc: any, verifier_dsc: any, parsedCallData_dsc: any[], formattedCallData_dsc: any;
const n_dsc = 121;
const k_dsc = 17;
const n_csca = 121;
const k_csca = 34;
const max_cert_bytes = 1664;
const dscCert = forge.pki.certificateFromPem(mock_dsc_sha256_rsa_4096);
const cscaCert = forge.pki.certificateFromPem(mock_csca_sha256_rsa_4096);
let inputs_csca = getCSCAInputs(BigInt(0).toString(), dscCert, cscaCert, n_dsc, k_dsc, n_csca, k_csca, max_cert_bytes, true);
let parsedCallData_csca: any;
let formattedCallData_csca: any;
// console.log(inputs_csca);
const dscCert_sha256 = forge.pki.certificateFromPem(mock_dsc_sha256_rsa_4096);
const cscaCert_sha256 = forge.pki.certificateFromPem(mock_csca_sha256_rsa_4096);
const dscCert_sha1 = forge.pki.certificateFromPem(mock_dsc_sha1_rsa_4096);
const cscaCert_sha1 = forge.pki.certificateFromPem(mock_csca_sha1_rsa_4096);
let user_identifier, current_date;
let registry: any, formatter: any, register: any, verifier_disclose: any, sbt: any, poseidonT3: any
@@ -85,7 +86,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
let bitmap, scope, user_address, majority, input_disclose: any;
let proof_disclose, publicSignals_disclose, proof_result_disclose, vkey_disclose, verified_disclose: any, rawCallData_disclose, parsedCallData_disclose: any[], formattedCallData_disclose: any;
let proof_csca, publicSignals_csca: any;
//let proof_csca, publicSignals_csca: any;
let secret: string = BigInt(0).toString();
let attestation_id: string = PASSPORT_ATTESTATION_ID;
@@ -99,27 +100,32 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
register_circuits.sha256WithRSAEncryption_65537.inputs = generateCircuitInputsRegister(
secret,
BigInt(0).toString(),
secret,
attestation_id,
mockPassportData_sha256WithRSAEncryption_65537,
mockPassportData_sha256_rsa_65537,
n_dsc,
k_dsc
);
register_circuits.sha1WithRSAEncryption_65537.inputs = generateCircuitInputsRegister(
secret,
secret,
attestation_id,
mockPassportData_sha1_rsa_65537,
n_dsc,
k_dsc
);
console.log("inputs signature length", register_circuits.sha256WithRSAEncryption_65537.inputs.signature.length);
// register_circuits.sha1WithRSAEncryption_65537.inputs = generateCircuitInputsRegister(
// secret,
// attestation_id,
// mockPassportData_sha1WithRSAEncryption_65537,
// );
dsc_circuits.sha256WithRSAEncryption_65537.inputs = getCSCAInputs(BigInt(0).toString(), dscCert_sha256, cscaCert_sha256, n_dsc, k_dsc, n_csca, k_csca, max_cert_bytes, true);
dsc_circuits.sha1WithRSAEncryption_65537.inputs = getCSCAInputs(BigInt(0).toString(), dscCert_sha1, cscaCert_sha1, n_dsc, k_dsc, n_csca, k_csca, max_cert_bytes, true);
// register_circuits.sha256WithRSASSAPSS_65537.inputs = generateCircuitInputsRegister(
// secret,
// attestation_id,
// mockPassportData_sha256WithRSASSAPSS_65537,
// );
console.log("inputs", register_circuits.sha256WithRSAEncryption_65537.inputs);
//console.log("inputs", register_circuits.sha256WithRSAEncryption_65537.inputs);
/*** Deploy contracts ***/
await deployContracts();
@@ -141,10 +147,17 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
};
}
Verifier_dsc = await ethers.getContractFactory("Verifier_dsc_4096");
verifier_dsc = await Verifier_dsc.deploy();
await verifier_dsc.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `Verifier_dsc deployed to ${verifier_dsc.target}`);
const Verifier_dsc_sha256_rsa_4096 = await ethers.getContractFactory("Verifier_dsc_sha256_rsa_4096");
const verifier_dsc_sha256_rsa_4096 = await Verifier_dsc_sha256_rsa_4096.deploy();
await verifier_dsc_sha256_rsa_4096.waitForDeployment();
dsc_circuits.sha256WithRSAEncryption_65537.verifier = verifier_dsc_sha256_rsa_4096;
console.log('\x1b[34m%s\x1b[0m', `Verifier_dsc_sha256_rsa_4096 deployed to ${verifier_dsc_sha256_rsa_4096.target}`);
const Verifier_dsc_sha1_rsa_4096 = await ethers.getContractFactory("Verifier_dsc_sha1_rsa_4096");
const verifier_dsc_sha1_rsa_4096 = await Verifier_dsc_sha1_rsa_4096.deploy();
await verifier_dsc_sha1_rsa_4096.waitForDeployment();
dsc_circuits.sha1WithRSAEncryption_65537.verifier = verifier_dsc_sha1_rsa_4096;
console.log('\x1b[34m%s\x1b[0m', `Verifier_dsc_sha1_rsa_4096 deployed to ${verifier_dsc_sha1_rsa_4096.target}`);
const Verifier_register_sha256WithRSAEncryption_65537 = await ethers.getContractFactory("Verifier_register_sha256WithRSAEncryption_65537");
const verifier_register_sha256WithRSAEncryption_65537 = await Verifier_register_sha256WithRSAEncryption_65537.deploy(deployOptions);
@@ -152,11 +165,11 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
register_circuits.sha256WithRSAEncryption_65537.verifier = verifier_register_sha256WithRSAEncryption_65537;
console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha256WithRSAEncryption_65537 deployed to ${verifier_register_sha256WithRSAEncryption_65537.target}`);
// const Verifier_register_sha1WithRSAEncryption_65537 = await ethers.getContractFactory("Verifier_register_sha1WithRSAEncryption_65537");
// const verifier_register_sha1WithRSAEncryption_65537 = await Verifier_register_sha1WithRSAEncryption_65537.deploy(deployOptions);
// await verifier_register_sha1WithRSAEncryption_65537.waitForDeployment();
// register_circuits.sha1WithRSAEncryption_65537.verifier = verifier_register_sha1WithRSAEncryption_65537;
// console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha1WithRSAEncryption_65537 deployed to ${verifier_register_sha1WithRSAEncryption_65537.target}`);
const Verifier_register_sha1WithRSAEncryption_65537 = await ethers.getContractFactory("Verifier_register_sha1WithRSAEncryption_65537");
const verifier_register_sha1WithRSAEncryption_65537 = await Verifier_register_sha1WithRSAEncryption_65537.deploy(deployOptions);
await verifier_register_sha1WithRSAEncryption_65537.waitForDeployment();
register_circuits.sha1WithRSAEncryption_65537.verifier = verifier_register_sha1WithRSAEncryption_65537;
console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha1WithRSAEncryption_65537 deployed to ${verifier_register_sha1WithRSAEncryption_65537.target}`);
// const Verifier_register_sha256WithRSASSAPSS_65537 = await ethers.getContractFactory("Verifier_register_sha256WithRSASSAPSS_65537");
// const verifier_register_sha256WithRSASSAPSS_65537 = await Verifier_register_sha256WithRSASSAPSS_65537.deploy(deployOptions);
@@ -171,7 +184,8 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
console.log('\x1b[34m%s\x1b[0m', `Formatter deployed to ${formatter.target}`);
const Registry = await ethers.getContractFactory("Registry");
registry = await Registry.deploy(formatRoot(inputs_csca.merkle_root.toString()), deployOptions);
const merkleTree = getCSCAModulusMerkleTree();
registry = await Registry.deploy(formatRoot(merkleTree.root), deployOptions);
await registry.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `Registry deployed to ${registry.target}`);
@@ -190,7 +204,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
await register.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `Register deployed to ${register.target}`);
console.log("register merkle root:", await registry.getMerkleRoot());
// console.log("register merkle root:", await registry.getMerkleRoot());
const Verifier_disclose = await ethers.getContractFactory("Verifier_disclose");
verifier_disclose = await Verifier_disclose.deploy(deployOptions);
@@ -198,9 +212,9 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
console.log('\x1b[34m%s\x1b[0m', `Verifier_disclose deployed to ${verifier_disclose.target}`);
await register.addSignatureAlgorithm(SignatureAlgorithm["sha256WithRSAEncryption_65537"], verifier_register_sha256WithRSAEncryption_65537.target);
await register.addCSCAVerifier(SignatureAlgorithm["sha256WithRSAEncryption_65537"], verifier_dsc.target);
// await register.addSignatureAlgorithm(SignatureAlgorithm["sha1WithRSAEncryption_65537"], verifier_register_sha1WithRSAEncryption_65537.target);
// await register.addSignatureAlgorithm(SignatureAlgorithm["sha256WithRSASSAPSS_65537"], verifier_register_sha256WithRSASSAPSS_65537.target);
await register.addCSCAVerifier(SignatureAlgorithm["sha256WithRSAEncryption_65537"], verifier_dsc_sha256_rsa_4096.target);
await register.addSignatureAlgorithm(SignatureAlgorithm["sha1WithRSAEncryption_65537"], verifier_register_sha1WithRSAEncryption_65537.target);
await register.addCSCAVerifier(SignatureAlgorithm["sha1WithRSAEncryption_65537"], verifier_dsc_sha1_rsa_4096.target);
const SBT = await ethers.getContractFactory("SBT");
sbt = await SBT.deploy(
@@ -229,24 +243,28 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
/*** Register flow ***/
describe("Proof of Passport - Register flow", function () {
const sigAlgNames = ['sha256WithRSAEncryption_65537'] //, 'sha1WithRSAEncryption_65537', 'sha256WithRSASSAPSS_65537']
const sigAlgNames = ['sha256WithRSAEncryption_65537', 'sha1WithRSAEncryption_65537'] //, 'sha1WithRSAEncryption_65537', 'sha256WithRSASSAPSS_65537']
before(async function () {
await Promise.all(sigAlgNames.map(async (sigAlgName) => {
const sigAlgArtifacts = register_circuits[sigAlgName];
const sigAlgArtifacts_register = register_circuits[sigAlgName];
/*** Groth16 saga Register***/
// Generate the proofs
console.log('\x1b[32m%s\x1b[0m', `Generating proof csca - ${sigAlgName}`);
console.log("csc_modulus_length", inputs_csca.csca_modulus.length);
//console.log("csc_modulus_length", inputs_csca.inputs.csca_modulus.length);
const proof_csca_result = await groth16.fullProve(
inputs_csca,
path_dsc_wasm,
path_dsc_zkey
dsc_circuits[sigAlgName].inputs.inputs,
dsc_circuits[sigAlgName].wasm,
dsc_circuits[sigAlgName].zkey
)
proof_csca = proof_csca_result.proof;
publicSignals_csca = proof_csca_result.publicSignals;
const proof_csca = proof_csca_result.proof;
const publicSignals_csca = proof_csca_result.publicSignals;
console.log('\x1b[32m%s\x1b[0m', `Proof generated csca - ${sigAlgName}`);
const vKey_csca = JSON.parse(fs.readFileSync(path_dsc_vkey) as unknown as string);
// console.log("proof_csca", proof_csca);
// console.log("publicSignals_csca", publicSignals_csca);
const vKey_csca = JSON.parse(fs.readFileSync(dsc_circuits[sigAlgName].vkey) as unknown as string);
const verified_csca = await groth16.verify(
vKey_csca,
publicSignals_csca,
@@ -255,20 +273,19 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
assert(verified_csca == true, 'Should verify')
console.log('\x1b[32m%s\x1b[0m', `Proof verified csca - ${sigAlgName}`);
const rawCallData_csca = await groth16.exportSolidityCallData(proof_csca, publicSignals_csca);
parsedCallData_csca = JSON.parse(`[${rawCallData_csca}]`);
console.log('parsedCallData_csca', parsedCallData_csca);
formattedCallData_csca = formatCallData_dsc(parsedCallData_csca);
console.log('formattedCallData_csca', formattedCallData_csca);
dsc_circuits[sigAlgName].parsedCallData = JSON.parse(`[${rawCallData_csca}]`);
dsc_circuits[sigAlgName].formattedCallData = formatCallData_dsc(dsc_circuits[sigAlgName].parsedCallData);
//console.log('inputs', sigAlgArtifacts_register.inputs);
console.log('\x1b[32m%s\x1b[0m', `Generating proof register - ${sigAlgName}`);
({ proof, publicSignals } = await groth16.fullProve(
sigAlgArtifacts.inputs,
sigAlgArtifacts.wasm,
sigAlgArtifacts.zkey
sigAlgArtifacts_register.inputs,
sigAlgArtifacts_register.wasm,
sigAlgArtifacts_register.zkey
))
console.log('\x1b[32m%s\x1b[0m', `Proof generated register - ${sigAlgName}`);
// Verify the proof
const vKey = JSON.parse(fs.readFileSync(sigAlgArtifacts.vkey) as unknown as string);
const vKey = JSON.parse(fs.readFileSync(sigAlgArtifacts_register.vkey) as unknown as string);
const verified = await groth16.verify(
vKey,
publicSignals,
@@ -292,45 +309,47 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
});
for (const sigAlgName of sigAlgNames) {
const sigAlgArtifacts = register_circuits[sigAlgName];
const sigAlgArtifacts_register = register_circuits[sigAlgName];
const sigAlgArtifacts_dsc = dsc_circuits[sigAlgName];
const sigAlgIndex = SignatureAlgorithm[sigAlgName as keyof typeof SignatureAlgorithm]
it(`Verifier contract verifies a correct proof - Register - ${sigAlgName}`, async function () {
expect(
await sigAlgArtifacts.verifier.verifyProof(
sigAlgArtifacts.parsedCallData[0],
sigAlgArtifacts.parsedCallData[1],
sigAlgArtifacts.parsedCallData[2],
sigAlgArtifacts.parsedCallData[3]
await sigAlgArtifacts_register.verifier.verifyProof(
sigAlgArtifacts_register.parsedCallData[0],
sigAlgArtifacts_register.parsedCallData[1],
sigAlgArtifacts_register.parsedCallData[2],
sigAlgArtifacts_register.parsedCallData[3]
)
).to.be.true;
});
it(`Verifier contract verifies a correct proof - DSC - ${sigAlgName}`, async function () {
expect(
await verifier_dsc.verifyProof(
parsedCallData_csca[0],
parsedCallData_csca[1],
parsedCallData_csca[2],
parsedCallData_csca[3]
await sigAlgArtifacts_dsc.verifier.verifyProof(
sigAlgArtifacts_dsc.parsedCallData[0],
sigAlgArtifacts_dsc.parsedCallData[1],
sigAlgArtifacts_dsc.parsedCallData[2],
sigAlgArtifacts_dsc.parsedCallData[3]
)
).to.be.true;
});
it(`Register with a wrong proof should fail - Register - ${sigAlgName}`, async function () {
await expect(register
.validateProof({ ...sigAlgArtifacts.formattedCallData, a: [0, 0] }, formattedCallData_csca, sigAlgIndex, sigAlgIndex))
.to.be.revertedWith("Register__InvalidProof");
.validateProof({ ...sigAlgArtifacts_register.formattedCallData, a: [0, 0] }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex))
.to.be.revertedWith("Register__InvalidProofRegister");
});
it(`Register with a wrong attestation id should fail - Register - ${sigAlgName}`, async function () {
await expect(register
.validateProof({ ...sigAlgArtifacts.formattedCallData, attestation_id: "10" }, formattedCallData_csca, sigAlgIndex, sigAlgIndex))
.validateProof({ ...sigAlgArtifacts_register.formattedCallData, attestation_id: "10" }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex))
.to.be.revertedWith("Register__InvalidAttestationId")
});
it(`Register with a wrong signature algorithm should fail - Register - ${sigAlgName}`, async function () {
await expect(register
.validateProof({ ...sigAlgArtifacts.formattedCallData }, formattedCallData_csca, sigAlgIndex + 1, sigAlgIndex))
.validateProof({ ...sigAlgArtifacts_register.formattedCallData }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex + 1, sigAlgIndex))
.to.be.revertedWith("Register__InvalidSignatureAlgorithm()")
.catch(error => {
assert(error.message.includes("Register__InvalidSignatureAlgorithm()"), "Expected revert with Register__InvalidSignatureAlgorithm(), but got another error");
@@ -339,14 +358,14 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
it(`Register with a wrong merkle root should fail - Register - ${sigAlgName}`, async function () {
await expect(register
.validateProof(sigAlgArtifacts.formattedCallData, { ...formattedCallData_csca, merkle_root: 0 }, sigAlgIndex, sigAlgIndex))
.validateProof(sigAlgArtifacts_register.formattedCallData, { ...sigAlgArtifacts_dsc.formattedCallData, merkle_root: 0 }, sigAlgIndex, sigAlgIndex))
.to.be.revertedWith("Register__InvalidMerkleRoot")
});
it(`Register should succeed - Register - ${sigAlgName}`, async function () {
await expect(register
.validateProof(sigAlgArtifacts.formattedCallData, formattedCallData_csca, sigAlgIndex, sigAlgIndex)).not.to.be.reverted;
imt.insert(BigInt(sigAlgArtifacts.formattedCallData.commitment));
.validateProof(sigAlgArtifacts_register.formattedCallData, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex)).not.to.be.reverted;
imt.insert(BigInt(sigAlgArtifacts_register.formattedCallData.commitment));
/// check if the merkle root is equal to the one from the imt
// console.log('\x1b[34m%s\x1b[0m', `IMT Merkle root of TS Object - TS: ${imt.root}`);
// console.log('\x1b[34m%s\x1b[0m', `Merkle root of contract - TSx: ${await register.getMerkleRoot()}`);
@@ -357,7 +376,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
// it(`Register with the same proof should fail - Register - ${sigAlgName}`, async function () {
// await expect(register
// .validateProof(sigAlgArtifacts.formattedCallData, sigAlgIndex))
// .validateProof(sigAlgArtifacts_register.formattedCallData, sigAlgIndex))
// .to.be.revertedWith("Register__YouAreUsingTheSameNullifierTwice()")
// .catch(error => {
// assert(error.message.includes("Register__YouAreUsingTheSameNullifierTwice()"), "Expected revert with Register__YouAreUsingTheSameNullifierTwice(), but got another error");
@@ -368,99 +387,99 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
/*** Disclose flow ***/
describe("Proof of Passport - Disclose flow", function () {
this.beforeAll(async function () {
user_address = await thirdAccount.getAddress();
// We only test with the sha256WithRSAEncryption_65537 commitment for now
// describe("Proof of Passport - Disclose flow", function () {
// this.beforeAll(async function () {
// user_address = await thirdAccount.getAddress();
// // We only test with the sha256WithRSAEncryption_65537 commitment for now
// refactor in generate inputs function
bitmap = Array(90).fill("1");
scope = BigInt(1).toString();
// // refactor in generate inputs function
// bitmap = Array(90).fill("1");
// scope = BigInt(1).toString();
majority = ["1", "8"];
input_disclose = generateCircuitInputsDisclose(
register_circuits.sha256WithRSAEncryption_65537.inputs.secret,
register_circuits.sha256WithRSAEncryption_65537.inputs.attestation_id,
mockPassportData_sha256WithRSAEncryption_65537,
imt as any,
majority,
bitmap,
scope,
BigInt(user_address.toString()).toString()
);
// Generate the proof
console.log('\x1b[32m%s\x1b[0m', 'Generating proof - Disclose');
try {
proof_result_disclose = await groth16.fullProve(
input_disclose,
path_disclose_wasm,
path_disclose_zkey
);
} catch (error) {
console.error("Error generating proof:", error);
throw error;
}
proof_disclose = proof_result_disclose.proof;
publicSignals_disclose = proof_result_disclose.publicSignals;
// majority = ["1", "8"];
// input_disclose = generateCircuitInputsDisclose(
// register_circuits.sha256WithRSAEncryption_65537.inputs.secret,
// register_circuits.sha256WithRSAEncryption_65537.inputs.attestation_id,
// mockPassportData_sha256_rsa_65537,
// imt as any,
// majority,
// bitmap,
// scope,
// BigInt(user_address.toString()).toString()
// );
// // Generate the proof
// console.log('\x1b[32m%s\x1b[0m', 'Generating proof - Disclose');
// try {
// proof_result_disclose = await groth16.fullProve(
// input_disclose,
// path_disclose_wasm,
// path_disclose_zkey
// );
// } catch (error) {
// console.error("Error generating proof:", error);
// throw error;
// }
// proof_disclose = proof_result_disclose.proof;
// publicSignals_disclose = proof_result_disclose.publicSignals;
console.log('\x1b[32m%s\x1b[0m', 'Proof generated - Disclose');
// Verify the proof
vkey_disclose = JSON.parse(fs.readFileSync(path_disclose_vkey) as unknown as string);
verified_disclose = await groth16.verify(
vkey_disclose,
publicSignals_disclose,
proof_disclose
)
console.log('\x1b[32m%s\x1b[0m', 'Proof verified - Disclose');
rawCallData_disclose = await groth16.exportSolidityCallData(proof_disclose, publicSignals_disclose);
parsedCallData_disclose = JSON.parse(`[${rawCallData_disclose}]`);
formattedCallData_disclose = formatCallData_disclose(parsedCallData_disclose);
console.log('formattedCallData_disclose', formattedCallData_disclose);
// console.log('\x1b[32m%s\x1b[0m', 'Proof generated - Disclose');
// // Verify the proof
// vkey_disclose = JSON.parse(fs.readFileSync(path_disclose_vkey) as unknown as string);
// verified_disclose = await groth16.verify(
// vkey_disclose,
// publicSignals_disclose,
// proof_disclose
// )
// console.log('\x1b[32m%s\x1b[0m', 'Proof verified - Disclose');
// rawCallData_disclose = await groth16.exportSolidityCallData(proof_disclose, publicSignals_disclose);
// parsedCallData_disclose = JSON.parse(`[${rawCallData_disclose}]`);
// formattedCallData_disclose = formatCallData_disclose(parsedCallData_disclose);
// // console.log('formattedCallData_disclose', formattedCallData_disclose);
})
// })
it("SBT mint should succeed - SBT", async function () {
await expect(sbt.mint(formattedCallData_disclose))
.to.not.be.reverted;
});
// it("SBT mint should succeed - SBT", async function () {
// await expect(sbt.mint(formattedCallData_disclose))
// .to.not.be.reverted;
// });
// // refactor in generate inputs function
// bitmap = Array(90).fill("1");
// scope = BigInt(1).toString();
// user_address = await thirdAccount.getAddress();
// majority = ["1", "8"];
// input_disclose = generateCircuitInputsDisclose(
// inputs.secret,
// inputs.attestation_id,
// passportData,
// imt as any,
// majority,
// bitmap,
// scope,
// BigInt(user_address.toString()).toString()
// );
// // Generate the proof
// console.log('\x1b[32m%s\x1b[0m', 'Generating proof - Disclose');
// try {
// proof_result_disclose = await groth16.fullProve(
// input_disclose,
// path_disclose_wasm,
// path_disclose_zkey
// );
// } catch (error) {
// console.error("Error generating proof:", error);
// throw error;
// }
// proof_disclose = proof_result_disclose.proof;
// publicSignals_disclose = proof_result_disclose.publicSignals;
// // // refactor in generate inputs function
// // bitmap = Array(90).fill("1");
// // scope = BigInt(1).toString();
// // user_address = await thirdAccount.getAddress();
// // majority = ["1", "8"];
// // input_disclose = generateCircuitInputsDisclose(
// // inputs.secret,
// // inputs.attestation_id,
// // passportData,
// // imt as any,
// // majority,
// // bitmap,
// // scope,
// // BigInt(user_address.toString()).toString()
// // );
// // // Generate the proof
// // console.log('\x1b[32m%s\x1b[0m', 'Generating proof - Disclose');
// // try {
// // proof_result_disclose = await groth16.fullProve(
// // input_disclose,
// // path_disclose_wasm,
// // path_disclose_zkey
// // );
// // } catch (error) {
// // console.error("Error generating proof:", error);
// // throw error;
// // }
// // proof_disclose = proof_result_disclose.proof;
// // publicSignals_disclose = proof_result_disclose.publicSignals;
// assert(verified_disclose == true, 'Should verify')
// // assert(verified_disclose == true, 'Should verify')
});
// });
})

View File

@@ -544,53 +544,53 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@nomicfoundation/edr-darwin-arm64@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.0.tgz#bbb43f0e01f40839b0bd38c2c443cb6910ae955f"
integrity sha512-7+rraFk9tCqvfemv9Ita5vTlSBAeO/S5aDKOgGRgYt0JEKZlrX161nDW6UfzMPxWl9GOLEDUzCEaYuNmXseUlg==
"@nomicfoundation/edr-darwin-arm64@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.2.tgz#2ff98535f272c9f2a7d06eeda93fe7b207a348a4"
integrity sha512-S+hhepupfqpBvMa9M1PVS08sVjGXsLnjyAsjhrrsjsNuTHVLhKzhkguvBD5g4If5skrwgOaVqpag4wnQbd15kQ==
"@nomicfoundation/edr-darwin-x64@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.0.tgz#b1ffcd9142418fd8498de34a7336b3f977907c86"
integrity sha512-+Hrc0mP9L6vhICJSfyGo/2taOToy1AIzVZawO3lU8Lf7oDQXfhQ4UkZnkWAs9SVu1eUwHUGGGE0qB8644piYgg==
"@nomicfoundation/edr-darwin-x64@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.2.tgz#001dcd0e7fa4c52046d283b0dc61e63a60c614dd"
integrity sha512-/zM94AUrXz6CmcsecRNHJ50jABDUFafmGc4iBmkfX/mTp4tVZj7XTyIogrQIt0FnTaeb4CgZoLap2+8tW/Uldg==
"@nomicfoundation/edr-linux-arm64-gnu@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.0.tgz#8173d16d4f6f2b3e82ba7096d2a1ea3619d8bfa7"
integrity sha512-4HUDMchNClQrVRfVTqBeSX92hM/3khCgpZkXP52qrnJPqgbdCxosOehlQYZ65wu0b/kaaZSyvACgvCLSQ5oSzQ==
"@nomicfoundation/edr-linux-arm64-gnu@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.2.tgz#6d19f8265c8ffb22e29bc5bbbb5d1913fe4b306b"
integrity sha512-TV3Pr2tFvvmCfPCi9PaCGLtqn+oLaPKfL2NWpnoCeFFdzDQXi2L930yP1oUPY5RXd78NLdVHMkEkbhb2b6Wuvg==
"@nomicfoundation/edr-linux-arm64-musl@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.0.tgz#b1ce293a7c3e0d9f70391e1aef1a82b83b997567"
integrity sha512-D4J935ZRL8xfnP3zIFlCI9jXInJ0loDUkCTLeCEbOf2uuDumWDghKNQlF1itUS+EHaR1pFVBbuwqq8hVK0dASg==
"@nomicfoundation/edr-linux-arm64-musl@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.2.tgz#0b01aa405fdc8048c7a8e95c737f29b437536a30"
integrity sha512-PALwrLBk1M9rolXyhSX8xdhe5jL0qf/PgiCIF7W7lUyVKrI/I0oiU0EHDk/Xw7yi2UJg4WRyhhZoHYa0g4g8Qg==
"@nomicfoundation/edr-linux-x64-gnu@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.0.tgz#4c12c4e4bfd3d837f5663ad7cbf7cb6d5634ef83"
integrity sha512-6x7HPy+uN5Cb9N77e2XMmT6+QSJ+7mRbHnhkGJ8jm4cZvWuj2Io7npOaeHQ3YHK+TiQpTnlbkjoOIpEwpY3XZA==
"@nomicfoundation/edr-linux-x64-gnu@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.2.tgz#10959fd4db9b333d3e0559cb893e109611889af0"
integrity sha512-5svkftypDjAZ1LxV1onojlaqPRxrTEjJLkrUwLL+Fao5ZMe7aTnk5QQ1Jv76gW6WYZnMXNgjPhRcnw3oSNrqFA==
"@nomicfoundation/edr-linux-x64-musl@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.0.tgz#8842004aa1a47c504f10863687da28b65dca7baa"
integrity sha512-3HFIJSXgyubOiaN4MWGXx2xhTnhwlJk0PiSYNf9+L/fjBtcRkb2nM910ZJHTvqCb6OT98cUnaKuAYdXIW2amgw==
"@nomicfoundation/edr-linux-x64-musl@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.2.tgz#8de64a2dfd869dad930dd0eb9572a0593d382379"
integrity sha512-qiMlXQTggdH9zfOB4Eil4rQ95z8s7QdLJcOfz5Aym12qJNkCyF9hi4cc4dDCWA0CdI3x3oLbuf8qb81SF8R45w==
"@nomicfoundation/edr-win32-x64-msvc@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.0.tgz#29d8bbb2edf9912a95f5453855cf17cdcb269957"
integrity sha512-CP4GsllEfXEz+lidcGYxKe5rDJ60TM5/blB5z/04ELVvw6/CK9eLcYeku7HV0jvV7VE6dADYKSdQyUkvd0El+A==
"@nomicfoundation/edr-win32-x64-msvc@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.2.tgz#13ad4bab9fd68853930e1a3d87c78d69d1d0e2ef"
integrity sha512-hDkAb0iaMmGYwBY/rA1oCX8VpsezfQcHPEPIEGXEcWC3WbnOgIZo0Qkpu/g0OMtFOJSQlWLXvKZuV7blhnrQag==
"@nomicfoundation/edr@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.4.0.tgz#4895ecb6ef321136db837458949c37cce4a29459"
integrity sha512-T96DMSogO8TCdbKKctvxfsDljbhFOUKWc9fHJhSeUh71EEho2qR4951LKQF7t7UWEzguVYh/idQr5L/E3QeaMw==
"@nomicfoundation/edr@^0.4.1":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.4.2.tgz#9d7550182d4f75d7510e265ebd3474c4f6fcb62a"
integrity sha512-U7v0HuZHfrsl/5FpUzuB2FYA0+FUglHHwiO6NhvLtNYKMZcPzdS6iUriMp/7GWs0SVxW3bAht9GinZPxdhVwWg==
dependencies:
"@nomicfoundation/edr-darwin-arm64" "0.4.0"
"@nomicfoundation/edr-darwin-x64" "0.4.0"
"@nomicfoundation/edr-linux-arm64-gnu" "0.4.0"
"@nomicfoundation/edr-linux-arm64-musl" "0.4.0"
"@nomicfoundation/edr-linux-x64-gnu" "0.4.0"
"@nomicfoundation/edr-linux-x64-musl" "0.4.0"
"@nomicfoundation/edr-win32-x64-msvc" "0.4.0"
"@nomicfoundation/edr-darwin-arm64" "0.4.2"
"@nomicfoundation/edr-darwin-x64" "0.4.2"
"@nomicfoundation/edr-linux-arm64-gnu" "0.4.2"
"@nomicfoundation/edr-linux-arm64-musl" "0.4.2"
"@nomicfoundation/edr-linux-x64-gnu" "0.4.2"
"@nomicfoundation/edr-linux-x64-musl" "0.4.2"
"@nomicfoundation/edr-win32-x64-msvc" "0.4.2"
"@nomicfoundation/ethereumjs-common@4.0.4":
version "4.0.4"
@@ -1754,10 +1754,10 @@ command-line-usage@^6.1.0:
table-layout "^1.0.2"
typical "^5.2.0"
commander@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e"
integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==
commander@^8.1.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
concat-map@0.0.1:
version "0.0.1"
@@ -2356,17 +2356,6 @@ fp-ts@^1.0.0:
resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a"
integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A==
fs-extra@^0.30.0:
version "0.30.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==
dependencies:
graceful-fs "^4.1.2"
jsonfile "^2.1.0"
klaw "^1.0.0"
path-is-absolute "^1.0.0"
rimraf "^2.2.8"
fs-extra@^10.0.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
@@ -2560,7 +2549,7 @@ gopd@^1.0.1:
dependencies:
get-intrinsic "^1.1.3"
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.9:
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
@@ -2595,14 +2584,14 @@ hardhat-gas-reporter@^1.0.10:
eth-gas-reporter "^0.2.25"
sha1 "^1.1.1"
hardhat@^2.22.3:
version "2.22.5"
resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.5.tgz#7e1a4311fa9e34a1cfe337784eae06706f6469a5"
integrity sha512-9Zq+HonbXCSy6/a13GY1cgHglQRfh4qkzmj1tpPlhxJDwNVnhxlReV6K7hCWFKlOrV13EQwsdcD0rjcaQKWRZw==
hardhat@^2.22.6:
version "2.22.6"
resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.6.tgz#d73caece246cd8219a1815554dabc31d400fa035"
integrity sha512-abFEnd9QACwEtSvZZGSmzvw7N3zhQN1cDKz5SLHAupfG24qTHofCjqvD5kT5Wwsq5XOL0ON1Mq5rr4v0XX5ciw==
dependencies:
"@ethersproject/abi" "^5.1.2"
"@metamask/eth-sig-util" "^4.0.0"
"@nomicfoundation/edr" "^0.4.0"
"@nomicfoundation/edr" "^0.4.1"
"@nomicfoundation/ethereumjs-common" "4.0.4"
"@nomicfoundation/ethereumjs-tx" "5.0.4"
"@nomicfoundation/ethereumjs-util" "9.0.4"
@@ -2636,7 +2625,7 @@ hardhat@^2.22.3:
raw-body "^2.4.1"
resolve "1.17.0"
semver "^6.3.0"
solc "0.7.3"
solc "0.8.26"
source-map-support "^0.5.13"
stacktrace-parser "^0.1.10"
tsort "0.0.1"
@@ -2985,13 +2974,6 @@ json-stringify-safe@^5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
jsonfile@^2.1.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==
optionalDependencies:
graceful-fs "^4.1.6"
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@@ -3036,13 +3018,6 @@ kind-of@^6.0.2:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
klaw@^1.0.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439"
integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==
optionalDependencies:
graceful-fs "^4.1.9"
kleur@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
@@ -3661,7 +3636,7 @@ require-directory@^2.1.1:
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
require-from-string@^2.0.0, require-from-string@^2.0.2:
require-from-string@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
@@ -3697,13 +3672,6 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rimraf@^2.2.8:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
dependencies:
glob "^7.1.3"
ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
@@ -3889,18 +3857,16 @@ snarkjs@^0.7.1:
logplease "^1.2.15"
r1csfile "0.0.48"
solc@0.7.3:
version "0.7.3"
resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a"
integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==
solc@0.8.26:
version "0.8.26"
resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a"
integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==
dependencies:
command-exists "^1.2.8"
commander "3.0.2"
commander "^8.1.0"
follow-redirects "^1.12.1"
fs-extra "^0.30.0"
js-sha3 "0.8.0"
memorystream "^0.3.1"
require-from-string "^2.0.0"
semver "^5.5.0"
tmp "0.0.33"

View File

@@ -25,7 +25,7 @@ describe('MODAL PROVER', function () {
this.timeout(0); // Disable timeout
describe("SHA256 RSA", async () => {
it("verify proof", async () => {
const circuitInputs = getCSCAInputs(
const inputs = getCSCAInputs(
BigInt(0).toString(),
dscCert_sha256_rsa,
cscaCert_sha256_rsa,
@@ -36,10 +36,6 @@ describe('MODAL PROVER', function () {
max_cert_bytes,
true
);
const inputs = {
"signature_algorithm": "sha256_rsa",
"inputs": circuitInputs
}
//console.log(JSON.stringify(inputs));
console.log('\x1b[34msending request to modal server\x1b[0m');
const response = await sendCSCARequest(inputs);
@@ -57,7 +53,7 @@ describe('MODAL PROVER', function () {
describe("SHA1 RSA", async () => {
it("verify proof", async () => {
const circuitInputs = getCSCAInputs(
const inputs = getCSCAInputs(
BigInt(0).toString(),
dscCert_sha1_rsa,
cscaCert_sha1_rsa,
@@ -68,10 +64,6 @@ describe('MODAL PROVER', function () {
max_cert_bytes,
true
);
const inputs = {
"signature_algorithm": "sha1_rsa",
"inputs": circuitInputs
}
console.log(JSON.stringify(inputs));
console.log('\x1b[34msending request to modal server\x1b[0m');

View File

@@ -1,3 +0,0 @@
TEST_ADDRESS = "0x000000000000000000000000000000000000000"
TOKEN_ID = "0"
MOCK_MERKLE_ROOT_CHECK = "false"

3
sdk/.gitignore vendored
View File

@@ -1,3 +1,4 @@
node_modules/
yarn.lock
yarn-error.log
yarn-error.log
dist

View File

@@ -0,0 +1,2 @@
import { QRCodeGenerator } from "./QRCodeGenerator";

File diff suppressed because one or more lines are too long

View File

@@ -1,18 +1,18 @@
export class ProofOfPassportVerifierReport {
scope: boolean = false;
merkle_root: boolean = false;
attestation_id: boolean = false;
current_date: boolean = false;
issuing_state: boolean = false;
name: boolean = false;
passport_number: boolean = false;
nationality: boolean = false;
date_of_birth: boolean = false;
gender: boolean = false;
expiry_date: boolean = false;
older_than: boolean = false;
owner_of: boolean = false;
proof: boolean = false;
scope: boolean = true;
merkle_root: boolean = true;
attestation_id: boolean = true;
current_date: boolean = true;
issuing_state: boolean = true;
name: boolean = true;
passport_number: boolean = true;
nationality: boolean = true;
date_of_birth: boolean = true;
gender: boolean = true;
expiry_date: boolean = true;
older_than: boolean = true;
owner_of: boolean = true;
proof: boolean = true;
valid: boolean = true;
@@ -21,8 +21,9 @@ export class ProofOfPassportVerifierReport {
constructor() { }
exposeAttribute(attribute: keyof ProofOfPassportVerifierReport) {
(this[attribute] as boolean) = true;
exposeAttribute(attribute: keyof ProofOfPassportVerifierReport, value: any = "", expectedValue: any = "") {
console.log('exposeAttribute', attribute, "value:", value, "expectedValue:", expectedValue);
(this[attribute] as boolean) = false;
this.valid = false;
}

View File

@@ -1,23 +1,19 @@
import { groth16 } from 'snarkjs';
import fs from 'fs';
import { attributeToPosition, countryCodes, DEFAULT_RPC_URL, PASSPORT_ATTESTATION_ID } from '../common/src/constants/constants';
import { attributeToPosition, countryCodes, DEFAULT_RPC_URL, PASSPORT_ATTESTATION_ID } from './common/src/constants/constants';
import { checkMerkleRoot, getCurrentDateFormatted, parsePublicSignals, unpackReveal } from './utils';
import dotenv from 'dotenv';
import { ProofOfPassportVerifierReport } from './ProofOfPassportVerifierReport';
import { vkey_disclose } from './common/src/constants/vkey';
dotenv.config();
const path_disclose_vkey = "../circuits/build/disclose_vkey.json";
const MOCK_MERKLE_ROOT_CHECK = process.env.MOCK_MERKLE_ROOT_CHECK === 'true' ? true : false;
const MOCK_MERKLE_ROOT_CHECK = false;
export class ProofOfPassportWeb2Verifier {
scope: string;
attestationId: string;
requirements: Array<[string, number | string]>;
requirements: string[][];
rpcUrl: string;
report: ProofOfPassportVerifierReport;
constructor(options: { scope: string, attestationId?: string, requirements?: Array<[string, number | string]>, rpcUrl?: string }) {
constructor(options: { scope: string, attestationId?: string, requirements?: string[][], rpcUrl?: string }) {
this.scope = options.scope;
this.attestationId = options.attestationId || PASSPORT_ATTESTATION_ID;
this.requirements = options.requirements || [];
@@ -29,7 +25,7 @@ export class ProofOfPassportWeb2Verifier {
const parsedPublicSignals = parsePublicSignals(proofOfPassportWeb2Inputs.publicSignals);
//1. Verify the scope
if (parsedPublicSignals.scope !== this.scope) {
this.report.exposeAttribute('scope');
this.report.exposeAttribute('scope', parsedPublicSignals.scope, this.scope);
}
console.log('\x1b[32m%s\x1b[0m', `- scope verified`);
@@ -42,13 +38,13 @@ export class ProofOfPassportWeb2Verifier {
//3. Verify the attestation_id
if (parsedPublicSignals.attestation_id !== this.attestationId) {
this.report.exposeAttribute('attestation_id');
this.report.exposeAttribute('attestation_id', parsedPublicSignals.attestation_id, this.attestationId);
}
console.log('\x1b[32m%s\x1b[0m', `- attestation_id verified`);
//4. Verify the current_date
if (parsedPublicSignals.current_date.toString() !== getCurrentDateFormatted().toString()) {
this.report.exposeAttribute('current_date');
this.report.exposeAttribute('current_date', parsedPublicSignals.current_date, getCurrentDateFormatted());
}
console.log('\x1b[32m%s\x1b[0m', `- current_date verified`);
@@ -77,11 +73,14 @@ export class ProofOfPassportWeb2Verifier {
}
//6. Verify the proof
const vkey_disclose = JSON.parse(fs.readFileSync(path_disclose_vkey) as unknown as string);
console.log(vkey_disclose);
console.log("publicSignals", proofOfPassportWeb2Inputs.publicSignals);
console.log("proof", proofOfPassportWeb2Inputs.proof);
const verified_disclose = await groth16.verify(
vkey_disclose,
proofOfPassportWeb2Inputs.publicSignals,
proofOfPassportWeb2Inputs.proof
proofOfPassportWeb2Inputs.proof as any
)
if (!verified_disclose) {
this.report.exposeAttribute('proof');

View File

@@ -1,7 +1,7 @@
import { DEFAULT_RPC_URL, PASSPORT_ATTESTATION_ID, SBT_ABI, SBT_CONTRACT_ADDRESS } from '../common/src/constants/constants';
import { DEFAULT_RPC_URL, PASSPORT_ATTESTATION_ID, SBT_ABI, SBT_CONTRACT_ADDRESS } from './common/src/constants/constants';
import { ethers } from 'ethers';
import { attributeToGetter } from './utils';
import { ProofOfPassportVerifierReport } from "./ProofOfPassportVerifierReport";
import { ProofOfPassportVerifierReport } from './ProofOfPassportVerifierReport';
export class ProofOfPassportWeb3Verifier {
scope: string;

21
sdk/QRCodeGenerator.ts Normal file
View File

@@ -0,0 +1,21 @@
import QRCode from 'easyqrcodejs';
import { AppType } from "../common/src/utils/appType";
export class QRCodeGenerator {
static async generateQRCode(appData: AppType, size: number = 256): Promise<HTMLElement> {
const qrData = this.serializeAppType(appData);
const options = {
text: qrData,
width: size,
height: size,
};
const element = document.createElement('div');
new QRCode(element, options);
return element;
}
private static serializeAppType(appType: AppType): string {
return JSON.stringify(appType);
}
}

View File

@@ -1,92 +0,0 @@
# SDK
## Installation
```bash
yarn add @proofofpassport/sdk
```
## Development
```bash
yarn install-sdk
```
## Tests
```bash
yarn test
```
## How to use
### Web2 applications
To use the `ProofOfPassportWeb2Verifier` in Web2 applications, import and initialize it as follows:
```typescript
import { ProofOfPassportWeb2Verifier } from '@proofofpassport/sdk';
const verifier = new ProofOfPassportWeb2Verifier({
scope: "yourScope",
requirements: [["older_than", "18"], ["nationality", "France"]]
});
```
#### parameters for `ProofOfPassportWeb2Verifier`
| Parameter | Optional | Description |
|---------------|----------|-------------|
| `scope` | No | The scope of your application, is unique for each application. |
| `attestationId` | Yes | The ID of the attestation, defaults to `PASSPORT_ATTESTATION_ID`. |
| `requirements` | Yes | An array of requirements, each an array with an attribute and its expected value. |
| `rpcUrl` | Yes | The RPC URL to connect to the blockchain, defaults to `DEFAULT_RPC_URL`. |
Finally, verify the proof:
The function fired from the Proof of Passport app will send a `ProofOfPassportWeb2Inputs` object.
```typescript
const result = await verifier.verify(proofOfPassportWeb2Inputs); // proofOfPassportWeb2Inputs : ProofOfPassportWeb2Inputs
```
### Web3 application
For Web3 applications, use the `ProofOfPassportWeb3Verifier` as follows:
```typescript
import { ProofOfPassportWeb3Verifier } from '@proofofpassport/sdk';
const verifier = new ProofOfPassportWeb3Verifier({
scope: "yourScope",
rpcUrl: "https://custom.rpc.url"
});
```
#### Parameters for `ProofOfPassportWeb3Verifier`
| Parameter | Optional | Description |
|---------------|----------|-------------|
| `scope` | No | The scope of the verification. |
| `attestationId` | Yes | The ID of the attestation, defaults to `PASSPORT_ATTESTATION_ID`. |
| `requirements` | Yes | An array of requirements, each an array with an attribute and its expected value. |
| `rpcUrl` | Yes | The RPC URL to connect to the blockchain, defaults to `DEFAULT_RPC_URL`. |
#### Verify the user owns a sbt which satisfies the requirements:
```typescript
const result = await verifier.verify(address, tokenId);
```
### Handle the report
Each verification will returns a ProofOfPassportReport object which contains all the informations about the verification of each requirement.
If a requirement is not satisfied, the corresponding field will be set to `true`.
The `valid` field will be `false` if there is at least one requirement that is not satisfied.
`nullifier` and `user_identifier` are also accessible as report fields.
```typescript
const report = await verifier.verify(publicSignals, proof);
const nullifier = report.nullifier;
const userIdentifier = report.user_identifier;
```

48
sdk/WebSocket.ts Normal file
View File

@@ -0,0 +1,48 @@
import io, { Socket } from 'socket.io-client';
export class ProofWebSocket {
private socket: Socket;
private callbacks: { [key: string]: (data: any) => void } = {};
constructor(url: string) {
this.socket = io(url);
this.setupListeners();
}
private setupListeners() {
this.socket.on('proof_generation_started', (data) => this.triggerCallback('proofGenerationStarted', data));
this.socket.on('proof_generation_progress', (data) => this.triggerCallback('proofGenerationProgress', data));
this.socket.on('proof_submitted', (data) => this.triggerCallback('proofSubmitted', data));
this.socket.on('proof_verified', (data) => this.triggerCallback('proofVerified', data));
}
private triggerCallback(event: string, data: any) {
if (this.callbacks[event]) {
this.callbacks[event](data);
}
}
on(event: string, callback: (data: any) => void) {
this.callbacks[event] = callback;
}
emitProofGenerationStarted(userId: string) {
this.socket.emit('proof_generation_started', { userId });
}
emitProofGenerationProgress(userId: string, progress: number) {
this.socket.emit('proof_generation_progress', { userId, progress });
}
emitProofSubmitted(userId: string, proofId: string) {
this.socket.emit('proof_submitted', { userId, proofId });
}
emitProofVerified(userId: string, proofId: string, isValid: boolean) {
this.socket.emit('proof_verified', { userId, proofId, isValid });
}
disconnect() {
this.socket.disconnect();
}
}

368
sdk/certificates.ts Normal file
View File

@@ -0,0 +1,368 @@
export const pem1 = `-----BEGIN CERTIFICATE-----
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
j/sfUhyHHc9GFJPteLrV
-----END CERTIFICATE-----
`
export const pem2 = `-----BEGIN CERTIFICATE-----
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
24YnLM+7w0NVPvwClrpt
-----END CERTIFICATE-----
`
export const pem3 = `-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
`
export const pem4 = `-----BEGIN CERTIFICATE-----
MIIHFDCCBPygAwIBAgIETjLQBjANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMC
VVMxGDAWBgNVBAoMD1UuUy4gR292ZXJubWVudDEcMBoGA1UECwwTRGVwYXJ0bWVu
dCBvZiBTdGF0ZTENMAsGA1UECwwETVJURDEiMCAGA1UECwwZQ2VydGlmaWNhdGlv
biBBdXRob3JpdGllczEpMCcGA1UECwwgVS5TLiBEZXBhcnRtZW50IG9mIFN0YXRl
IE1SVEQgQ0EwHhcNMTkxMTE0MTYzNzEyWhcNNDAwNTE0MTcwNzEyWjCBozELMAkG
A1UEBhMCVVMxGDAWBgNVBAoMD1UuUy4gR292ZXJubWVudDEcMBoGA1UECwwTRGVw
YXJ0bWVudCBvZiBTdGF0ZTENMAsGA1UECwwETVJURDEiMCAGA1UECwwZQ2VydGlm
aWNhdGlvbiBBdXRob3JpdGllczEpMCcGA1UECwwgVS5TLiBEZXBhcnRtZW50IG9m
IFN0YXRlIE1SVEQgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCj
Mg42Fipd4tZOLauEOb5fZlfU4xSv+PsNmBzrNdntXOxhUH7oBGIhuiTvtLE+2T1l
5Qiq6ONbn0nJv4RSIjqCIhk673NjsED41B+Fl7LDOvVcpeF9E53maZSK/c3Pm6Qw
EXAGgJo4dRyGirCaXfmUKT5fsrc05L74dZufG9FAWo4i2xNxoyDaOn0EX6+YevSd
u5yyLjMDcHNQpaytu9xXTkzgf/KjKu7/m6rwmS1LFvELMreIpdXKLpLBGQ6Il6Rv
O1Uqi4QtCVWGWEZpxQ5Dy5v49NriBFYpUe2HrxiZhbmTXb/YHnYKvMCd3EIZ7B83
kq8PLnChAQNcdwn472zneWJiNkU1Tlx4v5HjyNShctU+4KZcVAqqjU3+376VZHqJ
xbLy2WUdkayvUYNVfT4Rj7SAlRQtH5I/OwCq3kiAKrQGVD+LPiItRLx8CgezjoBT
e7/Ic1FqkG7dc6orAKZAfYc1S59RnIPnpxVogHMTQgtYrBjsdoRw/bzLQP/746mo
/PjhzxiHAtxJ2ghgkg5vcXMFWyr7UHbdV6pNnwjGkOQjjC6YEvAlL54nXfpcFR6A
vWFBC/kFGtw39eAn3DILjdA353wt8FZRlCh3LuQpcLQq2tq2AfDBrMJ3GXw9HenR
p5du95QFsmbJFBLbuMPKSdythSvOQbxZFaGtbS1RHQIDAQABo4IBTDCCAUgwHAYD
VR0SBBUwE4ERbXJ0ZG9wc0BzdGF0ZS5nb3YwHAYDVR0RBBUwE4ERbXJ0ZG9wc0Bz
dGF0ZS5nb3YwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwgZkG
A1UdHwSBkTCBjjCBi6CBiKCBhYYqaHR0cHM6Ly9wa2Rkb3dubG9hZDEuaWNhby5p
bnQvQ1JMcy9VU0EuY3JshipodHRwczovL3BrZGRvd25sb2FkMi5pY2FvLmludC9D
UkxzL1VTQS5jcmyGK2h0dHA6Ly9jcmxzLnBraS5zdGF0ZS5nb3YvY3Jscy9VU01S
VERDQS5jcmwwKwYDVR0QBCQwIoAPMjAxOTExMTQxNjM3MTJagQ8yMDI1MDUxNTEw
MDkwOVowHQYDVR0OBBYEFPGKi/tqRKNGgzTS1ZIVgViCSkz7MA0GCSqGSIb3DQEB
CwUAA4ICAQARoYLCR1di+iUGqrcBi/ABSFx4oHm2cJzMAT7cs6cUAbzeGhFELYEC
Jzjbwb93lQgg8IpFl8mcBPT4yoMlZDZKKzDiztI9hTwLJw054n5oRk6YJm/45g3Q
1HUb+0wv6HzXfRlCx1fjPsPQFOpcKIKgdNc1QarEaxnUSHG29ie9E2WR3dD8yCFW
kbdGvmlf4FO+P1O+gfUwSbfLuuUg5RDif9bU+D7VBzuC+6QxueKRo6y99ZZcmHTJ
6dsaw/oKABOB+FfSad2RGLvpIynpKjpPNpoFw8H8FcSpOiwpdtSp5tdgLAKVwR/6
hVMGhuwsSxmxknbLopaKSBC1shp4uZNOlSNjh/d2ssYfGPLrWuTARb/dD9H9SQjg
eqWZV8CJ8cNASsgenIwbygmH70J2p3+qlmA4WLq86qpOzrCUOZaUHYuVSjTEb8fy
CGUjAparnyVnPEUwqeVWOC9tbZtscV9WE4A9c0u8gr1DPVVWIdXrhdpXeOZQwJDm
sKLyTo/yp7GYLMBvNZcMz+orcsyTXoznGk/Xu/7piTpKQZ+EPT8yBp3zb2zNs0Cp
iNTD+szdm/UZE4Wl0kfzCPAz0fSKprZa7ifoiaZZzOwzkpnkpU2SuYcKQqyTw0E+
Up7Z2qhj2NjkxaikFjTjm4d03dwnU+ojALwufJG1LIj9VShAVQG0ZQ==
-----END CERTIFICATE-----
`
export const mock_csca = `-----BEGIN CERTIFICATE-----
MIIFpzCCA4+gAwIBAgIUVGoAk38qsh7YYIE2eANMIeZkr+IwDQYJKoZIhvcNAQEL
BQAwYzELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCU1vY2tTdGF0ZTERMA8GA1UEBwwI
TW9ja0NpdHkxGTAXBgNVBAoMEE1vY2tPcmdhbml6YXRpb24xEjAQBgNVBAMMCW1v
Y2tfY3NjYTAeFw0yNDA2MTgxOTA4MzJaFw0yNTA2MTgxOTA4MzJaMGMxCzAJBgNV
BAYTAlhYMRIwEAYDVQQIDAlNb2NrU3RhdGUxETAPBgNVBAcMCE1vY2tDaXR5MRkw
FwYDVQQKDBBNb2NrT3JnYW5pemF0aW9uMRIwEAYDVQQDDAltb2NrX2NzY2EwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDE0JWh/kOzueMgFHwqLHYabpx4
T0OV58DPuJObuMIKugw8/5l1VLg/Zq2II8/FoATn0Is3JYOidHnFskgkKjW89gxv
RYRlYFPcvRfAxy+3+AO2f3xCnavkNTUI3Jl9q3jBz05SqHgM1cHiYr61ZX5sA980
OveugRWBbT1mEUNhXTnegfPI9K3b+6YL0QXUePXGpRD9f5lTiCoE/mW8wGkieBYx
QEEskwVpV3cvqwoLCkbdZkRZmIsYE6u7HeAPw2p/yAK6DhqY/vH3svj3LpWvdzBi
Av1wBuuZ6IDgoB0tbgCPOUuc+btezBKhmZXDau0UZc9Y3ND+bMCQEWieXSwCWFYg
y41/onaCaLdT+kcvwdOENNVNvHpaYVDnZGWdt8A95w/dl4Dl19wcL3KkqxoFGB8e
wG+/SDnYTuuGWY3zaROJQ3KYlCqNi3+OuzZTBiJTujaL3Eb/+7Smhy/qtdd6bVUg
mpf3fdBHw+jjl2st+n1rfIYY8rYY7HGrJdome9jXS8pCNfnptp+J8urzgXfEXGFM
qHwMKu/vtfiBt4a1+GC/i2ssaXRcGABiI4xG4BQYXT+4U3p0pAA7cDNH5jN0Wny7
J5DuEyXzcrRQVFD9hiFmDJfAsc35UwHKpayu9F7JJC4EfWVdahgA9VLhxVIE+eTi
HPRHFyMaVaeqmjrBLQIDAQABo1MwUTAdBgNVHQ4EFgQUVGhgTF0HCJvSxKtE0BvV
tQNMt0cwHwYDVR0jBBgwFoAUVGhgTF0HCJvSxKtE0BvVtQNMt0cwDwYDVR0TAQH/
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAtyt8sirr9jc8i5xEnpV3YM6m0poY
bl2S5hDu+xmMRnl8r3lv3v1KE2XrZD0cldV8plYz6oXfWBkCj3j6RUbsNx8w1q27
Qsb2NC1KZljYG+kHavIIdJty9FOknhgYSYW+UKixSHPuAS+iJxEmGBN8GxhMPpzM
KRzWbpQuPZuBgyKRSeR5ytGqyZrEje9zhkdSg/aFYn3EzLw93CfzrDLrKmXc/dra
vEDyP34ts0Cy7UadCGkJN/SPuZpvF9Fy5f7l8ymHE319ipNZHIMhw50h0l/Puzjd
vn3iHWtwpFw5r+nJTr5zO+3yL4dPcp8XfX3Daa5nDfCJ7dd1wSOf+/1cvBLB5aKc
kyZ/ppvTc3oJAmFHAD2NXf15CUWE18Te/Vy9X2qI8LkFtea6GDF4VBewT2PATg12
r03xZWa6KFVbgTIq3GUvtZ8UHm+cluTFKX90rFtbzFo658mxQGw5RnE2zp340NzP
v9tNSlP4Tyzr2b1VoQcgmpQ987afINJG39lq2OsSrlK87p9bB4yoFSZwOfqok0nM
IICRxBuTUHLqP3Nhvo+tAl+iK848LDJVf87ZVQHl72JX4lkVvOo5LCXnOQPyowaP
D++J2c6tUj6gs9HAKVX7fH06m/2T5fJHae/OYx36O242yBXPQdHx6qloF/DNvGyM
EHC3NCCjLG5m6G0=
-----END CERTIFICATE-----
`
export const fr1pem = `-----BEGIN CERTIFICATE-----
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
3sTE6mYNoV8bK4+Y
-----END CERTIFICATE-----
`
export const fr2pem = `-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
`
export const fr3pem = `-----BEGIN CERTIFICATE-----
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
iksuh3S4gaW0c9jK
-----END CERTIFICATE-----
`
export const fr4pem = `-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
`
export const mockpem = `-----BEGIN CERTIFICATE-----
MIIFpzCCA4+gAwIBAgIUVGoAk38qsh7YYIE2eANMIeZkr+IwDQYJKoZIhvcNAQEL
BQAwYzELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCU1vY2tTdGF0ZTERMA8GA1UEBwwI
TW9ja0NpdHkxGTAXBgNVBAoMEE1vY2tPcmdhbml6YXRpb24xEjAQBgNVBAMMCW1v
Y2tfY3NjYTAeFw0yNDA2MTgxOTA4MzJaFw0yNTA2MTgxOTA4MzJaMGMxCzAJBgNV
BAYTAlhYMRIwEAYDVQQIDAlNb2NrU3RhdGUxETAPBgNVBAcMCE1vY2tDaXR5MRkw
FwYDVQQKDBBNb2NrT3JnYW5pemF0aW9uMRIwEAYDVQQDDAltb2NrX2NzY2EwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDE0JWh/kOzueMgFHwqLHYabpx4
T0OV58DPuJObuMIKugw8/5l1VLg/Zq2II8/FoATn0Is3JYOidHnFskgkKjW89gxv
RYRlYFPcvRfAxy+3+AO2f3xCnavkNTUI3Jl9q3jBz05SqHgM1cHiYr61ZX5sA980
OveugRWBbT1mEUNhXTnegfPI9K3b+6YL0QXUePXGpRD9f5lTiCoE/mW8wGkieBYx
QEEskwVpV3cvqwoLCkbdZkRZmIsYE6u7HeAPw2p/yAK6DhqY/vH3svj3LpWvdzBi
Av1wBuuZ6IDgoB0tbgCPOUuc+btezBKhmZXDau0UZc9Y3ND+bMCQEWieXSwCWFYg
y41/onaCaLdT+kcvwdOENNVNvHpaYVDnZGWdt8A95w/dl4Dl19wcL3KkqxoFGB8e
wG+/SDnYTuuGWY3zaROJQ3KYlCqNi3+OuzZTBiJTujaL3Eb/+7Smhy/qtdd6bVUg
mpf3fdBHw+jjl2st+n1rfIYY8rYY7HGrJdome9jXS8pCNfnptp+J8urzgXfEXGFM
qHwMKu/vtfiBt4a1+GC/i2ssaXRcGABiI4xG4BQYXT+4U3p0pAA7cDNH5jN0Wny7
J5DuEyXzcrRQVFD9hiFmDJfAsc35UwHKpayu9F7JJC4EfWVdahgA9VLhxVIE+eTi
HPRHFyMaVaeqmjrBLQIDAQABo1MwUTAdBgNVHQ4EFgQUVGhgTF0HCJvSxKtE0BvV
tQNMt0cwHwYDVR0jBBgwFoAUVGhgTF0HCJvSxKtE0BvVtQNMt0cwDwYDVR0TAQH/
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAtyt8sirr9jc8i5xEnpV3YM6m0poY
bl2S5hDu+xmMRnl8r3lv3v1KE2XrZD0cldV8plYz6oXfWBkCj3j6RUbsNx8w1q27
Qsb2NC1KZljYG+kHavIIdJty9FOknhgYSYW+UKixSHPuAS+iJxEmGBN8GxhMPpzM
KRzWbpQuPZuBgyKRSeR5ytGqyZrEje9zhkdSg/aFYn3EzLw93CfzrDLrKmXc/dra
vEDyP34ts0Cy7UadCGkJN/SPuZpvF9Fy5f7l8ymHE319ipNZHIMhw50h0l/Puzjd
vn3iHWtwpFw5r+nJTr5zO+3yL4dPcp8XfX3Daa5nDfCJ7dd1wSOf+/1cvBLB5aKc
kyZ/ppvTc3oJAmFHAD2NXf15CUWE18Te/Vy9X2qI8LkFtea6GDF4VBewT2PATg12
r03xZWa6KFVbgTIq3GUvtZ8UHm+cluTFKX90rFtbzFo658mxQGw5RnE2zp340NzP
v9tNSlP4Tyzr2b1VoQcgmpQ987afINJG39lq2OsSrlK87p9bB4yoFSZwOfqok0nM
IICRxBuTUHLqP3Nhvo+tAl+iK848LDJVf87ZVQHl72JX4lkVvOo5LCXnOQPyowaP
D++J2c6tUj6gs9HAKVX7fH06m/2T5fJHae/OYx36O242yBXPQdHx6qloF/DNvGyM
EHC3NCCjLG5m6G0=
-----END CERTIFICATE-----
`

View File

@@ -0,0 +1,159 @@
{
"protocol": "groth16",
"curve": "bn128",
"nPublic": 14,
"vk_alpha_1": [
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
"1"
],
"vk_beta_2": [
[
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
],
[
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
],
[
"1",
"0"
]
],
"vk_gamma_2": [
[
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
],
[
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
],
[
"1",
"0"
]
],
"vk_delta_2": [
[
"6942436740229168666595536581519256291593117600832247164924519038970269461046",
"17557865657217054151399710026819127874171362865266657132072043760282335721027"
],
[
"15629082942757783052734933529055204330846116501031658743204188522840567440030",
"866803245463331646327183913175583329159450203348438102150009828684148559895"
],
[
"1",
"0"
]
],
"vk_alphabeta_12": [
[
[
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
],
[
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
],
[
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
]
],
[
[
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
],
[
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
],
[
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
]
]
],
"IC": [
[
"10998553002727424987884583305349753345629818748955483305954960876370686844925",
"18369020735737057562107768810182682586161750799521907185011795199521493953276",
"1"
],
[
"3870156317905136354369536369223776179854927352937539086581682263147147725326",
"947908099816727525943796981035826395896386995128918341433720280874486019589",
"1"
],
[
"9619614659642762666110070745787072277198407288262286655564043642023793950605",
"1444870940646607538213811271690623291794427513321591343855928143309974143815",
"1"
],
[
"10290556281387838061211784545032614883237381276187632418810139452226710406378",
"12820288689147023950592422696432066467590193138126598372596214785570201388663",
"1"
],
[
"10044189939644279332588298610988772483187101321076758071894028734198440253205",
"15016612240779620571490237444430121691511928826472608688773111463692886510804",
"1"
],
[
"6158786594227478832634691320618082224218218524296943509099128649963428556955",
"2818896662082406397657145229256654653904841140122301210666395782176903475916",
"1"
],
[
"200295911748915977788397688942615122670319721182540082686195028815964792730",
"16374098866162622474777608838325780437892472095191094825634065695603492498672",
"1"
],
[
"1001933084599581827076405562561115761770358156189382784432273793509010836288",
"13618159500648302749264797924828312592779374840705268445533823753672345860949",
"1"
],
[
"12152127135355257668073159516593687751413730484411437719952408933610175077761",
"15590965974244077225547659000022179448961631917634079092877797469009672737373",
"1"
],
[
"14643873766083688335082369233094018379987105460165787549629338089338629672719",
"18976194036990056092890684065171543382286602242265347684324001010669281606450",
"1"
],
[
"4974359282562923295097396773583362835614429754286473873410152881834388935350",
"2615967425575591157936435871031665935046196308487298765704452331348089292330",
"1"
],
[
"16489750714044704248135942822786071904168862423655325973193848507501139487825",
"4644993658884496411511912365771411317040070112230395754480725062427812526601",
"1"
],
[
"11801682757910657983396995619983996921870874978799260563404809167285348391422",
"19228652101325919244735412842681375925619382430642205708320466729501949572254",
"1"
],
[
"4495248066509783309072792039672520701419947625749866524660708846549914823847",
"4585216314173588273427806971446529726371555267351812069737927114283850919560",
"1"
],
[
"18719866673490039760627957665040843673978402675108669037278157044178865894074",
"11183065716352601580915387671262116390467334689778841393328736869598818253587",
"1"
]
]
}

View File

@@ -0,0 +1,99 @@
{
"protocol": "groth16",
"curve": "bn128",
"nPublic": 2,
"vk_alpha_1": [
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
"1"
],
"vk_beta_2": [
[
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
],
[
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
],
[
"1",
"0"
]
],
"vk_gamma_2": [
[
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
],
[
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
],
[
"1",
"0"
]
],
"vk_delta_2": [
[
"5689878758968408864570330769586116386424915777760869435924001045372426387042",
"14835593574773248144471339475507473753186624066904877663229402603601341881110"
],
[
"2051149603231436076479384106975809917151570357124249160820058911298166997663",
"628452860859295088428620228489450512026200467380394004198146223506590955249"
],
[
"1",
"0"
]
],
"vk_alphabeta_12": [
[
[
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
],
[
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
],
[
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
]
],
[
[
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
],
[
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
],
[
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
]
]
],
"IC": [
[
"14532585603301627491293557600415273871129994972736322653869196794622673732921",
"18882397311658692526609112965864523608034856647654838257030831022893270548325",
"1"
],
[
"4186298633367159062520988354552715829159959996352603762446141935317873102425",
"3924212783150620566854971503130830169563464952561919541343311327675656189646",
"1"
],
[
"4437362653636713552232717650847448346211317604147264938993567382296904710753",
"2938386579388053271692442071404949636853984120968379123259292205410760857324",
"1"
]
]
}

Some files were not shown because too many files have changed in this diff Show More