Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Fix/test refactor prepare flow #213

Closed
wants to merge 13 commits into from
30 changes: 16 additions & 14 deletions circuits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,19 @@ yarn test

This will run tests with sample data generated on the fly.


## OpenPassport Prove circuit

OpenPassport Prove is the main circuit of the project.
It is used for these 3 different `circuit modes`:

- prove offChain
- prove onChain
- register

Learn more on these 3 use cases on [OpenPassport documentation.](https://docs.openpassport.app/docs/use-openpassport/quickstart)

The circuit achieves the following actions:

- verify the signature of the passport and the integrity of the datagroups
- disclose attributes
- verify that user's name is not part of the OFAC list
Expand All @@ -93,23 +95,21 @@ If this "everything circuit" is executing all those actions each time, we want a

In order to achieve that we will input a bitmap `selector_mode[2]` that will ensure that the circuit can only disclose the attributes related to the `circuit mode` selected.

| Circuit Mode | selector_mode[0] | selector_mode[1] |
| --- | --- | --- |
| prove offChain | 1 | 1 |
| prove onChain | 1 | 0 |
| register | 0 | 0 |
| Circuit Mode | selector_mode[0] | selector_mode[1] |
| -------------- | ---------------- | ---------------- |
| prove offChain | 1 | 1 |
| prove onChain | 1 | 0 |
| register | 0 | 0 |

Using the value [0,1] for `selector_mode` will fail proof generation.


Here are the attributes disclosed according to the `circuit_mode`:

| Circuit Mode | Attributes Disclosed |
| --- | --- |
| prove offChain | packedReveal-dg1, older than, OFAC, countryIsNotInList, pubKey |
| prove onChain | packedReveal-dg1, older than, OFAC, countryIsNotInList, blinded DSC commitment |
| register | blinded DSC commitment, commitment |

| Circuit Mode | Attributes Disclosed |
| -------------- | ------------------------------------------------------------------------------ |
| prove offChain | packedReveal-dg1, older than, OFAC, countryIsNotInList, pubKey |
| prove onChain | packedReveal-dg1, older than, OFAC, countryIsNotInList, blinded DSC commitment |
| register | blinded DSC commitment, commitment |

## Certificate Chain verification

Expand All @@ -119,7 +119,9 @@ Both DSC and CSCA lists are published on online registry of the ICAO, however ma
In order to maximize passport readability we need to verify the full certificate chain.

### On chain

To avoid huge proving time and (too) heavy zkeys, the signature of the passport data is verified on the mobile (the passport data never leaves the device) and the certificate chain verification is done on a remote modal server. A `blindedDscCommitment` is generated on both sides to link proofs.

### Off chain
In off chain setup users will send their DSC to the verifier along with their passport proof. The pubKey will be revealed as an output of the proof.

In off chain setup users will send their DSC to the verifier along with their passport proof. The pubKey will be revealed as an output of the proof.
51 changes: 51 additions & 0 deletions circuits/scripts/build_disclose_circuit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash

source "scripts/download_ptau.sh"

build_circuit() {
local CIRCUIT_NAME=$1
local CIRCUIT_TYPE=$2
local START_TIME=$(date +%s)

echo "compiling circuit: $CIRCUIT_NAME"
circom circuits/${CIRCUIT_TYPE}/${CIRCUIT_NAME}.circom -l node_modules -l ./node_modules/@zk-kit/binary-merkle-root.circom/src -l ./node_modules/circomlib/circuits/ --r1cs --O1 --wasm -c --output build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/

echo "building zkey"
yarn snarkjs groth16 setup build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/${CIRCUIT_NAME}.r1cs build/powersOfTau28_hez_final_20.ptau build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/${CIRCUIT_NAME}.zkey

echo "building vkey"
yarn snarkjs zkey contribute build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/${CIRCUIT_NAME}.zkey build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey -e="random text"
yarn snarkjs zkey export verificationkey build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/${CIRCUIT_NAME}_vkey.json

yarn snarkjs zkey export solidityverifier build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey build/${CIRCUIT_TYPE}/Verifier_${CIRCUIT_NAME}.sol
sed -i '' "s/Groth16Verifier/Verifier_${CIRCUIT_NAME}/g" build/${CIRCUIT_TYPE}/Verifier_${CIRCUIT_NAME}.sol
cp build/${CIRCUIT_TYPE}/${CIRCUIT_NAME}/Verifier_${CIRCUIT_NAME}.sol ../contracts/contracts/verifiers//${CIRCUIT_TYPE}/Verifier_${CIRCUIT_NAME}.sol
echo "copied Verifier_${CIRCUIT_NAME}.sol to contracts"

echo "Build of $CIRCUIT_NAME completed in $(($(date +%s) - START_TIME)) seconds"
echo "Size of ${CIRCUIT_NAME}.r1cs: $(wc -c <build/${CIRCUIT_NAME}.r1cs) bytes"
echo "Size of ${CIRCUIT_NAME}.wasm: $(wc -c <build/${CIRCUIT_NAME}_js/${CIRCUIT_NAME}.wasm) bytes"
echo "Size of ${CIRCUIT_NAME}_final.zkey: $(wc -c <build/${CIRCUIT_NAME}_final.zkey) bytes"
}

# Define circuits and their types
# name:folder:build_flag
# set build_flag to false if you want to skip the build
CIRCUITS=(
"vc_and_disclose:disclose:20:true"
"disclose:disclose:20:false"
"proveCountryIsNotInList:disclose:20:false"
"verify_commitment:disclose:22:false"
)

TOTAL_START_TIME=$(date +%s)
for circuit in "${CIRCUITS[@]}"; do
IFS=':' read -r CIRCUIT_NAME CIRCUIT_TYPE POWEROFTAU BUILD_FLAG <<< "$circuit"
if [ "$BUILD_FLAG" = "true" ]; then
echo "Debug: Building circuit $CIRCUIT_NAME of type $CIRCUIT_TYPE"
build_circuit "$CIRCUIT_NAME" "$CIRCUIT_TYPE"
else
echo "Skipping build for $CIRCUIT_NAME"
fi
done
echo "Total completed in $(($(date +%s) - TOTAL_START_TIME)) seconds"
21 changes: 11 additions & 10 deletions circuits/scripts/build_dsc_2048_circuits.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ build_circuit() {
local START_TIME=$(date +%s)

echo -e "\033[34mcompiling circuit: $CIRCUIT_NAME\033[0m"
circom circuits/tests/dsc/${CIRCUIT_NAME}.circom -l node_modules -l ./node_modules/@zk-kit/binary-merkle-root.circom/src -l ./node_modules/circomlib/circuits --r1cs --O1 --wasm -c --output build
mkdir -p ./build/dsc/${CIRCUIT_NAME}/
circom circuits/dsc/instances/${CIRCUIT_NAME}.circom -l node_modules -l ./node_modules/@zk-kit/binary-merkle-root.circom/src -l ./node_modules/circomlib/circuits --r1cs --O1 --wasm -c --output build/dsc/${CIRCUIT_NAME}/

echo -e "\033[34mbuilding zkey\033[0m"
yarn snarkjs groth16 setup build/${CIRCUIT_NAME}.r1cs build/powersOfTau28_hez_final_20.ptau build/${CIRCUIT_NAME}.zkey
yarn snarkjs groth16 setup build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}.r1cs build/powersOfTau28_hez_final_20.ptau build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}.zkey

