mirror of
https://github.com/selfxyz/self.git
synced 2026-02-18 18:14:34 -05:00
support for variable number of datagroups in circuit
This commit is contained in:
@@ -3,9 +3,9 @@ pragma circom 2.1.5;
|
||||
include "circomlib/circuits/bitify.circom";
|
||||
include "circomlib/circuits/sha256/sha256.circom";
|
||||
|
||||
template Sha256Bytes(max_num_bytes) {
|
||||
// Static length sha256 bytes, adapted from zk-email
|
||||
template Sha256BytesStatic(max_num_bytes) {
|
||||
signal input in_padded[max_num_bytes];
|
||||
// signal input in_len_padded_bytes;
|
||||
signal output out[256];
|
||||
|
||||
var num_bits = max_num_bytes * 8;
|
||||
@@ -19,7 +19,6 @@ template Sha256Bytes(max_num_bytes) {
|
||||
sha.in[i*8+j] <== bytes[i].out[7-j];
|
||||
}
|
||||
}
|
||||
// sha.in_len_padded_bits <== in_len_padded_bytes * 8;
|
||||
|
||||
for (var i = 0; i < 256; i++) {
|
||||
out[i] <== sha.out[i];
|
||||
@@ -2,18 +2,20 @@ pragma circom 2.1.5;
|
||||
|
||||
include "@zk-email/circuits/helpers/rsa.circom";
|
||||
include "@zk-email/circuits/helpers/extract.circom";
|
||||
include "./sha256Bytes.circom";
|
||||
include "@zk-email/circuits/helpers/sha.circom";
|
||||
include "./Sha256BytesStatic.circom";
|
||||
|
||||
template PassportVerifier(n, k) {
|
||||
template PassportVerifier(n, k, max_datahashes_bytes) {
|
||||
signal input mrz[93]; // formatted mrz (5 + 88) chars
|
||||
signal input dataHashes[297];
|
||||
signal input dataHashes[max_datahashes_bytes];
|
||||
signal input datahashes_padded_length;
|
||||
signal input eContentBytes[104];
|
||||
|
||||
signal input pubkey[k];
|
||||
signal input signature[k];
|
||||
|
||||
// compute sha256 of formatted mrz
|
||||
signal mrzSha[256] <== Sha256Bytes(93)(mrz);
|
||||
signal mrzSha[256] <== Sha256BytesStatic(93)(mrz);
|
||||
|
||||
// get output of sha256 into bytes to check against dataHashes
|
||||
component sha256_bytes[32];
|
||||
@@ -29,8 +31,8 @@ template PassportVerifier(n, k) {
|
||||
dataHashes[31 + i] === sha256_bytes[i].out;
|
||||
}
|
||||
|
||||
// hash dataHashes
|
||||
signal dataHashesSha[256] <== Sha256Bytes(297)(dataHashes);
|
||||
// hash dataHashes dynamically
|
||||
signal dataHashesSha[256] <== Sha256Bytes(max_datahashes_bytes)(dataHashes, datahashes_padded_length);
|
||||
|
||||
// get output of dataHashes sha256 into bytes to check against eContent
|
||||
component dataHashes_sha256_bytes[32];
|
||||
@@ -47,7 +49,7 @@ template PassportVerifier(n, k) {
|
||||
}
|
||||
|
||||
// hash eContentBytes
|
||||
signal eContentSha[256] <== Sha256Bytes(104)(eContentBytes);
|
||||
signal eContentSha[256] <== Sha256BytesStatic(104)(eContentBytes);
|
||||
|
||||
// get output of eContentBytes sha256 into k chunks of n bits each
|
||||
var msg_len = (256 + n) \ n;
|
||||
|
||||
@@ -4,9 +4,10 @@ include "circomlib/circuits/poseidon.circom";
|
||||
include "@zk-email/circuits/helpers/extract.circom";
|
||||
include "./passport_verifier.circom";
|
||||
|
||||
template ProofOfPassport(n, k) {
|
||||
template ProofOfPassport(n, k, max_datahashes_bytes) {
|
||||
signal input mrz[93]; // formatted mrz (5 + 88) chars
|
||||
signal input dataHashes[297];
|
||||
signal input dataHashes[max_datahashes_bytes];
|
||||
signal input datahashes_padded_length;
|
||||
signal input eContentBytes[104];
|
||||
signal input pubkey[k];
|
||||
signal input signature[k];
|
||||
@@ -15,9 +16,10 @@ template ProofOfPassport(n, k) {
|
||||
signal input address;
|
||||
|
||||
// Verify passport
|
||||
component PV = PassportVerifier(n, k);
|
||||
component PV = PassportVerifier(n, k, max_datahashes_bytes);
|
||||
PV.mrz <== mrz;
|
||||
PV.dataHashes <== dataHashes;
|
||||
PV.datahashes_padded_length <== datahashes_padded_length;
|
||||
PV.eContentBytes <== eContentBytes;
|
||||
PV.pubkey <== pubkey;
|
||||
PV.signature <== signature;
|
||||
@@ -45,7 +47,7 @@ template ProofOfPassport(n, k) {
|
||||
}
|
||||
}
|
||||
|
||||
component main { public [ address ] } = ProofOfPassport(64, 32);
|
||||
component main { public [ address ] } = ProofOfPassport(64, 32, 320);
|
||||
|
||||
// Us:
|
||||
// 11 + 1 + 3 + 1
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
"@types/node": "^20.6.3",
|
||||
"@types/node-forge": "^1.3.5",
|
||||
"@zk-email/circuits": "^3.2.2",
|
||||
"@zk-email/helpers": "^3.1.3",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"circom_tester": "^0.0.20",
|
||||
"circomlib": "^2.0.5",
|
||||
"js-sha256": "^0.10.1",
|
||||
"node-forge": "^1.3.1",
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Record the start time
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
# Check if the first argument is "app-only"
|
||||
if [ "$1" == "app-only" ]; then
|
||||
echo "Building only for the app"
|
||||
@@ -39,4 +42,9 @@ yarn snarkjs zkey export verificationkey build/proof_of_passport_final.zkey buil
|
||||
|
||||
yarn snarkjs zkey export solidityverifier build/proof_of_passport_final.zkey build/Verifier.sol
|
||||
cp build/Verifier.sol ../contracts/contracts/Verifier.sol
|
||||
echo "copied Verifier.sol to contracts"
|
||||
echo "copied Verifier.sol to contracts"
|
||||
|
||||
# Calculate and print the time taken by the whole script
|
||||
END_TIME=$(date +%s)
|
||||
ELAPSED_TIME=$(($END_TIME - $START_TIME))
|
||||
echo "Build completed in $ELAPSED_TIME seconds"
|
||||
@@ -1,12 +1,14 @@
|
||||
import { describe } from 'mocha'
|
||||
import chai, { assert, expect } from 'chai'
|
||||
import chaiAsPromised from 'chai-as-promised'
|
||||
import { hash, toUnsignedByte, arraysAreEqual, bytesToBigDecimal, formatAndConcatenateDataHashes, formatMrz, splitToWords } from '../../common/src/utils/utils'
|
||||
import { hash, toUnsignedByte, arraysAreEqual, bytesToBigDecimal, formatMrz, splitToWords } from '../../common/src/utils/utils'
|
||||
import { groth16 } from 'snarkjs'
|
||||
import { DataHash } from '../../common/src/utils/types'
|
||||
import { getPassportData } from '../../common/src/utils/passportData'
|
||||
import { attributeToPosition } from '../../common/src/constants/constants'
|
||||
import { MAX_DATAHASHES_LEN, attributeToPosition } from '../../common/src/constants/constants'
|
||||
import { sha256Pad } from '@zk-email/helpers'
|
||||
import path from "path";
|
||||
const fs = require('fs');
|
||||
const wasm_tester = require("circom_tester").wasm;
|
||||
|
||||
chai.use(chaiAsPromised)
|
||||
|
||||
@@ -21,13 +23,9 @@ describe('Circuit tests', function () {
|
||||
const passportData = getPassportData();
|
||||
|
||||
const formattedMrz = formatMrz(passportData.mrz);
|
||||
const mrzHash = hash(formatMrz(passportData.mrz));
|
||||
const concatenatedDataHashes = formatAndConcatenateDataHashes(
|
||||
mrzHash,
|
||||
passportData.dataGroupHashes as DataHash[],
|
||||
);
|
||||
|
||||
const concatenatedDataHashesHashDigest = hash(concatenatedDataHashes);
|
||||
|
||||
const concatenatedDataHashesHashDigest = hash(passportData.dataGroupHashes);
|
||||
console.log('concatenatedDataHashesHashDigest', concatenatedDataHashesHashDigest);
|
||||
|
||||
assert(
|
||||
arraysAreEqual(passportData.eContent.slice(72, 72 + 32), concatenatedDataHashesHashDigest),
|
||||
@@ -36,10 +34,16 @@ describe('Circuit tests', function () {
|
||||
|
||||
const reveal_bitmap = Array(88).fill('1');
|
||||
|
||||
const [messagePadded, messagePaddedLen] = sha256Pad(
|
||||
new Uint8Array(passportData.dataGroupHashes),
|
||||
MAX_DATAHASHES_LEN
|
||||
);
|
||||
|
||||
inputs = {
|
||||
mrz: formattedMrz.map(byte => String(byte)),
|
||||
reveal_bitmap: reveal_bitmap.map(byte => String(byte)),
|
||||
dataHashes: concatenatedDataHashes.map(toUnsignedByte).map(byte => String(byte)),
|
||||
dataHashes: Array.from(messagePadded).map((x) => x.toString()),
|
||||
datahashes_padded_length: messagePaddedLen.toString(),
|
||||
eContentBytes: passportData.eContent.map(toUnsignedByte).map(byte => String(byte)),
|
||||
pubkey: splitToWords(
|
||||
BigInt(passportData.pubKey.modulus),
|
||||
@@ -53,7 +57,8 @@ describe('Circuit tests', function () {
|
||||
),
|
||||
address: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // sample address
|
||||
}
|
||||
|
||||
|
||||
console.log('inputs', inputs);
|
||||
})
|
||||
|
||||
describe('Proof', function() {
|
||||
@@ -210,6 +215,19 @@ describe('Circuit tests', function () {
|
||||
|
||||
|
||||
})
|
||||
|
||||
// use these tests with .only to check changes without rebuilding the zkey
|
||||
describe('Circom tester tests', function() {
|
||||
it('should prove and verify with valid inputs', async function () {
|
||||
const circuit = await wasm_tester(
|
||||
path.join(__dirname, `../circuits/proof_of_passport.circom`),
|
||||
{ include: ["node_modules"] },
|
||||
);
|
||||
const w = await circuit.calculateWitness(inputs);
|
||||
await circuit.checkConstraints(w);
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user