Merge pull request #34 from zk-passport/dev

Fix poseidon bug
This commit is contained in:
turboblitz
2023-12-30 00:11:25 +01:00
committed by GitHub
33 changed files with 2901 additions and 26054 deletions

View File

@@ -1 +0,0 @@
{}

View File

@@ -35,10 +35,11 @@ import {
ButtonSpinner,
} from "@gluestack-ui/themed"
import { config } from "@gluestack-ui/config" // Optional if you want to use default theme
import Toast, { BaseToast, ErrorToast, SuccessToast, ToastProps } from 'react-native-toast-message';
// @ts-ignore
import PassportReader from 'react-native-passport-reader';
import {getFirstName, formatDuration } from './utils/utils';
import {getFirstName, formatDuration, checkInputs } from './utils/utils';
import {
DEFAULT_PNUMBER,
DEFAULT_DOB,
@@ -50,7 +51,6 @@ import {DataHash, PassportData} from '../common/src/utils/types';
import {
hash,
toUnsignedByte,
checkInputs,
bytesToBigDecimal,
dataHashesObjToArray,
formatAndConcatenateDataHashes,
@@ -193,11 +193,15 @@ function App(): JSX.Element {
setStep('scanCompleted');
}
async function scan() {
checkInputs(passportNumber, dateOfBirth, dateOfExpiry);
const check = checkInputs(passportNumber, dateOfBirth, dateOfExpiry)
if (!check.success) {
Toast.show({
type: 'error',
text1: check.message,
})
return
}
// 1. start a scan
// 2. press the back of your android phone against the passport
// 3. wait for the scan(...) Promise to get resolved/rejected
@@ -212,8 +216,12 @@ function App(): JSX.Element {
console.log('response', response);
console.log('scanned');
handleResponse(response);
} catch (e) {
} catch (e: any) {
console.log('error during scan :', e);
Toast.show({
type: 'error',
text1: e.message,
})
}
}
@@ -298,8 +306,6 @@ function App(): JSX.Element {
setTotalTime(end - start);
setProofResult(JSON.stringify(deserializedProof));
// les outputs publics vont être postés on-chain comment ?
});
};
@@ -357,7 +363,7 @@ function App(): JSX.Element {
<InputField
value={passportNumber}
onChangeText={setPassportNumber}
placeholder={DEFAULT_PNUMBER ?? 'Passport Number'}
placeholder={"Passport Number"}
/>
</Input>
<Text>Date of Birth</Text>
@@ -370,7 +376,7 @@ function App(): JSX.Element {
<InputField
value={dateOfBirth}
onChangeText={setDateOfBirth}
placeholder={DEFAULT_DOB ?? "YYMMDD"}
placeholder={"YYMMDD"}
/>
</Input>
<Text>Date of Expiry</Text>
@@ -383,7 +389,7 @@ function App(): JSX.Element {
<InputField
value={dateOfExpiry}
onChangeText={setDateOfExpiry}
placeholder={DEFAULT_DOE ?? "YYMMDD"}
placeholder={"YYMMDD"}
/>
</Input>
@@ -557,6 +563,7 @@ function App(): JSX.Element {
</View>
</ScrollView>
</SafeAreaView>
<Toast config={toastConfig} />
</GluestackUIProvider>
);
}
@@ -594,3 +601,49 @@ const styles = StyleSheet.create({
});
export default App;
export const toastConfig = {
info: (props: ToastProps) => (
<BaseToast
{...props}
contentContainerStyle={{ paddingHorizontal: 15 }}
text1Style={{
fontSize: 15,
fontWeight: "600",
}}
text2Style={{
fontSize: 15,
fontWeight: "500",
}}
/>
),
error: (props: ToastProps) => (
<ErrorToast
{...props}
contentContainerStyle={{ paddingHorizontal: 15}}
text1Style={{
fontSize: 15,
fontWeight: "600",
}}
text2Style={{
fontSize: 15,
fontWeight: "400",
}}
/>
),
success: (props: ToastProps) => (
<SuccessToast
{...props}
contentContainerStyle={{ paddingHorizontal: 15 }}
text1Style={{
fontSize: 15,
fontWeight: "600",
}}
text2Style={{
fontSize: 15,
fontWeight: "400",
}}
/>
),
};

View File

@@ -12,6 +12,11 @@ Install `nodejs v18`
yarn
```
In `/common`, also run:
```bash
yarn
```
#### Add circuit build
Go to the `circuit` folder of the monorepo and build the circuit.

View File

@@ -3,22 +3,18 @@ apply plugin: 'kotlin-android'
android {
compileSdkVersion 33
buildToolsVersion "25.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 22
targetSdkVersion 33
versionCode 1
versionName "1.0"
multiDexEnabled = true
ndkVersion = "23.1.7779620"
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}
dexOptions {
javaMaxHeapSize "4g"
}
buildTypes {
release {
minifyEnabled false

View File

@@ -286,8 +286,10 @@ dependencies = [
"ark-groth16",
"ark-std",
"color-eyre",
"hex",
"jni",
"log",
"num-bigint",
"serde",
"serde_derive",
"serde_json",

View File

@@ -24,3 +24,7 @@ android_logger = "0.8"
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
hex = "0.4"
num-bigint = { version = "=0.4.3", default-features = false, features = [
"rand",
] }

View File

@@ -1,4 +1,4 @@
use ark_circom::{CircomBuilder, CircomConfig};
use ark_circom::{ethereum, CircomBuilder, CircomConfig};
use ark_std::rand::thread_rng;
use color_eyre::Result;
use std::os::raw::c_int;
@@ -9,6 +9,10 @@ use ark_groth16::{Groth16, Proof};
// use ark_ff::QuadExtField;
use ark_ec::AffineRepr;
use num_bigint::{BigInt, Sign};
extern crate hex;
use hex::decode;
use std::time::Instant;
use std::convert::TryInto;
@@ -36,7 +40,7 @@ pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_callRustCode(
_: JClass,
) -> jstring {
android_logger::init_once(Config::default().with_min_level(Level::Trace));
log::warn!("log before imports");
log::error!("log before imports");
let my_int: c_int = -1;
let my_str: String = "no_proof".to_string();
@@ -58,7 +62,7 @@ pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_proveRSAInRust(
_: JClass,
) -> c_int {
fn run() -> Result<u128, Box<dyn std::error::Error>> {
println!("log before imports");
log::error!("log before imports");
Ok(10)
}
match run() {
@@ -83,7 +87,7 @@ pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_provePassport(
address: JString,
) -> jstring {
log::warn!("formatting inputsaaaa...");
log::error!("formatting inputsaaaa...");
fn run_proof(
mrz: JObject,
reveal_bitmap: JObject,
@@ -96,8 +100,8 @@ pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_provePassport(
) -> Result<jstring, Box<dyn std::error::Error>> {
android_logger::init_once(Config::default().with_min_level(Level::Trace));
log::warn!("formatting inputs...");
log::warn!("mrz_veccccccc");
log::error!("formatting inputs...");
log::error!("mrz_veccccccc");
let mrz_vec: Vec<String> = java_arraylist_to_rust_vec(&env, mrz)?;
let reveal_bitmap_vec: Vec<String> = java_arraylist_to_rust_vec(&env, reveal_bitmap)?;
@@ -107,18 +111,18 @@ pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_provePassport(
let pubkey_vec: Vec<String> = java_arraylist_to_rust_vec(&env, pubkey)?;
let address_str: String = env.get_string(address)?.into();
log::warn!("mrz_vec {:?}", mrz_vec);
log::warn!("reveal_bitmap_vec {:?}", reveal_bitmap_vec);
log::warn!("data_hashes_vec {:?}", data_hashes_vec);
log::warn!("e_content_bytes_vec {:?}", e_content_bytes_vec);
log::warn!("signature_vec {:?}", signature_vec);
log::warn!("pubkey_vec {:?}", pubkey_vec);
log::warn!("address_str {:?}", address_str);
log::error!("mrz_vec {:?}", mrz_vec);
log::error!("reveal_bitmap_vec {:?}", reveal_bitmap_vec);
log::error!("data_hashes_vec {:?}", data_hashes_vec);
log::error!("e_content_bytes_vec {:?}", e_content_bytes_vec);
log::error!("signature_vec {:?}", signature_vec);
log::error!("pubkey_vec {:?}", pubkey_vec);
log::error!("address_str {:?}", address_str);
log::warn!("loading circuit...");
const MAIN_WASM: &'static [u8] = include_bytes!("../passport/passport.wasm");
const MAIN_R1CS: &'static [u8] = include_bytes!("../passport/passport.r1cs");
log::warn!("circuit loaded");
log::error!("loading circuit...");
const MAIN_WASM: &'static [u8] = include_bytes!("../passport/proof_of_passport.wasm");
const MAIN_R1CS: &'static [u8] = include_bytes!("../passport/proof_of_passport.r1cs");
log::error!("circuit loaded");
let cfg = CircomConfig::<Bn254>::from_bytes(MAIN_WASM, MAIN_R1CS)?;
@@ -143,6 +147,9 @@ pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_provePassport(
.filter_map(|s| s.parse::<u128>().ok())
.for_each(|n| builder.push_input("pubkey", n));
let address_bigint = BigInt::from_bytes_be(Sign::Plus, &decode(&address_str[2..])?);
builder.push_input("address", address_bigint);
// create an empty instance for setting it up
let circom = builder.setup();
@@ -150,20 +157,25 @@ pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_provePassport(
let params = GrothBn::generate_random_parameters_with_reduction(circom, &mut rng)?;
let circom = builder.build()?;
println!("circuit built");
log::error!("circuit built");
let inputs = circom.get_public_inputs().unwrap();
log::error!("inputs: {:?}", inputs);
let converted_inputs: ethereum::Inputs = inputs.as_slice().into();
let inputs_str: Vec<String> = converted_inputs.0.iter().map(|value| format!("{}", value)).collect();
let serialized_inputs = serde_json::to_string(&inputs_str).unwrap();
log::error!("Serialized inputs: {:?}", serialized_inputs);
let start1 = Instant::now();
let proof = GrothBn::prove(&params, circom, &mut rng)?;
let proof_str = proof_to_proof_str(&proof);
let serialized_proof = serde_json::to_string(&proof_str).unwrap();
let duration1 = start1.elapsed();
println!("proof generated. Took: {:?}", duration1);
log::error!("proof generated. Took: {:?}", duration1);
let start2 = Instant::now();
@@ -171,13 +183,14 @@ pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_provePassport(
let verified = GrothBn::verify_with_processed_vk(&pvk, &inputs, &proof)?;
let duration2 = start2.elapsed();
println!("proof verified. Took: {:?}", duration2);
log::error!("proof verified. Took: {:?}", duration2);
assert!(verified);
let combined = json!({
"duration": duration1.as_millis(),
"serialized_proof": serialized_proof
"serialized_proof": serialized_proof,
"serialized_inputs": serialized_inputs
});
let combined_str = combined.to_string();

18844
app/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
"android": "react-native run-android",
"ios": "react-native run-ios",
"lint": "eslint .",
"start": "react-native start",
"start": "watchman watch-del-all && react-native start",
"test": "jest"
},
"dependencies": {
@@ -23,7 +23,8 @@
"react": "18.2.0",
"react-native": "0.72.3",
"react-native-passport-reader": "^1.0.3",
"react-native-svg": "13.4.0"
"react-native-svg": "13.4.0",
"react-native-toast-message": "^2.2.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",

View File

@@ -6,12 +6,5 @@ cd ../android
cd ..
mkdir -p android/react-native-passport-reader/android/src/main/jniLibs/arm64/
# if [ -f "ark-circom-passport/target/aarch64-linux-android/release/libark_circom_passport.so" ]; then
echo copied release version
cp ark-circom-passport/target/aarch64-linux-android/release/libark_circom_passport.so android/react-native-passport-reader/android/src/main/jniLibs/arm64/
# elif [ -f "ark-circom-passport/target/aarch64-linux-android/debug/libark_circom_passport.so" ]; then
# echo copied debug version
# cp ark-circom-passport/target/aarch64-linux-android/debug/libark_circom_passport.so android/react-native-passport-reader/android/src/main/jniLibs/arm64/
# fi
echo copied release version

View File

@@ -12,3 +12,29 @@ export function formatDuration(durationInMs: number) {
return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
}
export function checkInputs(
passportNumber: string,
dateOfBirth: string,
dateOfExpiry: string,
): {success: boolean, message: string} {
// if (passportNumber.length !== 9) {
// throw new Error('Passport number must be 9 characters long');
// }
if (dateOfBirth.length !== 6) {
return {
success: false,
message: 'Date of birth must be 6 characters long'
};
}
if (dateOfExpiry.length !== 6) {
return {
success: false,
message: 'Date of expiry must be 6 characters long'
};
}
return {
success: true,
message: ''
};
}

View File

@@ -1243,28 +1243,39 @@
dependencies:
tslib "^2.4.0"
"@gluestack-style/animation-resolver@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@gluestack-style/animation-resolver/-/animation-resolver-1.0.2.tgz#c889d82dbe99d6280c7c074fcd21e68b232a74ef"
integrity sha512-eWHm092eP4Z0DH4C1sxPkivBou89ZEG6zBUDEHtQsrW9xf9XN8wunda+ahsTvV2HkI8SsZ2sl/M38HkrKrcmtw==
"@gluestack-style/animation-resolver@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@gluestack-style/animation-resolver/-/animation-resolver-1.0.3.tgz#88ed314cf2e6f15b888cb09f5a7d970b0fe9ee30"
integrity sha512-SfBHBBY0PVlLDpYRMz0KKEcyc6GtZJpbt1yYlaaErVaRqPKI1cbBcgWAS29e23i2Q7iwLLRhRZnbnELigcp55w==
"@gluestack-style/legend-motion-animation-driver@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@gluestack-style/legend-motion-animation-driver/-/legend-motion-animation-driver-1.0.2.tgz#051c26b0d501e03b12e4dbfe01b292eee5c29c8f"
integrity sha512-rB5HIhVzpgPQ9C1JJvY30a1bP0sQRWWFgUHVaiefH8dA/XRAQpmAIMF48JDctrvoBi/tKp5xN10mLE5CtnDRHg==
"@gluestack-style/legend-motion-animation-driver@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@gluestack-style/legend-motion-animation-driver/-/legend-motion-animation-driver-1.0.3.tgz#e2408ff8515ced92cb75f096f5eeff1f9636a0da"
integrity sha512-sD6aFS6Tq5XpyjrboFEIc8LrRY4TA4kodFYHzk6mDchvbkdLODijtjnaDQB1UqihOkMRg49e7ANRAOzc7eymaQ==
"@gluestack-style/react@^1.0.12":
version "1.0.12"
resolved "https://registry.yarnpkg.com/@gluestack-style/react/-/react-1.0.12.tgz#00aff3fb03c20bd488f687076bf445cac97efb13"
integrity sha512-hI6y1P4k0ukg7vdJscnVilg6AdQJTdPrtnrRRSG4gdusrjuSP+PUycAnkgTgotCX6L8VS8JS0Ju/ii3JMt0Gtg==
"@gluestack-style/react@^1.0.12", "@gluestack-style/react@^1.0.18":
version "1.0.29"
resolved "https://registry.yarnpkg.com/@gluestack-style/react/-/react-1.0.29.tgz#253f92dbb78d4a49ef9c53b8c9c02872ff11dd31"
integrity sha512-NoI5kcVQsrhYYDld410YhuP7DVuB+k99b5ycOcarM1T55ZhZrmgwPBfG83/lVWT1w0wHcumHn6+pUSNBYQyr9g==
dependencies:
inline-style-prefixer "^6.0.1"
normalize-css-color "^1.0.2"
"@gluestack-ui/actionsheet@^0.2.30":
version "0.2.30"
resolved "https://registry.yarnpkg.com/@gluestack-ui/actionsheet/-/actionsheet-0.2.30.tgz#9fa902bc5f91f81a24035d7d478bc3e0b0fa3c69"
integrity sha512-+Bw8j+O3FOekdME53kWSaxuX8kssfQJjrWSr+v/OJGOYDGzZzEOZvZHwV1FO0HBFmR/rdcedzPdV9gQ38bh9Mg==
"@gluestack-ui/accordion@^0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@gluestack-ui/accordion/-/accordion-0.0.2.tgz#fb6ea69133169262c327c67f5bd2c0d3b6396a86"
integrity sha512-t9aTPgGPHVkfvIBpDm3NALfMNZKrkirG+R2ARHClyeAr+Ok8XslcAqup+g1apZUxJPhXCuEn2FCjVFW+1ROxzw==
dependencies:
"@gluestack-style/react" "^1.0.18"
"@gluestack-ui/utils" "^0.1.12"
"@react-native-aria/accordion" "^0.0.2"
"@react-native-aria/focus" "^0.2.9"
"@react-native-aria/interactions" "^0.2.11"
"@gluestack-ui/actionsheet@0.2.35":
version "0.2.35"
resolved "https://registry.yarnpkg.com/@gluestack-ui/actionsheet/-/actionsheet-0.2.35.tgz#17e374009cd44f36c94c12e8666ed811a8b682ff"
integrity sha512-Nkq3nHEz7Y0eemAQoHqSrrTDdPkbFme+fETy3kq8Q8faLFkjtyYapOS7tBmr0HPgxd24CBsnbKFloKLcghhf+g==
dependencies:
"@gluestack-ui/hooks" "^0.1.7"
"@gluestack-ui/overlay" "^0.1.12"
@@ -1321,15 +1332,10 @@
"@react-native-aria/utils" "^0.2.10"
"@react-stately/checkbox" "^3.4.2"
"@gluestack-ui/config@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@gluestack-ui/config/-/config-1.0.1.tgz#c748f579be6930e0cdd67e0edfac01fbe84f2b67"
integrity sha512-QyrxfkYn8QPiYjefjgwaMNbo8ojL7k0838F3G96DDJbWsl6RBG8PjhT6DiAmRhDe7k4zzixKKlaRHFfXHEo3FA==
"@gluestack-ui/config@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@gluestack-ui/config/-/config-1.0.3.tgz#27cb2d6dc9a738146fa47937d2b41e7217ef55d2"
integrity sha512-cP07ZOGDhwZKsTBdCUTa88O4KbRbAKArXyZcgTMZnoNJ5477psE9O9ClPd7xuPwJ/pLgh7NNCC1cAOMIpR0zpQ==
version "1.0.10"
resolved "https://registry.yarnpkg.com/@gluestack-ui/config/-/config-1.0.10.tgz#e0d226f95ea52900368e5b11e42f8d969268485d"
integrity sha512-19Ewiv/ETKKRlSCBwofoIA8v2ZouLeeycGWp87Okwlnrc6VdxEOrwm3OXmi1zxVe1lqQ2aNu1+Cvy/fTanh5CQ==
"@gluestack-ui/divider@^0.1.8":
version "0.1.8"
@@ -1358,19 +1364,19 @@
resolved "https://registry.yarnpkg.com/@gluestack-ui/hooks/-/hooks-0.1.10.tgz#96cb9277fe65ce37bd7204662f53267cc8829fae"
integrity sha512-/FCvXn/YeKztXgaad38xeHqApEqqFaFPFQdGrNdcM2b8GfMb55wwEyOVGs3qEhpZIFlfLPw3gC/ZdWMdBdsZ8Q==
"@gluestack-ui/icon@^0.1.18":
version "0.1.18"
resolved "https://registry.yarnpkg.com/@gluestack-ui/icon/-/icon-0.1.18.tgz#db97760a8616a54f5a8924f1c189046aa02c1e98"
integrity sha512-X35k3U2JHilpH24dPi5rxlniQWf+xIVLqhzHy4khLP08WZpBOzkKLTdnbmP76iArev5urXJtZtzs2eOJ8/Ow3A==
"@gluestack-ui/icon@^0.1.20":
version "0.1.20"
resolved "https://registry.yarnpkg.com/@gluestack-ui/icon/-/icon-0.1.20.tgz#4140b5e94efeeb953ddc2c828800b27e103f7bfa"
integrity sha512-f/+DGR3139LU9NbMMvoumZWIwqy4B4e+xc02kAAubiv7p7aqGDV5KPm2JN5vVmCwiDRxX5u0F3SxodSQhEoQZA==
dependencies:
"@gluestack-ui/provider" "^0.1.6"
"@gluestack-ui/utils" "^0.1.12"
"@react-native-aria/focus" "^0.2.9"
"@gluestack-ui/image@^0.1.6":
version "0.1.6"
resolved "https://registry.yarnpkg.com/@gluestack-ui/image/-/image-0.1.6.tgz#dfda76b984e7eeedf41f9ce8b7c84c18a565211c"
integrity sha512-b6WK1tCnlA1Es040H1k5WZsIlzzmoXNaapQ5j2EuX5dOrZOopBuiFLFqAEPiMdqUr8RjUC4nomBHm6taqP389A==
"@gluestack-ui/image@^0.1.7":
version "0.1.7"
resolved "https://registry.yarnpkg.com/@gluestack-ui/image/-/image-0.1.7.tgz#0cb2be72fd16a6a5d10aa850b9506f308330a901"
integrity sha512-ITfDX7gyxab+w0EMmJdITgG7EB2oF/3MfYgsFBV//VmIlu3OJg2xvnwvYzq3kNdGqr5Nt/5ZEG2ime7Kx2Wmxw==
dependencies:
"@gluestack-ui/utils" "^0.1.12"
"@react-native-aria/focus" "^0.2.9"
@@ -1393,10 +1399,10 @@
dependencies:
expo-linear-gradient "12.3.0"
"@gluestack-ui/link@^0.1.15":
version "0.1.15"
resolved "https://registry.yarnpkg.com/@gluestack-ui/link/-/link-0.1.15.tgz#c4db78400f6963ffea3622f9f735183b9c9d84f7"
integrity sha512-Kz5ZZRrjIy7Zo3CvW4Be734NQAPgkTCJwig/lxG1J/0JWe3wcbEwOI6kCiZScA1LQt40WIsHbO0XrZSYihcQTg==
"@gluestack-ui/link@^0.1.16":
version "0.1.16"
resolved "https://registry.yarnpkg.com/@gluestack-ui/link/-/link-0.1.16.tgz#43cb847c3929bf6a41e63fa13010732cc16b308a"
integrity sha512-tKUSwfxr02W/viDwZDpp5TgqD+8GNO685K9o8/6Br4dKUDdVsg+UBkUX6VwEtncyYjEQds6I28uqgKVuk1F5lg==
dependencies:
"@gluestack-ui/utils" "^0.1.12"
"@react-native-aria/focus" "^0.2.9"
@@ -1497,27 +1503,27 @@
dependencies:
"@react-native-aria/focus" "^0.2.7"
"@gluestack-ui/select@^0.1.19":
version "0.1.19"
resolved "https://registry.yarnpkg.com/@gluestack-ui/select/-/select-0.1.19.tgz#9305f38739d1c8152b16667437b89168cff8aaf8"
integrity sha512-R4HlLLlx8H/oa9kyXp/DGTFppmaBJ4NbvrnS7bHznjn3zixoE24K1DLbmmgO0KxIurSAPNk/M75nCImk7m9vPA==
"@gluestack-ui/select@^0.1.20":
version "0.1.20"
resolved "https://registry.yarnpkg.com/@gluestack-ui/select/-/select-0.1.20.tgz#312a1ed4328f04b6cf8535b9ac47ed6b336b68c9"
integrity sha512-97YNSPt71xgAz3AAjPgp7BvCuSS5+Bhbr3UfUVFRnOtyUiExJrtu54A2wYw7wVbEaqiMi7aNv7KKqQ/n2cK7AA==
dependencies:
"@gluestack-ui/form-control" "^0.1.14"
"@gluestack-ui/hooks" "^0.1.7"
"@gluestack-ui/utils" "^0.1.12"
"@react-native-aria/focus" "^0.2.9"
"@gluestack-ui/slider@^0.1.17":
version "0.1.17"
resolved "https://registry.yarnpkg.com/@gluestack-ui/slider/-/slider-0.1.17.tgz#b6c004ff5cc3ed2d818363bdf64d25531fd97c61"
integrity sha512-7BiUcNmdErOG3NODbegEyYGpX3trvJ3FfUnwpWNeB/K8E3hZbEcXGNlrhEOBDmBhDuL9JXKgbb78WNTdBzDVcA==
"@gluestack-ui/slider@^0.1.18":
version "0.1.18"
resolved "https://registry.yarnpkg.com/@gluestack-ui/slider/-/slider-0.1.18.tgz#7bf3b869cc6009f5a96e9b90eaccf01e0af3c043"
integrity sha512-Q9brkJnH9hlUeVrXowcsPRuclpczemxgXa0gSqR14DpLeinOqJgRCobg3uFiWjXqOOTHGC2oNik68tI4itehAQ==
dependencies:
"@gluestack-ui/form-control" "^0.1.14"
"@gluestack-ui/hooks" "^0.1.7"
"@gluestack-ui/utils" "^0.1.12"
"@react-aria/visually-hidden" "^3.8.1"
"@react-native-aria/interactions" "^0.2.11"
"@react-native-aria/slider" "^0.2.9"
"@react-native-aria/slider" "^0.2.10"
"@react-stately/slider" "^3.2.4"
"@gluestack-ui/spinner@^0.1.14":
@@ -1545,38 +1551,38 @@
"@react-native-aria/focus" "^0.2.9"
"@react-native-aria/interactions" "^0.2.11"
"@gluestack-ui/textarea@^0.1.18":
version "0.1.18"
resolved "https://registry.yarnpkg.com/@gluestack-ui/textarea/-/textarea-0.1.18.tgz#2991c770e6311105a0287dff392b50066243fa6a"
integrity sha512-DIDvkKGj+GgKZqugu3QttTU2bZU/XFrbcLwj9lyqYJXzG/g8UsGVnU5errVXYB1L+UgFSdxSZ8SDedknXgEFNQ==
"@gluestack-ui/textarea@^0.1.19":
version "0.1.19"
resolved "https://registry.yarnpkg.com/@gluestack-ui/textarea/-/textarea-0.1.19.tgz#71b1ecbe370a28a441206ffa3f0bfbdf8200d730"
integrity sha512-VYljvA5xrl856Oxbm951oDhxHYwHTjuIrk4+A+tIqRbgJodgzI1SgiU8DhgHTYAa+aYumMdyyrUPq6RL8ACIYQ==
dependencies:
"@gluestack-ui/form-control" "^0.1.14"
"@gluestack-ui/utils" "^0.1.12"
"@react-native-aria/focus" "^0.2.9"
"@gluestack-ui/themed@^1.0.11":
version "1.0.11"
resolved "https://registry.yarnpkg.com/@gluestack-ui/themed/-/themed-1.0.11.tgz#4457f2a8104840890fbe233a5f667d0e08b0d744"
integrity sha512-iAuGIAD/6aYVMDwTlxl3t0giKXAqc+ix4VIv3XOc0ry2isZO5aE7mE+CHq2i9boE9F9RjzVrsAyeE85qH1Ssbg==
version "1.0.30"
resolved "https://registry.yarnpkg.com/@gluestack-ui/themed/-/themed-1.0.30.tgz#7bba2335296f6902875f9f335eff41c83e57e76b"
integrity sha512-axzyF1W5O+d8dQjeaj7KgJwjmZKzIi3Zx3ztkPwzJy6XXJJJpLuxYZdyry9f9Z3URPjL2N/29Z1PnlaXFyd5wQ==
dependencies:
"@expo/html-elements" latest
"@gluestack-style/animation-resolver" "^1.0.2"
"@gluestack-style/legend-motion-animation-driver" "^1.0.2"
"@gluestack-ui/actionsheet" "^0.2.30"
"@gluestack-style/animation-resolver" "1.0.3"
"@gluestack-style/legend-motion-animation-driver" "1.0.3"
"@gluestack-ui/accordion" "^0.0.2"
"@gluestack-ui/actionsheet" "0.2.35"
"@gluestack-ui/alert" "^0.1.12"
"@gluestack-ui/alert-dialog" "^0.1.23"
"@gluestack-ui/avatar" "^0.1.15"
"@gluestack-ui/button" "^0.1.33"
"@gluestack-ui/checkbox" "^0.1.22"
"@gluestack-ui/config" "1.0.1"
"@gluestack-ui/divider" "^0.1.8"
"@gluestack-ui/fab" "^0.1.17"
"@gluestack-ui/form-control" "^0.1.15"
"@gluestack-ui/icon" "^0.1.18"
"@gluestack-ui/image" "^0.1.6"
"@gluestack-ui/icon" "^0.1.20"
"@gluestack-ui/image" "^0.1.7"
"@gluestack-ui/input" "^0.1.23"
"@gluestack-ui/linear-gradient" "^0.1.2"
"@gluestack-ui/link" "^0.1.15"
"@gluestack-ui/link" "^0.1.16"
"@gluestack-ui/menu" "^0.2.25"
"@gluestack-ui/modal" "^0.1.27"
"@gluestack-ui/overlay" "^0.1.12"
@@ -1585,20 +1591,20 @@
"@gluestack-ui/progress" "^0.1.12"
"@gluestack-ui/provider" "^0.1.10"
"@gluestack-ui/radio" "^0.1.23"
"@gluestack-ui/select" "^0.1.19"
"@gluestack-ui/slider" "^0.1.17"
"@gluestack-ui/select" "^0.1.20"
"@gluestack-ui/slider" "^0.1.18"
"@gluestack-ui/spinner" "^0.1.14"
"@gluestack-ui/switch" "^0.1.17"
"@gluestack-ui/tabs" "^0.1.14"
"@gluestack-ui/textarea" "^0.1.18"
"@gluestack-ui/toast" "^0.1.20"
"@gluestack-ui/textarea" "^0.1.19"
"@gluestack-ui/toast" "^1.0.2"
"@gluestack-ui/tooltip" "^0.1.24"
"@legendapp/motion" latest
"@gluestack-ui/toast@^0.1.20":
version "0.1.20"
resolved "https://registry.yarnpkg.com/@gluestack-ui/toast/-/toast-0.1.20.tgz#863453f75d2e941000204a9524161bfd2500e320"
integrity sha512-DRgihksQmbZ1/4UbCcCX3NwWsegIvIHwSpQv7dqJcjC7F50cBwcoMKbMOSQt/g4PhtIeMjr146tQFlY3u3V41A==
"@gluestack-ui/toast@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@gluestack-ui/toast/-/toast-1.0.2.tgz#0b9d6989794a707f239ae9da7ac8c3a730499035"
integrity sha512-RqlqEaoQesW5l6qZ8/hWqhidvRh5GwijsYj2j3CJy2qeFv/G5mtSliV0L4iZ6hSWQ0mW5cYxR/kCQ6EPDco/wQ==
dependencies:
"@gluestack-ui/hooks" "^0.1.7"
"@gluestack-ui/overlay" "^0.1.12"
@@ -1758,11 +1764,11 @@
strip-ansi "^6.0.0"
"@jest/create-cache-key-function@^29.2.1":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.6.2.tgz#b6b74fb741a7b7d9aa399c179694db8272283527"
integrity sha512-oGVRMr8na9h1vUiem1E/Uoxb/NR9BdfKb7IBZ+pNWxJQmTYSbDF0dsVBAGqNU7MBQwYJDyRx0H7H/0itiqAgQg==
version "29.7.0"
resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0"
integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==
dependencies:
"@jest/types" "^29.6.1"
"@jest/types" "^29.6.3"
"@jest/environment@^29.6.2":
version "29.6.2"
@@ -1774,6 +1780,16 @@
"@types/node" "*"
jest-mock "^29.6.2"
"@jest/environment@^29.7.0":
version "29.7.0"
resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7"
integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==
dependencies:
"@jest/fake-timers" "^29.7.0"
"@jest/types" "^29.6.3"
"@types/node" "*"
jest-mock "^29.7.0"
"@jest/expect-utils@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.6.2.tgz#1b97f290d0185d264dd9fdec7567a14a38a90534"
@@ -1801,6 +1817,18 @@
jest-mock "^29.6.2"
jest-util "^29.6.2"
"@jest/fake-timers@^29.7.0":
version "29.7.0"
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565"
integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==
dependencies:
"@jest/types" "^29.6.3"
"@sinonjs/fake-timers" "^10.0.2"
"@types/node" "*"
jest-message-util "^29.7.0"
jest-mock "^29.7.0"
jest-util "^29.7.0"
"@jest/globals@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.6.2.tgz#74af81b9249122cc46f1eb25793617eec69bf21a"
@@ -1848,6 +1876,13 @@
dependencies:
"@sinclair/typebox" "^0.27.8"
"@jest/schemas@^29.6.3":
version "29.6.3"
resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03"
integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==
dependencies:
"@sinclair/typebox" "^0.27.8"
"@jest/source-map@^29.6.0":
version "29.6.0"
resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.0.tgz#bd34a05b5737cb1a99d43e1957020ac8e5b9ddb1"
@@ -1932,6 +1967,18 @@
"@types/yargs" "^17.0.8"
chalk "^4.0.0"
"@jest/types@^29.6.3":
version "29.6.3"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59"
integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==
dependencies:
"@jest/schemas" "^29.6.3"
"@types/istanbul-lib-coverage" "^2.0.0"
"@types/istanbul-reports" "^3.0.0"
"@types/node" "*"
"@types/yargs" "^17.0.8"
chalk "^4.0.0"
"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
@@ -2214,6 +2261,11 @@
"@swc/helpers" "^0.5.0"
clsx "^1.1.1"
"@react-native-aria/accordion@^0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@react-native-aria/accordion/-/accordion-0.0.2.tgz#28e57f5c3690b2b33f36acd6aff7d91a75fbf384"
integrity sha512-2Wa/YDBc2aCunTLpqwxTfCwn1t63KSAIoXd0hqrUGJJF+N2bEs2Hqs9ZgyKJ/hzFxCknVPMqo0fEVE1H23Z5+g==
"@react-native-aria/checkbox@^0.2.6":
version "0.2.6"
resolved "https://registry.yarnpkg.com/@react-native-aria/checkbox/-/checkbox-0.2.6.tgz#80298eb1983e58d834fb9573e9082561368d60fa"
@@ -2292,10 +2344,10 @@
"@react-stately/radio" "^3.2.1"
"@react-types/radio" "^3.1.1"
"@react-native-aria/slider@^0.2.9":
version "0.2.9"
resolved "https://registry.yarnpkg.com/@react-native-aria/slider/-/slider-0.2.9.tgz#58c6aba74cbd03e4b3155bfee058552f6d4f7fc3"
integrity sha512-pyCiOy3L7SpzFHYsdGR054trfVMKizi/x10s5spzjXhMAEmYCuP5dEIo43DSz+ZieGGEk/cdvURxjVEwsgHznA==
"@react-native-aria/slider@^0.2.10":
version "0.2.10"
resolved "https://registry.yarnpkg.com/@react-native-aria/slider/-/slider-0.2.10.tgz#19cd79ac4481f41a744b4be5a179f9940e61670e"
integrity sha512-flwv/kKHrYmUqgMRO81VsZUccs9tf6dd9Z8SAerkVVj8BrJfVQ/Tb9cABaNsWHxIMUgtfKn0cMQYxLeySjjisw==
dependencies:
"@react-aria/focus" "^3.2.3"
"@react-aria/interactions" "^3.3.2"
@@ -2495,13 +2547,16 @@
integrity sha512-Im93xRJuHHxb1wniGhBMsxLwcfzdYreSZVQGDoMJgkd6+Iky61LInGEHnQCTN0fKNYF1Dvcofb4uMmE1RQHXHQ==
"@react-native/codegen@^0.72.6":
version "0.72.6"
resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.72.6.tgz#029cf61f82f5c6872f0b2ce58f27c4239a5586c8"
integrity sha512-idTVI1es/oopN0jJT/0jB6nKdvTUKE3757zA5+NPXZTeB46CIRbmmos4XBiAec8ufu9/DigLPbHTYAaMNZJ6Ig==
version "0.72.8"
resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.72.8.tgz#0593f628e1310f430450a9479fbb4be35e7b63d6"
integrity sha512-jQCcBlXV7B7ap5VlHhwIPieYz89yiRgwd2FPUBu+unz+kcJ6pAiB2U8RdLDmyIs8fiWd+Vq1xxaWs4TR329/ng==
dependencies:
"@babel/parser" "^7.20.0"
flow-parser "^0.206.0"
glob "^7.1.1"
invariant "^2.2.4"
jscodeshift "^0.14.0"
mkdirp "^0.5.1"
nullthrows "^1.1.1"
"@react-native/eslint-config@^0.72.2":
@@ -2549,9 +2604,9 @@
metro-runtime "0.76.7"
"@react-native/normalize-colors@*":
version "0.73.0"
resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.73.0.tgz#23e15cf2a2b73ac7e5e6df8d5b86b173cfb35a3f"
integrity sha512-EmSCmJ0djeMJadeFsms6Pl/R85i9xSJMc+tyJu/GEMkKXBVyYQyqanK4RHFU0v8MO90OWj+SiFXjCkKYiJ6mkg==
version "0.74.1"
resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.74.1.tgz#6e8ccf99954728dcd3cfe0d56e758ee5050a7bea"
integrity sha512-r+bTRs6pImqE3fx4h7bPzH2sOWSrnSHF/RJ7d00pNUj2P6ws3DdhS7WV+/7YosZkloYQfkiIkK3pIHvcYn665w==
"@react-native/normalize-colors@^0.72.0":
version "0.72.0"
@@ -2559,9 +2614,9 @@
integrity sha512-285lfdqSXaqKuBbbtP9qL2tDrfxdOFtIMvkKadtleRQkdOxx+uzGvFr82KHmc/sSiMtfXGp7JnFYWVh4sFl7Yw==
"@react-native/virtualized-lists@^0.72.6":
version "0.72.6"
resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.72.6.tgz#375f88a1371927d803afad8d8a0ede3261464030"
integrity sha512-JhT6ydu35LvbSKdwnhWDuGHMOwM0WAh9oza/X8vXHA8ELHRyQ/4p8eKz/bTQcbQziJaaleUURToGhFuCtgiMoA==
version "0.72.8"
resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.72.8.tgz#a2c6a91ea0f1d40eb5a122fb063daedb92ed1dc3"
integrity sha512-J3Q4Bkuo99k7mu+jPS9gSUSgq+lLRSI/+ahXNwV92XgJ/8UgOTxu2LPwhJnBk/sQKxq7E8WkZBnBiozukQMqrw==
dependencies:
invariant "^2.2.4"
nullthrows "^1.1.1"
@@ -4359,9 +4414,9 @@ entities@^4.2.0:
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
envinfo@^7.7.2:
version "7.10.0"
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.10.0.tgz#55146e3909cc5fe63c22da63fb15b05aeac35b13"
integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==
version "7.11.0"
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.0.tgz#c3793f44284a55ff8c82faf1ffd91bc6478ea01f"
integrity sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==
error-ex@^1.3.1:
version "1.3.2"
@@ -5028,7 +5083,7 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
glob@^7.1.3, glob@^7.1.4:
glob@^7.1.1, glob@^7.1.3, glob@^7.1.4:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
@@ -5656,7 +5711,19 @@ jest-each@^29.6.2:
jest-util "^29.6.2"
pretty-format "^29.6.2"
jest-environment-node@^29.2.1, jest-environment-node@^29.6.2:
jest-environment-node@^29.2.1:
version "29.7.0"
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376"
integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==
dependencies:
"@jest/environment" "^29.7.0"
"@jest/fake-timers" "^29.7.0"
"@jest/types" "^29.6.3"
"@types/node" "*"
jest-mock "^29.7.0"
jest-util "^29.7.0"
jest-environment-node@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.6.2.tgz#a9ea2cabff39b08eca14ccb32c8ceb924c8bb1ad"
integrity sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==
@@ -5725,6 +5792,21 @@ jest-message-util@^29.6.2:
slash "^3.0.0"
stack-utils "^2.0.3"
jest-message-util@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3"
integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==
dependencies:
"@babel/code-frame" "^7.12.13"
"@jest/types" "^29.6.3"
"@types/stack-utils" "^2.0.0"
chalk "^4.0.0"
graceful-fs "^4.2.9"
micromatch "^4.0.4"
pretty-format "^29.7.0"
slash "^3.0.0"
stack-utils "^2.0.3"
jest-mock@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.2.tgz#ef9c9b4d38c34a2ad61010a021866dad41ce5e00"
@@ -5734,6 +5816,15 @@ jest-mock@^29.6.2:
"@types/node" "*"
jest-util "^29.6.2"
jest-mock@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347"
integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==
dependencies:
"@jest/types" "^29.6.3"
"@types/node" "*"
jest-util "^29.7.0"
jest-pnp-resolver@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e"
@@ -5877,6 +5968,18 @@ jest-util@^29.6.2:
graceful-fs "^4.2.9"
picomatch "^2.2.3"
jest-util@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
dependencies:
"@jest/types" "^29.6.3"
"@types/node" "*"
chalk "^4.0.0"
ci-info "^3.2.0"
graceful-fs "^4.2.9"
picomatch "^2.2.3"
jest-validate@^29.2.1, jest-validate@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.2.tgz#25d972af35b2415b83b1373baf1a47bb266c1082"
@@ -6976,6 +7079,15 @@ pretty-format@^29.6.2:
ansi-styles "^5.0.0"
react-is "^18.0.0"
pretty-format@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==
dependencies:
"@jest/schemas" "^29.6.3"
ansi-styles "^5.0.0"
react-is "^18.0.0"
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -7073,9 +7185,9 @@ raw-body@2.5.2:
unpipe "1.0.0"
react-devtools-core@^4.27.2:
version "4.28.0"
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.0.tgz#3fa18709b24414adddadac33b6b9cea96db60f2f"
integrity sha512-E3C3X1skWBdBzwpOUbmXG8SgH6BtsluSMe+s6rRcujNKG1DGi8uIfhdhszkgDpAsMoE55hwqRUzeXCmETDBpTg==
version "4.28.5"
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.5.tgz#c8442b91f068cdf0c899c543907f7f27d79c2508"
integrity sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==
dependencies:
shell-quote "^1.6.1"
ws "^7"
@@ -7115,6 +7227,11 @@ react-native-svg@13.4.0:
css-select "^5.1.0"
css-tree "^1.1.3"
react-native-toast-message@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/react-native-toast-message/-/react-native-toast-message-2.2.0.tgz#c53a4746b15616858a7d61c4386b92cbe9fbf911"
integrity sha512-AFti8VzUk6JvyGAlLm9/BknTNDXrrhqnUk7ak/pM7uCTxDPveAu2ekszU0on6vnUPFnG04H/QfYE2IlETqeaWw==
react-native@0.72.3:
version "0.72.3"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.72.3.tgz#f8d85ec81c9f3592d091ec8e9ac1694956a72765"

View File

@@ -20,6 +20,12 @@ yarn
./scripts/build_circuit.sh
```
#### Build only to use the app, not for running tests (dev only, not secure)
```bash
./scripts/build_circuit.sh app-only
```
#### Run tests
```bash

View File

@@ -33,24 +33,16 @@ template ProofOfPassport(n, k) {
// we take nullifier = signature[0, 1] which it 64 + 64 bits long, so chance of collision is 2^128
signal output nullifier <== signature[0] * 2**64 + signature[1];
// Calculate the Poseidon hash of public public key and outputs it
// This can be used to verify the public key is correct in contract without requiring the actual key
// We are converting pub_key (modulus) in to 9 chunks of 242 bits, assuming original n, k are 121 and 17.
// This is because Posiedon circuit only support array of 16 elements.
// Otherwise we would have to output the ceil(256/31) = 9 field elements of the public key
var k2_chunked_size = k >> 1;
if(k % 2 == 1) {
k2_chunked_size += 1;
}
signal pubkey_hash_input[k2_chunked_size];
for(var i = 0; i < k2_chunked_size; i++) {
if(i==k2_chunked_size-1 && k2_chunked_size % 2 == 1) {
pubkey_hash_input[i] <== pubkey[2*i];
// we don't do Poseidon hash cuz it makes arkworks crash for obscure reasons
// we output the pubkey as 11 field elements. 9 is doable also cuz ceil(254/31) = 9
signal output pubkey_packed[11];
for (var i = 0; i < 11; i++) {
if (i < 10) {
pubkey_packed[i] <== pubkey[3*i] * 64 * 64 + pubkey[3*i + 1] * 64 + pubkey[3*i + 2];
} else {
pubkey_hash_input[i] <== pubkey[2*i] + (1<<n) * pubkey[2*i+1];
pubkey_packed[i] <== pubkey[3*i] * 64 * 64;
}
}
signal output pubkey_hash <== Poseidon(k2_chunked_size)(pubkey_hash_input);
}
component main { public [ address ] } = ProofOfPassport(64, 32);

View File

@@ -1,3 +1,12 @@
#!/bin/bash
# Check if the first argument is "app-only"
if [ "$1" == "app-only" ]; then
echo "Building only for the app"
APP_ONLY=1
else
APP_ONLY=0
fi
mkdir -p build
cd build
@@ -13,6 +22,19 @@ cd ..
echo "compiling circuit"
circom circuits/proof_of_passport.circom --r1cs --sym --wasm --output build
mkdir -p ../app/ark-circom-passport/passport/
cp build/proof_of_passport.r1cs ../app/ark-circom-passport/passport/
cp build/proof_of_passport_js/proof_of_passport.wasm ../app/ark-circom-passport/passport/
echo "copied proof_of_passport.r1cs and proof_of_passport.wasm to ark-circom-passport"
echo "file sizes:"
echo "Size of proof_of_passport.r1cs: $(wc -c <../app/ark-circom-passport/passport/proof_of_passport.r1cs) bytes"
echo "Size of proof_of_passport.wasm: $(wc -c <../app/ark-circom-passport/passport/proof_of_passport.wasm) bytes"
# If APP_ONLY is 1, exit the script here
if [ $APP_ONLY -eq 1 ]; then
exit 0
fi
echo "building zkey"
yarn snarkjs groth16 setup build/proof_of_passport.r1cs build/powersOfTau28_hez_final_20.ptau build/proof_of_passport.zkey
@@ -20,4 +42,6 @@ echo "building vkey"
echo "test random" | yarn snarkjs zkey contribute build/proof_of_passport.zkey build/proof_of_passport_final.zkey
yarn snarkjs zkey export verificationkey build/proof_of_passport_final.zkey build/verification_key.json
yarn snarkjs zkey export solidityverifier build/proof_of_passport_final.zkey build/Verifier.sol
yarn snarkjs zkey export solidityverifier build/proof_of_passport_final.zkey build/Verifier.sol
cp build/Verifier.sol ../contracts/contracts/Verifier.sol
echo "copied Verifier.sol to contracts"

View File

@@ -3,19 +3,18 @@ import chai, { assert, expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { hash, toUnsignedByte, arraysAreEqual, bytesToBigDecimal, formatAndConcatenateDataHashes, formatMrz, splitToWords } from '../../common/src/utils/utils'
import { groth16 } from 'snarkjs'
import { DataHash, PassportData } from '../../common/src/utils/types'
import { DataHash } from '../../common/src/utils/types'
import { getPassportData } from '../../common/src/utils/passportData'
import { attributeToPosition } from '../../common/src/constants/constants'
const fs = require('fs');
chai.use(chaiAsPromised)
console.log("The snarkjs error logs are normal and expected is the tests pass.")
console.log("The following snarkjs error logs are normal and expected if the tests pass.")
describe('Circuit tests', function () {
this.timeout(0)
let passportData: PassportData;
let inputs: any;
this.beforeAll(async () => {
@@ -30,14 +29,12 @@ describe('Circuit tests', function () {
const concatenatedDataHashesHashDigest = hash(concatenatedDataHashes);
// console.log('concatenatedDataHashesHashDigest', concatenatedDataHashesHashDigest)
// console.log('passportData.eContent.slice(72, 72 + 32)', passportData.eContent.slice(72, 72 + 32))
assert(
arraysAreEqual(passportData.eContent.slice(72, 72 + 32), concatenatedDataHashesHashDigest),
'concatenatedDataHashesHashDigest is at the right place in passportData.eContent'
)
const reveal_bitmap = Array.from({ length: 88 }, (_, i) => (i >= 16 && i <= 22) ? '1' : '0');
const reveal_bitmap = Array(88).fill('1');
inputs = {
mrz: formattedMrz.map(byte => String(byte)),
@@ -54,26 +51,19 @@ describe('Circuit tests', function () {
BigInt(64),
BigInt(32)
),
address: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
address: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // sample address
}
})
describe('Proof', function() {
it('should prove and verify with valid inputs', async function () {
// console.log('inputs', inputs)
const { proof, publicSignals } = await groth16.fullProve(
inputs,
"build/proof_of_passport_js/proof_of_passport.wasm",
"build/proof_of_passport_final.zkey"
)
// console.log('proof done');
const revealChars = publicSignals.slice(0, 88).map((byte: string) => String.fromCharCode(parseInt(byte, 10))).join('');
// console.log('reveal chars', revealChars);
const vKey = JSON.parse(fs.readFileSync("build/verification_key.json"));
const verified = await groth16.verify(
vKey,
@@ -82,8 +72,6 @@ describe('Circuit tests', function () {
)
assert(verified == true, 'Should verifiable')
// console.log('proof verified');
})
it('should fail to prove with invalid mrz', async function () {
@@ -125,16 +113,13 @@ describe('Circuit tests', function () {
)).to.be.rejected;
})
it.only("shouldn't allow address maleability", async function () {
it("shouldn't allow address maleability", async function () {
const { proof, publicSignals } = await groth16.fullProve(
inputs,
"build/proof_of_passport_js/proof_of_passport.wasm",
"build/proof_of_passport_final.zkey"
)
console.log('proof done');
console.log('publicSignals', publicSignals);
publicSignals[publicSignals.length - 1] = BigInt("0xC5B4F2A7Ea7F675Fca6EF724d6E06FFB40dFC93F").toString();
const vKey = JSON.parse(fs.readFileSync("build/verification_key.json"));

View File

@@ -6,4 +6,256 @@ export const attributeToPosition = {
date_of_birth: [57, 62],
gender: [64, 64],
expiry_date: [65, 70],
}
}
export const countryCodes = {
"AFG": "Afghanistan",
"ALA": "Aland Islands",
"ALB": "Albania",
"DZA": "Algeria",
"ASM": "American Samoa",
"AND": "Andorra",
"AGO": "Angola",
"AIA": "Anguilla",
"ATA": "Antarctica",
"ATG": "Antigua and Barbuda",
"ARG": "Argentina",
"ARM": "Armenia",
"ABW": "Aruba",
"AUS": "Australia",
"AUT": "Austria",
"AZE": "Azerbaijan",
"BHS": "Bahamas",
"BHR": "Bahrain",
"BGD": "Bangladesh",
"BRB": "Barbados",
"BLR": "Belarus",
"BEL": "Belgium",
"BLZ": "Belize",
"BEN": "Benin",
"BMU": "Bermuda",
"BTN": "Bhutan",
"BOL": "Bolivia (Plurinational State of)",
"BES": "Bonaire, Sint Eustatius and Saba",
"BIH": "Bosnia and Herzegovina",
"BWA": "Botswana",
"BVT": "Bouvet Island",
"BRA": "Brazil",
"IOT": "British Indian Ocean Territory",
"BRN": "Brunei Darussalam",
"BGR": "Bulgaria",
"BFA": "Burkina Faso",
"BDI": "Burundi",
"CPV": "Cabo Verde",
"KHM": "Cambodia",
"CMR": "Cameroon",
"CAN": "Canada",
"CYM": "Cayman Islands",
"CAF": "Central African Republic",
"TCD": "Chad",
"CHL": "Chile",
"CHN": "China",
"CXR": "Christmas Island",
"CCK": "Cocos (Keeling) Islands",
"COL": "Colombia",
"COM": "Comoros",
"COG": "Congo",
"COD": "Congo, Democratic Republic of the",
"COK": "Cook Islands",
"CRI": "Costa Rica",
"CIV": "Cote d'Ivoire",
"HRV": "Croatia",
"CUB": "Cuba",
"CUW": "Curacao",
"CYP": "Cyprus",
"CZE": "Czechia",
"DNK": "Denmark",
"DJI": "Djibouti",
"DMA": "Dominica",
"DOM": "Dominican Republic",
"ECU": "Ecuador",
"EGY": "Egypt",
"SLV": "El Salvador",
"GNQ": "Equatorial Guinea",
"ERI": "Eritrea",
"EST": "Estonia",
"SWZ": "Eswatini",
"ETH": "Ethiopia",
"FLK": "Falkland Islands (Malvinas)",
"FRO": "Faroe Islands",
"FJI": "Fiji",
"FIN": "Finland",
"FRA": "France",
"GUF": "French Guiana",
"PYF": "French Polynesia",
"ATF": "French Southern Territories",
"GAB": "Gabon",
"GMB": "Gambia",
"GEO": "Georgia",
"DEU": "Germany",
"GHA": "Ghana",
"GIB": "Gibraltar",
"GRC": "Greece",
"GRL": "Greenland",
"GRD": "Grenada",
"GLP": "Guadeloupe",
"GUM": "Guam",
"GTM": "Guatemala",
"GGY": "Guernsey",
"GIN": "Guinea",
"GNB": "Guinea-Bissau",
"GUY": "Guyana",
"HTI": "Haiti",
"HMD": "Heard Island and McDonald Islands",
"VAT": "Holy See",
"HND": "Honduras",
"HKG": "Hong Kong",
"HUN": "Hungary",
"ISL": "Iceland",
"IND": "India",
"IDN": "Indonesia",
"IRN": "Iran (Islamic Republic of)",
"IRQ": "Iraq",
"IRL": "Ireland",
"IMN": "Isle of Man",
"ISR": "Israel",
"ITA": "Italy",
"JAM": "Jamaica",
"JPN": "Japan",
"JEY": "Jersey",
"JOR": "Jordan",
"KAZ": "Kazakhstan",
"KEN": "Kenya",
"KIR": "Kiribati",
"PRK": "Korea (Democratic People's Republic of)",
"KOR": "Korea, Republic of",
"KWT": "Kuwait",
"KGZ": "Kyrgyzstan",
"LAO": "Lao People's Democratic Republic",
"LVA": "Latvia",
"LBN": "Lebanon",
"LSO": "Lesotho",
"LBR": "Liberia",
"LBY": "Libya",
"LIE": "Liechtenstein",
"LTU": "Lithuania",
"LUX": "Luxembourg",
"MAC": "Macao",
"MDG": "Madagascar",
"MWI": "Malawi",
"MYS": "Malaysia",
"MDV": "Maldives",
"MLI": "Mali",
"MLT": "Malta",
"MHL": "Marshall Islands",
"MTQ": "Martinique",
"MRT": "Mauritania",
"MUS": "Mauritius",
"MYT": "Mayotte",
"MEX": "Mexico",
"FSM": "Micronesia (Federated States of)",
"MDA": "Moldova, Republic of",
"MCO": "Monaco",
"MNG": "Mongolia",
"MNE": "Montenegro",
"MSR": "Montserrat",
"MAR": "Morocco",
"MOZ": "Mozambique",
"MMR": "Myanmar",
"NAM": "Namibia",
"NRU": "Nauru",
"NPL": "Nepal",
"NLD": "Netherlands",
"NCL": "New Caledonia",
"NZL": "New Zealand",
"NIC": "Nicaragua",
"NER": "Niger",
"NGA": "Nigeria",
"NIU": "Niue",
"NFK": "Norfolk Island",
"MKD": "North Macedonia",
"MNP": "Northern Mariana Islands",
"NOR": "Norway",
"OMN": "Oman",
"PAK": "Pakistan",
"PLW": "Palau",
"PSE": "Palestine, State of",
"PAN": "Panama",
"PNG": "Papua New Guinea",
"PRY": "Paraguay",
"PER": "Peru",
"PHL": "Philippines",
"PCN": "Pitcairn",
"POL": "Poland",
"PRT": "Portugal",
"PRI": "Puerto Rico",
"QAT": "Qatar",
"REU": "Reunion",
"ROU": "Romania",
"RUS": "Russian Federation",
"RWA": "Rwanda",
"BLM": "Saint Barthelemy",
"SHN": "Saint Helena, Ascension and Tristan da Cunha",
"KNA": "Saint Kitts and Nevis",
"LCA": "Saint Lucia",
"MAF": "Saint Martin (French part)",
"SPM": "Saint Pierre and Miquelon",
"VCT": "Saint Vincent and the Grenadines",
"WSM": "Samoa",
"SMR": "San Marino",
"STP": "Sao Tome and Principe",
"SAU": "Saudi Arabia",
"SEN": "Senegal",
"SRB": "Serbia",
"SYC": "Seychelles",
"SLE": "Sierra Leone",
"SGP": "Singapore",
"SXM": "Sint Maarten (Dutch part)",
"SVK": "Slovakia",
"SVN": "Slovenia",
"SLB": "Solomon Islands",
"SOM": "Somalia",
"ZAF": "South Africa",
"SGS": "South Georgia and the South Sandwich Islands",
"SSD": "South Sudan",
"ESP": "Spain",
"LKA": "Sri Lanka",
"SDN": "Sudan",
"SUR": "Suriname",
"SJM": "Svalbard and Jan Mayen",
"SWE": "Sweden",
"CHE": "Switzerland",
"SYR": "Syrian Arab Republic",
"TWN": "Taiwan, Province of China",
"TJK": "Tajikistan",
"TZA": "Tanzania, United Republic of",
"THA": "Thailand",
"TLS": "Timor-Leste",
"TGO": "Togo",
"TKL": "Tokelau",
"TON": "Tonga",
"TTO": "Trinidad and Tobago",
"TUN": "Tunisia",
"TUR": "Turkey",
"TKM": "Turkmenistan",
"TCA": "Turks and Caicos Islands",
"TUV": "Tuvalu",
"UGA": "Uganda",
"UKR": "Ukraine",
"ARE": "United Arab Emirates",
"GBR": "United Kingdom of Great Britain and Northern Ireland",
"USA": "United States of America",
"UMI": "United States Minor Outlying Islands",
"URY": "Uruguay",
"UZB": "Uzbekistan",
"VUT": "Vanuatu",
"VEN": "Venezuela (Bolivarian Republic of)",
"VNM": "Viet Nam",
"VGB": "Virgin Islands (British)",
"VIR": "Virgin Islands (U.S.)",
"WLF": "Wallis and Futuna",
"ESH": "Western Sahara",
"YEM": "Yemen",
"ZMB": "Zambia",
"ZWE": "Zimbabwe"
}

View File

@@ -105,23 +105,6 @@ export function assembleEContent(
return constructedEContent;
}
export function checkInputs(
passportNumber: string,
dateOfBirth: string,
dateOfExpiry: string,
): boolean {
// if (passportNumber.length !== 9) {
// throw new Error('Passport number must be 9 characters long');
// }
if (dateOfBirth.length !== 6) {
throw new Error('Date of birth must be 6 characters long');
}
if (dateOfExpiry.length !== 6) {
throw new Error('Date of expiry must be 6 characters long');
}
return true;
}
export function toUnsigned(byte: number) {
return byte & 0xff;
}

View File

@@ -1,32 +0,0 @@
pragma solidity ^0.8.13;
import "zodiac/core/Module.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
contract PassportRecoverySafeModule is Module {
ERC721Enumerable public passportSBT;
uint256 public id;
error NotAuthorized();
constructor() {
_transferOwnership(msg.sender);
}
function setUp(bytes memory initializeParams) public override {}
function init(address safe, address _passportSBT, uint256 _id) public {
setAvatar(safe);
setTarget(safe);
passportSBT = _passportSBT;
id = _id;
}
function claimSafe(bytes memory data) public {
if (passportSBT.ownerOf(id) == msg.sender) {
exec(avatar, 0, data, Enum.Operation.Call);
} else {
revert NotAuthorized();
}
}
}

View File

@@ -1,68 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import {Verifier} from "./RsaSha256Verifier.sol";
contract ProofOfBaguette is ERC721Enumerable, Ownable {
using Counters for Counters.Counter;
Verifier public immutable verifier;
address public cscaPubkey = 0x0000000000000000000000000000000000000000;
Counters.Counter public tokenCounter;
constructor(Verifier v) ERC721("ProofOfPassport", "ProofOfPassport") {
verifier = v;
transferOwnership(msg.sender);
}
function setCSCApubKey(address _CSCApubKey) public onlyOwner {
cscaPubkey = _CSCApubKey;
}
// function check(
// uint256[2] memory a,
// uint256[2][2] memory b,
// uint256[2] memory c,
// uint256[100] memory inputs
// ) public {
// require(Pairing.verifyProof(a, b, c, inputs), "Invalid Proof");
// }
function mint(
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
uint256[97] memory inputs
) public {
// Check eth address committed to in proof matches msg.sender, to avoid replayability
// require(address(uint160(inputs[addressIndexInSignals])) == msg.sender, "Invalid address");
// Verify that the public key for RSA matches the hardcoded one
// for (uint256 i = body_len; i < msg_len - 1; i++) {
// require(mailServer.isVerified(domain, i - body_len, inputs[i]), "Invalid: RSA modulus not matched");
// }
// Verify that the public key for RSA matches the hardcoded one
// commented out for now, since hard to keep up with all
// require(cscaPubkey == inputs[], "Invalid pubkey in inputs");
require(verifier.verifyProof(a, b, c, inputs), "Invalid Proof");
// Effects: Mint token
uint256 tokenId = tokenCounter.current() + 1;
_mint(msg.sender, tokenId);
tokenCounter.increment();
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal {
require(from == address(0), "Cannot transfer - Passport is soulbound");
}
}

View File

@@ -0,0 +1,203 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import {Groth16Verifier} from "./Verifier.sol";
import {Base64} from "./libraries/Base64.sol";
import {Formatter} from "./libraries/Formatter.sol";
import "hardhat/console.sol";
contract ProofOfPassport is ERC721Enumerable, Ownable {
using Strings for uint256;
using Base64 for *;
Groth16Verifier public immutable verifier;
Formatter public formatter;
address public cscaPubkey = 0x0000000000000000000000000000000000000000;
mapping(uint256 => bool) public nullifiers;
struct AttributePosition {
string name;
uint256 start;
uint256 end;
uint256 index;
}
struct Attributes {
string[7] values;
}
AttributePosition[] public attributePositions;
mapping(uint256 => Attributes) private tokenAttributes;
constructor(Groth16Verifier v, Formatter f) ERC721("ProofOfPassport", "ProofOfPassport") {
verifier = v;
formatter = f;
setupAttributes();
transferOwnership(msg.sender);
}
function setupAttributes() internal {
attributePositions.push(AttributePosition("issuing_state", 2, 4, 0));
attributePositions.push(AttributePosition("name", 5, 43, 1));
attributePositions.push(AttributePosition("passport_number", 44, 52, 2));
attributePositions.push(AttributePosition("nationality", 54, 56, 3));
attributePositions.push(AttributePosition("date_of_birth", 57, 62, 4));
attributePositions.push(AttributePosition("gender", 64, 64, 5));
attributePositions.push(AttributePosition("expiry_date", 65, 70, 6));
}
function setCSCApubKey(address _CSCApubKey) public onlyOwner {
cscaPubkey = _CSCApubKey;
}
function mint(
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
uint256[16] memory inputs
) public {
// check that the nullifier has not been used before
require(!nullifiers[inputs[3]], "Signature already nullified");
// Verify that the public key for RSA matches the hardcoded one
// for (uint256 i = body_len; i < msg_len - 1; i++) {
// require(mailServer.isVerified(domain, i - body_len, inputs[i]), "Invalid: RSA modulus not matched");
// }
// inputs[4]
// Verify that the public key for RSA matches the hardcoded one
// commented out for now, since hard to keep up with all
// require(cscaPubkey == inputs[], "Invalid pubkey in inputs");
require(verifier.verifyProof(a, b, c, inputs), "Invalid Proof");
// Effects: Mint token
address addr = address(uint160(inputs[inputs.length - 1])); // generally the last one
uint256 newTokenId = totalSupply();
_mint(addr, newTokenId);
nullifiers[inputs[3]] = true;
// Set attributes
uint256[3] memory firstThree = sliceFirstThree(inputs);
bytes memory charcodes = fieldElementsToBytes(firstThree);
// console.logBytes1(charcodes[21]);
Attributes storage attributes = tokenAttributes[newTokenId];
for (uint i = 0; i < attributePositions.length; i++) {
AttributePosition memory attribute = attributePositions[i];
bytes memory attributeBytes = new bytes(attribute.end - attribute.start + 1);
for (uint j = attribute.start; j <= attribute.end; j++) {
attributeBytes[j - attribute.start] = charcodes[j];
}
string memory attributeValue = string(attributeBytes);
attributes.values[i] = attributeValue;
console.log(attribute.name, attributes.values[i]);
}
}
function fieldElementsToBytes(uint256[3] memory publicSignals) public pure returns (bytes memory) {
uint8[3] memory bytesCount = [31, 31, 26];
bytes memory bytesArray = new bytes(88); // 31 + 31 + 26
uint256 index = 0;
for (uint256 i = 0; i < 3; i++) {
uint256 element = publicSignals[i];
for (uint8 j = 0; j < bytesCount[i]; j++) {
bytesArray[index++] = bytes1(uint8(element & 0xFF));
element = element >> 8;
}
}
return bytesArray;
}
function sliceFirstThree(uint256[16] memory input) public pure returns (uint256[3] memory) {
uint256[3] memory sliced;
for (uint256 i = 0; i < 3; i++) {
sliced[i] = input[i];
}
return sliced;
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId,
uint256 batchSize
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId, batchSize);
require(from == address(0), "Cannot transfer - Proof of Passport is soulbound");
}
function tokenURI(
uint256 _tokenId
) public view virtual override returns (string memory) {
require(
_exists(_tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
Attributes memory attributes = tokenAttributes[_tokenId];
console.log("Issuing state in tokenURI", attributes.values[0]);
string memory firstName;
string memory lastName;
(firstName, lastName) = formatter.formatName(attributes.values[1]);
bytes memory baseURI = (
abi.encodePacked(
'{ "attributes": [',
'{"trait_type": "Issuing State", "value": "',
formatter.formatCountryName(attributes.values[0]),
'"},{"trait_type": "FirstName", "value": "',
firstName,
'"},{"trait_type": "LastName", "value": "',
lastName,
'"},{"trait_type": "Passport Number", "value": "',
attributes.values[2],
'"},{"trait_type": "Nationality", "value": "',
formatter.formatCountryName(attributes.values[3]),
'"},{"trait_type": "Date of birth", "value": "',
formatter.formatDate(attributes.values[4]),
'"},{"trait_type": "Gender", "value": "',
attributes.values[5],
'"},{"trait_type": "Expiry date", "value": "',
formatter.formatDate(attributes.values[6]),
'"},{"trait_type": "Expired", "value": "',
isExpired(_tokenId) ? "Yes" : "No",
'"}',
"],",
'"description": "Proof of Passport guarantees possession of a valid passport.","external_url": "https://github.com/zk-passport/proof-of-passport","image": "https://i.imgur.com/9kvetij.png","name": "Proof of Passport #',
_tokenId.toString(),
'"}'
)
);
return
string(
abi.encodePacked(
"data:application/json;base64,",
baseURI.encode()
)
);
}
function isExpired(uint256 _tokenId) public view returns (bool) {
Attributes memory attributes = tokenAttributes[_tokenId];
uint256 expiryDate = formatter.dateToUnixTimestamp(attributes.values[6]);
return block.timestamp > expiryDate;
}
}

View File

@@ -1,713 +0,0 @@
//
// Copyright 2017 Christian Reitwiessner
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// 2019 OKIMS
// ported to solidity 0.5
// fixed linter warnings
// added requiere error messages
//
pragma solidity >=0.5.0;
library Pairing {
struct G1Point {
uint X;
uint Y;
}
// Encoding of field elements is: X[0] * z + X[1]
struct G2Point {
uint[2] X;
uint[2] Y;
}
/// @return the generator of G1
function P1() internal pure returns (G1Point memory) {
return G1Point(1, 2);
}
/// @return the generator of G2
function P2() internal pure returns (G2Point memory) {
// Original code point
return
G2Point(
[
11559732032986387107991004021392285783925812861821192530917403151452391805634,
10857046999023057135944570762232829481370756359578518086990519993285655852781
],
[
4082367875863433681332203403145435568316851327593401208105741076214120093531,
8495653923123431417604973247489272438418190587263600148770280649306958101930
]
);
/*
// Changed by Jordi point
return G2Point(
[10857046999023057135944570762232829481370756359578518086990519993285655852781,
11559732032986387107991004021392285783925812861821192530917403151452391805634],
[8495653923123431417604973247489272438418190587263600148770280649306958101930,
4082367875863433681332203403145435568316851327593401208105741076214120093531]
);
*/
}
/// @return the negation of p, i.e. p.addition(p.negate()) should be zero.
function negate(G1Point memory p) internal pure returns (G1Point memory) {
// The prime q in the base field F_q for G1
uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
if (p.X == 0 && p.Y == 0) return G1Point(0, 0);
return G1Point(p.X, q - (p.Y % q));
}
/// @return r the sum of two points of G1
function addition(
G1Point memory p1,
G1Point memory p2
) internal view returns (G1Point memory r) {
uint[4] memory input;
input[0] = p1.X;
input[1] = p1.Y;
input[2] = p2.X;
input[3] = p2.Y;
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60)
// Use "invalid" to make gas() estimation work
switch success
case 0 {
invalid()
}
}
require(success, "pairing-add-failed");
}
/// @return r the product of a point on G1 and a scalar, i.e.
/// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p.
function scalar_mul(
G1Point memory p,
uint s
) internal view returns (G1Point memory r) {
uint[3] memory input;
input[0] = p.X;
input[1] = p.Y;
input[2] = s;
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
// Use "invalid" to make gas() estimation work
switch success
case 0 {
invalid()
}
}
require(success, "pairing-mul-failed");
}
/// @return the result of computing the pairing check
/// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
/// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
/// return true.
function pairing(
G1Point[] memory p1,
G2Point[] memory p2
) internal view returns (bool) {
require(p1.length == p2.length, "pairing-lengths-failed");
uint elements = p1.length;
uint inputSize = elements * 6;
uint[] memory input = new uint[](inputSize);
for (uint i = 0; i < elements; i++) {
input[i * 6 + 0] = p1[i].X;
input[i * 6 + 1] = p1[i].Y;
input[i * 6 + 2] = p2[i].X[0];
input[i * 6 + 3] = p2[i].X[1];
input[i * 6 + 4] = p2[i].Y[0];
input[i * 6 + 5] = p2[i].Y[1];
}
uint[1] memory out;
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(
sub(gas(), 2000),
8,
add(input, 0x20),
mul(inputSize, 0x20),
out,
0x20
)
// Use "invalid" to make gas() estimation work
switch success
case 0 {
invalid()
}
}
require(success, "pairing-opcode-failed");
return out[0] != 0;
}
/// Convenience method for a pairing check for two pairs.
function pairingProd2(
G1Point memory a1,
G2Point memory a2,
G1Point memory b1,
G2Point memory b2
) internal view returns (bool) {
G1Point[] memory p1 = new G1Point[](2);
G2Point[] memory p2 = new G2Point[](2);
p1[0] = a1;
p1[1] = b1;
p2[0] = a2;
p2[1] = b2;
return pairing(p1, p2);
}
/// Convenience method for a pairing check for three pairs.
function pairingProd3(
G1Point memory a1,
G2Point memory a2,
G1Point memory b1,
G2Point memory b2,
G1Point memory c1,
G2Point memory c2
) internal view returns (bool) {
G1Point[] memory p1 = new G1Point[](3);
G2Point[] memory p2 = new G2Point[](3);
p1[0] = a1;
p1[1] = b1;
p1[2] = c1;
p2[0] = a2;
p2[1] = b2;
p2[2] = c2;
return pairing(p1, p2);
}
/// Convenience method for a pairing check for four pairs.
function pairingProd4(
G1Point memory a1,
G2Point memory a2,
G1Point memory b1,
G2Point memory b2,
G1Point memory c1,
G2Point memory c2,
G1Point memory d1,
G2Point memory d2
) internal view returns (bool) {
G1Point[] memory p1 = new G1Point[](4);
G2Point[] memory p2 = new G2Point[](4);
p1[0] = a1;
p1[1] = b1;
p1[2] = c1;
p1[3] = d1;
p2[0] = a2;
p2[1] = b2;
p2[2] = c2;
p2[3] = d2;
return pairing(p1, p2);
}
}
contract Verifier {
using Pairing for *;
struct VerifyingKey {
Pairing.G1Point alfa1;
Pairing.G2Point beta2;
Pairing.G2Point gamma2;
Pairing.G2Point delta2;
Pairing.G1Point[] IC;
}
struct Proof {
Pairing.G1Point A;
Pairing.G2Point B;
Pairing.G1Point C;
}
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
vk.alfa1 = Pairing.G1Point(
10315822838385842923250715267205960664501004234546269981482666228112421301117,
15862104134162712938961972115840401024611162066277059180121297134493484755175
);
vk.beta2 = Pairing.G2Point(
[
16075180890105261855785821136620370206478347851900063884177434889569117892728,
8999056094627160946941478319055654711627346279360998804980685260524215980818
],
[
19289495299100654012777091634160205804317123853627581171870946780589078726579,
7456059757481809576237403196787593289176357510985305159986791878645463459018
]
);
vk.gamma2 = Pairing.G2Point(
[
13277046752313471688255968585488007150536152283305619319249966594057859924122,
1540853480038841992778609939618416755409643379500817690706199269912373494426
],
[
16195521367762890658515156444872542211791369361419964244676840991686196711549,
1050887057282964430320854978389799561269435789211688186694933498698817462348
]
);
vk.delta2 = Pairing.G2Point(
[
1662324983131052880488960499832632400354165691268048997945168703365805496815,
13662480426324514348188284803730524793155591206442565309405901461008907655891
],
[
15309139646391078466810181691750047695011680065613748420932752259577867509989,
11930459767156654479077330634914217815349186680049037714663239653430389142355
]
);
vk.IC = new Pairing.G1Point[](98);
vk.IC[0] = Pairing.G1Point(
1386156676430625766660721327519749365352708612284380407007672518761930314522,
5895979564403280714499324620374725835931311522554339174840912272198002116986
);
vk.IC[1] = Pairing.G1Point(
174429888906575054944644195492533447677698808764744275768027474986091262795,
19449982332092198717836917024306177058078885300180691030479512833448493420426
);
vk.IC[2] = Pairing.G1Point(
4940702259943724495655268600320625166138928124318746483111841772203931372898,
21300085871907717167823229271273029592921718070696716598133485043371262113949
);
vk.IC[3] = Pairing.G1Point(
3970523900986966741454839663423325691036075995128843350657752858925317431017,
539367542421702393681320993411652316058906805217114528699814649881160035531
);
vk.IC[4] = Pairing.G1Point(
14541643345260800436706406996787362480110194544530475630171161698573516679920,
4783331606526584048777066954770982727121131692786538183643102121348439890988
);
vk.IC[5] = Pairing.G1Point(
1075474176916105569002317826203973479107209650628777996236377287648466962810,
3232058447014508876051800237288950058552252367302714558767792524271099812787
);
vk.IC[6] = Pairing.G1Point(
2175834186336017845410894889748902248994354180137067840445873611529706706903,
3085466328487208450052471722737790746659231597949473931302689657743879290415
);
vk.IC[7] = Pairing.G1Point(
8148131669390700325085948796744014848738121345402965689215540127469598163871,
1459937161639492891103296404430347140474089613091612181507607941234824828188
);
vk.IC[8] = Pairing.G1Point(
19724824811793942534870544715526571102183990820436521365546859310276823467490,
9742652052240076179420483064624381054258687108701843582619502567192627148901
);
vk.IC[9] = Pairing.G1Point(
7516612085018412567965384915697804249943140639755254403509406043424863699565,
13609389560576142128414010599204241098833066563137827296644138017315963061370
);
vk.IC[10] = Pairing.G1Point(
5396430636568898715071511450196374579073195772247524680870475881840606697294,
14213494996959147888574066917872324178671816323712570898472101313990748811357
);
vk.IC[11] = Pairing.G1Point(
19580033029544330967448763121940485539766629034681462072482784578056476122075,
4714739906270684478426827011422485533664415859906533725309733675967596336877
);
vk.IC[12] = Pairing.G1Point(
6962906881391363529838287799824200955017681097924230628024324423216037180574,
2533319035586796547972968495763128583304226889898155603872302902791149215692
);
vk.IC[13] = Pairing.G1Point(
17536765943492961589593406025711160790038974470090381500798551989642376205429,
9210978437865389852687238356987463161070296894056858501516143895498895127801
);
vk.IC[14] = Pairing.G1Point(
12879519606836370836828899572118098335153146603118228135363495427283082247364,
5758811831466689143387239476857856589657131463745229429624027029582131264569
);
vk.IC[15] = Pairing.G1Point(
15735427660464208356818266871402603071222212568728528929189278663470048519151,
18580418584929980580683876981646262205040063567947776691626290499751484842387
);
vk.IC[16] = Pairing.G1Point(
16672772973559614591916036849008777420093824711538705835090610899870382314653,
8188923103596302037595788157162335200890030912840313545299503026362065475579
);
vk.IC[17] = Pairing.G1Point(
3482245003117717783432002198738459699873717589098511868698895399302488358634,
19652796079067654964753702546413435895310867146965033514795952134870224747298
);
vk.IC[18] = Pairing.G1Point(
9382323532935595934689116629634156851330374962350295158341742092304036335698,
291925329935370804008844005614341459550809875961285224043109628983162794811
);
vk.IC[19] = Pairing.G1Point(
6912981219684193325373956580555507527124688523637412271688548642710145407324,
17719276416320101991178800934805150313358144003174217318902641925424693400899
);
vk.IC[20] = Pairing.G1Point(
19266481578774074906374076433526482559085483237651754027979037618702501848415,
4864429104782323549403921207719837137283226783050574715140728078210440815125
);
vk.IC[21] = Pairing.G1Point(
14887253562463317132282666699497653091722231007983834420246533880775604202046,
20039483939999528919395933890813583839636534363798896837987674667077445002909
);
vk.IC[22] = Pairing.G1Point(
12508816416091085449368756125649842984927777064057218811145926432353321314907,
1029754988093911081347891722709482405445904745087304835816390911520486811458
);
vk.IC[23] = Pairing.G1Point(
2005084167017357346303758528212973722634282057561071593677784384715301762428,
5542975189718331938312935936918047907052872873683385011086540332580563138005
);
vk.IC[24] = Pairing.G1Point(
574144171155849827838725501058774562989672318997217369030672907489094325392,
19011911734470524036198981595964567011458551418797935766148211921982472474741
);
vk.IC[25] = Pairing.G1Point(
3608292935417210943680485162182048774922203693936402328868647729908340527540,
19717618713526912033181757546212053048433914196349054761157402425200075671138
);
vk.IC[26] = Pairing.G1Point(
16163461701324146513568429102887561273066181667891291346998415488778690716805,
18662884437485380367184050862289985597601843562942757559581184607687570812550
);
vk.IC[27] = Pairing.G1Point(
14994566112480375832970198317517069193388049320082571292718031142344097962255,
19889898631674322802597671404075063684983733435916365516196892134719573840178
);
vk.IC[28] = Pairing.G1Point(
736585196548664503732509698047552122038996165424116313982190787863322931826,
21019115756986596749277994511714050838771464310078186895547975840389783871138
);
vk.IC[29] = Pairing.G1Point(
10974717193636000167380652442472909714934064969981711063607439335825119243469,
8613997549030193852101564196304783271636045228187714896154399752466639047526
);
vk.IC[30] = Pairing.G1Point(
15515808334102622843044245600125992020384745623672581785591253976335954691668,
7056069273753880907078615715739794771659566915279338309055469505277556660014
);
vk.IC[31] = Pairing.G1Point(
2026995926214775331423673216302815034683334238220808093286826947311593039794,
14548613909100523536915943149130374917224265797462738040649328509010392696205
);
vk.IC[32] = Pairing.G1Point(
7347999393948250440988207859344770709243120088530457172274758503515633459971,
20430173716253509790919340588694849367500686486837868170440361371544940846857
);
vk.IC[33] = Pairing.G1Point(
8726020462171177960911520449113858654607194259478482096783149613868723406121,
21109992085518709586188037780336334901483462217597999928530659225385204929051
);
vk.IC[34] = Pairing.G1Point(
18759571018089650279499799472273628763502429845355459478077716291216286451672,
3061120585842126900115563926687483611216432798358081316062265175950975462706
);
vk.IC[35] = Pairing.G1Point(
10081168513618588217797803738246975722763428651743613956930591217530005755308,
5223516720621635076713966633725260161024836955550260381664330387742167168437
);
vk.IC[36] = Pairing.G1Point(
18623257401997776504806348144872345347118220689716572995578481344526381397027,
12738216514382521354381755763633144591976312475306345247101617502260715984300
);
vk.IC[37] = Pairing.G1Point(
12613017704259258984783441890484052267798710998400588809375095368441312203177,
13154863759245282454936298393415245536123605264867594333724866438497549024170
);
vk.IC[38] = Pairing.G1Point(
12709290832361335753305864258009255307237010774441288781285781702671213114765,
18349056269309660723886180747727132860619888970885172282384405779461541989577
);
vk.IC[39] = Pairing.G1Point(
17447538751610051385783414732492525667137731039071585637687353043409911312358,
8705755619226884560464931039313987689788884448049673193589169040745836183092
);
vk.IC[40] = Pairing.G1Point(
19903040530418130172724072033663794977209466570949249258688233439835382961705,
6538405654339479654547899704613913798731714798978111499534963418797636778536
);
vk.IC[41] = Pairing.G1Point(
20190111036656612665976758535510402352901099971723589132364459219237140650804,
11657276287181136248459738132957662348970456139200020118947243073509600583324
);
vk.IC[42] = Pairing.G1Point(
5496409758069382276348459990808117794030958339567169207650726751174822075842,
15398624126895562271141819515160389374772951137601086902126706157329463089406
);
vk.IC[43] = Pairing.G1Point(
8151283523500801176883094078648061648579761104703136856876223887187491028764,
19699576961944733283219819902822060278574556991476755360120251735226112577042
);
vk.IC[44] = Pairing.G1Point(
8533704954946914002953946046744749163319734782733169970628585647060058140849,
5141897905579649570194799195601184296177984332792452257361194331009931371352
);
vk.IC[45] = Pairing.G1Point(
17671515716110934550447360224709626247970759130056552979213535489731669688446,
1690274318568461080087753254251786392263489028973782647985819430312525336960
);
vk.IC[46] = Pairing.G1Point(
8478603008571616038378551513375406458692917186348304648150064228029895779958,
20116202548019188938994896483571557179861045004954664127312673627929525959276
);
vk.IC[47] = Pairing.G1Point(
6432981094696267073379852248786055231176785645227335199813013566498759785384,
14983269753830770996227222283167931949083546323507335724535651513681318189079
);
vk.IC[48] = Pairing.G1Point(
9455507927501800915564496121759986854117031410770932562840240404182614698028,
5285955876415145827392451089524707681594893418176652281578834051447348307955
);
vk.IC[49] = Pairing.G1Point(
20714130644236382051591460208572376019763347755510239498689871430769906890685,
18654357373482716030683276562311098400463035289899424564068036000769595694407
);
vk.IC[50] = Pairing.G1Point(
16832181157818881181838165095351716004273729658170734148090869509398951353661,
13189116767733698206617444976497238961678787103102046696228609244708542732492
);
vk.IC[51] = Pairing.G1Point(
8076452889145567190300790005312690920477320514039067078236315139521658556063,
890666235559929062329759673773557091924363971646065907430303231638612724999
);
vk.IC[52] = Pairing.G1Point(
8358804823290743257390543678494170562797974621132658774911399394185092545208,
20752753364958656771514688460585465011660082299985374260145811301437669043257
);
vk.IC[53] = Pairing.G1Point(
431866034143667612182321520413242716471591638473939166320447500693829929824,
13272258147627911088702851414812922302256821216107539459911504860535837022135
);
vk.IC[54] = Pairing.G1Point(
9173989288857204293038005754886211674464077439638776033201321349164196474616,
9129103250645493108241162941947967350521408326116971248120638209361233930192
);
vk.IC[55] = Pairing.G1Point(
14370826205941952851735365552127894021162133888463493633318496244143095511040,
1651163962095785808536509256199563475789494126010520314335456260358111804976
);
vk.IC[56] = Pairing.G1Point(
12951186966437270849914379924115857496875963456775592910919046812882705115830,
16465255691963080311345885861560112122320977883916615486276340659371056324863
);
vk.IC[57] = Pairing.G1Point(
3283421748134600628821861152296048618970465417807515877620876335991742901315,
321535500846302427006164553338203893489982138176792264731766129421299212286
);
vk.IC[58] = Pairing.G1Point(
16855387142616687237143755251732902794908605199755471474196892846417162793353,
6761300099779160392813801467707189572028647758855510242027256178070516219805
);
vk.IC[59] = Pairing.G1Point(
15257833521992801874267530841829063197963470852447328292085028034633128521860,
2677084778946138423753273144604322607349537157189860183844829718089957601689
);
vk.IC[60] = Pairing.G1Point(
12162232048810887816633786290513237732818779568650791939302917523152130208608,
21333612874220018324963566977200031875031579203366186578790260941880595484190
);
vk.IC[61] = Pairing.G1Point(
3391460336279928586355347127909680776960941614168264915045172621785079485704,
12982837279076354859831048030572798151280294385261501888099056857982051493723
);
vk.IC[62] = Pairing.G1Point(
15657943681489382687201670166559198773174544761807418817146753024083872167923,
18015415673040996199684319960118318566240959606331772073882264856214095914848
);
vk.IC[63] = Pairing.G1Point(
8764939161163047254075099233130913745881634109004943576089798043960197509190,
8107199767148537717254346850921330983657137386989043360271851202867981408937
);
vk.IC[64] = Pairing.G1Point(
10021072243678930222406582984936927324952592680308844821701808488346598011536,
18628636656506555862260913227929463140408813957986050071538961255104712647438
);
vk.IC[65] = Pairing.G1Point(
17321445808461122141320330203945732558478795973243070098294285860455518065400,
16836801211792107863813977849708073042443024384474661086287213089562566255496
);
vk.IC[66] = Pairing.G1Point(
6861883922532910695796926319034380512803020100037212756359821156112905138580,
4119726663248857193393003082612555725457402139141352624262468551517744622172
);
vk.IC[67] = Pairing.G1Point(
20779722207278452530034931086404649516930804730094114642064752236829364601447,
923216039876130666302755287286364480134410103154729240965964497426983067027
);
vk.IC[68] = Pairing.G1Point(
18223166030017443686801675867411730766342079179157572962560303448024540378873,
19137631582171918191178945920059761447327783213698872810575523895658550121438
);
vk.IC[69] = Pairing.G1Point(
19280775121328851013552281475852868120438320598442383749752027288009797861226,
12490038968016646741084557672265847583317098207883228839969661867319900663938
);
vk.IC[70] = Pairing.G1Point(
15266937199766366472290794995102829438088329284982774063851360931479775159611,
13689004097893574081491974026588805143385995491553380346109157632864045768875
);
vk.IC[71] = Pairing.G1Point(
17127411247775554441458092526202757327238548637076996720303283409273103437241,
10596065368731694429534822719625874694561881193931687112659878038042780625711
);
vk.IC[72] = Pairing.G1Point(
20787730078931630052831457097859925558304786674420765003148675017286328663454,
4766261406083257091458978020157041851129907303478874471741979469684861357286
);
vk.IC[73] = Pairing.G1Point(
7658787061468359549149413908281153599600426600224344615749437495818897340061,
19492153087231292728213440771478900053083907495283660596623580137450879415100
);
vk.IC[74] = Pairing.G1Point(
2659875083118001544715497837457590514140432874048404892210543537504037071661,
15950956910927529441229027517507989615611330940703370326686704858035089993977
);
vk.IC[75] = Pairing.G1Point(
894399989010319765961292956333169984328533949797732202422998120207741013782,
20592958484709720804789976380652330981257235977335874841811437076585969381001
);
vk.IC[76] = Pairing.G1Point(
20463015942337846506404366208676722951112664440577043884221657224419349265426,
6421219926717668723328940652796576549618654759959257419184397188890959888254
);
vk.IC[77] = Pairing.G1Point(
9120006372090123874675982389686869282084694298376106330824231921836495845409,
15465095824110179992312247621712212010265469017852248921480310833628600196157
);
vk.IC[78] = Pairing.G1Point(
20878479603359665116911215284012493370991345348316318380338256326707347229536,
4023483592190020939497447440294056485175982685635791231809180749028140340638
);
vk.IC[79] = Pairing.G1Point(
8597284910335812117769054177782693879835500749625261064784252225098566359260,
1994440743925322001344248550218761689604854304576917328729121903199340521566
);
vk.IC[80] = Pairing.G1Point(
7226426264671955929078859416556503158659896696978967948922009868308681953328,
5002887692172752997421567561731103949750630834248867239253107045744551201397
);
vk.IC[81] = Pairing.G1Point(
8163659204347449052568944424719246353276866468717985570811227109999390783526,
2423554439374965365549822958553913623548960716554949332971802593317970068208
);
vk.IC[82] = Pairing.G1Point(
1452926204022804055491637328319845396827870792644285034170433031762060878731,
4515541462700718639411085202358475754243785926272495802232114060028112391704
);
vk.IC[83] = Pairing.G1Point(
10425052225329871422199244352265298427973414162141911718953442959319724848059,
6000980400205901551254828664011101250210525131160335488511361553516655902490
);
vk.IC[84] = Pairing.G1Point(
3443318109975964447008176890335731705529322253119216155023763429975158085456,
21667811197670469631232954863890416289566410095141706262390806877014912268732
);
vk.IC[85] = Pairing.G1Point(
11012015869641066138899933574589113596936265876486762743315648962963495824732,
17255543862480532041551281296396472142322479563450509347024960074045362179060
);
vk.IC[86] = Pairing.G1Point(
15356674987302087761214804729834932350868870076692636651461027280636953611115,
106117314594064361971425646139042972248859283384292253606696261962696377665
);
vk.IC[87] = Pairing.G1Point(
19394337841622616135946277478438753742631263129950419370472461951284656870437,
18658921822284494457486069764820562705515256999764362724356266226041497733846
);
vk.IC[88] = Pairing.G1Point(
19875109758700507740317077711867102397002017483813266849042947928472067707358,
19410883671720154448415997196283075716793971043467577411686702678513758313202
);
vk.IC[89] = Pairing.G1Point(
7249713751934247391364446379816208988062392543310362185047382861082689029853,
15650473527588496827417556647724864391410175426412916274036894124836771437372
);
vk.IC[90] = Pairing.G1Point(
10681784480850187071361190982043613309470613382346001095644109815254178261562,
21463186786189007954888872290310300639849300805770275708108444072996981167758
);
vk.IC[91] = Pairing.G1Point(
2236471884703014171599710044819634924237606371553705429021763383635629939512,
8591793843410995494533247352157879065992731222902203603345134905701260856709
);
vk.IC[92] = Pairing.G1Point(
19527584213761472463971374073739673431341601035403206019474791549273088278339,
17023146508154304148121691671727331328909786836109367376841186597185724956581
);
vk.IC[93] = Pairing.G1Point(
13014073780365318482787844435657644319669081253207330065868995816477880130774,
7445666461778273821119755595191049214876947852015119252135282618289816306885
);
vk.IC[94] = Pairing.G1Point(
12572056578214122696110853014461970380570794921497586679104888016792687653897,
4719197114816095442488216520733780832840070057650826491567278989945747530502
);
vk.IC[95] = Pairing.G1Point(
16403748676169345391285149130393817667502440052483475786225216623710841245155,
662053335174191665497628974718863306486637341349159158533932987069502165029
);
vk.IC[96] = Pairing.G1Point(
17138980304892429856246490017005560669710783569541041650327401681838238378449,
9291405839197739071712757020744264998332332192064696611245414441329433805436
);
vk.IC[97] = Pairing.G1Point(
6594423345144626172531684508535057814902607027465847698107011859735578724064,
1609167828729266896521507304269994081996148238161423140896831053169366858561
);
}
function verify(
uint[] memory input,
Proof memory proof
) internal view returns (uint) {
uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
VerifyingKey memory vk = verifyingKey();
require(input.length + 1 == vk.IC.length, "verifier-bad-input");
// Compute the linear combination vk_x
Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);
for (uint i = 0; i < input.length; i++) {
require(
input[i] < snark_scalar_field,
"verifier-gte-snark-scalar-field"
);
vk_x = Pairing.addition(
vk_x,
Pairing.scalar_mul(vk.IC[i + 1], input[i])
);
}
vk_x = Pairing.addition(vk_x, vk.IC[0]);
if (
!Pairing.pairingProd4(
Pairing.negate(proof.A),
proof.B,
vk.alfa1,
vk.beta2,
vk_x,
vk.gamma2,
proof.C,
vk.delta2
)
) return 1;
return 0;
}
function verifyProof(
uint[2] memory a,
uint[2][2] memory b,
uint[2] memory c,
uint[97] memory input
) public view returns (bool r) {
Proof memory proof;
proof.A = Pairing.G1Point(a[0], a[1]);
proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]);
proof.C = Pairing.G1Point(c[0], c[1]);
uint[] memory inputValues = new uint[](input.length);
for (uint i = 0; i < input.length; i++) {
inputValues[i] = input[i];
}
if (verify(inputValues, proof) == 0) {
return true;
} else {
return false;
}
}
}

View File

@@ -0,0 +1,275 @@
// 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 Groth16Verifier {
// 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 = 3037890460429929853828629296742086109008517454031147703442813108881426331381;
uint256 constant deltax2 = 11415705872230497398160420978210813941423805400115940468997080730756770095941;
uint256 constant deltay1 = 4781886835288895006988886960857872859778352874458931312709265942186357137609;
uint256 constant deltay2 = 6660151851452724449234553790200573309196429136517999261040530971073361464771;
uint256 constant IC0x = 4897812530436581420070048815704719785256466787655503857610889333796081821201;
uint256 constant IC0y = 21324217308758963004039464033551222626995062428505595457846546072979649950535;
uint256 constant IC1x = 3402067829842345916430895428185245090645621522198317090797379965574771542636;
uint256 constant IC1y = 15689341079133962080137763365487039194375030636040098473539254350433970371666;
uint256 constant IC2x = 17395362500217368985868893090734905039167826866091632900857231867723495577602;
uint256 constant IC2y = 7930260148586132748363663695528567251481992615924576457603406418853534765181;
uint256 constant IC3x = 585494952178863414068208567603839798093905284375122061973360892129986520320;
uint256 constant IC3y = 9052106461455604192832593945466435172808609013430707922648579604917214395471;
uint256 constant IC4x = 7009544555987721721525965879762930953012066717281509356647068054408609863246;
uint256 constant IC4y = 9820829334259318510794834811753840115411696228971683399345859623869811549881;
uint256 constant IC5x = 14238418207024939545815829157744718461870627038741425938816007286311574134474;
uint256 constant IC5y = 281828200475697177916593309667507636329345262293367509851063337891478088781;
uint256 constant IC6x = 2588875801176981985506740691573068253787601389179711941209167172577223524972;
uint256 constant IC6y = 15518320710469760878810555468816349074382837865578096899468878146062509663814;
uint256 constant IC7x = 17316533695265131380437649603796400699657451230738779001098608159520582988369;
uint256 constant IC7y = 8192809588256960378913803069056080395056022087843425771582496472786713726350;
uint256 constant IC8x = 7407001681033909392094003743482787694603426004447721439357204522366208646546;
uint256 constant IC8y = 14678011064151490372018354732758508739891026527348606433971585164806457243690;
uint256 constant IC9x = 14324550585252189304511012915310919737099760521255841560510202883547241215550;
uint256 constant IC9y = 17843516173433864891394764190574725294294272661192260445890002683170043518436;
uint256 constant IC10x = 7539891259658208616633326740578026995822087197681333710337145994575633967330;
uint256 constant IC10y = 11252528180616460725708054390959401682257312545535188972038868508936671228701;
uint256 constant IC11x = 13300379642556942794398405666278194834327040509717856013516915921151482858342;
uint256 constant IC11y = 3765685546823952453740511654773017065896884149593650080085427606727523849353;
uint256 constant IC12x = 9268919849281685133024784239234560640021437913056581963083327429501365255031;
uint256 constant IC12y = 11222912618976361984001818562665888490194957370177999142904578411305511279126;
uint256 constant IC13x = 2597478889552428352737130179687206531821645186216868965539289093449836402726;
uint256 constant IC13y = 757968852987628828382971340903318389342984851650872494795704692702408158904;
uint256 constant IC14x = 16147563600769233454259564579865458680953713847620754688678964339139397943562;
uint256 constant IC14y = 3229058257062194976564868360849873757615447419031013710509312378420932332089;
uint256 constant IC15x = 11276405747528923910383092138862864843497716277810279291090775583122182049041;
uint256 constant IC15y = 17478497004985764197329627914040721906294759410027200889688899456335265284727;
uint256 constant IC16x = 7537276704716430448981792598508402432998887447285614055846784939499149706536;
uint256 constant IC16y = 13397681836333574838145763582606233729786782316119672353292568940401561429759;
// 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[16] 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)))
g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128)))
g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160)))
g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192)))
g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224)))
g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256)))
g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288)))
g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320)))
g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352)))
g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384)))
g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416)))
g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448)))
g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480)))
// -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)))
checkField(calldataload(add(_pubSignals, 160)))
checkField(calldataload(add(_pubSignals, 192)))
checkField(calldataload(add(_pubSignals, 224)))
checkField(calldataload(add(_pubSignals, 256)))
checkField(calldataload(add(_pubSignals, 288)))
checkField(calldataload(add(_pubSignals, 320)))
checkField(calldataload(add(_pubSignals, 352)))
checkField(calldataload(add(_pubSignals, 384)))
checkField(calldataload(add(_pubSignals, 416)))
checkField(calldataload(add(_pubSignals, 448)))
checkField(calldataload(add(_pubSignals, 480)))
checkField(calldataload(add(_pubSignals, 512)))
// Validate all evaluations
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
mstore(0, isValid)
return(0, 0x20)
}
}
}

View File

@@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
/// @title Base64
/// @author Brecht Devos - <brecht@loopring.org>
/// @notice Provides a function for encoding some bytes in base64
pragma solidity ^0.8.18;
library Base64 {
string internal constant TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function encode(bytes memory data) internal pure returns (string memory) {
if (data.length == 0) return '';
// load the table into memory
string memory table = TABLE;
// multiply by 4/3 rounded up
uint256 encodedLen = 4 * ((data.length + 2) / 3);
// add some extra buffer at the end required for the writing
string memory result = new string(encodedLen + 32);
assembly {
// set the actual output length
mstore(result, encodedLen)
// prepare the lookup table
let tablePtr := add(table, 1)
// input ptr
let dataPtr := data
let endPtr := add(dataPtr, mload(data))
// result ptr, jump over length
let resultPtr := add(result, 32)
// run over the input, 3 bytes at a time
for {} lt(dataPtr, endPtr) {}
{
dataPtr := add(dataPtr, 3)
// read 3 bytes
let input := mload(dataPtr)
// write 4 characters
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
resultPtr := add(resultPtr, 1)
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
resultPtr := add(resultPtr, 1)
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F)))))
resultPtr := add(resultPtr, 1)
mstore(resultPtr, shl(248, mload(add(tablePtr, and( input, 0x3F)))))
resultPtr := add(resultPtr, 1)
}
// padding with '='
switch mod(mload(data), 3)
case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
}
return result;
}
}

View File

@@ -0,0 +1,166 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Formatter is Ownable {
mapping(string => string) private countryCodes;
constructor() {
transferOwnership(msg.sender);
}
function formatName(string memory input) public pure returns (string memory firstName, string memory lastName) {
bytes memory inputBytes = bytes(input);
bytes memory firstNameBytes;
bytes memory lastNameBytes;
uint i = 0;
// Extract last name
while(i < inputBytes.length && inputBytes[i] != '<') {
lastNameBytes = abi.encodePacked(lastNameBytes, inputBytes[i]);
i++;
}
// Skip the separator "<<"
i += 2;
// Extract first names
while(i < inputBytes.length) {
if(inputBytes[i] == '<') {
if (i + 1 < inputBytes.length && inputBytes[i + 1] == '<') {
break;
}
firstNameBytes = abi.encodePacked(firstNameBytes, ' ');
} else {
firstNameBytes = abi.encodePacked(firstNameBytes, inputBytes[i]);
}
i++;
}
firstName = string(firstNameBytes);
lastName = string(lastNameBytes);
}
function formatDate(string memory date) public pure returns (string memory) {
// Ensure the date string is the correct length
require(bytes(date).length == 6, "Invalid date length");
string memory year = substring(date, 0, 2);
string memory month = substring(date, 2, 4);
string memory day = substring(date, 4, 6);
return string(abi.encodePacked(day, "-", month, "-", year));
}
function substring(string memory str, uint startIndex, uint endIndex) public pure returns (string memory) {
bytes memory strBytes = bytes(str);
bytes memory result = new bytes(endIndex - startIndex);
for(uint i = startIndex; i < endIndex; i++) {
result[i - startIndex] = strBytes[i];
}
return string(result);
}
function formatCountryName(string memory code) public view returns (string memory) {
string memory countryName = countryCodes[code];
if(bytes(countryName).length == 0) {
return code;
}
return countryName;
}
function addCountryCodes(string[][] memory codeToName) public onlyOwner {
for(uint i = 0; i < codeToName.length; i++) {
string memory code = codeToName[i][0];
string memory name = codeToName[i][1];
countryCodes[code] = name;
}
}
function dateToUnixTimestamp(string memory date) public pure returns (uint256) {
// Ensure the date string is the correct length (6 characters)
require(bytes(date).length == 6, "Invalid date length");
// Extract day, month, and year
uint year = parseDatePart(substring(date, 0, 2)) + 2000;
uint month = parseDatePart(substring(date, 2, 4));
uint day = parseDatePart(substring(date, 4, 6));
// Convert to Unix timestamp
return toTimestamp(year, month, day);
}
// Helper function to convert a string to an integer
function parseDatePart(string memory value) internal pure returns (uint) {
bytes memory tempEmptyStringTest = bytes(value);
if (tempEmptyStringTest.length == 0) {
return 0;
}
uint digit;
uint result;
for (uint i = 0; i < tempEmptyStringTest.length; i++) {
digit = uint(uint8(tempEmptyStringTest[i])) - 48; // '0' is 48 in ASCII
result = result * 10 + digit;
}
return result;
}
// Convert date to Unix timestamp
function toTimestamp(uint256 year, uint256 month, uint256 day) internal pure returns (uint timestamp) {
uint16 i;
// Year
for (i = 1970; i < year; i++) {
if (isLeapYear(i)) {
timestamp += 366 days;
} else {
timestamp += 365 days;
}
}
// Month
uint8[12] memory monthDayCounts;
monthDayCounts[0] = 31;
if (isLeapYear(year)) {
monthDayCounts[1] = 29;
} else {
monthDayCounts[1] = 28;
}
monthDayCounts[2] = 31;
monthDayCounts[3] = 30;
monthDayCounts[4] = 31;
monthDayCounts[5] = 30;
monthDayCounts[6] = 31;
monthDayCounts[7] = 31;
monthDayCounts[8] = 30;
monthDayCounts[9] = 31;
monthDayCounts[10] = 30;
monthDayCounts[11] = 31;
for (i = 1; i < month; i++) {
timestamp += monthDayCounts[i - 1] * 1 days;
}
// Day
timestamp += (day - 1) * 1 days;
return timestamp;
}
// Check if year is a leap year
function isLeapYear(uint256 year) internal pure returns (bool) {
if (year % 4 != 0) {
return false;
} else if (year % 100 != 0) {
return true;
} else if (year % 400 != 0) {
return false;
} else {
return true;
}
}
}

View File

@@ -1,16 +1,12 @@
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
require("dotenv").config();
import "hardhat-contract-sizer";
const config: HardhatUserConfig = {
solidity: "0.8.9",
solidity: "0.8.18",
defaultNetwork: "hardhat",
networks: {
hardhat: {
chainId: process.env.HARDHAT_CHAIN_ID
? Number(process.env.HARDHAT_CHAIN_ID)
: 31337,
},
goerli: {
url: "https://eth-goerli.public.blastapi.io",
accounts: [process.env.PKEY as string],
@@ -19,26 +15,10 @@ const config: HardhatUserConfig = {
url: "https://polygon.llamarpc.com",
accounts: [process.env.PKEY as string],
},
gnosis: {
url: "https://rpc.chiado.gnosis.gateway.fm",
mumbai: {
url: "https://polygon-mumbai-bor.publicnode.com",
accounts: [process.env.PKEY as string],
},
linea: {
url: `https://linea-goerli.infura.io/v3/${process.env.INFURA_KEY}`,
accounts: [process.env.PKEY as string],
},
mantle: {
url: "https://rpc.testnet.mantle.xyz",
accounts: [process.env.PKEY as string],
},
neon: {
url: "https://devnet.neonevm.org",
accounts: [process.env.PKEY as string],
},
celo: {
url: "https://alfajores-forno.celo-testnet.org",
accounts: [process.env.PKEY as string],
},
}
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -2,12 +2,16 @@
"name": "hardhat-project",
"devDependencies": {
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
"@types/snarkjs": "^0.7.7",
"hardhat": "^2.17.0",
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
},
"dependencies": {
"@openzeppelin/contracts": "^4.9.2",
"dotenv": "^16.3.1"
"axios": "^1.6.2",
"dotenv": "^16.3.1",
"hardhat-contract-sizer": "^2.10.0",
"snarkjs": "^0.7.2"
}
}

