mirror of
https://github.com/selfxyz/self.git
synced 2026-02-08 13:25:59 -05:00
@@ -1 +0,0 @@
|
||||
{}
|
||||
77
app/App.tsx
77
app/App.tsx
@@ -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",
|
||||
}}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
2
app/ark-circom-passport/Cargo.lock
generated
2
app/ark-circom-passport/Cargo.lock
generated
@@ -286,8 +286,10 @@ dependencies = [
|
||||
"ark-groth16",
|
||||
"ark-std",
|
||||
"color-eyre",
|
||||
"hex",
|
||||
"jni",
|
||||
"log",
|
||||
"num-bigint",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
||||
@@ -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",
|
||||
] }
|
||||
@@ -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(¶ms, 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
18844
app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||
|
||||
@@ -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
|
||||
@@ -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: ''
|
||||
};
|
||||
}
|
||||
|
||||
301
app/yarn.lock
301
app/yarn.lock
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
@@ -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"));
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
203
contracts/contracts/ProofOfPassport.sol
Normal file
203
contracts/contracts/ProofOfPassport.sol
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
275
contracts/contracts/Verifier.sol
Normal file
275
contracts/contracts/Verifier.sol
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
63
contracts/contracts/libraries/Base64.sol
Normal file
63
contracts/contracts/libraries/Base64.sol
Normal 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;
|
||||
}
|
||||
}
|
||||
166
contracts/contracts/libraries/Formatter.sol
Normal file
166
contracts/contracts/libraries/Formatter.sol
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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],
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
2136
contracts/package-lock.json
generated
2136
contracts/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
93
contracts/scripts/mint.ts
Normal 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()
|
||||
@@ -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"
|
||||
// );
|
||||
// });
|
||||
});
|
||||
});
|
||||
256
contracts/test/ProofOfPassport.ts
Normal file
256
contracts/test/ProofOfPassport.ts
Normal 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);
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
4972
contracts/yarn.lock
4972
contracts/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user