Skip to main content

world_id_proof/
lib.rs

1#![cfg_attr(not(test), warn(unused_crate_dependencies))]
2
3use eddsa_babyjubjub::EdDSAPrivateKey;
4use groth16_material::Groth16Error;
5
6use world_id_primitives::{
7    AuthenticatorPublicKeySet, TREE_DEPTH, merkle::MerkleInclusionProof,
8    oprf::WorldIdRequestAuthError,
9};
10use zeroize::{Zeroize, ZeroizeOnDrop};
11
12/// Circuit input types for Circom/Groth16 circuits (query, nullifier, ownership proofs).
13pub mod circuit_inputs;
14
15pub mod compress;
16pub use compress::ProofCompression;
17pub(crate) mod oprf_query;
18pub use oprf_query::{FullOprfOutput, OprfEntrypoint};
19
20pub mod proof;
21pub use proof::*;
22
23use provekit_common::{InputMap, InputValue, NoirElement};
24
25use world_id_primitives::FieldElement;
26
27#[cfg(any(feature = "zk-ownership-prove", feature = "zk-ownership-verify"))]
28pub mod ownership_proof;
29
30pub use provekit_common::{NoirProof, WhirR1CSProof};
31
32/// Error type for OPRF operations and proof generation.
33#[derive(Debug, thiserror::Error)]
34pub enum ProofError {
35    /// Authentication error returned by the OPRF nodes (e.g. unknown RP, invalid proof).
36    #[error(transparent)]
37    RequestAuthError(#[from] WorldIdRequestAuthError),
38    /// Non-auth error originating from `oprf_client`.
39    #[error(transparent)]
40    OprfError(taceo_oprf::client::Error),
41    /// Errors originating from proof inputs
42    #[error(transparent)]
43    ProofInputError(#[from] errors::ProofInputError),
44    /// Errors originating from Groth16 proof generation or verification.
45    #[error(transparent)]
46    ZkError(#[from] Groth16Error),
47    /// Error generating a Noir Proof with ProveKit
48    #[error("proof generation error: {0}")]
49    GenerationError(String),
50    /// Error verifying a Noir Proof with ProveKit. This usually means the proof is invalid.
51    #[error("proof verification error: {0}")]
52    Verification(String),
53    /// Catch-all for other internal errors.
54    #[error(transparent)]
55    InternalError(#[from] eyre::Report),
56}
57
58pub trait NoirCircuitInput {
59    fn into_witness(self) -> Result<InputMap, ProofError>;
60}
61
62pub trait NoirRepresentable {
63    fn into_noir_value(self) -> InputValue;
64}
65
66impl NoirRepresentable for FieldElement {
67    fn into_noir_value(self) -> InputValue {
68        InputValue::Field(NoirElement::from_repr(*self))
69    }
70}
71
72impl From<taceo_oprf::client::Error> for ProofError {
73    fn from(err: taceo_oprf::client::Error) -> Self {
74        if let taceo_oprf::client::Error::ThresholdServiceError(ref svc) = err
75            && svc.kind.is_auth()
76        {
77            return Self::RequestAuthError(WorldIdRequestAuthError::from(svc.error_code));
78        }
79        Self::OprfError(err)
80    }
81}
82
83/// Inputs from the Authenticator to generate a nullifier or blinding factor.
84#[derive(Zeroize, ZeroizeOnDrop)]
85pub struct AuthenticatorProofInput {
86    /// The set of all public keys for all the user's authenticators.
87    #[zeroize(skip)]
88    pub key_set: AuthenticatorPublicKeySet,
89    /// Inclusion proof in the World ID Registry.
90    #[zeroize(skip)]
91    pub inclusion_proof: MerkleInclusionProof<TREE_DEPTH>,
92    /// The off-chain signer key for the Authenticator.
93    private_key: EdDSAPrivateKey,
94    /// The index at which the authenticator key is located in the `key_set`.
95    pub key_index: u64,
96}
97
98impl AuthenticatorProofInput {
99    /// Creates a new authenticator proof input.
100    #[must_use]
101    pub const fn new(
102        key_set: AuthenticatorPublicKeySet,
103        inclusion_proof: MerkleInclusionProof<TREE_DEPTH>,
104        private_key: EdDSAPrivateKey,
105        key_index: u64,
106    ) -> Self {
107        Self {
108            key_set,
109            inclusion_proof,
110            private_key,
111            key_index,
112        }
113    }
114}