Verify Self Protocol identity proofs inside SP1 zkVM.
Takes a Self Protocol Groth16 BN254 proof (passport, local ID etc.), verifies it inside SP1, and extracts identity fields (name, nationality, DOB, issuing state, age threshold) as ABI-encoded public values.
program/ SP1 guest — Groth16 verification + MRZ field extraction
script/ Host scripts — execute, prove, EVM proof, vkey
lib/ Shared ABI types (SelfIdPublicValues)
self2gnark/ Go converter — Self Protocol JSON -> gnark binary format
sp1-verifier-patch/ Patched sp1-verifier with BN254 pairing for RISC-V
self-vkeys/ Self Protocol verification keys
test-data/ Mock passport proof
- Rust + SP1 toolchain (
sp1up) - Go 1.21+
# 1. Convert a Self Protocol proof to gnark binary format
cd self2gnark
go run main.go --proof ../test-data/passport_proof.json
# 2. Execute inside SP1 (no proof generation, just runs the program)
cd ../script
cargo run --release -- --executeExpected output:
groth16_verified: true
attestation_id: 1
surname: DOE
given_name: JOHN
nationality: USA
dob: 041023
older_than: 18
Generate a SP1 proof:
cd script
cargo run --release -- --proveUsing the Succinct prover network:
cp .env.example .env
# set NETWORK_PRIVATE_KEY in .env
cargo run --release -- --prove --networkTEE private proving:
cargo run --release -- --prove --network --privateGenerate a Groth16 or PLONK proof for on-chain verification:
cd script
cargo run --release --bin evm -- --system groth16
cargo run --release --bin evm -- --system plonkGet the program verification key for your contract:
cargo run --release --bin vkeyThe stock sp1-verifier v5.2.4 has a bug in prepare_inputs where public inputs with scalar value 0 (all-zero bytes) cause Fr::from_slice to fail. Self Protocol proofs commonly have zero-valued public signals, so verification panics on valid proofs. The sp1-verifier-patch fixes this by pinning substrate-bn-succinct to 0.6.0-v5.0.0 and explicitly skipping zero-valued inputs in the MSM accumulator (if *i != Fr::zero() { acc + (*b * *i) } else { acc }).
SP1 v6 fixes this natively, but it's still in prerelease and the BN254 precompiles are not yet optimized, Groth16 verification costs ~100M+ cycles instead of ~8M. Once v6 stabilizes, this patch can be dropped.
| ID | Type | Layout |
|---|---|---|
| 1 | E-Passport | 3 packed elements, 93 bytes |
| 2 | EU ID Card | 4 packed elements, 94 bytes |
| 3 | Aadhaar | TODO: converter supports it, SP1 guest layout missing |