View File

@@ -1,19 +1,25 @@
import { ethers } from "hardhat";
import { countryCodes } from "../../common/src/constants/constants";
async function main() {
const Verifier = await ethers.getContractFactory("Verifier");
const Verifier = await ethers.getContractFactory("Groth16Verifier");
const verifier = await Verifier.deploy();
await verifier.waitForDeployment();
await verifier.deployed();
console.log(`Verifier deployed to ${verifier.target}`);
console.log(`RsaSha256Verifier deployed to ${verifier.address}`);
const Formatter = await ethers.getContractFactory("Formatter");
const formatter = await Formatter.deploy();
await formatter.waitForDeployment();
await formatter.addCountryCodes(Object.entries(countryCodes));
const ProofOfBaguette = await ethers.getContractFactory("ProofOfBaguette");
const proofOfBaguette = await ProofOfBaguette.deploy(verifier.address);
console.log(`Formatter deployed to ${formatter.target}`);
await proofOfBaguette.deployed();
const ProofOfPassport = await ethers.getContractFactory("ProofOfPassport");
const proofOfPassport = await ProofOfPassport.deploy(verifier.target, formatter.target);
await proofOfPassport.waitForDeployment();
console.log(`ProofOfBaguette deployed to ${proofOfBaguette.address}`);
console.log(`ProofOfPassport NFT deployed to ${proofOfPassport.target}`);
}
// We recommend this pattern to be able to use async/await everywhere

