use std::collections::HashMap;
use eddsa_babyjubjub::EdDSASignature;
use groth16_material::circom::ProofInput;
use ruint::aliases::U256;
use world_id_primitives::{
AuthenticatorPublicKeySet, FieldElement, MAX_AUTHENTICATOR_KEYS, merkle::MerkleInclusionProof,
};
type BaseField = ark_babyjubjub::Fq;
type ScalarField = ark_babyjubjub::Fr;
type Affine = ark_babyjubjub::EdwardsAffine;
#[inline]
pub(crate) fn fq_to_u256_vec(f: ark_babyjubjub::Fq) -> Vec<U256> {
vec![f.into()]
}
#[inline]
pub(crate) fn fq_seq_to_u256_vec(fs: &[ark_babyjubjub::Fq]) -> Vec<U256> {
fs.iter().copied().map(Into::into).collect()
}
#[inline]
pub(crate) fn fr_to_u256_vec(f: ark_babyjubjub::Fr) -> Vec<U256> {
vec![f.into()]
}
#[inline]
pub(crate) fn affine_to_u256_vec(p: ark_babyjubjub::EdwardsAffine) -> Vec<U256> {
vec![p.x.into(), p.y.into()]
}
#[inline]
pub(crate) fn affine_seq_to_u256_vec(ps: &[ark_babyjubjub::EdwardsAffine]) -> Vec<U256> {
ps.iter()
.copied()
.flat_map(|p| [p.x.into(), p.y.into()])
.collect()
}
#[derive(Debug, Clone)]
pub struct QueryProofCircuitInput<const MAX_DEPTH: usize> {
pub pk: [Affine; MAX_AUTHENTICATOR_KEYS],
pub pk_index: BaseField,
pub s: ScalarField,
pub r: Affine,
pub merkle_root: BaseField,
pub depth: BaseField,
pub mt_index: BaseField,
pub siblings: [BaseField; MAX_DEPTH],
pub beta: ScalarField,
pub rp_id: BaseField,
pub action: BaseField,
pub nonce: BaseField,
}
impl<const MAX_DEPTH: usize> ProofInput for QueryProofCircuitInput<MAX_DEPTH> {
fn prepare_input(&self) -> HashMap<String, Vec<U256>> {
let mut map = HashMap::new();
map.insert("pk".to_owned(), affine_seq_to_u256_vec(&self.pk));
map.insert("pk_index".to_owned(), fq_to_u256_vec(self.pk_index));
map.insert("s".to_owned(), fr_to_u256_vec(self.s));
map.insert("r".to_owned(), affine_to_u256_vec(self.r));
map.insert("merkle_root".to_owned(), fq_to_u256_vec(self.merkle_root));
map.insert("depth".to_owned(), fq_to_u256_vec(self.depth));
map.insert("mt_index".to_owned(), fq_to_u256_vec(self.mt_index));
map.insert("siblings".to_owned(), fq_seq_to_u256_vec(&self.siblings));
map.insert("beta".to_owned(), fr_to_u256_vec(self.beta));
map.insert("rp_id".to_owned(), fq_to_u256_vec(self.rp_id));
map.insert("action".to_owned(), fq_to_u256_vec(self.action));
map.insert("nonce".to_owned(), fq_to_u256_vec(self.nonce));
map
}
}
#[derive(Debug, Clone)]
pub struct NullifierProofCircuitInput<const MAX_DEPTH: usize> {
pub query_input: QueryProofCircuitInput<MAX_DEPTH>,
pub issuer_schema_id: BaseField,
pub cred_pk: Affine,
pub cred_hashes: [BaseField; 2],
pub cred_genesis_issued_at: BaseField,
pub cred_expires_at: BaseField,
pub cred_s: ScalarField,
pub cred_r: Affine,
pub current_timestamp: BaseField,
pub cred_genesis_issued_at_min: BaseField,
pub cred_sub_blinding_factor: BaseField,
pub cred_id: BaseField,
pub id_commitment_r: BaseField,
pub id_commitment: BaseField,
pub dlog_e: BaseField,
pub dlog_s: ScalarField,
pub oprf_pk: Affine,
pub oprf_response_blinded: Affine,
pub oprf_response: Affine,
pub signal_hash: BaseField,
}
impl<const MAX_DEPTH: usize> ProofInput for NullifierProofCircuitInput<MAX_DEPTH> {
fn prepare_input(&self) -> std::collections::HashMap<String, Vec<ruint::aliases::U256>> {
let mut map = self.query_input.prepare_input();
map.insert(
"issuer_schema_id".to_owned(),
fq_to_u256_vec(self.issuer_schema_id),
);
map.insert("cred_pk".to_owned(), affine_to_u256_vec(self.cred_pk));
map.insert(
"cred_hashes".to_owned(),
fq_seq_to_u256_vec(&self.cred_hashes),
);
map.insert(
"cred_genesis_issued_at".to_owned(),
fq_to_u256_vec(self.cred_genesis_issued_at),
);
map.insert(
"cred_genesis_issued_at_min".to_owned(),
fq_to_u256_vec(self.cred_genesis_issued_at_min),
);
map.insert(
"cred_expires_at".to_owned(),
fq_to_u256_vec(self.cred_expires_at),
);
map.insert("cred_id".to_owned(), fq_to_u256_vec(self.cred_id));
map.insert(
"cred_user_id_r".to_owned(),
fq_to_u256_vec(self.cred_sub_blinding_factor),
);
map.insert("cred_s".to_owned(), fr_to_u256_vec(self.cred_s));
map.insert("cred_r".to_owned(), affine_to_u256_vec(self.cred_r));
map.insert(
"id_commitment_r".to_owned(),
fq_to_u256_vec(self.id_commitment_r),
);
map.insert(
"id_commitment".to_owned(),
fq_to_u256_vec(self.id_commitment),
);
map.insert("dlog_e".to_owned(), fq_to_u256_vec(self.dlog_e));
map.insert("dlog_s".to_owned(), fr_to_u256_vec(self.dlog_s));
map.insert("oprf_pk".to_owned(), affine_to_u256_vec(self.oprf_pk));
map.insert(
"oprf_response_blinded".to_owned(),
affine_to_u256_vec(self.oprf_response_blinded),
);
map.insert(
"oprf_response".to_owned(),
affine_to_u256_vec(self.oprf_response),
);
map.insert("signal_hash".to_owned(), fq_to_u256_vec(self.signal_hash));
map.insert(
"current_timestamp".to_owned(),
fq_to_u256_vec(self.current_timestamp),
);
map
}
}
#[derive(Debug, Clone)]
pub struct OwnershipProofCircuitInput<const MAX_DEPTH: usize> {
pub key_index: u64,
pub key_set: AuthenticatorPublicKeySet,
pub inclusion_proof: MerkleInclusionProof<MAX_DEPTH>,
pub nonce: FieldElement,
pub signature: EdDSASignature,
pub commitment_blinder: FieldElement,
}