if command -v openssl &> /dev/null
then
Expand All @@ -32,12 +33,12 @@ build_circuit() {
fi

echo -e "\033[34mbuilding vkey\033[0m"
echo $RAND_STR | yarn snarkjs zkey contribute build/${CIRCUIT_NAME}.zkey build/${CIRCUIT_NAME}_final.zkey
yarn snarkjs zkey export verificationkey build/${CIRCUIT_NAME}_final.zkey build/${CIRCUIT_NAME}_vkey.json
echo $RAND_STR | yarn snarkjs zkey contribute build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}.zkey build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey
yarn snarkjs zkey export verificationkey build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}_vkey.json

yarn snarkjs zkey export solidityverifier build/${CIRCUIT_NAME}_final.zkey build/Verifier_${CIRCUIT_NAME}.sol
sed -i '' "s/Groth16Verifier/Verifier_${CIRCUIT_NAME}/g" build/Verifier_${CIRCUIT_NAME}.sol
cp build/Verifier_${CIRCUIT_NAME}.sol ../contracts/contracts/Verifier_${CIRCUIT_NAME}.sol
yarn snarkjs zkey export solidityverifier build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey build/dsc/Verifier_${CIRCUIT_NAME}.sol
sed -i '' "s/Groth16Verifier/Verifier_${CIRCUIT_NAME}/g" build/dsc/Verifier_${CIRCUIT_NAME}.sol
cp build/dsc/Verifier_${CIRCUIT_NAME}.sol ../contracts/contracts/dsc/Verifier_${CIRCUIT_NAME}.sol
echo -e "\033[34mcopied Verifier_${CIRCUIT_NAME}.sol to contracts\033[0m"