93
contracts/scripts/mint.ts Normal file
View File

@@ -0,0 +1,93 @@
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect, assert } from "chai";
import { ethers } from "hardhat";
import { DataHash } from "../../common/src/utils/types";
import { getPassportData } from "../../common/src/utils/passportData";
import { attributeToPosition } from "../../common/src/constants/constants";
import { formatMrz, splitToWords, formatAndConcatenateDataHashes, toUnsignedByte, hash, bytesToBigDecimal } from "../../common/src/utils/utils";
import { groth16 } from 'snarkjs'
const fs = require('fs');
async function main() {
const proofOfPassportAddress = "0x64BfefF18335E3cac8cF8f8E37Ac921371d9c5aa"
const proofOfPassport = await ethers.getContractAt("ProofOfPassport", proofOfPassportAddress);
const passportData = getPassportData();
const formattedMrz = formatMrz(passportData.mrz);
const mrzHash = hash(formatMrz(passportData.mrz));
const concatenatedDataHashes = formatAndConcatenateDataHashes(
mrzHash,
passportData.dataGroupHashes as DataHash[],
);
const attributeToReveal = {
issuing_state: true,
name: true,
passport_number: true,
nationality: true,
date_of_birth: true,
gender: true,
expiry_date: true,
}
const bitmap = Array(88).fill('0');
Object.entries(attributeToReveal).forEach(([attribute, reveal]) => {
if (reveal) {
const [start, end] = attributeToPosition[attribute as keyof typeof attributeToPosition];
bitmap.fill('1', start, end + 1);
}
});
const inputs = {
mrz: formattedMrz.map(byte => String(byte)),
reveal_bitmap: bitmap.map(byte => String(byte)),
dataHashes: concatenatedDataHashes.map(toUnsignedByte).map(byte => String(byte)),
eContentBytes: passportData.eContent.map(toUnsignedByte).map(byte => String(byte)),
pubkey: splitToWords(
BigInt(passportData.pubKey.modulus as string),
BigInt(64),
BigInt(32)
),
signature: splitToWords(
BigInt(bytesToBigDecimal(passportData.encryptedDigest)),
BigInt(64),
BigInt(32)
),
address: "0x9D392187c08fc28A86e1354aD63C70897165b982", // goerli test account
}
console.log('generating proof...');
const { proof, publicSignals } = await groth16.fullProve(
inputs,
"../circuits/build/proof_of_passport_js/proof_of_passport.wasm",
"../circuits/build/proof_of_passport_final.zkey"
)
console.log('proof done');
const vKey = JSON.parse(fs.readFileSync("../circuits/build/verification_key.json"));
const verified = await groth16.verify(
vKey,
publicSignals,
proof
)
assert(verified == true, 'Should verifiable')
const cd = await groth16.exportSolidityCallData(proof, publicSignals);
const callData = JSON.parse(`[${cd}]`);
console.log('callData', callData);
const tx = await proofOfPassport.mint(...callData);
const receipt = await tx.wait();
console.log('receipt', receipt?.hash);
const tokenURI = await proofOfPassport.tokenURI(0);
console.log('tokenURI', tokenURI);
}
main()

