indy_data_types/anoncreds/
credential.rs

1use std::collections::HashMap;
2
3use zeroize::Zeroize;
4
5use crate::identifiers::cred_def::CredentialDefinitionId;
6use crate::identifiers::rev_reg::RevocationRegistryId;
7use crate::identifiers::schema::SchemaId;
8use crate::{Validatable, ValidationError};
9
10#[derive(Debug)]
11#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
12pub struct Credential {
13    pub schema_id: SchemaId,
14    pub cred_def_id: CredentialDefinitionId,
15    pub rev_reg_id: Option<RevocationRegistryId>,
16    pub values: CredentialValues,
17    pub signature: cl_type!(CredentialSignature),
18    pub signature_correctness_proof: cl_type!(SignatureCorrectnessProof),
19    pub rev_reg: Option<cl_type!(RevocationRegistry)>,
20    pub witness: Option<cl_type!(Witness)>,
21}
22
23#[cfg(any(feature = "cl", feature = "cl_native"))]
24impl Credential {
25    pub fn try_clone(&self) -> Result<Self, crate::ConversionError> {
26        Ok(Self {
27            schema_id: self.schema_id.clone(),
28            cred_def_id: self.cred_def_id.clone(),
29            rev_reg_id: self.rev_reg_id.clone(),
30            values: self.values.clone(),
31            signature: self.signature.try_clone().map_err(|e| e.to_string())?,
32            signature_correctness_proof: self
33                .signature_correctness_proof
34                .try_clone()
35                .map_err(|e| e.to_string())?,
36            rev_reg: self.rev_reg.clone(),
37            witness: self.witness.clone(),
38        })
39    }
40}
41
42impl Credential {
43    pub const QUALIFIABLE_TAGS: [&'static str; 5] = [
44        "issuer_did",
45        "cred_def_id",
46        "schema_id",
47        "schema_issuer_did",
48        "rev_reg_id",
49    ];
50}
51
52impl Validatable for Credential {
53    fn validate(&self) -> Result<(), ValidationError> {
54        self.schema_id.validate()?;
55        self.cred_def_id.validate()?;
56        self.values.validate()?;
57
58        if self.rev_reg_id.is_some() && (self.witness.is_none() || self.rev_reg.is_none()) {
59            return Err("Credential validation failed: `witness` and `rev_reg` must be passed for revocable Credential".into());
60        }
61
62        if self.values.0.is_empty() {
63            return Err("Credential validation failed: `values` is empty".into());
64        }
65
66        Ok(())
67    }
68}
69
70#[derive(Clone, Debug, PartialEq, Eq)]
71#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
72pub struct CredentialInfo {
73    pub referent: String,
74    pub attrs: ShortCredentialValues,
75    pub schema_id: SchemaId,
76    pub cred_def_id: CredentialDefinitionId,
77    pub rev_reg_id: Option<RevocationRegistryId>,
78    pub cred_rev_id: Option<String>,
79}
80
81pub type ShortCredentialValues = HashMap<String, String>;
82
83#[derive(Clone, Debug, Default, PartialEq, Eq)]
84#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
85pub struct CredentialValues(pub HashMap<String, AttributeValues>);
86
87impl Drop for CredentialValues {
88    fn drop(&mut self) {
89        self.zeroize();
90    }
91}
92
93impl Validatable for CredentialValues {
94    fn validate(&self) -> Result<(), ValidationError> {
95        if self.0.is_empty() {
96            return Err("CredentialValues validation failed: empty list has been passed".into());
97        }
98
99        Ok(())
100    }
101}
102
103impl Zeroize for CredentialValues {
104    fn zeroize(&mut self) {
105        for attr in self.0.values_mut() {
106            attr.zeroize();
107        }
108    }
109}
110
111#[derive(Clone, Debug, PartialEq, Eq, Zeroize)]
112#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
113pub struct AttributeValues {
114    pub raw: String,
115    pub encoded: String,
116}