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}