View File

@@ -1,229 +0,0 @@
import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
import { expect } from "chai";
import { ethers } from "hardhat";
const exampleCorrectProof = {
a: [
"0x0c7141194fa7a5a26dd3834bd9490908286e3c772dcaecca314b74a58a222642",
"0x0494611f581503a05ebd4e8fe17e9c7ec05a0c022081bbe6115a6bf8afcd8c19",
],
b: [
[
"0x01b8ab498c66a313e3320b0a65d94ab35e4be73616a56b33685415e5b312cb57",
"0x071417e130b6f8c45cee4644adbb90ae62c542ec26fa83377b86fadfe737cddc",
],
[
"0x2d991227175693d047f1e976af6986a58aa313d75677a0e70939b3ddb1912df2",
"0x1326e7a60a10320b5477d3bbc824121d1cbf2381293a09bf82ff5418897d7706",
],
],
c: [
"0x19912bf5bfee2e72d3cc357fa6b94741ba70bb9e25ca72922cc23cef79adab68",
"0x1dc4caae04391e8d72f288970e195f1d317476a1890977083d8db832c5a6552a",
],
input: [
"0x0000000000000000000000000000000000000000000000000000000000010001",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000df267467de87516",
"0x000000000000000000000000000000000000000000000000584863641a75504b",
"0x000000000000000000000000000000000000000000000000595bf81a28dc3bd7",
"0x0000000000000000000000000000000000000000000000008276a24b60f02a0b",
"0x000000000000000000000000000000000000000000000000f394de395425db5b",
"0x000000000000000000000000000000000000000000000000a37863419a2760b9",
"0x0000000000000000000000000000000000000000000000002332cde4996e768d",
"0x00000000000000000000000000000000000000000000000034042fb8b18a254d",
"0x000000000000000000000000000000000000000000000000ad20de3a2a2c4881",
"0x000000000000000000000000000000000000000000000000572b030ef7b362db",
"0x000000000000000000000000000000000000000000000000128b7757b2f7b52e",
"0x000000000000000000000000000000000000000000000000c59817a889d2eee4",
"0x000000000000000000000000000000000000000000000000a6536f0357bb6a04",
"0x00000000000000000000000000000000000000000000000031c38d88190cb650",
"0x000000000000000000000000000000000000000000000000e06a5416c45a9abc",
"0x000000000000000000000000000000000000000000000000ec78fad95ccef0cb",
"0x00000000000000000000000000000000000000000000000006c08a020dadcb14",
"0x000000000000000000000000000000000000000000000000463dd85433924204",
"0x000000000000000000000000000000000000000000000000ad2dadc6dea40729",
"0x000000000000000000000000000000000000000000000000671e4175104c69c8",
"0x0000000000000000000000000000000000000000000000000a5b8d4c2d09d069",
"0x000000000000000000000000000000000000000000000000456c4a0208587c36",
"0x000000000000000000000000000000000000000000000000338e93e219412835",
"0x00000000000000000000000000000000000000000000000098cd81aa3d338a4e",
"0x00000000000000000000000000000000000000000000000015e468738c5d802c",
"0x000000000000000000000000000000000000000000000000bd84a973c66e6c07",
"0x000000000000000000000000000000000000000000000000366076382e2a9543",
"0x0000000000000000000000000000000000000000000000004d6bfec592ef1293",
"0x0000000000000000000000000000000000000000000000002f6b635940e079b0",
"0x000000000000000000000000000000000000000000000000dbaeda10ef7c7eea",
"0x000000000000000000000000000000000000000000000000f26255cb75fe2de2",
"0x0000000000000000000000000000000000000000000000005a78c5d241463136",
"0x0000000000000000000000000000000000000000000000008464dcde99f9a9a1",
"0x00000000000000000000000000000000000000000000000016ef65b0eb49c697",
"0x0000000000000000000000000000000000000000000000006ba33075968396c2",
"0x000000000000000000000000000000000000000000000000d08f6baf1487b58f",
"0x000000000000000000000000000000000000000000000000baad9f5ed4b6886c",
"0x000000000000000000000000000000000000000000000000a2566cbdc9aa0e3c",
"0x000000000000000000000000000000000000000000000000ca7a946dd7ac86de",
"0x00000000000000000000000000000000000000000000000010451eff67ed87f6",
"0x00000000000000000000000000000000000000000000000058ac64a2c6e26bf0",
"0x0000000000000000000000000000000000000000000000005debfc3fb15ef7b4",
"0x0000000000000000000000000000000000000000000000009d7b54d9509b03f9",
"0x00000000000000000000000000000000000000000000000023fc9c3e6cd4902e",
"0x000000000000000000000000000000000000000000000000ff26d5c66d231641",
"0x000000000000000000000000000000000000000000000000cf9d58eeff43ce2c",
"0x00000000000000000000000000000000000000000000000078d4d439d2d659b0",
"0x000000000000000000000000000000000000000000000000d2817dd436d5aef7",
"0x00000000000000000000000000000000000000000000000078dc49129d55531b",
"0x000000000000000000000000000000000000000000000000f9e2cc1e9ca4f476",
"0x00000000000000000000000000000000000000000000000058cb0085fa356b13",
"0x000000000000000000000000000000000000000000000000d02d9fabcd899520",
"0x000000000000000000000000000000000000000000000000f54a26c2ca3493f1",
"0x00000000000000000000000000000000000000000000000027cd08da32ce263e",
"0x00000000000000000000000000000000000000000000000080e4cdb79e0cdf46",
"0x000000000000000000000000000000000000000000000000882f2281537ac7aa",
"0x000000000000000000000000000000000000000000000000bb456e5f8ce32148",
"0x0000000000000000000000000000000000000000000000006c25614d99232b98",
"0x0000000000000000000000000000000000000000000000005af2acb5f5c2bedf",
"0x0000000000000000000000000000000000000000000000000072a3c7868f8504",
"0x000000000000000000000000000000000000000000000000da6834a23075f203",
"0x000000000000000000000000000000000000000000000000094a9b9ecf98e97e",
"0x0000000000000000000000000000000000000000000000009e8ce7916ab0fb0b",
"0x000000000000000000000000000000000000000000000000df11ba06d7937a05",
"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8",
],
};
describe("ProofOfBaguette", function () {
// We define a fixture to reuse the same setup in every test.
// We use loadFixture to run this setup once, snapshot that state,
// and reset Hardhat Network to that snapshot in every test.
async function deployFixture() {
// Contracts are deployed using the first signer/account by default
const [owner, otherAccount] = await ethers.getSigners();
const Verifier = await ethers.getContractFactory("Verifier");
const verifier = await Verifier.deploy();
console.log("otherAccount", otherAccount.address);
console.log("owner", owner.address);
await verifier.deployed();
console.log(`RsaSha256Verifier deployed to ${verifier.address}`);
const ProofOfBaguette = await ethers.getContractFactory("ProofOfBaguette");
const proofOfBaguette = await ProofOfBaguette.deploy(verifier.address);
await proofOfBaguette.deployed();
console.log(`ProofOfBaguette deployed to ${proofOfBaguette.address}`);
return { verifier, proofOfBaguette, owner, otherAccount };
}
describe("Deployment", function () {
it("Verifier verifies correct example signature", async () => {
const { verifier } = await loadFixture(deployFixture);
expect(
await verifier.verifyProof(
exampleCorrectProof.a as any,
exampleCorrectProof.b as any,
exampleCorrectProof.c as any,
exampleCorrectProof.input
)
).to.be.true;
});
it("Should allow a user to mint a SBT", async function () {
const { proofOfBaguette, otherAccount } = await loadFixture(
deployFixture
);
await proofOfBaguette
.connect(otherAccount)
.mint(
exampleCorrectProof.a as any,
exampleCorrectProof.b as any,
exampleCorrectProof.c as any,
exampleCorrectProof.input
);
expect(await proofOfBaguette.balanceOf(otherAccount.address)).to.equal(1);
});
it("Shouldn't allow an invalid proof", async function () {
const { proofOfBaguette, otherAccount } = await loadFixture(
deployFixture
);
let invalidA = exampleCorrectProof.a;
invalidA[1] =
"0x1cdbaf59a0439d55f19162ee0be5a501f5b55c669a6e1f8d27b75d95ff31ff7b";
expect(
proofOfBaguette
.connect(otherAccount)
.mint(
invalidA as any,
exampleCorrectProof.b as any,
exampleCorrectProof.c as any,
exampleCorrectProof.input
)
).to.be.revertedWith("Invalid proof");
});
// it("Should set the right owner", async function () {
// const { lock, owner } = await loadFixture(deployOneYearLockFixture);
// expect(await lock.owner()).to.equal(owner.address);
// });
// it("Should receive and store the funds to lock", async function () {
// const { lock, lockedAmount } = await loadFixture(
// deployOneYearLockFixture
// );
// expect(await ethers.provider.getBalance(lock.address)).to.equal(
// lockedAmount
// );
// });
// it("Should fail if the unlockTime is not in the future", async function () {
// // We don't use the fixture here because we want a different deployment
// const latestTime = await time.latest();
// const Lock = await ethers.getContractFactory("Lock");
// await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
// "Unlock time should be in the future"
// );
// });
});
});

