Skip to main content

indy_credx/services/
types.rs

1use std::collections::HashSet;
2
3pub use indy_data_types::{
4    anoncreds::{
5        cred_def::{
6            CredentialDefinition, CredentialDefinitionPrivate, CredentialKeyCorrectnessProof,
7            SignatureType,
8        },
9        cred_offer::CredentialOffer,
10        cred_request::{CredentialRequest, CredentialRequestMetadata},
11        credential::{AttributeValues, Credential, CredentialValues},
12        link_secret::LinkSecret,
13        pres_request::PresentationRequest,
14        presentation::Presentation,
15        rev_reg::{RevocationRegistry, RevocationRegistryDelta},
16        rev_reg_def::{
17            IssuanceType, RegistryType, RevocationRegistryDefinition,
18            RevocationRegistryDefinitionPrivate,
19        },
20        schema::{AttributeNames, Schema},
21    },
22    did::DidValue,
23    invalid, CredentialDefinitionId, RevocationRegistryId, SchemaId, Validatable, ValidationError,
24};
25
26use crate::anoncreds_clsignatures::{RevocationRegistry as CryptoRevocationRegistry, Witness};
27use crate::error::Error;
28use crate::services::helpers::encode_credential_attribute;
29
30#[derive(Debug, Default, Clone, Serialize, Deserialize)]
31pub struct CredentialDefinitionConfig {
32    pub support_revocation: bool,
33}
34
35impl CredentialDefinitionConfig {
36    pub fn new(support_revocation: bool) -> Self {
37        Self { support_revocation }
38    }
39}
40
41impl Validatable for CredentialDefinitionConfig {}
42
43#[derive(Debug, Default)]
44pub struct MakeCredentialValues(pub(crate) CredentialValues);
45
46impl MakeCredentialValues {
47    pub fn add_encoded(
48        &mut self,
49        name: impl Into<String>,
50        raw: impl Into<String>,
51        encoded: String,
52    ) {
53        self.0 .0.insert(
54            name.into(),
55            AttributeValues {
56                raw: raw.into(),
57                encoded,
58            },
59        );
60    }
61
62    pub fn add_raw(
63        &mut self,
64        name: impl Into<String>,
65        raw: impl Into<String>,
66    ) -> Result<(), Error> {
67        let raw = raw.into();
68        let encoded = encode_credential_attribute(&raw)?;
69        self.0
70             .0
71            .insert(name.into(), AttributeValues { raw, encoded });
72        Ok(())
73    }
74}
75
76impl From<MakeCredentialValues> for CredentialValues {
77    fn from(val: MakeCredentialValues) -> CredentialValues {
78        val.0
79    }
80}
81
82#[derive(Debug, Default)]
83pub struct PresentCredentials<'p>(pub(crate) Vec<PresentCredential<'p>>);
84
85impl<'p> PresentCredentials<'p> {
86    #[inline]
87    pub fn new() -> Self {
88        Self::default()
89    }
90
91    pub fn add_credential(
92        &mut self,
93        cred: &'p Credential,
94        timestamp: Option<u64>,
95        rev_state: Option<&'p CredentialRevocationState>,
96    ) -> AddCredential<'_, 'p> {
97        let idx = self.0.len();
98        self.0.push(PresentCredential {
99            cred,
100            timestamp,
101            rev_state,
102            requested_attributes: HashSet::new(),
103            requested_predicates: HashSet::new(),
104        });
105        AddCredential {
106            present: &mut self.0[idx],
107        }
108    }
109
110    pub fn is_empty(&self) -> bool {
111        self.len() == 0
112    }
113
114    pub fn len(&self) -> usize {
115        self.0.iter().filter(|c| !c.is_empty()).count()
116    }
117}
118
119impl Validatable for PresentCredentials<'_> {
120    fn validate(&self) -> std::result::Result<(), ValidationError> {
121        let mut attr_names = HashSet::new();
122        let mut pred_names = HashSet::new();
123
124        for c in self.0.iter() {
125            for (name, _reveal) in c.requested_attributes.iter() {
126                if !attr_names.insert(name.as_str()) {
127                    return Err(invalid!("Duplicate requested attribute referent: {}", name));
128                }
129            }
130
131            for name in c.requested_predicates.iter() {
132                if !pred_names.insert(name.as_str()) {
133                    return Err(invalid!("Duplicate requested predicate referent: {}", name));
134                }
135            }
136
137            if c.timestamp.is_some() != c.rev_state.is_some() {
138                return Err(invalid!(
139                    "Either timestamp and revocation state must be presented, or neither"
140                ));
141            }
142        }
143
144        Ok(())
145    }
146}
147
148#[derive(Debug)]
149pub(crate) struct PresentCredential<'p> {
150    pub cred: &'p Credential,
151    pub timestamp: Option<u64>,
152    pub rev_state: Option<&'p CredentialRevocationState>,
153    pub requested_attributes: HashSet<(String, bool)>,
154    pub requested_predicates: HashSet<String>,
155}
156
157impl PresentCredential<'_> {
158    #[inline]
159    pub fn is_empty(&self) -> bool {
160        self.requested_attributes.is_empty() && self.requested_predicates.is_empty()
161    }
162}
163
164#[derive(Debug)]
165pub struct AddCredential<'a, 'p> {
166    present: &'a mut PresentCredential<'p>,
167}
168
169impl<'a, 'p> AddCredential<'a, 'p> {
170    pub fn add_requested_attribute(&mut self, referent: impl Into<String>, revealed: bool) {
171        self.present
172            .requested_attributes
173            .insert((referent.into(), revealed));
174    }
175
176    pub fn add_requested_predicate(&mut self, referent: impl Into<String>) {
177        self.present.requested_predicates.insert(referent.into());
178    }
179}
180
181#[derive(Clone, Debug, PartialEq, Eq, Hash)]
182pub(crate) struct ProvingCredentialKey {
183    pub cred_id: String,
184    pub timestamp: Option<u64>,
185}
186
187#[derive(Clone, Debug, Serialize, Deserialize)]
188pub struct CredentialRevocationState {
189    pub witness: Witness,
190    pub(crate) rev_reg: CryptoRevocationRegistry,
191    pub(crate) timestamp: u64,
192}
193
194impl Validatable for CredentialRevocationState {
195    fn validate(&self) -> std::result::Result<(), ValidationError> {
196        if self.timestamp == 0 {
197            return Err(invalid!(
198                "Credential Revocation State validation failed: `timestamp` must be greater than 0",
199            ));
200        }
201        Ok(())
202    }
203}
204
205pub struct CredentialRevocationConfig<'a> {
206    pub reg_def: &'a RevocationRegistryDefinition,
207    pub reg_def_private: &'a RevocationRegistryDefinitionPrivate,
208    pub registry: &'a RevocationRegistry,
209    pub registry_idx: u32,
210    pub registry_used: &'a HashSet<u32>,
211}
212
213impl<'a> std::fmt::Debug for CredentialRevocationConfig<'a> {
214    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215        write!(
216            f,
217            "CredentialRevocationConfig {{ reg_def: {:?}, private: {:?}, registry: {:?}, idx: {} }}",
218            self.reg_def,
219            secret!(self.reg_def_private),
220            self.registry,
221            secret!(self.registry_idx),
222        )
223    }
224}