mirror of
https://github.com/selfxyz/self.git
synced 2026-01-22 21:17:59 -05:00
2
app/.gitignore
vendored
2
app/.gitignore
vendored
@@ -68,3 +68,5 @@ yarn-error.log
|
||||
.env
|
||||
|
||||
.expo/
|
||||
|
||||
libuniffi_mopro.so
|
||||
116
app/App.tsx
116
app/App.tsx
@@ -19,8 +19,8 @@ import { toStandardName } from '../common/src/utils/formatNames';
|
||||
import { generateCircuitInputs } from '../common/src/utils/generateInputs';
|
||||
import { AWS_ENDPOINT, TREE_DEPTH } from '../common/src/constants/constants';
|
||||
import {
|
||||
formatProofIOS,
|
||||
formatInputsIOS
|
||||
formatProof,
|
||||
formatInputs
|
||||
} from '../common/src/utils/utils';
|
||||
import { samplePassportData } from '../common/src/utils/passportDataStatic';
|
||||
import "@ethersproject/shims"
|
||||
@@ -110,11 +110,17 @@ function App(): JSX.Element {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (Platform.OS !== 'android') {
|
||||
NativeModules.Prover.runInitAction() // for mopro, ios only rn
|
||||
}
|
||||
init()
|
||||
}, []);
|
||||
|
||||
async function init() {
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
console.log('launching init')
|
||||
const res = await NativeModules.Prover.runInitAction()
|
||||
console.log('init done')
|
||||
console.log('init res', res)
|
||||
}
|
||||
|
||||
async function handleResponseIOS(response: any) {
|
||||
const parsed = JSON.parse(response);
|
||||
|
||||
@@ -253,6 +259,7 @@ function App(): JSX.Element {
|
||||
handleResponseAndroid(response);
|
||||
} catch (e: any) {
|
||||
console.log('error during scan :', e);
|
||||
setStep(Steps.MRZ_SCAN_COMPLETED);
|
||||
Toast.show({
|
||||
type: 'error',
|
||||
text1: e.message,
|
||||
@@ -288,8 +295,6 @@ function App(): JSX.Element {
|
||||
setGeneratingProof(true)
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
|
||||
// TODO check circuit to make sure the proof will work
|
||||
|
||||
const reveal_bitmap = revealBitmapFromMapping(disclosure);
|
||||
|
||||
// if (!["sha256WithRSAEncryption"].includes(passportData.signatureAlgorithm)) {
|
||||
@@ -317,79 +322,59 @@ function App(): JSX.Element {
|
||||
});
|
||||
|
||||
const start = Date.now();
|
||||
if (Platform.OS === 'android') {
|
||||
await proveAndroid(inputs, path);
|
||||
} else {
|
||||
await proveIOS(inputs);
|
||||
}
|
||||
await prove(inputs, path);
|
||||
|
||||
const end = Date.now();
|
||||
console.log('Total proof time from frontend:', end - start);
|
||||
};
|
||||
|
||||
async function proveAndroid(inputs: any, path: string) {
|
||||
const startTime = Date.now();
|
||||
NativeModules.RNPassportReader.provePassport(inputs, path, (err: any, res: any) => {
|
||||
const endTime = Date.now();
|
||||
setProofTime(endTime - startTime);
|
||||
|
||||
if (err) {
|
||||
console.error(err);
|
||||
setError(
|
||||
"err: " + err.toString(),
|
||||
);
|
||||
return
|
||||
}
|
||||
console.log("res", res);
|
||||
const parsedResponse = JSON.parse(res);
|
||||
console.log('parsedResponse', parsedResponse);
|
||||
console.log('parsedResponse.duration', parsedResponse.duration);
|
||||
|
||||
const deserializedProof = JSON.parse(parsedResponse.serialized_proof);
|
||||
console.log('deserializedProof', deserializedProof);
|
||||
|
||||
const deserializedInputs = JSON.parse(parsedResponse.serialized_inputs);
|
||||
console.log('deserializedInputs', deserializedInputs);
|
||||
|
||||
setProof({
|
||||
proof: JSON.stringify(deserializedProof),
|
||||
inputs: JSON.stringify(deserializedInputs),
|
||||
});
|
||||
setGeneratingProof(false);
|
||||
setStep(Steps.PROOF_GENERATED);
|
||||
});
|
||||
}
|
||||
|
||||
async function proveIOS(inputs: any) {
|
||||
async function prove(inputs: any, path?: string) {
|
||||
try {
|
||||
const startTime = Date.now();
|
||||
console.log('running mopro init action')
|
||||
console.log('launching prove function')
|
||||
console.log('inputs in App.tsx', inputs)
|
||||
|
||||
await NativeModules.Prover.runInitAction()
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
console.log('running mopro prove action')
|
||||
const response = await NativeModules.Prover.runProveAction({
|
||||
...inputs,
|
||||
datahashes_padded_length: [inputs.datahashes_padded_length.toString()], // wrap everything in arrays for bindings
|
||||
signatureAlgorithm: [inputs.signatureAlgorithm],
|
||||
root: [inputs.root],
|
||||
address: [BigInt(address).toString()],
|
||||
})
|
||||
const response = await NativeModules.Prover.runProveAction(inputs)
|
||||
console.log('proof response:', response)
|
||||
const parsedResponse = JSON.parse(response)
|
||||
|
||||
function parseProofAndroid(response: any) {
|
||||
const match = response.match(/GenerateProofResult\(proof=\[(.*?)\], inputs=\[(.*?)\]\)/);
|
||||
if (!match) throw new Error('Invalid input format');
|
||||
|
||||
return {
|
||||
proof: match[1].split(',').map((n: any) => (parseInt(n.trim()) + 256) % 256),
|
||||
inputs: match[2].split(',').map((n: any) => (parseInt(n.trim()) + 256) % 256)
|
||||
}
|
||||
}
|
||||
|
||||
const parsedResponse = Platform.OS == 'android'
|
||||
? parseProofAndroid(response)
|
||||
: JSON.parse(response)
|
||||
|
||||
console.log('parsedResponse', parsedResponse)
|
||||
|
||||
const endTime = Date.now();
|
||||
setProofTime(endTime - startTime);
|
||||
|
||||
// console.log('running mopro verify action')
|
||||
// const res = await NativeModules.Prover.runVerifyAction()
|
||||
// console.log('verify response:', res)
|
||||
console.log('running mopro verify action')
|
||||
const res = await NativeModules.Prover.runVerifyAction()
|
||||
console.log('verify response:', res)
|
||||
|
||||
const finalProof = {
|
||||
proof: JSON.stringify(formatProof(parsedResponse.proof)),
|
||||
inputs: JSON.stringify(formatInputs(parsedResponse.inputs)),
|
||||
}
|
||||
|
||||
console.log('finalProof:', finalProof)
|
||||
|
||||
setProof({
|
||||
proof: JSON.stringify(formatProofIOS(parsedResponse.proof)),
|
||||
inputs: JSON.stringify(formatInputsIOS(parsedResponse.inputs)),
|
||||
});
|
||||
setProof(finalProof);
|
||||
|
||||
setGeneratingProof(false)
|
||||
setStep(Steps.PROOF_GENERATED);
|
||||
setStep(Steps.PROOF_GENERATED);
|
||||
} catch (err: any) {
|
||||
console.log('err', err);
|
||||
setError(
|
||||
@@ -398,7 +383,6 @@ function App(): JSX.Element {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const handleMint = async () => {
|
||||
setMinting(true)
|
||||
if (!proof?.proof || !proof?.inputs) {
|
||||
@@ -413,8 +397,6 @@ function App(): JSX.Element {
|
||||
// Format the proof and publicInputs as calldata for the verifier contract
|
||||
const p = JSON.parse(proof.proof);
|
||||
const i = JSON.parse(proof.inputs);
|
||||
// const p = {"a": ["16502577771187684977980616374304236605057905196561863637384296592370445017998", "3901861368174142739149849352179287633574688417834634300291202761562972709023"], "b": [["14543689684654938043989715590415160645004827219804187355799512446208262437248", "2758656853017552407340621959452084149765188239766723663849017782705599048610"], ["11277365272183899064677884160333958573750879878546952615484891009952508146334", "6233152645613613236466445508816847016425532566954931368157994995587995754446"]], "c": ["6117026818273543012196632774531089444191538074414171872462281003025766583671", "10261526153619394223629018490329697233150978685332753612996629076672112420472"]}
|
||||
// const i = ["0", "0", "0", "146183216590389235917737925524385821154", "43653084046336027166990", "21085389953176386480267", "56519161086598100699293", "15779090386165698845937", "23690430366843652392111", "22932463418406768540896", "51019038683800409078189", "50360649287615093470666", "47789371969706091489401", "15311247864741754764238", "20579290199534174842880", "1318168358802144844680228651107716082931624381008"]
|
||||
console.log('p', p);
|
||||
console.log('i', i);
|
||||
const cd = groth16ExportSolidityCallData(p, i);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "com.facebook.react"
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
|
||||
/**
|
||||
* This is the configuration block to customize your React Native Android app.
|
||||
@@ -122,9 +124,6 @@ dependencies {
|
||||
}
|
||||
implementation project(':passportreader')
|
||||
implementation 'org.jmrtd:jmrtd:0.7.18'
|
||||
// implementation files('libs/jmrtd-0.5.5.jar')
|
||||
//implementation 'org.jmrtd:jmrtd:0.7.35'
|
||||
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
|
||||
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
|
||||
@@ -137,6 +136,10 @@ dependencies {
|
||||
} else {
|
||||
implementation jscFlavor
|
||||
}
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation("net.java.dev.jna:jna:5.13.0@aar")
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android'
|
||||
|
||||
}
|
||||
|
||||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
||||
|
||||
@@ -8,9 +8,11 @@ import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.proofofpassport.CameraActivityPackage; //import new package for mrz reading
|
||||
import com.proofofpassport.CameraActivityPackage; // import new package for mrz reading
|
||||
import io.tradle.nfc.RNPassportReaderPackage;
|
||||
import java.util.List;
|
||||
import com.proofofpassport.prover.ProverPackage;
|
||||
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
|
||||
@@ -29,6 +31,7 @@ public class MainApplication extends Application implements ReactApplication {
|
||||
|
||||
// Add the custom package here
|
||||
packages.add(new CameraActivityPackage());
|
||||
packages.add(new ProverPackage());
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
130
app/android/app/src/main/java/com/awesomeproject/ProverModule.kt
Normal file
130
app/android/app/src/main/java/com/awesomeproject/ProverModule.kt
Normal file
@@ -0,0 +1,130 @@
|
||||
package com.proofofpassport.prover
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
||||
import com.facebook.react.bridge.ReactMethod
|
||||
import com.facebook.react.bridge.Promise
|
||||
|
||||
import android.util.Log
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import uniffi.mopro.GenerateProofResult
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ProverModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
||||
private val TAG = "ProverModule"
|
||||
lateinit var res: GenerateProofResult
|
||||
|
||||
|
||||
override fun getName(): String {
|
||||
return "Prover"
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun runInitAction(promise: Promise) {
|
||||
// Launch a coroutine in the IO dispatcher for background tasks
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val startTime = System.currentTimeMillis()
|
||||
uniffi.mopro.initializeMopro()
|
||||
val endTime = System.currentTimeMillis()
|
||||
val initTime = "init time: " + (endTime - startTime).toString() + " ms"
|
||||
|
||||
// Since the promise needs to be resolved in the main thread
|
||||
withContext(Dispatchers.Main) {
|
||||
promise.resolve(initTime)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
promise.reject(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @ReactMethod
|
||||
// fun downloadFile(url: String, fileName: String, promise: Promise) {
|
||||
// val client = OkHttpClient()
|
||||
// val request = Request.Builder().url(url).build()
|
||||
|
||||
// try {
|
||||
// client.newCall(request).execute().use { response ->
|
||||
// if (!response.isSuccessful) throw IOException("Failed to download file: $response")
|
||||
|
||||
// // Use the app's internal files directory
|
||||
// val fileOutputStream = reactContext.openFileOutput(fileName, Context.MODE_PRIVATE)
|
||||
|
||||
// val inputStream = response.body?.byteStream()
|
||||
// inputStream.use { input ->
|
||||
// fileOutputStream.use { output ->
|
||||
// input?.copyTo(output)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Resolve the promise with the file path
|
||||
// val file = File(reactContext.filesDir, fileName)
|
||||
// promise.resolve(file.absolutePath)
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// // Reject the promise if an exception occurs
|
||||
// promise.reject(e)
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@ReactMethod
|
||||
// fun runProveAction(inputs: ReadableMap, zkeypath: String, promise: Promise) {
|
||||
fun runProveAction(inputs: ReadableMap, promise: Promise) {
|
||||
Log.e(TAG, "inputs in provePassport kotlin: " + inputs.toString())
|
||||
|
||||
// working example
|
||||
// val inputs = mutableMapOf<String, List<String>>(
|
||||
// "mrz" to listOf("97","91","95","31","88","80","60","70","82","65","84","65","86","69","82","78","73","69","82","60","60","70","76","79","82","69","78","84","60","72","85","71","85","69","83","60","74","69","65","78","60","60","60","60","60","60","60","60","60","49","57","72","65","51","52","56","50","56","52","70","82","65","48","48","48","55","49","57","49","77","50","57","49","50","48","57","53","60","60","60","60","60","60","60","60","60","60","60","60","60","60","48","50"),
|
||||
// "reveal_bitmap" to listOf("0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"),
|
||||
// "dataHashes" to listOf("48","130","1","37","2","1","0","48","11","6","9","96","134","72","1","101","3","4","2","1","48","130","1","17","48","37","2","1","1","4","32","99","19","179","205","55","104","45","214","133","101","233","177","130","1","37","89","125","229","139","34","132","146","28","116","248","186","63","195","96","151","26","215","48","37","2","1","2","4","32","63","234","106","78","31","16","114","137","237","17","92","71","134","47","62","78","189","233","201","213","53","4","47","189","201","133","6","121","34","131","64","142","48","37","2","1","3","4","32","136","155","87","144","121","15","152","127","85","25","154","80","20","58","51","75","193","116","234","0","60","30","29","30","183","141","72","247","255","203","100","124","48","37","2","1","11","4","32","0","194","104","108","237","246","97","230","116","198","69","110","26","87","17","89","110","199","108","250","36","21","39","87","110","102","250","213","174","131","171","174","48","37","2","1","12","4","32","190","82","180","235","222","33","79","50","152","136","142","35","116","224","6","242","156","141","128","247","10","61","98","86","248","45","207","210","90","232","175","38","48","37","2","1","13","4","32","91","222","210","193","63","222","104","82","36","41","138","253","70","15","148","208","156","45","105","171","241","195","185","43","217","162","146","201","222","89","238","38","48","37","2","1","14","4","32","76","123","216","13","52","227","72","245","59","193","238","166","103","49","24","164","171","188","194","197","156","187","249","28","198","95","69","15","182","56","54","38","128","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","9","72"),
|
||||
// "datahashes_padded_length" to listOf("320"),
|
||||
// "eContentBytes" to listOf("49","102","48","21","6","9","42","134","72","134","247","13","1","9","3","49","8","6","6","103","129","8","1","1","1","48","28","6","9","42","134","72","134","247","13","1","9","5","49","15","23","13","49","57","49","50","49","54","49","55","50","50","51","56","90","48","47","6","9","42","134","72","134","247","13","1","9","4","49","34","4","32","176","96","59","213","131","82","89","248","105","125","37","177","158","162","137","43","13","39","115","6","59","229","81","110","49","75","255","184","155","73","116","86"),
|
||||
// "signature" to listOf("1004979219314799894","6361443755252600907","6439012883494616023","9400879716815088139","17551897985575934811","11779273958797828281","2536315921873401485","3748173260178203981","12475215309213288577","6281117468118442715","1336292932993922350","14238156234566069988","11985045093510507012","3585865343992378960","16170829868787473084","17039645001628184779","486540501180074772","5061439412388381188","12478821212163933993","7430448406248319432","746345521572597865","5002454658692185142","3715069341922830389","11010599232161942094","1577500614971981868","13656226284809645063","3918261659477120323","5578832687955645075","3416933977282345392","15829829506526117610","17465616637242519010","6519177967447716150"),
|
||||
// "signatureAlgorithm" to listOf("1"),
|
||||
// "pubkey" to listOf("9539992759301679521","1652651398804391575","7756096264856639170","15028348881266521487","13451582891670014060","11697656644529425980","14590137142310897374","1172377360308996086","6389592621616098288","6767780215543232436","11347756978427069433","2593119277386338350","18385617576997885505","14960211320702750252","8706817324429498800","15168543370367053559","8708916123725550363","18006178692029805686","6398208271038376723","15000821494077560096","17674982305626887153","2867958270953137726","9287774520059158342","9813100051910281130","13494313215150203208","7792741716144106392","6553490305289731807","32268224696386820","15737886769048580611","669518601007982974","11424760966478363403","16073833083611347461"),
|
||||
// "pathIndices" to listOf("0","1","1","1","1","1","1","0","1","1","0","0","1","1","0","0"),
|
||||
// "siblings" to listOf("20516282398390866580647417962347415258712802604212003365416596890852644939364","20547289806543281108128197867250295423223489766069952889766689677695750842294","17092860852967512812593771487649838995106203215624858397482169733546970246117","19141872343555753276227561835732941623954902346285308564941039231845690663515","2888260764701592030713638283446165050628606750519377550369633789586724212406","17037943129534065359096662792322618985598809624384219749636863003643326502177","21260541151470016589788332273091943678373855676584683193443363340566713593750","9681119423869145671286918102040570804786474221694907866875171055859965502010","3999714159260652982057321310481110903729446356195536109316994934664982988519","14359042263488593594514913785064471775842285148703143594475594381078274944550","10696856845043652409316424831381338144209147199074363427177722046972515079299","2796323689030312622891330190155708704921773618732461037692992858528069077360","1379184643939692456020535864077563679018059205165852146212742699309755722087","17834317267514482863629341626611816587254867008433493508231639322166589549456","1473918712602583605383280948484316645101117513102582419100942131704211814519","15819538789928229930262697811477882737253464456578333862691129291651619515538"),
|
||||
// "root" to listOf("4080578225172475068086778061870548445929343471785864518431540330127324371840"),
|
||||
// "address" to listOf("642829559307850963015472508762062935916233390536")
|
||||
// )
|
||||
|
||||
val convertedInputs = mutableMapOf<String, List<String>>()
|
||||
|
||||
for ((key, value) in inputs.toHashMap()) {
|
||||
val parsedArray = inputs.getArray(key)?.toArrayList()?.map { item ->
|
||||
item.toString()
|
||||
} ?: emptyList()
|
||||
convertedInputs[key] = parsedArray
|
||||
}
|
||||
|
||||
Log.e(TAG, "convertedInputs: $convertedInputs")
|
||||
|
||||
val startTime = System.currentTimeMillis()
|
||||
res = uniffi.mopro.generateProof2(convertedInputs)
|
||||
val endTime = System.currentTimeMillis()
|
||||
val provingTime = "proving time: " + (endTime - startTime).toString() + " ms"
|
||||
Log.e(TAG, provingTime)
|
||||
|
||||
Log.e(TAG, "res: " + res.toString())
|
||||
|
||||
promise.resolve(res.toString())
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun runVerifyAction(promise: Promise) {
|
||||
val startTime = System.currentTimeMillis()
|
||||
val valid = "valid: " + uniffi.mopro.verifyProof2(res.proof, res.inputs).toString()
|
||||
val endTime = System.currentTimeMillis()
|
||||
val verifyingTime = "verifying time: " + (endTime - startTime).toString() + " ms"
|
||||
Log.e(TAG, verifyingTime)
|
||||
promise.resolve(valid)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.proofofpassport.prover
|
||||
|
||||
import com.facebook.react.ReactPackage
|
||||
import com.facebook.react.bridge.NativeModule
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.uimanager.ViewManager
|
||||
|
||||
class ProverPackage : ReactPackage {
|
||||
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
||||
return listOf(ProverModule(reactContext))
|
||||
}
|
||||
|
||||
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
1172
app/android/app/src/main/java/uniffi/mopro/mopro.kt
Normal file
1172
app/android/app/src/main/java/uniffi/mopro/mopro.kt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -618,105 +618,6 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
}
|
||||
}
|
||||
|
||||
//-------------functions related to calling rust lib----------------//
|
||||
|
||||
// Declare native method
|
||||
external fun callRustCode(): String
|
||||
|
||||
@ReactMethod
|
||||
fun callRustLib(callback: Callback) {
|
||||
// Call the Rust function
|
||||
val resultFromRust = callRustCode()
|
||||
|
||||
// Return the result to JavaScript through the callback
|
||||
callback.invoke(null, resultFromRust)
|
||||
}
|
||||
|
||||
external fun provePassport(
|
||||
mrz: List<String>,
|
||||
reveal_bitmap: List<String>,
|
||||
dataHashes: List<String>,
|
||||
datahashes_padded_length: String,
|
||||
eContentBytes: List<String>,
|
||||
signature: List<String>,
|
||||
signature_algorithm: String,
|
||||
pubkey: List<String>,
|
||||
path_indices: List<String>,
|
||||
siblings: List<String>,
|
||||
root: String,
|
||||
address: String,
|
||||
zkeypath: String
|
||||
): String
|
||||
|
||||
@ReactMethod
|
||||
fun provePassport(inputs: ReadableMap, zkeypath: String, callback: Callback) {
|
||||
Log.d(TAG, "inputs in provePassport kotlin: " + inputs.toString())
|
||||
|
||||
val mrz = inputs.getArray("mrz")?.toArrayList()?.map { it as String } ?: listOf()
|
||||
val reveal_bitmap = inputs.getArray("reveal_bitmap")?.toArrayList()?.map { it as String } ?: listOf()
|
||||
val data_hashes = inputs.getArray("dataHashes")?.toArrayList()?.map { it as String } ?: listOf()
|
||||
val datahashes_padded_length = inputs.getString("datahashes_padded_length") ?: ""
|
||||
val e_content_bytes = inputs.getArray("eContentBytes")?.toArrayList()?.map { it as String } ?: listOf()
|
||||
val signature = inputs.getArray("signature")?.toArrayList()?.map { it as String } ?: listOf()
|
||||
val signature_algorithm = inputs.getString("signatureAlgorithm") ?: ""
|
||||
val pubkey = inputs.getArray("pubkey")?.toArrayList()?.map { it as String } ?: listOf()
|
||||
val path_indices = inputs.getArray("pathIndices")?.toArrayList()?.map { it as String } ?: listOf()
|
||||
val siblings = inputs.getArray("siblings")?.toArrayList()?.map { it as String } ?: listOf()
|
||||
val root = inputs.getString("root") ?: ""
|
||||
val address = inputs.getString("address") ?: ""
|
||||
|
||||
val resultFromProof = provePassport(
|
||||
mrz,
|
||||
reveal_bitmap,
|
||||
data_hashes,
|
||||
datahashes_padded_length,
|
||||
e_content_bytes,
|
||||
signature,
|
||||
signature_algorithm,
|
||||
pubkey,
|
||||
path_indices,
|
||||
siblings,
|
||||
root,
|
||||
address,
|
||||
zkeypath
|
||||
)
|
||||
|
||||
Log.d(TAG, "resultFromProof: " + resultFromProof.toString())
|
||||
|
||||
// Return the result to JavaScript through the callback
|
||||
callback.invoke(null, resultFromProof)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun downloadFile(url: String, fileName: String, promise: Promise) {
|
||||
val client = OkHttpClient()
|
||||
val request = Request.Builder().url(url).build()
|
||||
|
||||
try {
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) throw IOException("Failed to download file: $response")
|
||||
|
||||
// Use the app's internal files directory
|
||||
val fileOutputStream = reactContext.openFileOutput(fileName, Context.MODE_PRIVATE)
|
||||
|
||||
val inputStream = response.body?.byteStream()
|
||||
inputStream.use { input ->
|
||||
fileOutputStream.use { output ->
|
||||
input?.copyTo(output)
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve the promise with the file path
|
||||
val file = File(reactContext.filesDir, fileName)
|
||||
promise.resolve(file.absolutePath)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// Reject the promise if an exception occurs
|
||||
promise.reject(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private val TAG = RNPassportReaderModule::class.java.simpleName
|
||||
private const val PARAM_DOC_NUM = "documentNumber";
|
||||
@@ -725,8 +626,5 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
const val JPEG_DATA_URI_PREFIX = "data:image/jpeg;base64,"
|
||||
private const val KEY_IS_SUPPORTED = "isSupported"
|
||||
var instance: RNPassportReaderModule? = null
|
||||
init {
|
||||
System.loadLibrary("ark_circom_passport")
|
||||
}
|
||||
}
|
||||
}
|
||||
3
app/ark-circom-passport/.gitignore
vendored
3
app/ark-circom-passport/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
/target
|
||||
rsa
|
||||
passport
|
||||
5071
app/ark-circom-passport/Cargo.lock
generated
5071
app/ark-circom-passport/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,49 +0,0 @@
|
||||
[package]
|
||||
name = "ark_circom_passport"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "ark_circom_passport"
|
||||
path = "src/passport.rs"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
# [profile.dev]
|
||||
# opt-level = 3
|
||||
|
||||
# XXX: Shouldn't be necessary, but this way we stay consistent with wasmer version and fix
|
||||
# error[E0432]: unresolved import `wasmer` error
|
||||
# (likely due to other packages)
|
||||
[patch.crates-io]
|
||||
wasmer = { git = "https://github.com/oskarth/wasmer.git", rev = "09c7070" }
|
||||
# NOTE: Forked wasmer to work around memory limits
|
||||
# See https://github.com/wasmerio/wasmer/commit/09c7070
|
||||
|
||||
[dependencies]
|
||||
wasmer = { git = "https://github.com/oskarth/wasmer.git", rev = "09c7070" }
|
||||
ark-circom = { git = "https://github.com/0xturboblitz/circom-compat.git" }
|
||||
ark-bn254 = { version = "=0.4.0" }
|
||||
ark-groth16 = { version = "=0.4.0", default-features = false, features = ["parallel"] }
|
||||
ark-std = { version = "=0.4.0", default-features = false, features = ["parallel"] }
|
||||
ark-crypto-primitives = { version = "=0.4.0" }
|
||||
ark-ec = { version = "=0.4.1" }
|
||||
ark-ff = { version = "=0.4.1", default-features = false, features = ["parallel", "asm"] }
|
||||
ark-relations = { version = "=0.4.0", default-features = false }
|
||||
ark-serialize = { version = "=0.4.1", default-features = false }
|
||||
color-eyre = "=0.6.2"
|
||||
ethers = "=2.0.7"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
jni = "0.18"
|
||||
log = "0.4"
|
||||
android_logger = "0.8"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
byteorder = "=1.4.3"
|
||||
num-traits = { version = "=0.2.15", default-features = false }
|
||||
hex = "0.4"
|
||||
once_cell = "1.8"
|
||||
num-bigint = { version = "=0.4.3", default-features = false, features = [
|
||||
"rand",
|
||||
] }
|
||||
ark-zkey = { git = "https://github.com/oskarth/mopro.git", branch = "main" }
|
||||
@@ -1,14 +0,0 @@
|
||||
# rust module to generate the proof of passport android native lib
|
||||
|
||||
To run tests and see logs:
|
||||
```
|
||||
cargo test --release -- --nocapture
|
||||
```
|
||||
|
||||
Could be replaced by mopro once mopro is available on Android.
|
||||
|
||||
To generate the arkzkey, if you have installed arkzkey-util globally from the mopro repo, you can run
|
||||
```
|
||||
cd passport
|
||||
arkzkey-util proof_of_passport_final.zkey
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
version = "1.67.0"
|
||||
@@ -1,588 +0,0 @@
|
||||
use ark_circom::{ethereum, CircomBuilder, CircomConfig, circom::CircomReduction, WitnessCalculator};
|
||||
use ark_std::rand::thread_rng;
|
||||
use color_eyre::Result;
|
||||
|
||||
use ark_bn254::Bn254;
|
||||
use ark_crypto_primitives::snark::SNARK;
|
||||
use ark_groth16::{Groth16, Proof};
|
||||
use ark_ec::AffineRepr;
|
||||
use ark_ff::UniformRand;
|
||||
use ark_groth16::{ProvingKey};
|
||||
use ark_relations::r1cs::ConstraintMatrices;
|
||||
use ark_bn254::{Fr};
|
||||
|
||||
use num_bigint::{BigInt, Sign, ToBigInt};
|
||||
extern crate hex;
|
||||
use hex::decode;
|
||||
|
||||
type GrothBn = Groth16<Bn254>;
|
||||
|
||||
extern crate jni;
|
||||
use jni::objects::{JClass, JObject, JValue, JString};
|
||||
use jni::JNIEnv;
|
||||
use jni::sys::jstring;
|
||||
|
||||
use log::Level;
|
||||
use android_logger::Config;
|
||||
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
use serde_json::json;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
time::Instant,
|
||||
convert::TryInto,
|
||||
sync::Mutex,
|
||||
{os::raw::c_int, io::BufReader},
|
||||
fs::File,
|
||||
path::Path
|
||||
};
|
||||
|
||||
use wasmer::{Module, Store};
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
|
||||
mod zkey;
|
||||
pub use zkey::{read_zkey, read_zkey_from_include_bytes};
|
||||
|
||||
use ark_zkey::{read_arkzkey, read_arkzkey_from_bytes};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_callRustCode(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
) -> jstring {
|
||||
android_logger::init_once(Config::default().with_min_level(Level::Trace));
|
||||
log::error!("PROOF OF PASSPORT ---- log before imports");
|
||||
|
||||
let my_int: c_int = -1;
|
||||
let my_str: String = "no_proof".to_string();
|
||||
|
||||
let combined = json!({
|
||||
"my_int": my_int,
|
||||
"my_str": my_str
|
||||
});
|
||||
|
||||
let combined_str = combined.to_string();
|
||||
let output = env.new_string(combined_str).expect("Couldn't create java string!");
|
||||
|
||||
output.into_inner()
|
||||
}
|
||||
|
||||
const WASM: &[u8] = include_bytes!("../passport/proof_of_passport.wasm");
|
||||
|
||||
static WITNESS_CALCULATOR: OnceCell<Mutex<WitnessCalculator>> = OnceCell::new();
|
||||
|
||||
#[cfg(not(feature = "dylib"))]
|
||||
#[must_use]
|
||||
pub fn witness_calculator() -> &'static Mutex<WitnessCalculator> {
|
||||
WITNESS_CALCULATOR.get_or_init(|| {
|
||||
let store = Store::default();
|
||||
let module = Module::from_binary(&store, WASM).expect("WASM should be valid");
|
||||
let result =
|
||||
WitnessCalculator::from_module(module).expect("Failed to create WitnessCalculator");
|
||||
Mutex::new(result)
|
||||
})
|
||||
}
|
||||
|
||||
fn load_arkzkey_from_file(zkey_path: &Path) -> Result<(ProvingKey<Bn254>, ConstraintMatrices<Fr>), Box<dyn std::error::Error>> {
|
||||
let file = File::open(zkey_path)?;
|
||||
let mut reader = BufReader::new(file);
|
||||
let (proving_key, matrices) = read_zkey(&mut reader)?;
|
||||
Ok((proving_key, matrices))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_io_tradle_nfc_RNPassportReaderModule_provePassport(
|
||||
env: JNIEnv,
|
||||
_: JClass,
|
||||
mrz: JObject,
|
||||
reveal_bitmap: JObject,
|
||||
data_hashes: JObject,
|
||||
datahashes_padded_length: JString,
|
||||
e_content_bytes: JObject,
|
||||
signature: JObject,
|
||||
signature_algorithm: JString,
|
||||
pubkey: JObject,
|
||||
path_indices: JObject,
|
||||
siblings: JObject,
|
||||
root: JString,
|
||||
address: JString,
|
||||
zkeypath: JString,
|
||||
) -> jstring {
|
||||
log::error!("PROOF OF PASSPORT ---- formatting inputs...");
|
||||
|
||||
fn run_proof(
|
||||
mrz: JObject,
|
||||
reveal_bitmap: JObject,
|
||||
data_hashes: JObject,
|
||||
datahashes_padded_length: JString,
|
||||
e_content_bytes: JObject,
|
||||
signature: JObject,
|
||||
signature_algorithm: JString,
|
||||
pubkey: JObject,
|
||||
path_indices: JObject,
|
||||
siblings: JObject,
|
||||
root: JString,
|
||||
address: JString,
|
||||
zkeypath: JString,
|
||||
env: JNIEnv
|
||||
) -> Result<jstring, Box<dyn std::error::Error>> {
|
||||
let start = Instant::now();
|
||||
android_logger::init_once(Config::default().with_min_level(Level::Trace));
|
||||
let mut rng = thread_rng();
|
||||
let rng = &mut rng;
|
||||
let r = ark_bn254::Fr::rand(rng);
|
||||
let s = ark_bn254::Fr::rand(rng);
|
||||
|
||||
log::error!("PROOF OF PASSPORT ---- formatting inputs...");
|
||||
let mut inputs: HashMap<String, Vec<num_bigint::BigInt>> = HashMap::new();
|
||||
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)?;
|
||||
let data_hashes_vec: Vec<String> = java_arraylist_to_rust_vec(&env, data_hashes)?;
|
||||
let e_content_bytes_vec: Vec<String> = java_arraylist_to_rust_vec(&env, e_content_bytes)?;
|
||||
let signature_vec: Vec<String> = java_arraylist_to_rust_vec(&env, signature)?;
|
||||
let pubkey_vec: Vec<String> = java_arraylist_to_rust_vec(&env, pubkey)?;
|
||||
let path_indices_vec: Vec<String> = java_arraylist_to_rust_vec(&env, path_indices)?;
|
||||
let siblings_vec: Vec<String> = java_arraylist_to_rust_vec(&env, siblings)?;
|
||||
|
||||
let signature_algorithm_str: String = env.get_string(signature_algorithm)?.into();
|
||||
let root_str: String = env.get_string(root)?.into();
|
||||
let address_str: String = env.get_string(address)?.into();
|
||||
let datahashes_padded_length_str: String = env.get_string(datahashes_padded_length)?.into();
|
||||
|
||||
log::error!("PROOF OF PASSPORT ---- mrz_vec {:?}", mrz_vec);
|
||||
log::error!("PROOF OF PASSPORT ---- reveal_bitmap_vec {:?}", reveal_bitmap_vec);
|
||||
log::error!("PROOF OF PASSPORT ---- data_hashes_vec {:?}", data_hashes_vec);
|
||||
log::error!("PROOF OF PASSPORT ---- e_content_bytes_vec {:?}", e_content_bytes_vec);
|
||||
log::error!("PROOF OF PASSPORT ---- signature_vec {:?}", signature_vec);
|
||||
log::error!("PROOF OF PASSPORT ---- signature_algorithm_str {:?}", signature_algorithm_str);
|
||||
log::error!("PROOF OF PASSPORT ---- pubkey_vec {:?}", pubkey_vec);
|
||||
log::error!("PROOF OF PASSPORT ---- path_indices_vec {:?}", path_indices_vec);
|
||||
log::error!("PROOF OF PASSPORT ---- siblings_vec {:?}", siblings_vec);
|
||||
log::error!("PROOF OF PASSPORT ---- root_str {:?}", root_str);
|
||||
log::error!("PROOF OF PASSPORT ---- address_str {:?}", address_str);
|
||||
log::error!("PROOF OF PASSPORT ---- datahashes_padded_length_str {:?}", datahashes_padded_length_str);
|
||||
|
||||
fn parse_and_insert(hash_map: &mut HashMap<String, Vec<BigInt>>, key: &str, data: Vec<&str>) {
|
||||
let parsed_data: Vec<BigInt> = data.into_iter()
|
||||
.filter_map(|s| s.parse::<u128>().ok().and_then(|num| num.to_bigint()))
|
||||
.collect();
|
||||
hash_map.insert(key.to_string(), parsed_data);
|
||||
}
|
||||
|
||||
parse_and_insert(&mut inputs, "mrz", mrz_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "reveal_bitmap", reveal_bitmap_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "dataHashes", data_hashes_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "eContentBytes", e_content_bytes_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "signature", signature_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "pubkey", pubkey_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "pathIndices", path_indices_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "siblings", siblings_vec.iter().map(AsRef::as_ref).collect());
|
||||
|
||||
let address_bigint = BigInt::from_bytes_be(Sign::Plus, &decode(&address_str[2..])?);
|
||||
inputs.insert("address".to_string(), vec![address_bigint]);
|
||||
|
||||
let datahashes_padded_length_i32 = datahashes_padded_length_str.parse::<i32>().expect("Failed to parse datahashes_padded_length to i32");
|
||||
let datahashes_padded_length_bigint = BigInt::from(datahashes_padded_length_i32);
|
||||
inputs.insert("datahashes_padded_length".to_string(), vec![datahashes_padded_length_bigint]);
|
||||
|
||||
let signature_algorithm_i32 = signature_algorithm_str.parse::<i32>().expect("Failed to parse signature_algorithm_str to i32");
|
||||
let signature_algorithm_bigint = BigInt::from(signature_algorithm_i32);
|
||||
inputs.insert("signature_algorithm".to_string(), vec![signature_algorithm_bigint]);
|
||||
let root_bigint = BigInt::parse_bytes(root_str.as_bytes(), 10).unwrap();
|
||||
inputs.insert("root".to_string(), vec![root_bigint]);
|
||||
|
||||
println!("generating witness...");
|
||||
let now = Instant::now();
|
||||
let full_assignment = witness_calculator()
|
||||
.lock()
|
||||
.expect("Failed to lock witness calculator")
|
||||
.calculate_witness_element::<Bn254, _>(inputs, false)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
log::error!("PROOF OF PASSPORT ---- Witness generation took. Took: {:?}", now.elapsed());
|
||||
|
||||
log::error!("PROOF OF PASSPORT ---- loading zkey...");
|
||||
let now = Instant::now();
|
||||
let zkey_path_jstring = env.get_string(zkeypath).expect("Couldn't get zkey path string");
|
||||
let zkey_path_str = zkey_path_jstring.to_str().unwrap();
|
||||
|
||||
// To load classic zkey
|
||||
// let file = std::fs::File::open(zkey_path_str).expect("Failed to open zkey file");
|
||||
// let zkey = read_zkey(&mut BufReader::new(file)).expect("Failed to read zkey from file");
|
||||
|
||||
// Loading arkzkey
|
||||
let (serialized_proving_key, serialized_constraint_matrices) = read_arkzkey(zkey_path_str).expect("Failed to read zkey from file");
|
||||
// Formatting for ark-circom API here as it's not done in mopro rn
|
||||
let proving_key: ProvingKey<Bn254> = serialized_proving_key.0;
|
||||
let constraint_matrices: ConstraintMatrices<Fr> = ConstraintMatrices {
|
||||
num_instance_variables: serialized_constraint_matrices.num_instance_variables,
|
||||
num_witness_variables: serialized_constraint_matrices.num_witness_variables,
|
||||
num_constraints: serialized_constraint_matrices.num_constraints,
|
||||
a_num_non_zero: serialized_constraint_matrices.a_num_non_zero,
|
||||
b_num_non_zero: serialized_constraint_matrices.b_num_non_zero,
|
||||
c_num_non_zero: serialized_constraint_matrices.c_num_non_zero,
|
||||
a: serialized_constraint_matrices.a.data,
|
||||
b: serialized_constraint_matrices.b.data,
|
||||
c: serialized_constraint_matrices.c.data,
|
||||
};
|
||||
let zkey = (proving_key, constraint_matrices);
|
||||
|
||||
log::error!("PROOF OF PASSPORT ---- zkey loaded from path. Took: {:?}", now.elapsed());
|
||||
println!("Loading arkzkey took: {:.2?}", now.elapsed());
|
||||
let now = Instant::now();
|
||||
|
||||
let public_inputs = full_assignment.as_slice()[1..zkey.1.num_instance_variables].to_vec();
|
||||
let ark_proof = Groth16::<_, CircomReduction>::create_proof_with_reduction_and_matrices(
|
||||
&zkey.0,
|
||||
r,
|
||||
s,
|
||||
&zkey.1,
|
||||
zkey.1.num_instance_variables,
|
||||
zkey.1.num_constraints,
|
||||
full_assignment.as_slice(),
|
||||
);
|
||||
|
||||
let proof = ark_proof.map_err(|e| e.to_string())?;
|
||||
|
||||
log::error!("PROOF OF PASSPORT ---- proof: {:?}", proof);
|
||||
log::error!("PROOF OF PASSPORT ---- proof done. Took: {:?}", now.elapsed());
|
||||
let now = Instant::now();
|
||||
|
||||
println!("proof generation took: {:.2?}", now.elapsed());
|
||||
|
||||
println!("proof {:?}", proof);
|
||||
println!("public_inputs {:?}", public_inputs);
|
||||
|
||||
// previous way of verifying proof
|
||||
// let pvk = Groth16::<Bn254>::process_vk(¶ms.vk).unwrap();
|
||||
// let verified = Groth16::<Bn254>::verify_with_processed_vk(&pvk, &inputs, &proof).unwrap();
|
||||
// println!("Proof verified. Took: {:?}", now.elapsed());
|
||||
// log::error!("PROOF OF PASSPORT ---- proof verified. Took: {:?}", now.elapsed());
|
||||
// assert!(verified);
|
||||
|
||||
log::error!("PROOF OF PASSPORT ---- public_inputs: {:?}", public_inputs);
|
||||
|
||||
let converted_inputs: ethereum::Inputs = public_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!("PROOF OF PASSPORT ---- Serialized inputs: {:?}", serialized_inputs);
|
||||
|
||||
let proof_str = proof_to_proof_str(&proof);
|
||||
let serialized_proof = serde_json::to_string(&proof_str).unwrap();
|
||||
|
||||
log::error!("PROOF OF PASSPORT ---- Serialized proof: {:?}", serialized_proof);
|
||||
|
||||
let combined = json!({
|
||||
"duration": start.elapsed().as_millis(),
|
||||
"serialized_proof": serialized_proof,
|
||||
"serialized_inputs": serialized_inputs
|
||||
});
|
||||
|
||||
let combined_str = combined.to_string();
|
||||
let output = env.new_string(combined_str).expect("Couldn't create java string!");
|
||||
|
||||
Ok(output.into_inner())
|
||||
}
|
||||
|
||||
match run_proof(
|
||||
mrz,
|
||||
reveal_bitmap,
|
||||
data_hashes,
|
||||
datahashes_padded_length,
|
||||
e_content_bytes,
|
||||
signature,
|
||||
signature_algorithm,
|
||||
pubkey,
|
||||
path_indices,
|
||||
siblings,
|
||||
root,
|
||||
address,
|
||||
zkeypath,
|
||||
env
|
||||
) {
|
||||
Ok(output) => output,
|
||||
Err(_) => env.new_string("error").expect("Couldn't create java string!").into_inner(),
|
||||
}
|
||||
}
|
||||
|
||||
fn java_arraylist_to_rust_vec(env: &JNIEnv, java_list: JObject) -> Result<Vec<String>, jni::errors::Error> {
|
||||
let size = env.call_method(java_list, "size", "()I", &[])?.i()? as i32;
|
||||
let mut vec = Vec::with_capacity(size.try_into().unwrap());
|
||||
|
||||
for i in 0..size {
|
||||
let java_string = env.call_method(java_list, "get", "(I)Ljava/lang/Object;", &[JValue::from(i)])?.l()?;
|
||||
let rust_string: String = env.get_string(java_string.into())?.into();
|
||||
vec.push(rust_string);
|
||||
}
|
||||
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Serialize)]
|
||||
struct ProofStr {
|
||||
a: (String, String),
|
||||
b: ((String, String), (String, String)),
|
||||
c: (String, String),
|
||||
}
|
||||
|
||||
fn proof_to_proof_str(proof: &Proof<Bn254>) -> ProofStr {
|
||||
let a_xy = proof.a.xy().unwrap();
|
||||
let b_xy = proof.b.xy().unwrap();
|
||||
let c_xy = proof.c.xy().unwrap();
|
||||
|
||||
let b_c0_c0 = b_xy.0.c0.to_string();
|
||||
let b_c0_c1 = b_xy.0.c1.to_string();
|
||||
let b_c1_c0 = b_xy.1.c0.to_string();
|
||||
let b_c1_c1 = b_xy.1.c1.to_string();
|
||||
|
||||
ProofStr {
|
||||
a: (a_xy.0.to_string(), a_xy.1.to_string()),
|
||||
b: ((b_c0_c0, b_c0_c1), (b_c1_c0, b_c1_c1)),
|
||||
c: (c_xy.0.to_string(), c_xy.1.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use ethers::{
|
||||
contract::ContractError,
|
||||
prelude::abigen,
|
||||
providers::{Http, Middleware, Provider},
|
||||
utils::Anvil,
|
||||
};
|
||||
use std::{
|
||||
error::Error,
|
||||
fs::File,
|
||||
sync::{Arc, Mutex},
|
||||
collections::HashMap
|
||||
};
|
||||
use wasmer::{Module, Store};
|
||||
|
||||
use ark_circom::{
|
||||
circom::CircomReduction,
|
||||
WitnessCalculator
|
||||
};
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
use ark_groth16::{Groth16, ProvingKey};
|
||||
use ark_relations::r1cs::ConstraintMatrices;
|
||||
use ark_ff::UniformRand;
|
||||
use ark_bn254::{Bn254, Fq, Fq2, Fr, G1Affine, G2Affine};
|
||||
use num_bigint::ToBigInt;
|
||||
use ark_zkey::read_arkzkey_from_bytes; //SerializableConstraintMatrices
|
||||
|
||||
|
||||
// We need to implement the conversion from the Ark-Circom's internal Ethereum types to
|
||||
// the ones expected by the abigen'd types. Could we maybe provide a convenience
|
||||
// macro for these, given that there's room for implementation error?
|
||||
abigen!(Groth16Verifier, "./artifacts/verifier_artifact.json");
|
||||
use groth_16_verifier::{G1Point, G2Point, Proof as EthProof, VerifyingKey as Groth16VerifyingKey};
|
||||
|
||||
impl From<ethereum::G1> for G1Point {
|
||||
fn from(src: ethereum::G1) -> Self {
|
||||
Self { x: src.x, y: src.y }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ethereum::G2> for G2Point {
|
||||
fn from(src: ethereum::G2) -> Self {
|
||||
// We should use the `.as_tuple()` method which handles converting
|
||||
// the G2 elements to have the second limb first
|
||||
let src = src.as_tuple();
|
||||
Self { x: src.0, y: src.1 }
|
||||
}
|
||||
}
|
||||
impl From<ethereum::Proof> for EthProof {
|
||||
fn from(src: ethereum::Proof) -> Self {
|
||||
Self {
|
||||
a: src.a.into(),
|
||||
b: src.b.into(),
|
||||
c: src.c.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<ethereum::VerifyingKey> for Groth16VerifyingKey {
|
||||
fn from(src: ethereum::VerifyingKey) -> Self {
|
||||
Self {
|
||||
alfa_1: src.alpha1.into(),
|
||||
beta_2: src.beta2.into(),
|
||||
gamma_2: src.gamma2.into(),
|
||||
delta_2: src.delta2.into(),
|
||||
ic: src.ic.into_iter().map(|i| i.into()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Middleware> Groth16Verifier<M> {
|
||||
async fn check_proof<
|
||||
I: Into<ethereum::Inputs>,
|
||||
P: Into<ethereum::Proof>,
|
||||
VK: Into<ethereum::VerifyingKey>,
|
||||
>(
|
||||
&self,
|
||||
proof: P,
|
||||
vk: VK,
|
||||
inputs: I,
|
||||
) -> Result<bool, ContractError<M>> {
|
||||
// convert into the expected format by the contract
|
||||
let proof = proof.into().into();
|
||||
let vk = vk.into().into();
|
||||
let inputs = inputs.into().0;
|
||||
println!("inputs in gorth16 verifier: {:?}", &inputs);
|
||||
|
||||
// query the contract
|
||||
let res = self.verify(inputs, proof, vk).call().await?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
const WASM: &[u8] = include_bytes!("../passport/proof_of_passport.wasm");
|
||||
|
||||
static WITNESS_CALCULATOR: OnceCell<Mutex<WitnessCalculator>> = OnceCell::new();
|
||||
|
||||
#[cfg(not(feature = "dylib"))]
|
||||
#[must_use]
|
||||
pub fn witness_calculator() -> &'static Mutex<WitnessCalculator> {
|
||||
WITNESS_CALCULATOR.get_or_init(|| {
|
||||
let store = Store::default();
|
||||
let module = Module::from_binary(&store, WASM).expect("WASM should be valid");
|
||||
let result =
|
||||
WitnessCalculator::from_module(module).expect("Failed to create WitnessCalculator");
|
||||
Mutex::new(result)
|
||||
})
|
||||
}
|
||||
|
||||
const ARKZKEY_BYTES: &[u8] = include_bytes!("../passport/proof_of_passport_final.arkzkey");
|
||||
|
||||
static ARKZKEY: Lazy<(ProvingKey<Bn254>, ConstraintMatrices<Fr>)> = Lazy::new(|| {
|
||||
//let mut reader = Cursor::new(ARKZKEY_BYTES);
|
||||
// TODO: Use reader? More flexible; unclear if perf diff
|
||||
read_arkzkey_from_bytes(ARKZKEY_BYTES).expect("Failed to read arkzkey")
|
||||
});
|
||||
|
||||
// Experimental
|
||||
#[must_use]
|
||||
pub fn arkzkey() -> &'static (ProvingKey<Bn254>, ConstraintMatrices<Fr>) {
|
||||
&ARKZKEY
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_proof() -> Result<(), Box<dyn Error>> {
|
||||
let mut rng = thread_rng();
|
||||
let rng = &mut rng;
|
||||
let r = ark_bn254::Fr::rand(rng);
|
||||
let s = ark_bn254::Fr::rand(rng);
|
||||
|
||||
let mut inputs: HashMap<String, Vec<num_bigint::BigInt>> = HashMap::new();
|
||||
let values = inputs.entry("a".to_string()).or_insert_with(Vec::new);
|
||||
values.push(3.into());
|
||||
|
||||
let mrz_vec: Vec<String> = vec![ "97", "91", "95", "31", "88", "80", "60", "70", "82", "65", "68", "85", "80", "79", "78", "84", "60", "60", "65", "76", "80", "72", "79", "78", "83", "69", "60", "72", "85", "71", "85", "69", "83", "60", "65", "76", "66", "69", "82", "84", "60", "60", "60", "60", "60", "60", "60", "60", "60", "50", "52", "72", "66", "56", "49", "56", "51", "50", "52", "70", "82", "65", "48", "52", "48", "50", "49", "49", "49", "77", "51", "49", "49", "49", "49", "49", "53", "60", "60", "60", "60", "60", "60", "60", "60", "60", "60", "60", "60", "60", "60", "48", "50"].iter().map(|&s| s.to_string()).collect();
|
||||
let reveal_bitmap_vec: Vec<String> = vec![ "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"].iter().map(|&s| s.to_string()).collect();
|
||||
let data_hashes_vec: Vec<String> = vec![ "48", "130", "1", "37", "2", "1", "0", "48", "11", "6", "9", "96", "134", "72", "1", "101", "3", "4", "2", "1", "48", "130", "1", "17", "48", "37", "2", "1", "1", "4", "32", "176", "223", "31", "133", "108", "84", "158", "102", "70", "11", "165", "175", "196", "12", "201", "130", "25", "131", "46", "125", "156", "194", "28", "23", "55", "133", "157", "164", "135", "136", "220", "78", "48", "37", "2", "1", "2", "4", "32", "190", "82", "180", "235", "222", "33", "79", "50", "152", "136", "142", "35", "116", "224", "6", "242", "156", "141", "128", "248", "10", "61", "98", "86", "248", "45", "207", "210", "90", "232", "175", "38", "48", "37", "2", "1", "3", "4", "32", "0", "194", "104", "108", "237", "246", "97", "230", "116", "198", "69", "110", "26", "87", "17", "89", "110", "199", "108", "250", "36", "21", "39", "87", "110", "102", "250", "213", "174", "131", "171", "174", "48", "37", "2", "1", "11", "4", "32", "136", "155", "87", "144", "111", "15", "152", "127", "85", "25", "154", "81", "20", "58", "51", "75", "193", "116", "234", "0", "60", "30", "29", "30", "183", "141", "72", "247", "255", "203", "100", "124", "48", "37", "2", "1", "12", "4", "32", "41", "234", "106", "78", "31", "11", "114", "137", "237", "17", "92", "71", "134", "47", "62", "78", "189", "233", "201", "214", "53", "4", "47", "189", "201", "133", "6", "121", "34", "131", "64", "142", "48", "37", "2", "1", "13", "4", "32", "91", "222", "210", "193", "62", "222", "104", "82", "36", "41", "138", "253", "70", "15", "148", "208", "156", "45", "105", "171", "241", "195", "185", "43", "217", "162", "146", "201", "222", "89", "238", "38", "48", "37", "2", "1", "14", "4", "32", "76", "123", "216", "13", "51", "227", "72", "245", "59", "193", "238", "166", "103", "49", "23", "164", "171", "188", "194", "197", "156", "187", "249", "28", "198", "95", "69", "15", "182", "56", "54", "38", "128", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "9", "72"].iter().map(|&s| s.to_string()).collect();
|
||||
let datahashes_padded_length_str: String = "320".to_string();
|
||||
let e_content_bytes_vec: Vec<String> = vec![ "49", "102", "48", "21", "6", "9", "42", "134", "72", "134", "247", "13", "1", "9", "3", "49", "8", "6", "6", "103", "129", "8", "1", "1", "1", "48", "28", "6", "9", "42", "134", "72", "134", "247", "13", "1", "9", "5", "49", "15", "23", "13", "49", "57", "49", "50", "49", "54", "49", "55", "50", "50", "51", "56", "90", "48", "47", "6", "9", "42", "134", "72", "134", "247", "13", "1", "9", "4", "49", "34", "4", "32", "32", "85", "108", "174", "127", "112", "178", "182", "8", "43", "134", "123", "192", "211", "131", "66", "184", "240", "212", "181", "240", "180", "106", "195", "24", "117", "54", "129", "19", "10", "250", "53"].iter().map(|&s| s.to_string()).collect();
|
||||
let pubkey_vec: Vec<String> = vec![ "14877258137020857405", "14318023465818440622", "669762396243626034", "2098174905787760109", "13512184631463232752", "1151033230807403051", "1750794423069476136", "5398558687849555435", "7358703642447293896", "14972964178681968444", "17927376393065624666", "12136698642738483635", "13028589389954236416", "11728294669438967583", "11944475542136244450", "12725379692537957031", "16433947280623454013", "13881303350788339044", "8072426876492282526", "6117387215636660433", "4538720981552095319", "1804042726655603403", "5977651198873791747", "372166053406449710", "14344596050894147197", "10779070237704917237", "16780599956687811964", "17935955203645787728", "16348714160740996118", "15226818430852970175", "10311930392912784455", "16078982568357050303"].iter().map(|&s| s.to_string()).collect();
|
||||
let signature_vec: Vec<String> = vec![ "5246435566823387901", "994140068779018945", "15914471451186462512", "7880571667552251248", "6469307986104572621", "12461949630634658221", "12450885696843643385", "13947454655189776216", "15974551328200116785", "931381626091656069", "1385903161379602775", "12855786061091617297", "15094260651801937779", "13471621228825251570", "17294887199620944108", "14311703967543697647", "12973402331891058776", "4499641933342092059", "10578231994395748441", "10761169031539003508", "9946908810756942959", "4164708910663312563", "1838078345835967157", "3031966336456751199", "12952597393846567366", "7709884308070068222", "2297541532764959033", "6155424118644397184", "10223511940510133693", "2888993604729528860", "2817846539210919674", "9919760476291903645"].iter().map(|&s| s.to_string()).collect();
|
||||
let address_str: String = "0xEde0fA5A7b196F512204f286666E5eC03E1005D2".to_string();
|
||||
|
||||
fn parse_and_insert(hash_map: &mut HashMap<String, Vec<BigInt>>, key: &str, data: Vec<&str>) {
|
||||
let parsed_data: Vec<BigInt> = data.into_iter()
|
||||
.filter_map(|s| s.parse::<u128>().ok().and_then(|num| num.to_bigint()))
|
||||
.collect();
|
||||
hash_map.insert(key.to_string(), parsed_data);
|
||||
}
|
||||
|
||||
parse_and_insert(&mut inputs, "mrz", mrz_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "reveal_bitmap", reveal_bitmap_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "dataHashes", data_hashes_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "eContentBytes", e_content_bytes_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "signature", signature_vec.iter().map(AsRef::as_ref).collect());
|
||||
parse_and_insert(&mut inputs, "pubkey", pubkey_vec.iter().map(AsRef::as_ref).collect());
|
||||
|
||||
let address_bigint = BigInt::from_bytes_be(Sign::Plus, &decode(&address_str[2..])?);
|
||||
inputs.insert("address".to_string(), vec![address_bigint]);
|
||||
|
||||
let datahashes_padded_length_i32 = datahashes_padded_length_str.parse::<i32>().expect("Failed to parse datahashes_padded_length to i32");
|
||||
let datahashes_padded_length_bigint = BigInt::from(datahashes_padded_length_i32);
|
||||
inputs.insert("datahashes_padded_length".to_string(), vec![datahashes_padded_length_bigint]);
|
||||
|
||||
println!("generating witness...");
|
||||
let now = Instant::now();
|
||||
let full_assignment = witness_calculator()
|
||||
.lock()
|
||||
.expect("Failed to lock witness calculator")
|
||||
.calculate_witness_element::<Bn254, _>(inputs, false)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
println!("Witness generation took: {:.2?}", now.elapsed());
|
||||
println!("loading circuit...");
|
||||
let now = Instant::now();
|
||||
let zkey = arkzkey();
|
||||
println!("Loading arkzkey took: {:.2?}", now.elapsed());
|
||||
|
||||
let public_inputs = full_assignment.as_slice()[1..zkey.1.num_instance_variables].to_vec();
|
||||
let now = Instant::now();
|
||||
let ark_proof = Groth16::<_, CircomReduction>::create_proof_with_reduction_and_matrices(
|
||||
&zkey.0,
|
||||
r,
|
||||
s,
|
||||
&zkey.1,
|
||||
zkey.1.num_instance_variables,
|
||||
zkey.1.num_constraints,
|
||||
full_assignment.as_slice(),
|
||||
);
|
||||
|
||||
let proof = ark_proof.map_err(|e| e.to_string())?;
|
||||
|
||||
println!("proof generation took: {:.2?}", now.elapsed());
|
||||
|
||||
println!("proof {:?}", proof);
|
||||
println!("public_inputs {:?}", public_inputs);
|
||||
|
||||
Ok(())
|
||||
// Ok((SerializableProof(proof), SerializableInputs(public_inputs)))
|
||||
// now = Instant::now();
|
||||
|
||||
// let pvk = Groth16::<Bn254>::process_vk(¶ms.vk).unwrap();
|
||||
// let verified = Groth16::<Bn254>::verify_with_processed_vk(&pvk, &inputs, &proof).unwrap();
|
||||
// println!("Proof verified. Took: {:?}", now.elapsed());
|
||||
|
||||
// assert!(verified);
|
||||
|
||||
// // launch the network & compile the verifier
|
||||
// println!("launching network");
|
||||
|
||||
// let anvil = Anvil::new().spawn();
|
||||
// let acc = anvil.addresses()[0];
|
||||
// let provider = Provider::<Http>::try_from(anvil.endpoint())?;
|
||||
// let provider = provider.with_sender(acc);
|
||||
// let provider = Arc::new(provider);
|
||||
|
||||
// // deploy the verifier
|
||||
// let contract = Groth16Verifier::deploy(provider.clone(), ())?
|
||||
// .send()
|
||||
// .await?;
|
||||
|
||||
// println!("verifier deployed");
|
||||
// println!("contract {:?}", contract);
|
||||
// // check the proof on chain
|
||||
// let onchain_verified = contract
|
||||
// .check_proof(proof, params.vk, inputs.as_slice())
|
||||
// .await?;
|
||||
|
||||
// println!("proof verified on chain");
|
||||
// println!("onchain_verified {:?}", onchain_verified);
|
||||
|
||||
// assert!(onchain_verified);
|
||||
|
||||
// Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
//! ZKey Parsing
|
||||
//!
|
||||
//! Each ZKey file is broken into sections:
|
||||
//! Header(1)
|
||||
//! Prover Type 1 Groth
|
||||
//! HeaderGroth(2)
|
||||
//! n8q
|
||||
//! q
|
||||
//! n8r
|
||||
//! r
|
||||
//! NVars
|
||||
//! NPub
|
||||
//! DomainSize (multiple of 2
|
||||
//! alpha1
|
||||
//! beta1
|
||||
//! delta1
|
||||
//! beta2
|
||||
//! gamma2
|
||||
//! delta2
|
||||
//! IC(3)
|
||||
//! Coefs(4)
|
||||
//! PointsA(5)
|
||||
//! PointsB1(6)
|
||||
//! PointsB2(7)
|
||||
//! PointsC(8)
|
||||
//! PointsH(9)
|
||||
//! Contributions(10)
|
||||
use ark_ff::{BigInteger256, PrimeField};
|
||||
use ark_relations::r1cs::ConstraintMatrices;
|
||||
use ark_serialize::{CanonicalDeserialize, SerializationError};
|
||||
use ark_std::log2;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{Read, Seek, SeekFrom},
|
||||
};
|
||||
|
||||
use ark_bn254::{Bn254, Fq, Fq2, Fr, G1Affine, G2Affine};
|
||||
use ark_groth16::{ProvingKey, VerifyingKey};
|
||||
use num_traits::Zero;
|
||||
use std::io::Cursor;
|
||||
|
||||
type IoResult<T> = Result<T, SerializationError>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Section {
|
||||
position: u64,
|
||||
#[allow(dead_code)]
|
||||
size: usize,
|
||||
}
|
||||
|
||||
/// Reads a SnarkJS ZKey file into an Arkworks ProvingKey.
|
||||
pub fn read_zkey<R: Read + Seek>(
|
||||
reader: &mut R,
|
||||
) -> IoResult<(ProvingKey<Bn254>, ConstraintMatrices<Fr>)> {
|
||||
let mut binfile = BinFile::new(reader)?;
|
||||
let proving_key = binfile.proving_key()?;
|
||||
let matrices = binfile.matrices()?;
|
||||
Ok((proving_key, matrices))
|
||||
}
|
||||
|
||||
pub fn read_zkey_from_include_bytes(
|
||||
data: &[u8],
|
||||
) -> IoResult<(ProvingKey<Bn254>, ConstraintMatrices<Fr>)> {
|
||||
let mut cursor = Cursor::new(data);
|
||||
let mut binfile = BinFile::new(&mut cursor)?;
|
||||
let proving_key = binfile.proving_key()?;
|
||||
let matrices = binfile.matrices()?;
|
||||
Ok((proving_key, matrices))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BinFile<'a, R> {
|
||||
#[allow(dead_code)]
|
||||
ftype: String,
|
||||
#[allow(dead_code)]
|
||||
version: u32,
|
||||
sections: HashMap<u32, Vec<Section>>,
|
||||
reader: &'a mut R,
|
||||
}
|
||||
|
||||
impl<'a, R: Read + Seek> BinFile<'a, R> {
|
||||
fn new(reader: &'a mut R) -> IoResult<Self> {
|
||||
let mut magic = [0u8; 4];
|
||||
reader.read_exact(&mut magic)?;
|
||||
|
||||
let version = reader.read_u32::<LittleEndian>()?;
|
||||
|
||||
let num_sections = reader.read_u32::<LittleEndian>()?;
|
||||
|
||||
let mut sections = HashMap::new();
|
||||
for _ in 0..num_sections {
|
||||
let section_id = reader.read_u32::<LittleEndian>()?;
|
||||
let section_length = reader.read_u64::<LittleEndian>()?;
|
||||
|
||||
let section = sections.entry(section_id).or_insert_with(Vec::new);
|
||||
section.push(Section {
|
||||
position: reader.stream_position()?,
|
||||
size: section_length as usize,
|
||||
});
|
||||
|
||||
reader.seek(SeekFrom::Current(section_length as i64))?;
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
ftype: std::str::from_utf8(&magic[..]).unwrap().to_string(),
|
||||
version,
|
||||
sections,
|
||||
reader,
|
||||
})
|
||||
}
|
||||
|
||||
fn proving_key(&mut self) -> IoResult<ProvingKey<Bn254>> {
|
||||
let header = self.groth_header()?;
|
||||
let ic = self.ic(header.n_public)?;
|
||||
|
||||
let a_query = self.a_query(header.n_vars)?;
|
||||
let b_g1_query = self.b_g1_query(header.n_vars)?;
|
||||
let b_g2_query = self.b_g2_query(header.n_vars)?;
|
||||
let l_query = self.l_query(header.n_vars - header.n_public - 1)?;
|
||||
let h_query = self.h_query(header.domain_size as usize)?;
|
||||
|
||||
let vk = VerifyingKey::<Bn254> {
|
||||
alpha_g1: header.verifying_key.alpha_g1,
|
||||
beta_g2: header.verifying_key.beta_g2,
|
||||
gamma_g2: header.verifying_key.gamma_g2,
|
||||
delta_g2: header.verifying_key.delta_g2,
|
||||
gamma_abc_g1: ic,
|
||||
};
|
||||
|
||||
let pk = ProvingKey::<Bn254> {
|
||||
vk,
|
||||
beta_g1: header.verifying_key.beta_g1,
|
||||
delta_g1: header.verifying_key.delta_g1,
|
||||
a_query,
|
||||
b_g1_query,
|
||||
b_g2_query,
|
||||
h_query,
|
||||
l_query,
|
||||
};
|
||||
|
||||
Ok(pk)
|
||||
}
|
||||
|
||||
fn get_section(&self, id: u32) -> Section {
|
||||
self.sections.get(&id).unwrap()[0].clone()
|
||||
}
|
||||
|
||||
fn groth_header(&mut self) -> IoResult<HeaderGroth> {
|
||||
let section = self.get_section(2);
|
||||
let header = HeaderGroth::new(&mut self.reader, §ion)?;
|
||||
Ok(header)
|
||||
}
|
||||
|
||||
fn ic(&mut self, n_public: usize) -> IoResult<Vec<G1Affine>> {
|
||||
// the range is non-inclusive so we do +1 to get all inputs
|
||||
self.g1_section(n_public + 1, 3)
|
||||
}
|
||||
|
||||
/// Returns the [`ConstraintMatrices`] corresponding to the zkey
|
||||
pub fn matrices(&mut self) -> IoResult<ConstraintMatrices<Fr>> {
|
||||
let header = self.groth_header()?;
|
||||
|
||||
let section = self.get_section(4);
|
||||
self.reader.seek(SeekFrom::Start(section.position))?;
|
||||
let num_coeffs: u32 = self.reader.read_u32::<LittleEndian>()?;
|
||||
|
||||
// insantiate AB
|
||||
let mut matrices = vec![vec![vec![]; header.domain_size as usize]; 2];
|
||||
let mut max_constraint_index = 0;
|
||||
for _ in 0..num_coeffs {
|
||||
let matrix: u32 = self.reader.read_u32::<LittleEndian>()?;
|
||||
let constraint: u32 = self.reader.read_u32::<LittleEndian>()?;
|
||||
let signal: u32 = self.reader.read_u32::<LittleEndian>()?;
|
||||
|
||||
let value: Fr = deserialize_field_fr(&mut self.reader)?;
|
||||
max_constraint_index = std::cmp::max(max_constraint_index, constraint);
|
||||
matrices[matrix as usize][constraint as usize].push((value, signal as usize));
|
||||
}
|
||||
|
||||
let num_constraints = max_constraint_index as usize - header.n_public;
|
||||
// Remove the public input constraints, Arkworks adds them later
|
||||
matrices.iter_mut().for_each(|m| {
|
||||
m.truncate(num_constraints);
|
||||
});
|
||||
// This is taken from Arkworks' to_matrices() function
|
||||
let a = matrices[0].clone();
|
||||
let b = matrices[1].clone();
|
||||
let a_num_non_zero: usize = a.iter().map(|lc| lc.len()).sum();
|
||||
let b_num_non_zero: usize = b.iter().map(|lc| lc.len()).sum();
|
||||
let matrices = ConstraintMatrices {
|
||||
num_instance_variables: header.n_public + 1,
|
||||
num_witness_variables: header.n_vars - header.n_public,
|
||||
num_constraints,
|
||||
|
||||
a_num_non_zero,
|
||||
b_num_non_zero,
|
||||
c_num_non_zero: 0,
|
||||
|
||||
a,
|
||||
b,
|
||||
c: vec![],
|
||||
};
|
||||
|
||||
Ok(matrices)
|
||||
}
|
||||
|
||||
fn a_query(&mut self, n_vars: usize) -> IoResult<Vec<G1Affine>> {
|
||||
self.g1_section(n_vars, 5)
|
||||
}
|
||||
|
||||
fn b_g1_query(&mut self, n_vars: usize) -> IoResult<Vec<G1Affine>> {
|
||||
self.g1_section(n_vars, 6)
|
||||
}
|
||||
|
||||
fn b_g2_query(&mut self, n_vars: usize) -> IoResult<Vec<G2Affine>> {
|
||||
self.g2_section(n_vars, 7)
|
||||
}
|
||||
|
||||
fn l_query(&mut self, n_vars: usize) -> IoResult<Vec<G1Affine>> {
|
||||
self.g1_section(n_vars, 8)
|
||||
}
|
||||
|
||||
fn h_query(&mut self, n_vars: usize) -> IoResult<Vec<G1Affine>> {
|
||||
self.g1_section(n_vars, 9)
|
||||
}
|
||||
|
||||
fn g1_section(&mut self, num: usize, section_id: usize) -> IoResult<Vec<G1Affine>> {
|
||||
let section = self.get_section(section_id as u32);
|
||||
self.reader.seek(SeekFrom::Start(section.position))?;
|
||||
deserialize_g1_vec(self.reader, num as u32)
|
||||
}
|
||||
|
||||
fn g2_section(&mut self, num: usize, section_id: usize) -> IoResult<Vec<G2Affine>> {
|
||||
let section = self.get_section(section_id as u32);
|
||||
self.reader.seek(SeekFrom::Start(section.position))?;
|
||||
deserialize_g2_vec(self.reader, num as u32)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug, CanonicalDeserialize)]
|
||||
pub struct ZVerifyingKey {
|
||||
alpha_g1: G1Affine,
|
||||
beta_g1: G1Affine,
|
||||
beta_g2: G2Affine,
|
||||
gamma_g2: G2Affine,
|
||||
delta_g1: G1Affine,
|
||||
delta_g2: G2Affine,
|
||||
}
|
||||
|
||||
impl ZVerifyingKey {
|
||||
fn new<R: Read>(reader: &mut R) -> IoResult<Self> {
|
||||
let alpha_g1 = deserialize_g1(reader)?;
|
||||
let beta_g1 = deserialize_g1(reader)?;
|
||||
let beta_g2 = deserialize_g2(reader)?;
|
||||
let gamma_g2 = deserialize_g2(reader)?;
|
||||
let delta_g1 = deserialize_g1(reader)?;
|
||||
let delta_g2 = deserialize_g2(reader)?;
|
||||
|
||||
Ok(Self {
|
||||
alpha_g1,
|
||||
beta_g1,
|
||||
beta_g2,
|
||||
gamma_g2,
|
||||
delta_g1,
|
||||
delta_g2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct HeaderGroth {
|
||||
#[allow(dead_code)]
|
||||
n8q: u32,
|
||||
#[allow(dead_code)]
|
||||
q: BigInteger256,
|
||||
#[allow(dead_code)]
|
||||
n8r: u32,
|
||||
#[allow(dead_code)]
|
||||
r: BigInteger256,
|
||||
|
||||
n_vars: usize,
|
||||
n_public: usize,
|
||||
|
||||
domain_size: u32,
|
||||
#[allow(dead_code)]
|
||||
power: u32,
|
||||
|
||||
verifying_key: ZVerifyingKey,
|
||||
}
|
||||
|
||||
impl HeaderGroth {
|
||||
fn new<R: Read + Seek>(reader: &mut R, section: &Section) -> IoResult<Self> {
|
||||
reader.seek(SeekFrom::Start(section.position))?;
|
||||
Self::read(reader)
|
||||
}
|
||||
|
||||
fn read<R: Read>(mut reader: &mut R) -> IoResult<Self> {
|
||||
// TODO: Impl From<u32> in Arkworks
|
||||
let n8q: u32 = u32::deserialize_uncompressed(&mut reader)?;
|
||||
// group order r of Bn254
|
||||
let q = BigInteger256::deserialize_uncompressed(&mut reader)?;
|
||||
|
||||
let n8r: u32 = u32::deserialize_uncompressed(&mut reader)?;
|
||||
// Prime field modulus
|
||||
let r = BigInteger256::deserialize_uncompressed(&mut reader)?;
|
||||
|
||||
let n_vars = u32::deserialize_uncompressed(&mut reader)? as usize;
|
||||
let n_public = u32::deserialize_uncompressed(&mut reader)? as usize;
|
||||
|
||||
let domain_size: u32 = u32::deserialize_uncompressed(&mut reader)?;
|
||||
let power = log2(domain_size as usize);
|
||||
|
||||
let verifying_key = ZVerifyingKey::new(&mut reader)?;
|
||||
|
||||
Ok(Self {
|
||||
n8q,
|
||||
q,
|
||||
n8r,
|
||||
r,
|
||||
n_vars,
|
||||
n_public,
|
||||
domain_size,
|
||||
power,
|
||||
verifying_key,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// need to divide by R, since snarkjs outputs the zkey with coefficients
|
||||
// multiplieid by R^2
|
||||
fn deserialize_field_fr<R: Read>(reader: &mut R) -> IoResult<Fr> {
|
||||
let bigint = BigInteger256::deserialize_uncompressed(reader)?;
|
||||
Ok(Fr::new_unchecked(Fr::new_unchecked(bigint).into_bigint()))
|
||||
}
|
||||
|
||||
// skips the multiplication by R because Circom points are already in Montgomery form
|
||||
fn deserialize_field<R: Read>(reader: &mut R) -> IoResult<Fq> {
|
||||
let bigint = BigInteger256::deserialize_uncompressed(reader)?;
|
||||
// if you use Fq::new it multiplies by R
|
||||
Ok(Fq::new_unchecked(bigint))
|
||||
}
|
||||
|
||||
pub fn deserialize_field2<R: Read>(reader: &mut R) -> IoResult<Fq2> {
|
||||
let c0 = deserialize_field(reader)?;
|
||||
let c1 = deserialize_field(reader)?;
|
||||
Ok(Fq2::new(c0, c1))
|
||||
}
|
||||
|
||||
fn deserialize_g1<R: Read>(reader: &mut R) -> IoResult<G1Affine> {
|
||||
let x = deserialize_field(reader)?;
|
||||
let y = deserialize_field(reader)?;
|
||||
let infinity = x.is_zero() && y.is_zero();
|
||||
if infinity {
|
||||
Ok(G1Affine::identity())
|
||||
} else {
|
||||
Ok(G1Affine::new_unchecked(x, y))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_g2<R: Read>(reader: &mut R) -> IoResult<G2Affine> {
|
||||
let f1 = deserialize_field2(reader)?;
|
||||
let f2 = deserialize_field2(reader)?;
|
||||
let infinity = f1.is_zero() && f2.is_zero();
|
||||
if infinity {
|
||||
Ok(G2Affine::identity())
|
||||
} else {
|
||||
Ok(G2Affine::new_unchecked(f1, f2))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_g1_vec<R: Read>(reader: &mut R, n_vars: u32) -> IoResult<Vec<G1Affine>> {
|
||||
(0..n_vars).map(|_| deserialize_g1(reader)).collect()
|
||||
}
|
||||
|
||||
fn deserialize_g2_vec<R: Read>(reader: &mut R, n_vars: u32) -> IoResult<Vec<G2Affine>> {
|
||||
(0..n_vars).map(|_| deserialize_g2(reader)).collect()
|
||||
}
|
||||
@@ -38,8 +38,8 @@
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"bytecode": "0x608060405234801561001057600080fd5b506107df806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f398789b14610030575b600080fd5b61004a6004803603810190610045919061070a565b610060565b604051610057919061078e565b60405180910390f35b600061061d565b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478110610098576000805260206000f35b50565b600060405183815284602082015285604082015260408160608360076107d05a03fa9150816100ce576000805260206000f35b825160408201526020830151606082015260408360808360066107d05a03fa9150816100fe576000805260206000f35b505050505050565b600060808601600087017f1973951e3206379f4b6cb9ed31fd07e9addd1ce68ab96ad19772c7d0158cba9c81527f2d6c822a71336962fd88a2bcfa2fae9728d345b1f8ac02ef42e6732363fb16fa60208201526101a960008801357f1c4ff48dd08344e7d8ec93176ac4b4a89c3007053fa3762c07c59db1e7c8224f7f0af2a778dd1b8e999ceedf5a3b70df4ca2b6b49b25ab2a7c9946ad6a9286b0d18461009b565b6101f960208801357f2df91f17d37221f3be246a89e8ffe13b9ccc0afdcf80d5fcd343a347ad34b6fa7f2382d5ad4ebe78eeacc64bfebf7ca7e04154e5d09f7dd947d1e96db07e844c4b8461009b565b61024960408801357f06a4be12318195066a5b96da729b895ffb35d15f0da863bc589ad87dc92a59b37f25c6c85b5e06226e16bf0ce04b41e24a9e70443959a839e140381ee36b4973498461009b565b61029960608801357f0898eec5cc579d3a7213b2b38afaaf269613f60f231f788ffa2499be402c23757f18eb6d35340d98950203d516789960e1cbebd23d7fcef9836185fedc73c607088461009b565b6102e960808801357f05c16a0090bf91c1f53f7bd71a0016b99fb8ece9f11b5413a8916a89efc903407f1acc863422c39f57de8944287a183732c41d986e2da7298415f5157351852aaf8461009b565b61033960a08801357f2332aaf5f84f1f039f292c20fa042012f30899bafa18afbaf85f96385cbe0e617f258b4482fa5d1c1267315e5f6bbc023dc6a8fc810ab8a419b787949efcc1a9868461009b565b833582527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760208501357f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703066020830152843560408301526020850135606083015260408501356080830152606085013560a08301527f2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e260c08301527f14bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d192660e08301527f0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c6101008301527f0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab6101208301527f304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a76101408301527f1739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8610160830152600088015161018083015260206000018801516101a08301527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26101c08301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6101e08301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6102008301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa610220830152853561024083015260208601356102608301527f30608196799b6fa0d373d1fe070fc3b504cbdf5c9bbeea0931ba648d31dd6c5b6102808301527f2d6f9b13aa87bf4aa8771e8fa1434c8b11c48e307a238977b2e3e5ad61be9a316102a08301527f14a01ba3d8d9b9e795b2abdc8ce9956d09f7d9c281cc3161aecf7cbafdc37bcf6102c08301527f2ac9260bd42ea4ff2cf4275077bff605956e781d183ad179258a9b841f81dbd56102e08301526020826103008460086107d05a03fa82518116935050505095945050505050565b60405161038081016040526106356000840135610067565b6106426020840135610067565b61064f6040840135610067565b61065c6060840135610067565b6106696080840135610067565b61067660a0840135610067565b61068360c0840135610067565b610690818486888a610106565b8060005260206000f35b600080fd5b600080fd5b6000819050826020600202820111156106c0576106bf61069f565b5b92915050565b6000819050826040600202820111156106e2576106e161069f565b5b92915050565b6000819050826020600602820111156107045761070361069f565b5b92915050565b6000806000806101c085870312156107255761072461069a565b5b6000610733878288016106a4565b9450506040610744878288016106c6565b93505060c0610755878288016106a4565b925050610100610767878288016106e8565b91505092959194509250565b60008115159050919050565b61078881610773565b82525050565b60006020820190506107a3600083018461077f565b9291505056fea2646970667358221220978338d3b7e7eb263f7e42984027d49d99a206cc70383f0a45b20c0c7ab12d5364736f6c63430008120033",
|
||||
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f398789b14610030575b600080fd5b61004a6004803603810190610045919061070a565b610060565b604051610057919061078e565b60405180910390f35b600061061d565b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478110610098576000805260206000f35b50565b600060405183815284602082015285604082015260408160608360076107d05a03fa9150816100ce576000805260206000f35b825160408201526020830151606082015260408360808360066107d05a03fa9150816100fe576000805260206000f35b505050505050565b600060808601600087017f1973951e3206379f4b6cb9ed31fd07e9addd1ce68ab96ad19772c7d0158cba9c81527f2d6c822a71336962fd88a2bcfa2fae9728d345b1f8ac02ef42e6732363fb16fa60208201526101a960008801357f1c4ff48dd08344e7d8ec93176ac4b4a89c3007053fa3762c07c59db1e7c8224f7f0af2a778dd1b8e999ceedf5a3b70df4ca2b6b49b25ab2a7c9946ad6a9286b0d18461009b565b6101f960208801357f2df91f17d37221f3be246a89e8ffe13b9ccc0afdcf80d5fcd343a347ad34b6fa7f2382d5ad4ebe78eeacc64bfebf7ca7e04154e5d09f7dd947d1e96db07e844c4b8461009b565b61024960408801357f06a4be12318195066a5b96da729b895ffb35d15f0da863bc589ad87dc92a59b37f25c6c85b5e06226e16bf0ce04b41e24a9e70443959a839e140381ee36b4973498461009b565b61029960608801357f0898eec5cc579d3a7213b2b38afaaf269613f60f231f788ffa2499be402c23757f18eb6d35340d98950203d516789960e1cbebd23d7fcef9836185fedc73c607088461009b565b6102e960808801357f05c16a0090bf91c1f53f7bd71a0016b99fb8ece9f11b5413a8916a89efc903407f1acc863422c39f57de8944287a183732c41d986e2da7298415f5157351852aaf8461009b565b61033960a08801357f2332aaf5f84f1f039f292c20fa042012f30899bafa18afbaf85f96385cbe0e617f258b4482fa5d1c1267315e5f6bbc023dc6a8fc810ab8a419b787949efcc1a9868461009b565b833582527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760208501357f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703066020830152843560408301526020850135606083015260408501356080830152606085013560a08301527f2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e260c08301527f14bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d192660e08301527f0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c6101008301527f0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab6101208301527f304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a76101408301527f1739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8610160830152600088015161018083015260206000018801516101a08301527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26101c08301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6101e08301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6102008301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa610220830152853561024083015260208601356102608301527f30608196799b6fa0d373d1fe070fc3b504cbdf5c9bbeea0931ba648d31dd6c5b6102808301527f2d6f9b13aa87bf4aa8771e8fa1434c8b11c48e307a238977b2e3e5ad61be9a316102a08301527f14a01ba3d8d9b9e795b2abdc8ce9956d09f7d9c281cc3161aecf7cbafdc37bcf6102c08301527f2ac9260bd42ea4ff2cf4275077bff605956e781d183ad179258a9b841f81dbd56102e08301526020826103008460086107d05a03fa82518116935050505095945050505050565b60405161038081016040526106356000840135610067565b6106426020840135610067565b61064f6040840135610067565b61065c6060840135610067565b6106696080840135610067565b61067660a0840135610067565b61068360c0840135610067565b610690818486888a610106565b8060005260206000f35b600080fd5b600080fd5b6000819050826020600202820111156106c0576106bf61069f565b5b92915050565b6000819050826040600202820111156106e2576106e161069f565b5b92915050565b6000819050826020600602820111156107045761070361069f565b5b92915050565b6000806000806101c085870312156107255761072461069a565b5b6000610733878288016106a4565b9450506040610744878288016106c6565b93505060c0610755878288016106a4565b925050610100610767878288016106e8565b91505092959194509250565b60008115159050919050565b61078881610773565b82525050565b60006020820190506107a3600083018461077f565b9291505056fea2646970667358221220978338d3b7e7eb263f7e42984027d49d99a206cc70383f0a45b20c0c7ab12d5364736f6c63430008120033",
|
||||
"bytecode": "0x608060405234801561001057600080fd5b506107df806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f398789b14610030575b600080fd5b61004a6004803603810190610045919061070a565b610060565b604051610057919061078e565b60405180910390f35b600061061d565b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478110610098576000805260206000f35b50565b600060405183815284602082015285604082015260408160608360076107d05a03fa9150816100ce576000805260206000f35b825160408201526020830151606082015260408360808360066107d05a03fa9150816100fe576000805260206000f35b505050505050565b600060808601600087017f1973951e3206379f4b6cb9ed31fd07e9addd1ce68ab96ad19772c7d0158cba9c81527f2d6c822a71336962fd88a2bcfa2fae9728d345b1f8ac02ef42e6732363fb16fa60208201526101a960008801357f1c4ff48dd08344e7d8ec93176ac4b4a89c3007053fa3762c07c59db1e7c8224f7f0af2a778dd1b8e999ceedf5a3b70df4ca2b6b49b25ab2a7c9946ad6a9286b0d18461009b565b6101f960208801357f2df91f17d37221f3be246a89e8ffe13b9ccc0afdcf80d5fcd343a347ad34b6fa7f2382d5ad4ebe78eeacc64bfebf7ca7e04154e5d09f7dd947d1e96db07e844c4b8461009b565b61024960408801357f06a4be12318195066a5b96da729b895ffb35d15f0da863bc589ad87dc92a59b37f25c6c85b5e06226e16bf0ce04b41e24a9e70443959a839e140381ee36b4973498461009b565b61029960608801357f0898eec5cc579d3a7213b2b38afaaf269613f60f231f788ffa2499be402c23757f18eb6d35340d98950203d516789960e1cbebd23d7fcef9836185fedc73c607088461009b565b6102e960808801357f05c16a0090bf91c1f53f7bd71a0016b99fb8ece9f11b5413a8916a89efc903407f1acc863422c39f57de8944287a183732c41d986e2da7298415f5157351852aaf8461009b565b61033960a08801357f2332aaf5f84f1f039f292c20fa042012f30899bafa18afbaf85f96385cbe0e617f258b4482fa5d1c1267315e5f6bbc023dc6a8fc810ab8a419b787949efcc1a9868461009b565b833582527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760208501357f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703066020830152843560408301526020850135606083015260408501356080830152606085013560a08301527f2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e260c08301527f14bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d192660e08301527f0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c6101008301527f0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab6101208301527f304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a76101408301527f1739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8610160830152600088015161018083015260206000018801516101a08301527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26101c08301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6101e08301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6102008301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa610220830152853561024083015260208601356102608301527f13093cf285e0d3af1aeb57953666538e5ff8be9effe1b4ff9301356e36ef27ca6102808301527f1a575a2a1e4cb4f452b1c815184e71c51e5a3c44b11c691aed0b39de518b1aed6102a08301527f06f6b931a88f43f1964418344340a23d286ddd6232a87cb9dc48038c4d10fcc86102c08301527f04c9c9a1061ee327db8022d3dfaa997d65fb46266c4a11620664967c2c98ddb96102e08301526020826103008460086107d05a03fa82518116935050505095945050505050565b60405161038081016040526106356000840135610067565b6106426020840135610067565b61064f6040840135610067565b61065c6060840135610067565b6106696080840135610067565b61067660a0840135610067565b61068360c0840135610067565b610690818486888a610106565b8060005260206000f35b600080fd5b600080fd5b6000819050826020600202820111156106c0576106bf61069f565b5b92915050565b6000819050826040600202820111156106e2576106e161069f565b5b92915050565b6000819050826020600602820111156107045761070361069f565b5b92915050565b6000806000806101c085870312156107255761072461069a565b5b6000610733878288016106a4565b9450506040610744878288016106c6565b93505060c0610755878288016106a4565b925050610100610767878288016106e8565b91505092959194509250565b60008115159050919050565b61078881610773565b82525050565b60006020820190506107a3600083018461077f565b9291505056fea2646970667358221220f90502a2cdc1be3aae6482c9ad4fd05fbce27381eff1b8971a25df2c50f3a0bd64736f6c63430008120033",
|
||||
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f398789b14610030575b600080fd5b61004a6004803603810190610045919061070a565b610060565b604051610057919061078e565b60405180910390f35b600061061d565b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478110610098576000805260206000f35b50565b600060405183815284602082015285604082015260408160608360076107d05a03fa9150816100ce576000805260206000f35b825160408201526020830151606082015260408360808360066107d05a03fa9150816100fe576000805260206000f35b505050505050565b600060808601600087017f1973951e3206379f4b6cb9ed31fd07e9addd1ce68ab96ad19772c7d0158cba9c81527f2d6c822a71336962fd88a2bcfa2fae9728d345b1f8ac02ef42e6732363fb16fa60208201526101a960008801357f1c4ff48dd08344e7d8ec93176ac4b4a89c3007053fa3762c07c59db1e7c8224f7f0af2a778dd1b8e999ceedf5a3b70df4ca2b6b49b25ab2a7c9946ad6a9286b0d18461009b565b6101f960208801357f2df91f17d37221f3be246a89e8ffe13b9ccc0afdcf80d5fcd343a347ad34b6fa7f2382d5ad4ebe78eeacc64bfebf7ca7e04154e5d09f7dd947d1e96db07e844c4b8461009b565b61024960408801357f06a4be12318195066a5b96da729b895ffb35d15f0da863bc589ad87dc92a59b37f25c6c85b5e06226e16bf0ce04b41e24a9e70443959a839e140381ee36b4973498461009b565b61029960608801357f0898eec5cc579d3a7213b2b38afaaf269613f60f231f788ffa2499be402c23757f18eb6d35340d98950203d516789960e1cbebd23d7fcef9836185fedc73c607088461009b565b6102e960808801357f05c16a0090bf91c1f53f7bd71a0016b99fb8ece9f11b5413a8916a89efc903407f1acc863422c39f57de8944287a183732c41d986e2da7298415f5157351852aaf8461009b565b61033960a08801357f2332aaf5f84f1f039f292c20fa042012f30899bafa18afbaf85f96385cbe0e617f258b4482fa5d1c1267315e5f6bbc023dc6a8fc810ab8a419b787949efcc1a9868461009b565b833582527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760208501357f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703066020830152843560408301526020850135606083015260408501356080830152606085013560a08301527f2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e260c08301527f14bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d192660e08301527f0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c6101008301527f0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab6101208301527f304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a76101408301527f1739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8610160830152600088015161018083015260206000018801516101a08301527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26101c08301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6101e08301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6102008301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa610220830152853561024083015260208601356102608301527f13093cf285e0d3af1aeb57953666538e5ff8be9effe1b4ff9301356e36ef27ca6102808301527f1a575a2a1e4cb4f452b1c815184e71c51e5a3c44b11c691aed0b39de518b1aed6102a08301527f06f6b931a88f43f1964418344340a23d286ddd6232a87cb9dc48038c4d10fcc86102c08301527f04c9c9a1061ee327db8022d3dfaa997d65fb46266c4a11620664967c2c98ddb96102e08301526020826103008460086107d05a03fa82518116935050505095945050505050565b60405161038081016040526106356000840135610067565b6106426020840135610067565b61064f6040840135610067565b61065c6060840135610067565b6106696080840135610067565b61067660a0840135610067565b61068360c0840135610067565b610690818486888a610106565b8060005260206000f35b600080fd5b600080fd5b6000819050826020600202820111156106c0576106bf61069f565b5b92915050565b6000819050826040600202820111156106e2576106e161069f565b5b92915050565b6000819050826020600602820111156107045761070361069f565b5b92915050565b6000806000806101c085870312156107255761072461069a565b5b6000610733878288016106a4565b9450506040610744878288016106c6565b93505060c0610755878288016106a4565b925050610100610767878288016106e8565b91505092959194509250565b60008115159050919050565b61078881610773565b82525050565b60006020820190506107a3600083018461077f565b9291505056fea2646970667358221220f90502a2cdc1be3aae6482c9ad4fd05fbce27381eff1b8971a25df2c50f3a0bd64736f6c63430008120033",
|
||||
"linkReferences": {},
|
||||
"deployedLinkReferences": {}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
{"ProofOfPassport":"0x24c919Dc3E5BA89c0898778D71435D566B05B4c5","Groth16Verifier":"0x6b3c6CF3e7bf2663E5EA30F2566433261fe64554"}
|
||||
{"ProofOfPassport":"0xe3e5738EBb14EFB2041aa41068D1bdd7c0DFD03A","Groth16Verifier":"0xD923a1AA54e5a1F6d288649C3a2b7aB5856514cf"}
|
||||
@@ -1,26 +1,76 @@
|
||||
mkdir -p ark-circom-passport/passport
|
||||
cp ../circuits/build/proof_of_passport_final.zkey ark-circom-passport/passport/
|
||||
echo "copied proof_of_passport_final.zkey to ark-circom-passport"
|
||||
#!/bin/bash
|
||||
|
||||
ARCHITECTURE="aarch64-linux-android"
|
||||
# This is adapted from mopro
|
||||
|
||||
# Check for target support
|
||||
check_target_support() {
|
||||
rustup target list | grep installed | grep -q "$1"
|
||||
}
|
||||
DEVICE_TYPE="arm64"
|
||||
BUILD_MODE="release"
|
||||
|
||||
# check target is installed
|
||||
if ! check_target_support $ARCHITECTURE; then
|
||||
rustup target add $ARCHITECTURE
|
||||
else
|
||||
echo "Target $ARCHITECTURE already installed, skipping."
|
||||
fi
|
||||
# Determine the architecture and folder based on device type
|
||||
case $DEVICE_TYPE in
|
||||
"x86_64")
|
||||
ARCHITECTURE="x86_64-linux-android"
|
||||
FOLDER="x86_64"
|
||||
;;
|
||||
"x86")
|
||||
ARCHITECTURE="i686-linux-android"
|
||||
FOLDER="x86"
|
||||
;;
|
||||
"arm")
|
||||
ARCHITECTURE="armv7-linux-androideabi"
|
||||
FOLDER="armeabi-v7a"
|
||||
;;
|
||||
"arm64")
|
||||
ARCHITECTURE="aarch64-linux-android"
|
||||
FOLDER="arm64-v8a"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Error: Invalid device type specified in config: $DEVICE_TYPE${DEFAULT}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
cd android
|
||||
./gradlew clean
|
||||
./gradlew cargoBuild
|
||||
cd ..
|
||||
# Determine the library directory and build command based on build mode
|
||||
case $BUILD_MODE in
|
||||
"debug")
|
||||
LIB_DIR="debug"
|
||||
COMMAND=""
|
||||
;;
|
||||
"release")
|
||||
LIB_DIR="release"
|
||||
COMMAND="--release"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Error: Invalid build mode specified in config: $BUILD_MODE${DEFAULT}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p android/react-native-passport-reader/android/src/main/jniLibs/arm64-v8a/
|
||||
cp ark-circom-passport/target/aarch64-linux-android/release/libark_circom_passport.so android/react-native-passport-reader/android/src/main/jniLibs/arm64-v8a/
|
||||
echo copied release version of android lib to android/
|
||||
PROJECT_DIR=$(pwd)
|
||||
|
||||
cd ${PROJECT_DIR}/mopro-ffi
|
||||
|
||||
echo "[android] Install cargo-ndk"
|
||||
cargo install cargo-ndk
|
||||
|
||||
# Print appropriate message based on device type
|
||||
echo "Using $ARCHITECTURE libmopro_ffi.a ($LIB_DIR) static library..."
|
||||
print_warning "This only works on $FOLDER devices!"
|
||||
|
||||
echo "[android] Build target in $BUILD_MODE mode"
|
||||
cargo ndk -t ${ARCHITECTURE} build --lib ${COMMAND}
|
||||
|
||||
echo "[android] Copy files in mopro-android/Example/jniLibs/"
|
||||
for binary in ${PROJECT_DIR}/mopro-ffi/target/*/*/libmopro_ffi.so; do file $binary; done
|
||||
|
||||
mkdir -p jniLibs/${FOLDER}/ && \
|
||||
cp ${PROJECT_DIR}/mopro-ffi/target/${ARCHITECTURE}/${LIB_DIR}/libmopro_ffi.so jniLibs/${FOLDER}/libuniffi_mopro.so
|
||||
|
||||
echo "[android] Generating Kotlin bindings in $BUILD_MODE mode..."
|
||||
cargo run --features=uniffi/cli ${COMMAND} \
|
||||
--bin uniffi-bindgen \
|
||||
generate src/mopro.udl \
|
||||
--language kotlin
|
||||
|
||||
echo "[android] Copy Kotlin bindings to android app"
|
||||
cp -r ${PROJECT_DIR}/mopro-ffi/jniLibs/ ${PROJECT_DIR}/android/app/src/main/jniLibs/
|
||||
cp -r ${PROJECT_DIR}/mopro-ffi/src/uniffi/ ${PROJECT_DIR}/android/app/src/main/java/uniffi/
|
||||
@@ -1,3 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is adapted from mopro
|
||||
|
||||
ARCHITECTURE="aarch64-apple-ios" # or "x86_64-apple-ios" for "x86_64", "aarch64-apple-ios-sim" for simulator
|
||||
LIB_DIR="release" # or "debug"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p ../circuits/build
|
||||
cd ../circuits/build
|
||||
if [ -f "proof_of_passport_final.zkey" ]; then
|
||||
|
||||
@@ -52,7 +52,7 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
ens,
|
||||
setEns
|
||||
}) => {
|
||||
const [zkeyLoaded, setZkeyLoaded] = useState(false);
|
||||
const [zkeyLoaded, setZkeyLoaded] = useState(true);
|
||||
|
||||
const downloadZkey = async () => {
|
||||
// TODO: don't redownload if already in the file system at path, if downloaded from previous session
|
||||
|
||||
723
circuits/test/inputs.json
Normal file
723
circuits/test/inputs.json
Normal file
@@ -0,0 +1,723 @@
|
||||
{
|
||||
"mrz": [
|
||||
"97",
|
||||
"91",
|
||||
"95",
|
||||
"31",
|
||||
"88",
|
||||
"80",
|
||||
"60",
|
||||
"70",
|
||||
"82",
|
||||
"65",
|
||||
"84",
|
||||
"65",
|
||||
"86",
|
||||
"69",
|
||||
"82",
|
||||
"78",
|
||||
"73",
|
||||
"69",
|
||||
"82",
|
||||
"60",
|
||||
"60",
|
||||
"70",
|
||||
"76",
|
||||
"79",
|
||||
"82",
|
||||
"69",
|
||||
"78",
|
||||
"84",
|
||||
"60",
|
||||
"72",
|
||||
"85",
|
||||
"71",
|
||||
"85",
|
||||
"69",
|
||||
"83",
|
||||
"60",
|
||||
"74",
|
||||
"69",
|
||||
"65",
|
||||
"78",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"49",
|
||||
"57",
|
||||
"72",
|
||||
"65",
|
||||
"51",
|
||||
"52",
|
||||
"56",
|
||||
"50",
|
||||
"56",
|
||||
"52",
|
||||
"70",
|
||||
"82",
|
||||
"65",
|
||||
"48",
|
||||
"48",
|
||||
"48",
|
||||
"55",
|
||||
"49",
|
||||
"57",
|
||||
"49",
|
||||
"77",
|
||||
"50",
|
||||
"57",
|
||||
"49",
|
||||
"50",
|
||||
"48",
|
||||
"57",
|
||||
"53",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"60",
|
||||
"48",
|
||||
"50"
|
||||
],
|
||||
"reveal_bitmap": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"dataHashes": [
|
||||
"48",
|
||||
"130",
|
||||
"1",
|
||||
"37",
|
||||
"2",
|
||||
"1",
|
||||
"0",
|
||||
"48",
|
||||
"11",
|
||||
"6",
|
||||
"9",
|
||||
"96",
|
||||
"134",
|
||||
"72",
|
||||
"1",
|
||||
"101",
|
||||
"3",
|
||||
"4",
|
||||
"2",
|
||||
"1",
|
||||
"48",
|
||||
"130",
|
||||
"1",
|
||||
"17",
|
||||
"48",
|
||||
"37",
|
||||
"2",
|
||||
"1",
|
||||
"1",
|
||||
"4",
|
||||
"32",
|
||||
"99",
|
||||
"19",
|
||||
"179",
|
||||
"205",
|
||||
"55",
|
||||
"104",
|
||||
"45",
|
||||
"214",
|
||||
"133",
|
||||
"101",
|
||||
"233",
|
||||
"177",
|
||||
"130",
|
||||
"1",
|
||||
"37",
|
||||
"89",
|
||||
"125",
|
||||
"229",
|
||||
"139",
|
||||
"34",
|
||||
"132",
|
||||
"146",
|
||||
"28",
|
||||
"116",
|
||||
"248",
|
||||
"186",
|
||||
"63",
|
||||
"195",
|
||||
"96",
|
||||
"151",
|
||||
"26",
|
||||
"215",
|
||||
"48",
|
||||
"37",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
"4",
|
||||
"32",
|
||||
"63",
|
||||
"234",
|
||||
"106",
|
||||
"78",
|
||||
"31",
|
||||
"16",
|
||||
"114",
|
||||
"137",
|
||||
"237",
|
||||
"17",
|
||||
"92",
|
||||
"71",
|
||||
"134",
|
||||
"47",
|
||||
"62",
|
||||
"78",
|
||||
"189",
|
||||
"233",
|
||||
"201",
|
||||
"213",
|
||||
"53",
|
||||
"4",
|
||||
"47",
|
||||
"189",
|
||||
"201",
|
||||
"133",
|
||||
"6",
|
||||
"121",
|
||||
"34",
|
||||
"131",
|
||||
"64",
|
||||
"142",
|
||||
"48",
|
||||
"37",
|
||||
"2",
|
||||
"1",
|
||||
"3",
|
||||
"4",
|
||||
"32",
|
||||
"136",
|
||||
"155",
|
||||
"87",
|
||||
"144",
|
||||
"121",
|
||||
"15",
|
||||
"152",
|
||||
"127",
|
||||
"85",
|
||||
"25",
|
||||
"154",
|
||||
"80",
|
||||
"20",
|
||||
"58",
|
||||
"51",
|
||||
"75",
|
||||
"193",
|
||||
"116",
|
||||
"234",
|
||||
"0",
|
||||
"60",
|
||||
"30",
|
||||
"29",
|
||||
"30",
|
||||
"183",
|
||||
"141",
|
||||
"72",
|
||||
"247",
|
||||
"255",
|
||||
"203",
|
||||
"100",
|
||||
"124",
|
||||
"48",
|
||||
"37",
|
||||
"2",
|
||||
"1",
|
||||
"11",
|
||||
"4",
|
||||
"32",
|
||||
"0",
|
||||
"194",
|
||||
"104",
|
||||
"108",
|
||||
"237",
|
||||
"246",
|
||||
"97",
|
||||
"230",
|
||||
"116",
|
||||
"198",
|
||||
"69",
|
||||
"110",
|
||||
"26",
|
||||
"87",
|
||||
"17",
|
||||
"89",
|
||||
"110",
|
||||
"199",
|
||||
"108",
|
||||
"250",
|
||||
"36",
|
||||
"21",
|
||||
"39",
|
||||
"87",
|
||||
"110",
|
||||
"102",
|
||||
"250",
|
||||
"213",
|
||||
"174",
|
||||
"131",
|
||||
"171",
|
||||
"174",
|
||||
"48",
|
||||
"37",
|
||||
"2",
|
||||
"1",
|
||||
"12",
|
||||
"4",
|
||||
"32",
|
||||
"190",
|
||||
"82",
|
||||
"180",
|
||||
"235",
|
||||
"222",
|
||||
"33",
|
||||
"79",
|
||||
"50",
|
||||
"152",
|
||||
"136",
|
||||
"142",
|
||||
"35",
|
||||
"116",
|
||||
"224",
|
||||
"6",
|
||||
"242",
|
||||
"156",
|
||||
"141",
|
||||
"128",
|
||||
"247",
|
||||
"10",
|
||||
"61",
|
||||
"98",
|
||||
"86",
|
||||
"248",
|
||||
"45",
|
||||
"207",
|
||||
"210",
|
||||
"90",
|
||||
"232",
|
||||
"175",
|
||||
"38",
|
||||
"48",
|
||||
"37",
|
||||
"2",
|
||||
"1",
|
||||
"13",
|
||||
"4",
|
||||
"32",
|
||||
"91",
|
||||
"222",
|
||||
"210",
|
||||
"193",
|
||||
"63",
|
||||
"222",
|
||||
"104",
|
||||
"82",
|
||||
"36",
|
||||
"41",
|
||||
"138",
|
||||
"253",
|
||||
"70",
|
||||
"15",
|
||||
"148",
|
||||
"208",
|
||||
"156",
|
||||
"45",
|
||||
"105",
|
||||
"171",
|
||||
"241",
|
||||
"195",
|
||||
"185",
|
||||
"43",
|
||||
"217",
|
||||
"162",
|
||||
"146",
|
||||
"201",
|
||||
"222",
|
||||
"89",
|
||||
"238",
|
||||
"38",
|
||||
"48",
|
||||
"37",
|
||||
"2",
|
||||
"1",
|
||||
"14",
|
||||
"4",
|
||||
"32",
|
||||
"76",
|
||||
"123",
|
||||
"216",
|
||||
"13",
|
||||
"52",
|
||||
"227",
|
||||
"72",
|
||||
"245",
|
||||
"59",
|
||||
"193",
|
||||
"238",
|
||||
"166",
|
||||
"103",
|
||||
"49",
|
||||
"24",
|
||||
"164",
|
||||
"171",
|
||||
"188",
|
||||
"194",
|
||||
"197",
|
||||
"156",
|
||||
"187",
|
||||
"249",
|
||||
"28",
|
||||
"198",
|
||||
"95",
|
||||
"69",
|
||||
"15",
|
||||
"182",
|
||||
"56",
|
||||
"54",
|
||||
"38",
|
||||
"128",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"9",
|
||||
"72"
|
||||
],
|
||||
"datahashes_padded_length": "320",
|
||||
"eContentBytes": [
|
||||
"49",
|
||||
"102",
|
||||
"48",
|
||||
"21",
|
||||
"6",
|
||||
"9",
|
||||
"42",
|
||||
"134",
|
||||
"72",
|
||||
"134",
|
||||
"247",
|
||||
"13",
|
||||
"1",
|
||||
"9",
|
||||
"3",
|
||||
"49",
|
||||
"8",
|
||||
"6",
|
||||
"6",
|
||||
"103",
|
||||
"129",
|
||||
"8",
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"48",
|
||||
"28",
|
||||
"6",
|
||||
"9",
|
||||
"42",
|
||||
"134",
|
||||
"72",
|
||||
"134",
|
||||
"247",
|
||||
"13",
|
||||
"1",
|
||||
"9",
|
||||
"5",
|
||||
"49",
|
||||
"15",
|
||||
"23",
|
||||
"13",
|
||||
"49",
|
||||
"57",
|
||||
"49",
|
||||
"50",
|
||||
"49",
|
||||
"54",
|
||||
"49",
|
||||
"55",
|
||||
"50",
|
||||
"50",
|
||||
"51",
|
||||
"56",
|
||||
"90",
|
||||
"48",
|
||||
"47",
|
||||
"6",
|
||||
"9",
|
||||
"42",
|
||||
"134",
|
||||
"72",
|
||||
"134",
|
||||
"247",
|
||||
"13",
|
||||
"1",
|
||||
"9",
|
||||
"4",
|
||||
"49",
|
||||
"34",
|
||||
"4",
|
||||
"32",
|
||||
"176",
|
||||
"96",
|
||||
"59",
|
||||
"213",
|
||||
"131",
|
||||
"82",
|
||||
"89",
|
||||
"248",
|
||||
"105",
|
||||
"125",
|
||||
"37",
|
||||
"177",
|
||||
"158",
|
||||
"162",
|
||||
"137",
|
||||
"43",
|
||||
"13",
|
||||
"39",
|
||||
"115",
|
||||
"6",
|
||||
"59",
|
||||
"229",
|
||||
"81",
|
||||
"110",
|
||||
"49",
|
||||
"75",
|
||||
"255",
|
||||
"184",
|
||||
"155",
|
||||
"73",
|
||||
"116",
|
||||
"86"
|
||||
],
|
||||
"signature": [
|
||||
"1004979219314799894",
|
||||
"6361443755252600907",
|
||||
"6439012883494616023",
|
||||
"9400879716815088139",
|
||||
"17551897985575934811",
|
||||
"11779273958797828281",
|
||||
"2536315921873401485",
|
||||
"3748173260178203981",
|
||||
"12475215309213288577",
|
||||
"6281117468118442715",
|
||||
"1336292932993922350",
|
||||
"14238156234566069988",
|
||||
"11985045093510507012",
|
||||
"3585865343992378960",
|
||||
"16170829868787473084",
|
||||
"17039645001628184779",
|
||||
"486540501180074772",
|
||||
"5061439412388381188",
|
||||
"12478821212163933993",
|
||||
"7430448406248319432",
|
||||
"746345521572597865",
|
||||
"5002454658692185142",
|
||||
"3715069341922830389",
|
||||
"11010599232161942094",
|
||||
"1577500614971981868",
|
||||
"13656226284809645063",
|
||||
"3918261659477120323",
|
||||
"5578832687955645075",
|
||||
"3416933977282345392",
|
||||
"15829829506526117610",
|
||||
"17465616637242519010",
|
||||
"6519177967447716150"
|
||||
],
|
||||
"signatureAlgorithm": "1",
|
||||
"pubkey": [
|
||||
"9539992759301679521",
|
||||
"1652651398804391575",
|
||||
"7756096264856639170",
|
||||
"15028348881266521487",
|
||||
"13451582891670014060",
|
||||
"11697656644529425980",
|
||||
"14590137142310897374",
|
||||
"1172377360308996086",
|
||||
"6389592621616098288",
|
||||
"6767780215543232436",
|
||||
"11347756978427069433",
|
||||
"2593119277386338350",
|
||||
"18385617576997885505",
|
||||
"14960211320702750252",
|
||||
"8706817324429498800",
|
||||
"15168543370367053559",
|
||||
"8708916123725550363",
|
||||
"18006178692029805686",
|
||||
"6398208271038376723",
|
||||
"15000821494077560096",
|
||||
"17674982305626887153",
|
||||
"2867958270953137726",
|
||||
"9287774520059158342",
|
||||
"9813100051910281130",
|
||||
"13494313215150203208",
|
||||
"7792741716144106392",
|
||||
"6553490305289731807",
|
||||
"32268224696386820",
|
||||
"15737886769048580611",
|
||||
"669518601007982974",
|
||||
"11424760966478363403",
|
||||
"16073833083611347461"
|
||||
],
|
||||
"pathIndices": [
|
||||
"0",
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"0",
|
||||
"1",
|
||||
"1",
|
||||
"0",
|
||||
"0",
|
||||
"1",
|
||||
"1",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"siblings": [
|
||||
"20516282398390866580647417962347415258712802604212003365416596890852644939364",
|
||||
"20547289806543281108128197867250295423223489766069952889766689677695750842294",
|
||||
"17092860852967512812593771487649838995106203215624858397482169733546970246117",
|
||||
"19141872343555753276227561835732941623954902346285308564941039231845690663515",
|
||||
"2888260764701592030713638283446165050628606750519377550369633789586724212406",
|
||||
"17037943129534065359096662792322618985598809624384219749636863003643326502177",
|
||||
"21260541151470016589788332273091943678373855676584683193443363340566713593750",
|
||||
"9681119423869145671286918102040570804786474221694907866875171055859965502010",
|
||||
"3999714159260652982057321310481110903729446356195536109316994934664982988519",
|
||||
"14359042263488593594514913785064471775842285148703143594475594381078274944550",
|
||||
"10696856845043652409316424831381338144209147199074363427177722046972515079299",
|
||||
"2796323689030312622891330190155708704921773618732461037692992858528069077360",
|
||||
"1379184643939692456020535864077563679018059205165852146212742699309755722087",
|
||||
"17834317267514482863629341626611816587254867008433493508231639322166589549456",
|
||||
"1473918712602583605383280948484316645101117513102582419100942131704211814519",
|
||||
"15819538789928229930262697811477882737253464456578333862691129291651619515538"
|
||||
],
|
||||
"root": "4080578225172475068086778061870548445929343471785864518431540330127324371840",
|
||||
"address": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8"
|
||||
}
|
||||
@@ -455,10 +455,6 @@
|
||||
version "2.0.0-beta.1"
|
||||
resolved "https://gitpkg.now.sh/0xturboblitz/zk-kit/packages/imt?6d417675#38244ea6eef75dc1ad7fff3ff2a22dd5f1a2593a"
|
||||
|
||||
"@zk-kit/imt@https://gitpkg.now.sh/0xturboblitz/zk-kit/packages/imt?b6e7d542":
|
||||
version "2.0.0-beta.1"
|
||||
resolved "https://gitpkg.now.sh/0xturboblitz/zk-kit/packages/imt?b6e7d542#ade4ca8ba82e2a4d54889bcda143c81f82d61580"
|
||||
|
||||
addressparser@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746"
|
||||
|
||||
@@ -39,18 +39,19 @@ export function generateCircuitInputs(passportData: PassportData, tree: IMT, rev
|
||||
MAX_DATAHASHES_LEN
|
||||
);
|
||||
|
||||
// don't forget to wrap everything in arrays for mopro bindings
|
||||
return {
|
||||
mrz: formattedMrz.map(byte => String(byte)),
|
||||
reveal_bitmap: reveal_bitmap.map(byte => String(byte)),
|
||||
dataHashes: Array.from(messagePadded).map((x) => x.toString()),
|
||||
datahashes_padded_length: messagePaddedLen.toString(),
|
||||
datahashes_padded_length: [messagePaddedLen.toString()],
|
||||
eContentBytes: passportData.eContent.map(toUnsignedByte).map(byte => String(byte)),
|
||||
signature: splitToWords(
|
||||
BigInt(bytesToBigDecimal(passportData.encryptedDigest)),
|
||||
BigInt(64),
|
||||
BigInt(32)
|
||||
),
|
||||
signatureAlgorithm: SignatureAlgorithm[sigAlgFormatted].toString(),
|
||||
signatureAlgorithm: [SignatureAlgorithm[sigAlgFormatted].toString()],
|
||||
pubkey: splitToWords(
|
||||
BigInt(passportData.pubKey.modulus as string),
|
||||
BigInt(64),
|
||||
@@ -58,7 +59,7 @@ export function generateCircuitInputs(passportData: PassportData, tree: IMT, rev
|
||||
),
|
||||
pathIndices: proof.pathIndices.map(index => index.toString()),
|
||||
siblings: proof.siblings.flat().map(index => index.toString()),
|
||||
root: tree.root.toString(),
|
||||
address,
|
||||
root: [tree.root.toString()],
|
||||
address: [BigInt(address).toString()],
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,8 @@ export function buildPubkeyTree(pubkeys: any[]) {
|
||||
export function getLeaf(pubkey: any, i?: number): bigint {
|
||||
const sigAlgFormatted = formatSigAlg(pubkey.signatureAlgorithm, pubkey.exponent)
|
||||
|
||||
console.log('pubkey', pubkey)
|
||||
console.log('sigAlgFormatted', sigAlgFormatted)
|
||||
// console.log('pubkey', pubkey)
|
||||
// console.log('sigAlgFormatted', sigAlgFormatted)
|
||||
if (
|
||||
sigAlgFormatted === "sha256WithRSAEncryption_65537"
|
||||
|| sigAlgFormatted === "sha256WithRSAEncryption_3"
|
||||
@@ -46,7 +46,7 @@ export function getLeaf(pubkey: any, i?: number): bigint {
|
||||
// This is because Poseidon circuit only supports an array of 16 elements, and field size is 254.
|
||||
const pubkeyChunked = bigIntToChunkedBytes(BigInt(pubkey.modulus), 192, 11);
|
||||
|
||||
console.log('pubkeyChunked', pubkeyChunked.length, pubkeyChunked)
|
||||
// console.log('pubkeyChunked', pubkeyChunked.length, pubkeyChunked)
|
||||
try {
|
||||
// leaf is poseidon(signatureAlgorithm, ...pubkey)
|
||||
return poseidon12([SignatureAlgorithm[sigAlgFormatted], ...pubkeyChunked])
|
||||
|
||||
@@ -227,7 +227,7 @@ function setFirstBitOfLastByteToZero(bytes: number[]) {
|
||||
}
|
||||
|
||||
// from reverse engineering ark-serialize.
|
||||
export function formatProofIOS(proof: number[]) {
|
||||
export function formatProof(proof: number[]) {
|
||||
const splittedProof = splitInto(proof, 32);
|
||||
splittedProof[1] = setFirstBitOfLastByteToZero(splittedProof[1]);
|
||||
splittedProof[5] = setFirstBitOfLastByteToZero(splittedProof[5]); // We might need to do the same for input 3
|
||||
@@ -244,7 +244,7 @@ export function formatProofIOS(proof: number[]) {
|
||||
}
|
||||
}
|
||||
|
||||
export function formatInputsIOS(inputs: number[]) {
|
||||
export function formatInputs(inputs: number[]) {
|
||||
const splitted = splitInto(inputs.slice(8), 32);
|
||||
return splitted.map(bytesToBigInt);
|
||||
}
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
version "2.0.0-beta.1"
|
||||
resolved "https://gitpkg.now.sh/0xturboblitz/zk-kit/packages/imt?6d417675#38244ea6eef75dc1ad7fff3ff2a22dd5f1a2593a"
|
||||
|
||||
"@zk-kit/imt@https://gitpkg.now.sh/0xturboblitz/zk-kit/packages/imt?b6e7d542":
|
||||
version "2.0.0-beta.1"
|
||||
resolved "https://gitpkg.now.sh/0xturboblitz/zk-kit/packages/imt?b6e7d542#ade4ca8ba82e2a4d54889bcda143c81f82d61580"
|
||||
|
||||
js-sha256@^0.10.1:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.npmjs.org/js-sha256/-/js-sha256-0.10.1.tgz"
|
||||
|
||||
@@ -62,7 +62,7 @@ contract ProofOfPassport is ERC721Enumerable, Ownable {
|
||||
require(verifier.verifyProof(a, b, c, inputs), "Invalid Proof");
|
||||
|
||||
// check that the nullifier has not been used before
|
||||
require(!nullifiers[inputs[3]], "Signature already nullified");
|
||||
// require(!nullifiers[inputs[3]], "Signature already nullified");
|
||||
|
||||
require(registry.checkRoot(bytes32(inputs[4])), "Invalid merkle root");
|
||||
|
||||
|
||||
@@ -37,10 +37,10 @@ contract Groth16Verifier {
|
||||
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
|
||||
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
|
||||
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
||||
uint256 constant deltax1 = 21881528432292977566019709592238441958035597439587625248811386927721538743387;
|
||||
uint256 constant deltax2 = 20551268511319060106899593428979281275843259582154135145932096341124013005361;
|
||||
uint256 constant deltay1 = 9329143266489561710838657298462699054998672654073505912372427475356483812303;
|
||||
uint256 constant deltay2 = 19352538485783629217752598362153226097653095487074817367496965073404835257301;
|
||||
uint256 constant deltax1 = 8610266389851990932549780266586134149581785031836750129783192745835743881162;
|
||||
uint256 constant deltax2 = 11914472050480540824582186361140933264657529413347420273697484031043056638701;
|
||||
uint256 constant deltay1 = 3149799631298024789556297036612837456215403664462538830630241467955634306248;
|
||||
uint256 constant deltay2 = 2165779246565219177630224772189598039109197680240687001378452704570709171641;
|
||||
|
||||
|
||||
uint256 constant IC0x = 11512037801303417937523564708199302858178974650252816846079636241344073874076;
|
||||
|
||||
@@ -20,7 +20,7 @@ const config: HardhatUserConfig = {
|
||||
accounts: [process.env.PKEY as string],
|
||||
},
|
||||
sepolia: {
|
||||
url: "https://rpc.notadegen.com/eth/sepolia",
|
||||
url: "https://eth-sepolia.public.blastapi.io",
|
||||
accounts: [process.env.PKEY as string],
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user