echo -e "\033[32mBuild of $CIRCUIT_NAME completed in $(($(date +%s) - START_TIME)) seconds\033[0m"
Expand All @@ -51,9 +52,9 @@ build_circuit() {
# Define circuits and their deployment flags
# name:deploy_flag
CIRCUITS=(
"dsc_sha256_rsapss_2048:true"
"dsc_sha256_rsa_2048:true"
"dsc_sha1_rsa_2048:true"
"dsc_rsapss_65537_sha256_2048:true"
"dsc_rsa_65537_sha256_2048:true"
"dsc_rsa_65537_sha1_2048:true"
)

for circuit in "${CIRCUITS[@]}"; do
Expand Down
15 changes: 8 additions & 7 deletions circuits/scripts/build_dsc_4096_circuits.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ build_circuit() {
local START_TIME=$(date +%s)

echo -e "\033[34mcompiling circuit: $CIRCUIT_NAME\033[0m"
circom circuits/dsc/instances/${CIRCUIT_NAME}.circom -l node_modules -l ./node_modules/@zk-kit/binary-merkle-root.circom/src -l ./node_modules/circomlib/circuits --r1cs --O1 --wasm -c --output build
mkdir -p ./build/dsc/${CIRCUIT_NAME}/
circom circuits/dsc/instances/${CIRCUIT_NAME}.circom -l node_modules -l ./node_modules/@zk-kit/binary-merkle-root.circom/src -l ./node_modules/circomlib/circuits --r1cs --O1 --wasm -c --output build/dsc/${CIRCUIT_NAME}/

echo -e "\033[34mbuilding zkey\033[0m"
NODE_OPTIONS="--max-old-space-size=8192" yarn snarkjs groth16 setup build/${CIRCUIT_NAME}.r1cs build/powersOfTau28_hez_final_22.ptau build/${CIRCUIT_NAME}.zkey
NODE_OPTIONS="--max-old-space-size=8192" yarn snarkjs groth16 setup build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}.r1cs build/powersOfTau28_hez_final_22.ptau build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}.zkey

if command -v openssl &> /dev/null
then
Expand All @@ -32,12 +33,12 @@ build_circuit() {
fi

echo -e "\033[34mbuilding vkey\033[0m"
echo $RAND_STR | yarn snarkjs zkey contribute build/${CIRCUIT_NAME}.zkey build/${CIRCUIT_NAME}_final.zkey
yarn snarkjs zkey export verificationkey build/${CIRCUIT_NAME}_final.zkey build/${CIRCUIT_NAME}_vkey.json
echo $RAND_STR | yarn snarkjs zkey contribute build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}.zkey build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey
yarn snarkjs zkey export verificationkey build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}_vkey.json

yarn snarkjs zkey export solidityverifier build/${CIRCUIT_NAME}_final.zkey build/Verifier_${CIRCUIT_NAME}.sol
sed -i '' "s/Groth16Verifier/Verifier_${CIRCUIT_NAME}/g" build/Verifier_${CIRCUIT_NAME}.sol
cp build/Verifier_${CIRCUIT_NAME}.sol ../contracts/contracts/Verifier_${CIRCUIT_NAME}.sol
yarn snarkjs zkey export solidityverifier build/dsc/${CIRCUIT_NAME}/${CIRCUIT_NAME}_final.zkey build/dsc/Verifier_${CIRCUIT_NAME}.sol
sed -i '' "s/Groth16Verifier/Verifier_${CIRCUIT_NAME}/g" build/dsc/Verifier_${CIRCUIT_NAME}.sol
cp build/dsc/Verifier_${CIRCUIT_NAME}.sol ../contracts/contracts/dsc/Verifier_${CIRCUIT_NAME}.sol
echo -e "\033[34mcopied Verifier_${CIRCUIT_NAME}.sol to contracts\033[0m"