View File

@@ -0,0 +1,256 @@
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect, assert } from "chai";
import { ethers } from "hardhat";
import { DataHash } from "../../common/src/utils/types";
import { getPassportData } from "../../common/src/utils/passportData";
import { attributeToPosition } from "../../common/src/constants/constants";
import { formatMrz, splitToWords, formatAndConcatenateDataHashes, toUnsignedByte, hash, bytesToBigDecimal } from "../../common/src/utils/utils";
import { groth16 } from 'snarkjs'
import { countryCodes } from "../../common/src/constants/constants";
import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers";
import axios from 'axios';
const fs = require('fs');
describe("Proof of Passport", function () {
this.timeout(0);
async function deployFixture() {
const [owner, otherAccount, thirdAccount] = await ethers.getSigners();
const Verifier = await ethers.getContractFactory("Groth16Verifier");
const verifier = await Verifier.deploy();
await verifier.waitForDeployment();
console.log(`Verifier deployed to ${verifier.target}`);
const Formatter = await ethers.getContractFactory("Formatter");
const formatter = await Formatter.deploy();
await formatter.waitForDeployment();
await formatter.addCountryCodes(Object.entries(countryCodes));
console.log(`Formatter deployed to ${formatter.target}`);
const ProofOfPassport = await ethers.getContractFactory("ProofOfPassport");
const proofOfPassport = await ProofOfPassport.deploy(verifier.target, formatter.target);
await proofOfPassport.waitForDeployment();
console.log(`ProofOfPassport NFT deployed to ${proofOfPassport.target}`);
const passportData = getPassportData();
const formattedMrz = formatMrz(passportData.mrz);
const mrzHash = hash(formatMrz(passportData.mrz));
const concatenatedDataHashes = formatAndConcatenateDataHashes(
mrzHash,
passportData.dataGroupHashes as DataHash[],
);
const attributeToReveal = {
issuing_state: true,
name: true,
passport_number: true,
nationality: true,
date_of_birth: true,
gender: true,
expiry_date: true,
}
const bitmap = Array(88).fill('0');
Object.entries(attributeToReveal).forEach(([attribute, reveal]) => {
if (reveal) {
const [start, end] = attributeToPosition[attribute as keyof typeof attributeToPosition];
bitmap.fill('1', start, end + 1);
}
});
const inputs = {
mrz: formattedMrz.map(byte => String(byte)),
reveal_bitmap: bitmap.map(byte => String(byte)),
dataHashes: concatenatedDataHashes.map(toUnsignedByte).map(byte => String(byte)),
eContentBytes: passportData.eContent.map(toUnsignedByte).map(byte => String(byte)),
pubkey: splitToWords(
BigInt(passportData.pubKey.modulus as string),
BigInt(64),
BigInt(32)
),
signature: splitToWords(
BigInt(bytesToBigDecimal(passportData.encryptedDigest)),
BigInt(64),
BigInt(32)
),
address: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // hardhat account 1
}
console.log('generating proof...');
const { proof, publicSignals } = await groth16.fullProve(
inputs,
"../circuits/build/proof_of_passport_js/proof_of_passport.wasm",
"../circuits/build/proof_of_passport_final.zkey"
)
console.log('proof done');
const revealChars = publicSignals.slice(0, 88).map((byte: string) => String.fromCharCode(parseInt(byte, 10))).join('');
const vKey = JSON.parse(fs.readFileSync("../circuits/build/verification_key.json"));
const verified = await groth16.verify(
vKey,
publicSignals,
proof
)
assert(verified == true, 'Should verifiable')
const cd = await groth16.exportSolidityCallData(proof, publicSignals);
const callData = JSON.parse(`[${cd}]`);
console.log('callData', callData);
return { verifier, proofOfPassport, formatter, owner, otherAccount, thirdAccount, passportData, inputs, proof, publicSignals, revealChars, callData };
}
describe("Proof of Passport SBT", function () {
it("Verifier verifies a correct proof", async () => {
const { verifier, callData } = await loadFixture(deployFixture);
expect(
await verifier.verifyProof(callData[0], callData[1], callData[2], callData[3])
).to.be.true;
});
it("Should allow SBT minting", async function () {
const { proofOfPassport, otherAccount, thirdAccount, callData } = await loadFixture(
deployFixture
);
await proofOfPassport
.connect(thirdAccount) // fine that it's not the same account as address is taken from the proof
.mint(...callData);
expect(await proofOfPassport.balanceOf(otherAccount.address)).to.equal(1);
});
it("Shouldn't allow minting with an invalid proof", async function () {
const { proofOfPassport, otherAccount, callData } = await loadFixture(
deployFixture
);
const badCallData = JSON.parse(JSON.stringify(callData));
badCallData[0][1] = "0x1cdbaf59a0439d55f19162ee0be5a501f5b55c669a6e1f8d27b75d95ff31ff7b";
expect(
proofOfPassport
.connect(otherAccount)
.mint(...badCallData as any)
).to.be.revertedWith("Invalid proof");
});
it("Should have a correct tokenURI a user to mint a SBT", async function () {
const { proofOfPassport, otherAccount, callData } = await loadFixture(
deployFixture
);
console.log('callData', callData)
const tx = await proofOfPassport
.connect(otherAccount)
.mint(...callData);
await tx.wait();
const tokenURI = await proofOfPassport.tokenURI(0);
console.log('tokenURI', tokenURI);
const decodedTokenURI = Buffer.from(tokenURI.split(',')[1], 'base64').toString();
let parsedTokenURI;
try {
parsedTokenURI = JSON.parse(decodedTokenURI);
} catch (e) {
assert(false, 'TokenURI is not a valid JSON');
}
console.log('parsedTokenURI', parsedTokenURI);
});
it("Should convert ISO dates to unix timestamps correctly", async function () {
const { formatter } = await loadFixture(
deployFixture
);
const unix_timestamp = await formatter.dateToUnixTimestamp("230512") // 2023 05 12
console.log('unix_timestamp', unix_timestamp.toString());
var date = new Date(Number(unix_timestamp) * 1000);
console.log("date:", date.toUTCString());
expect(date.getUTCFullYear()).to.equal(2023);
expect(date.getUTCMonth()).to.equal(4);
expect(date.getUTCDate()).to.equal(12);
})
it("Should support expiry", async function () {
const { proofOfPassport, otherAccount, callData } = await loadFixture(
deployFixture
);
const tx = await proofOfPassport
.connect(otherAccount)
.mint(...callData);
await tx.wait();
const tokenURI = await proofOfPassport.tokenURI(0);
const decodedTokenURI = Buffer.from(tokenURI.split(',')[1], 'base64').toString();
const parsedTokenURI = JSON.parse(decodedTokenURI);
const expired = parsedTokenURI.attributes.find((attribute: any) => attribute.trait_type === 'Expired');
expect(expired.value).to.equal('No');
await time.increaseTo(2240161656); // 2040
const tokenURIAfter = await proofOfPassport.tokenURI(0);
const decodedTokenURIAfter = Buffer.from(tokenURIAfter.split(',')[1], 'base64').toString();
const parsedTokenURIAfter = JSON.parse(decodedTokenURIAfter);
const expiredAfter = parsedTokenURIAfter.attributes.find((attribute: any) => attribute.trait_type === 'Expired');
expect(expiredAfter.value).to.equal('Yes');
})
});
describe("Minting using lambda function", function () {
it.skip("Should allow minting using lambda function", async function () {
const { callData } = await loadFixture(
deployFixture
);
const proofOfPassportOnMumbaiAddress = '0xaf0f1669385182829d0DEa233E83299DED28954A';
const provider = new ethers.JsonRpcProvider('https://polygon-mumbai-bor.publicnode.com');
const proofOfPassportOnMumbai = await ethers.getContractAt('ProofOfPassport', proofOfPassportOnMumbaiAddress);
const transactionRequest = await proofOfPassportOnMumbai
.mint.populateTransaction(...callData);
console.log('transactionRequest', transactionRequest);
try {
const apiEndpoint = process.env.AWS_ENDPOINT;
if (!apiEndpoint) {
throw new Error('AWS_ENDPOINT env variable is not set');
}
const response = await axios.post(apiEndpoint, {
chain: "mumbai",
tx_data: transactionRequest
});
console.log('response status', response.status)
console.log('response data', response.data)
const receipt = await provider.waitForTransaction(response.data.hash);
console.log('receipt', receipt)
} catch (err) {
console.log('err', err);
}
});
})
});

File diff suppressed because it is too large Load Diff