world-id-proof 0.13.0

World ID Proof crate
Documentation
/// Identifies one of the ZK artifacts a [`crate::artifacts::ZkArtifactSource`] can provide.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ZkArtifactKind {
    QueryMaterial,
    NullifierMaterial,
    OwnershipProver,
    OwnershipVerifier,
}

impl std::fmt::Display for ZkArtifactKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let name = match self {
            Self::QueryMaterial => "query proof material",
            Self::NullifierMaterial => "nullifier proof material",
            Self::OwnershipProver => "ownership prover",
            Self::OwnershipVerifier => "ownership verifier",
        };
        f.write_str(name)
    }
}

/// Error returned by [`crate::artifacts::ZkArtifactSource`] implementations.
#[derive(Debug, thiserror::Error)]
pub enum ZkArtifactError {
    /// The source is not configured to provide this artifact (e.g. no path was
    /// set on a filesystem source, or a dummy source was used).
    #[error(
        "{kind} is not provided by this ZK artifact source{}",
        fmt_detail(detail)
    )]
    NotProvided {
        kind: ZkArtifactKind,
        /// Optional source-specific hint on how to make the artifact available.
        detail: Option<String>,
    },
    /// The artifact can never be provided on this target/feature combination.
    #[error("{kind} is unavailable: {reason}")]
    Unavailable {
        kind: ZkArtifactKind,
        reason: &'static str,
    },
    /// The artifact exists but its bytes could not be read, parsed, or verified.
    #[error("failed to load {kind}: {message}")]
    Load {
        kind: ZkArtifactKind,
        message: String,
    },
}

impl ZkArtifactError {
    /// The artifact this error refers to.
    #[must_use]
    pub fn kind(&self) -> ZkArtifactKind {
        match self {
            Self::NotProvided { kind, .. }
            | Self::Unavailable { kind, .. }
            | Self::Load { kind, .. } => *kind,
        }
    }

    /// Wraps an underlying load failure, preserving its full error chain in the message.
    pub fn load(kind: ZkArtifactKind, error: impl Into<eyre::Report>) -> Self {
        Self::Load {
            kind,
            message: format!("{:#}", error.into()),
        }
    }
}

fn fmt_detail(detail: &Option<String>) -> String {
    detail
        .as_deref()
        .map(|d| format!(" ({d})"))
        .unwrap_or_default()
}