echo -e "\033[32mBuild of $CIRCUIT_NAME completed in $(($(date +%s) - START_TIME)) seconds\033[0m"
Expand Down
22 changes: 20 additions & 2 deletions common/src/utils/generateInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export function generateCircuitInputsDisclose(
selector_dg1: string[],
selector_older_than: string,
scope: string,
user_identifier: string
user_identifier: string,
user_identifier_type: 'uuid' | 'hex' | 'ascii' = DEFAULT_USER_ID_TYPE
) {

const pubkey_leaf = getLeaf(passportData.dsc);
Expand Down Expand Up @@ -71,7 +72,7 @@ export function generateCircuitInputsDisclose(
scope: [castFromScope(scope)],
current_date: getCurrentDateYYMMDD().map(datePart => BigInt(datePart).toString()),
majority: majority.split('').map(char => BigInt(char.charCodeAt(0)).toString()),
user_identifier: [castFromUUID(user_identifier)],
user_identifier: [formatInput(parseUIDToBigInt(user_identifier, user_identifier_type))],
};
}

Expand Down Expand Up @@ -258,3 +259,20 @@ export function formatInput(input: any) {
return [BigInt(input).toString()];
}
}

export function generatePassportMerkleTreeWithCommitment(
secret: string,
attestation_id: string,
passportData: PassportData,
pubkeyTreeDepth: number
): LeanIMT<bigint> {
const pubkey_leaf = getLeaf(passportData.dsc);
const fomatterMrz = formatMrz(passportData.mrz);
const mrz_bytes = packBytes(fomatterMrz);

const commitment = generateCommitment(secret, attestation_id, pubkey_leaf, mrz_bytes, passportData.dg2Hash);

const merkletree = new LeanIMT<bigint>((a, b) => poseidon2([a, b]), [BigInt(pubkeyTreeDepth)]);
merkletree.insert(commitment);
return merkletree;
}
13 changes: 13 additions & 0 deletions common/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,16 @@ export function castCSCAProof(proof: any): Proof {
}
}

export type SBTProof = {
nullifier: string,
revealedData_packed: string[],
older_than: string[],
attestation_id: string,
merkle_root: string,
scope: string,
current_date: number[] | string[],
user_identifier: string,
a: [string, string],
b: [[string, string], [string, string]],
c: [string, string]
}
10 changes: 6 additions & 4 deletions contracts/contracts/SBT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ pragma solidity ^0.8.18;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import {Verifier_disclose} from "./Verifier_disclose.sol";
import {Verifier_vc_and_disclose} from "./verifiers/disclose/Verifier_vc_and_disclose.sol";
import {Base64} from "./libraries/Base64.sol";
import {Formatter} from "./Formatter.sol";
import {Registry} from "./Registry.sol";
import {IRegister} from "./interfaces/IRegister.sol";
import "hardhat/console.sol";

contract SBT is ERC721Enumerable, Ownable {
using Strings for uint256;
using Base64 for *;

Verifier_disclose public immutable verifier;
Verifier_vc_and_disclose public immutable verifier;
Formatter public formatter;
IRegister public register;

Expand All @@ -26,6 +25,7 @@ contract SBT is ERC721Enumerable, Ownable {
struct SBTProof {
uint nullifier;
uint[3] revealedData_packed;
uint[2] older_than;
uint attestation_id;
uint merkle_root;
uint scope;
Expand All @@ -52,7 +52,7 @@ contract SBT is ERC721Enumerable, Ownable {
mapping(uint256 => Attributes) private tokenAttributes;

constructor(
Verifier_disclose v,
Verifier_vc_and_disclose v,
Formatter f,
IRegister r
) ERC721("OpenPassport", "OpenPassport") {
Expand Down Expand Up @@ -108,6 +108,8 @@ contract SBT is ERC721Enumerable, Ownable {
uint(proof.revealedData_packed[0]),
uint(proof.revealedData_packed[1]),
uint(proof.revealedData_packed[2]),
uint(proof.older_than[0]),
uint(proof.older_than[1]),
uint(proof.attestation_id),
uint(proof.merkle_root),
uint(proof.scope),
Expand Down
Loading
Loading