From 1112011dc22fc578834de4d5e3185161e38275f0 Mon Sep 17 00:00:00 2001 From: Bogdan Mircea Date: Tue, 15 Aug 2023 16:36:38 +0300 Subject: [PATCH 1/7] Simplified TailsFileReader Signed-off-by: Bogdan Mircea --- src/error.rs | 6 +++ src/services/prover.rs | 2 +- src/services/tails.rs | 106 ++++++++++------------------------------- 3 files changed, 31 insertions(+), 83 deletions(-) diff --git a/src/error.rs b/src/error.rs index 12141a3f..46c4af54 100644 --- a/src/error.rs +++ b/src/error.rs @@ -140,6 +140,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: std::cell::BorrowMutError) -> Self { + Self::from(ErrorKind::IOError).with_cause(err) + } +} + impl From for Error { fn from(err: serde_json::Error) -> Self { // FIXME could be input or output... diff --git a/src/services/prover.rs b/src/services/prover.rs index bde5467a..79affe6e 100644 --- a/src/services/prover.rs +++ b/src/services/prover.rs @@ -665,7 +665,7 @@ pub fn create_or_update_revocation_state( let mut issued = HashSet::::new(); let mut revoked = HashSet::::new(); - let tails_reader = TailsFileReader::new(tails_path); + let tails_reader = TailsFileReader::new(tails_path)?; let witness = if let (Some(source_rev_state), Some(source_rev_list)) = (rev_state, old_rev_status_list) { diff --git a/src/services/tails.rs b/src/services/tails.rs index ca9cf209..2b2d5d06 100644 --- a/src/services/tails.rs +++ b/src/services/tails.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; use std::fmt::Debug; use std::fs::File; -use std::io::{BufRead, BufReader, BufWriter, Read, Seek, SeekFrom, Write}; +use std::io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write}; use std::path::{Path, PathBuf}; use rand::random; @@ -18,24 +18,32 @@ const TAILS_BLOB_TAG_SZ: u8 = 2; const TAIL_SIZE: usize = Tail::BYTES_REPR_SIZE; #[derive(Debug)] -pub struct TailsReader { - inner: Box>, +pub struct TailsFileReader { + file: RefCell>, } -impl TailsReader { - pub(crate) fn new(inner: TR) -> Self { - Self { - inner: Box::new(RefCell::new(inner)), - } +impl TailsFileReader { + pub fn new

(path: P) -> Result + where + P: AsRef, + { + let file = RefCell::new(BufReader::new(File::open(path)?)); + let reader = Self { file }; + Ok(reader) } -} -pub trait TailsReaderImpl: Debug + Send { - fn hash(&mut self) -> Result, Error>; - fn read(&mut self, size: usize, offset: usize) -> Result, Error>; + fn read(&self, size: usize, offset: usize) -> Result, Error> { + let mut buf = vec![0u8; size]; + + let mut file = self.file.try_borrow_mut()?; + file.seek(SeekFrom::Start(offset as u64))?; + file.read_exact(buf.as_mut_slice())?; + + Ok(buf) + } } -impl RevocationTailsAccessor for TailsReader { +impl RevocationTailsAccessor for TailsFileReader { fn access_tail( &self, tail_id: u32, @@ -44,8 +52,6 @@ impl RevocationTailsAccessor for TailsReader { trace!("access_tail >>> tail_id: {:?}", tail_id); let tail_bytes = self - .inner - .borrow_mut() .read( TAIL_SIZE, TAIL_SIZE * tail_id as usize + TAILS_BLOB_TAG_SZ as usize, @@ -63,70 +69,6 @@ impl RevocationTailsAccessor for TailsReader { } } -#[derive(Debug)] -pub struct TailsFileReader { - path: String, - file: Option>, - hash: Option>, -} - -impl TailsFileReader { - pub fn new(path: &str) -> TailsReader { - TailsReader::new(Self { - path: path.to_owned(), - file: None, - hash: None, - }) - } - - pub fn open(&mut self) -> Result<&mut BufReader, Error> { - if self.file.is_none() { - let file = File::open(self.path.clone())?; - self.file.replace(BufReader::new(file)); - } - Ok(self.file.as_mut().unwrap()) - } - - pub fn close(&mut self) { - self.file.take(); - } -} - -impl TailsReaderImpl for TailsFileReader { - fn hash(&mut self) -> Result, Error> { - if let Some(hash) = self.hash.as_ref() { - return Ok(hash.clone()); - } - - let file = self.open()?; - file.seek(SeekFrom::Start(0))?; - let mut hasher = Sha256::default(); - - loop { - let buf = file.fill_buf()?; - let len = buf.len(); - if len == 0 { - break; - } - hasher.update(&buf); - file.consume(len); - } - let hash = hasher.finalize().to_vec(); - self.hash.replace(hash.clone()); - Ok(hash) - } - - fn read(&mut self, size: usize, offset: usize) -> Result, Error> { - let mut buf = vec![0u8; size]; - - let file = self.open()?; - file.seek(SeekFrom::Start(offset as u64))?; - file.read_exact(buf.as_mut_slice())?; - - Ok(buf) - } -} - pub trait TailsWriter: std::fmt::Debug { fn write( &mut self, @@ -182,17 +124,17 @@ impl TailsWriter for TailsFileWriter { let mut buf = BufWriter::new(file); let mut hasher = Sha256::default(); let version = &[0u8, 2u8]; - buf.write(version)?; + buf.write_all(version)?; hasher.update(version); while let Some(tail) = generator.try_next()? { let tail_bytes = tail.to_bytes()?; - buf.write(&tail_bytes)?; + buf.write_all(&tail_bytes)?; hasher.update(&tail_bytes); } let mut file = buf .into_inner() .map_err(|e| err_msg!("Error flushing output file: {e}"))?; - let tails_size = file.seek(SeekFrom::Current(0))?; + let tails_size = file.stream_position()?; let hash = base58::encode(hasher.finalize()); let target_path = self.root_path.join(&hash); drop(file); From ac2854048e2bcc2606c3a69a0d19455d0a15177a Mon Sep 17 00:00:00 2001 From: Bogdan Mircea Date: Tue, 15 Aug 2023 18:41:46 +0300 Subject: [PATCH 2/7] Introduced ReferencesMap trait and tweaked function signatures Signed-off-by: Bogdan Mircea --- src/services/prover.rs | 19 +++--- src/services/verifier.rs | 59 ++++++++++------- src/utils/map.rs | 133 +++++++++++++++++++++++++++++++++++++++ src/utils/mod.rs | 2 + tests/anoncreds_demos.rs | 25 ++++---- 5 files changed, 196 insertions(+), 42 deletions(-) create mode 100644 src/utils/map.rs diff --git a/src/services/prover.rs b/src/services/prover.rs index 79affe6e..b03adbf1 100644 --- a/src/services/prover.rs +++ b/src/services/prover.rs @@ -27,6 +27,7 @@ use crate::services::helpers::{ get_revealed_attributes_for_credential, new_nonce, }; use crate::types::{CredentialRevocationState, PresentCredentials}; +use crate::utils::map::ReferencesMap; use crate::utils::validation::Validatable; use bitvec::bitvec; use std::collections::{HashMap, HashSet}; @@ -398,14 +399,18 @@ pub fn process_credential( /// &cred_defs /// ).expect("Unable to create presentation"); /// ``` -pub fn create_presentation( +pub fn create_presentation( pres_req: &PresentationRequest, credentials: PresentCredentials, self_attested: Option>, link_secret: &LinkSecret, - schemas: &HashMap<&SchemaId, &Schema>, - cred_defs: &HashMap<&CredentialDefinitionId, &CredentialDefinition>, -) -> Result { + schemas: &T, + cred_defs: &U, +) -> Result +where + T: ReferencesMap + std::fmt::Debug, + U: ReferencesMap + std::fmt::Debug, +{ trace!("create_proof >>> credentials: {:?}, pres_req: {:?}, credentials: {:?}, self_attested: {:?}, link_secret: {:?}, schemas: {:?}, cred_defs: {:?}", credentials, pres_req, credentials, &self_attested, secret!(&link_secret), schemas, cred_defs); @@ -436,12 +441,12 @@ pub fn create_presentation( } let credential = present.cred; - let schema = *schemas - .get(&credential.schema_id) + let schema = schemas + .get_ref(&credential.schema_id) .ok_or_else(|| err_msg!("Schema not provided for ID: {}", credential.schema_id))?; let cred_def_id = CredentialDefinitionId::new(credential.cred_def_id.clone())?; - let cred_def = *cred_defs.get(&cred_def_id).ok_or_else(|| { + let cred_def = cred_defs.get_ref(&cred_def_id).ok_or_else(|| { err_msg!( "Credential Definition not provided for ID: {}", credential.cred_def_id diff --git a/src/services/verifier.rs b/src/services/verifier.rs index bff6def7..6c4f9296 100644 --- a/src/services/verifier.rs +++ b/src/services/verifier.rs @@ -22,6 +22,7 @@ use crate::services::helpers::build_non_credential_schema; use crate::services::helpers::build_sub_proof_request; use crate::services::helpers::get_predicates_for_credential; use crate::services::helpers::get_revealed_attributes_for_credential; +use crate::utils::map::ReferencesMap; use crate::utils::query::Query; use crate::utils::validation::LEGACY_DID_IDENTIFIER; @@ -43,17 +44,22 @@ static INTERNAL_TAG_MATCHER: Lazy = Lazy::new(|| Regex::new("^attr::([^:]+)::(value|marker)$").unwrap()); /// Verify an incoming proof presentation -pub fn verify_presentation( +pub fn verify_presentation( presentation: &Presentation, pres_req: &PresentationRequest, - schemas: &HashMap<&SchemaId, &Schema>, - cred_defs: &HashMap<&CredentialDefinitionId, &CredentialDefinition>, - rev_reg_defs: Option<&HashMap<&RevocationRegistryDefinitionId, &RevocationRegistryDefinition>>, + schemas: &T, + cred_defs: &U, + rev_reg_defs: Option<&V>, rev_status_lists: Option>, - nonrevoke_interval_override: Option< - &HashMap<&RevocationRegistryDefinitionId, HashMap>, - >, -) -> Result { + nonrevoke_interval_override: Option<&Z>, +) -> Result +where + T: ReferencesMap + std::fmt::Debug, + U: ReferencesMap + std::fmt::Debug, + V: ReferencesMap + + std::fmt::Debug, + Z: ReferencesMap> + std::fmt::Debug, +{ trace!("verify >>> presentation: {:?}, pres_req: {:?}, schemas: {:?}, cred_defs: {:?}, rev_reg_defs: {:?} rev_status_lists: {:?}", presentation, pres_req, schemas, cred_defs, rev_reg_defs, rev_status_lists); @@ -98,11 +104,11 @@ pub fn verify_presentation( let identifier = presentation.identifiers[sub_proof_index].clone(); let schema = schemas - .get(&identifier.schema_id) + .get_ref(&identifier.schema_id) .ok_or_else(|| err_msg!("Schema not provided for ID: {:?}", identifier.schema_id))?; let cred_def_id = CredentialDefinitionId::new(identifier.cred_def_id.clone())?; - let cred_def = cred_defs.get(&cred_def_id).ok_or_else(|| { + let cred_def = cred_defs.get_ref(&cred_def_id).ok_or_else(|| { err_msg!( "Credential Definition not provided for ID: {:?}", identifier.cred_def_id @@ -203,7 +209,7 @@ pub fn verify_presentation( // Override Interval if an earlier `from` value is accepted by the verifier nonrevoke_interval_override.map(|maps| { - maps.get(&rev_reg_def_id).map(|map| { + maps.get_ref(&rev_reg_def_id).map(|map| { cred_nonrevoked_interval .as_mut() .map(|int| int.update_with_override(map)) @@ -217,9 +223,8 @@ pub fn verify_presentation( let rev_reg_def = Some( rev_reg_defs - .as_ref() .ok_or_else(|| err_msg!("Could not load the Revocation Registry Definition"))? - .get(&rev_reg_def_id) + .get_ref(&rev_reg_def_id) .ok_or_else(|| { err_msg!( "Revocation Registry Definition not provided for ID: {:?}", @@ -494,16 +499,20 @@ fn verify_revealed_attribute_value( } #[allow(clippy::too_many_arguments)] -fn verify_requested_restrictions( +fn verify_requested_restrictions( pres_req: &PresentationRequestPayload, - schemas: &HashMap<&SchemaId, &Schema>, - cred_defs: &HashMap<&CredentialDefinitionId, &CredentialDefinition>, + schemas: &T, + cred_defs: &U, requested_proof: &RequestedProof, received_revealed_attrs: &HashMap, received_unrevealed_attrs: &HashMap, received_predicates: &HashMap, self_attested_attrs: &HashSet, -) -> Result<()> { +) -> Result<()> +where + T: ReferencesMap, + U: ReferencesMap, +{ let proof_attr_identifiers: HashMap = received_revealed_attrs .iter() .chain(received_unrevealed_attrs) @@ -661,12 +670,16 @@ fn is_self_attested( } } -fn gather_filter_info( +fn gather_filter_info( referent: &str, identifiers: &HashMap, - schemas: &HashMap<&SchemaId, &Schema>, - cred_defs: &HashMap<&CredentialDefinitionId, &CredentialDefinition>, -) -> Result { + schemas: &T, + cred_defs: &U, +) -> Result +where + T: ReferencesMap, + U: ReferencesMap, +{ let identifier = identifiers.get(referent).ok_or_else(|| { err_msg!( InvalidState, @@ -679,11 +692,11 @@ fn gather_filter_info( let cred_def_id = &identifier.cred_def_id; let schema = schemas - .get(schema_id) + .get_ref(schema_id) .ok_or_else(|| err_msg!("schema_id {schema_id} could not be found in the schemas"))?; let cred_def = cred_defs - .get(cred_def_id) + .get_ref(cred_def_id) .ok_or_else(|| err_msg!("cred_def_id {cred_def_id} could not be found in the cred_defs"))?; Ok(Filter { diff --git a/src/utils/map.rs b/src/utils/map.rs new file mode 100644 index 00000000..68acf31f --- /dev/null +++ b/src/utils/map.rs @@ -0,0 +1,133 @@ +use std::{borrow::Borrow, collections::HashMap, hash::Hash}; + +/// Trait primarily added to accommodate both native and FFI usage of maps. +/// +/// In FFI, only object references are available. So, if something like a [`HashMap`] is required, +/// then it has to be constructed from those references. +/// +/// In native Rust code, the tendency is to already have the [`HashMap`] containing owned values +/// so it would be great to be able to work with that rather tha construct a new [`HashMap`] with +/// references from the one we already have. +pub trait ReferencesMap +where + K: std::hash::Hash + Eq, +{ + type Iter<'a>: IntoIterator + where + K: 'a, + V: 'a, + Self: 'a; + + fn get_ref(&self, key: &Q) -> Option<&V> + where + for<'a> &'a K: Borrow, + K: Borrow, + Q: Hash + Eq; + + fn iter_ref(&self) -> Self::Iter<'_>; +} + +impl ReferencesMap for HashMap +where + K: std::hash::Hash + Eq, +{ + type Iter<'a> = std::collections::hash_map::Iter<'a, K, V> + where + K: 'a, + V: 'a, + Self: 'a; + + fn get_ref(&self, key: &Q) -> Option<&V> + where + for<'a> &'a K: Borrow, + K: Borrow, + Q: Hash + Eq, + { + self.get(key) + } + + fn iter_ref(&self) -> Self::Iter<'_> { + self.iter() + } +} + +type MapFnBothRef<'a, K, V> = fn((&'a &'a K, &'a &'a V)) -> (&'a K, &'a V); +type MapIterBothRef<'a, K, V> = std::collections::hash_map::Iter<'a, &'a K, &'a V>; + +impl ReferencesMap for HashMap<&K, &V> +where + K: std::hash::Hash + Eq, +{ + type Iter<'a> = std::iter::Map, MapFnBothRef<'a, K, V>> + where + K: 'a, + V: 'a, + Self: 'a; + + fn get_ref(&self, key: &Q) -> Option<&V> + where + for<'a> &'a K: Borrow, + K: Borrow, + Q: Hash + Eq, + { + self.get(key).copied() + } + + fn iter_ref(&self) -> Self::Iter<'_> { + self.iter().map(|(k, v)| (*k, *v)) + } +} + +type MapFnKeyRef<'a, K, V> = fn((&'a &'a K, &'a V)) -> (&'a K, &'a V); +type MapIterKeyRef<'a, K, V> = std::collections::hash_map::Iter<'a, &'a K, V>; + +impl ReferencesMap for HashMap<&K, V> +where + K: std::hash::Hash + Eq, +{ + type Iter<'a> = std::iter::Map, MapFnKeyRef<'a, K, V>> + where + K: 'a, + V: 'a, + Self: 'a; + + fn get_ref(&self, key: &Q) -> Option<&V> + where + for<'a> &'a K: Borrow, + K: Borrow, + Q: Hash + Eq, + { + self.get(key) + } + + fn iter_ref(&self) -> Self::Iter<'_> { + self.iter().map(|(k, v)| (*k, v)) + } +} + +type MapFnValueRef<'a, K, V> = fn((&'a K, &'a &'a V)) -> (&'a K, &'a V); +type MapIterValueRef<'a, K, V> = std::collections::hash_map::Iter<'a, K, &'a V>; + +impl ReferencesMap for HashMap +where + K: std::hash::Hash + Eq, +{ + type Iter<'a> = std::iter::Map, MapFnValueRef<'a, K, V>> + where + K: 'a, + V: 'a, + Self: 'a; + + fn get_ref(&self, key: &Q) -> Option<&V> + where + for<'a> &'a K: Borrow, + K: Borrow, + Q: Hash + Eq, + { + self.get(key).copied() + } + + fn iter_ref(&self) -> Self::Iter<'_> { + self.iter().map(|(k, v)| (k, *v)) + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d1956f23..60bfbf60 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -9,3 +9,5 @@ pub mod query; #[macro_use] pub mod macros; + +pub mod map; diff --git a/tests/anoncreds_demos.rs b/tests/anoncreds_demos.rs index 18635f05..7b7db1de 100644 --- a/tests/anoncreds_demos.rs +++ b/tests/anoncreds_demos.rs @@ -5,6 +5,7 @@ use anoncreds::data_types::schema::SchemaId; use anoncreds::issuer; use anoncreds::prover; use anoncreds::tails::TailsFileWriter; +use anoncreds::types::RevocationRegistryDefinition; use anoncreds::types::{CredentialRevocationConfig, PresentCredentials}; use anoncreds::verifier; use serde_json::json; @@ -179,9 +180,9 @@ fn anoncreds_demo_works_for_single_issuer_single_prover() { &pres_request, &schemas, &cred_defs, + None::<&HashMap>, None, - None, - None, + None::<&HashMap>>, ) .expect("Error verifying presentation"); @@ -353,7 +354,7 @@ fn anoncreds_demo_works_with_revocation_for_single_issuer_single_prover() { &cred_defs, Some(&rev_reg_def_map), Some(rev_status_list.clone()), - None, + None::<&HashMap>>, ) .expect("Error verifying presentation"); assert!(valid); @@ -401,7 +402,7 @@ fn anoncreds_demo_works_with_revocation_for_single_issuer_single_prover() { &cred_defs, Some(&rev_reg_def_map), Some(rev_status_list), - None, + None::<&HashMap>>, ) .expect("Error verifying presentation"); assert!(!valid); @@ -576,9 +577,9 @@ fn anoncreds_demo_works_for_multiple_issuer_single_prover() { &pres_request, &schemas, &cred_defs, + None::<&HashMap>, None, - None, - None, + None::<&HashMap>>, ) .expect("Error verifying presentation"); assert!(valid); @@ -705,9 +706,9 @@ fn anoncreds_demo_proof_does_not_verify_with_wrong_attr_and_predicates() { &pres_request, &schemas, &cred_defs, + None::<&HashMap>, None, - None, - None, + None::<&HashMap>>, ); assert!(valid.is_err()) @@ -877,9 +878,9 @@ fn anoncreds_demo_works_for_requested_attribute_in_upper_case() { &pres_request, &schemas, &cred_defs, + None::<&HashMap>, None, - None, - None, + None::<&HashMap>>, ) .expect("Error verifying presentation"); @@ -1060,9 +1061,9 @@ fn anoncreds_demo_works_for_twice_entry_of_attribute_from_different_credential() &pres_request, &schemas, &cred_defs, + None::<&HashMap>, None, - None, - None, + None::<&HashMap>>, ) .expect("Error verifying presentation"); assert!(valid); From 3c8ea03b5c4d6873d2a7a3debe671f171cc90d0d Mon Sep 17 00:00:00 2001 From: Bogdan Mircea Date: Tue, 15 Aug 2023 19:14:32 +0300 Subject: [PATCH 3/7] Added IntoIterator generic for rev_status_lists in verify_presentation Signed-off-by: Bogdan Mircea --- src/ffi/presentation.rs | 4 +++- src/services/prover.rs | 2 +- src/services/verifier.rs | 11 ++++++----- src/utils/mod.rs | 2 +- src/utils/{map.rs => ref_map.rs} | 0 tests/anoncreds_demos.rs | 10 +++++----- 6 files changed, 16 insertions(+), 13 deletions(-) rename src/utils/{map.rs => ref_map.rs} (100%) diff --git a/src/ffi/presentation.rs b/src/ffi/presentation.rs index 7c980300..f039837f 100644 --- a/src/ffi/presentation.rs +++ b/src/ffi/presentation.rs @@ -333,13 +333,15 @@ pub extern "C" fn anoncreds_verify_presentation( .insert(*req_timestamp, *override_timestamp); } + let rev_status_lists = rev_status_list.as_ref().map(|v| v.iter().copied()); + let verify = verify_presentation( presentation.load()?.cast_ref()?, pres_req.load()?.cast_ref()?, &schemas, &cred_defs, rev_reg_defs, - rev_status_list, + rev_status_lists, Some(&map_nonrevoked_interval_override), )?; unsafe { *result_p = i8::from(verify) }; diff --git a/src/services/prover.rs b/src/services/prover.rs index b03adbf1..245f4bae 100644 --- a/src/services/prover.rs +++ b/src/services/prover.rs @@ -27,7 +27,7 @@ use crate::services::helpers::{ get_revealed_attributes_for_credential, new_nonce, }; use crate::types::{CredentialRevocationState, PresentCredentials}; -use crate::utils::map::ReferencesMap; +use crate::utils::ref_map::ReferencesMap; use crate::utils::validation::Validatable; use bitvec::bitvec; use std::collections::{HashMap, HashSet}; diff --git a/src/services/verifier.rs b/src/services/verifier.rs index 6c4f9296..f55182e8 100644 --- a/src/services/verifier.rs +++ b/src/services/verifier.rs @@ -22,8 +22,8 @@ use crate::services::helpers::build_non_credential_schema; use crate::services::helpers::build_sub_proof_request; use crate::services::helpers::get_predicates_for_credential; use crate::services::helpers::get_revealed_attributes_for_credential; -use crate::utils::map::ReferencesMap; use crate::utils::query::Query; +use crate::utils::ref_map::ReferencesMap; use crate::utils::validation::LEGACY_DID_IDENTIFIER; use once_cell::sync::Lazy; @@ -44,13 +44,13 @@ static INTERNAL_TAG_MATCHER: Lazy = Lazy::new(|| Regex::new("^attr::([^:]+)::(value|marker)$").unwrap()); /// Verify an incoming proof presentation -pub fn verify_presentation( +pub fn verify_presentation<'a, T, U, V, I, Z>( presentation: &Presentation, pres_req: &PresentationRequest, schemas: &T, cred_defs: &U, rev_reg_defs: Option<&V>, - rev_status_lists: Option>, + rev_status_lists: Option, nonrevoke_interval_override: Option<&Z>, ) -> Result where @@ -58,6 +58,7 @@ where U: ReferencesMap + std::fmt::Debug, V: ReferencesMap + std::fmt::Debug, + I: IntoIterator + Clone + std::fmt::Debug, Z: ReferencesMap> + std::fmt::Debug, { trace!("verify >>> presentation: {:?}, pres_req: {:?}, schemas: {:?}, cred_defs: {:?}, rev_reg_defs: {:?} rev_status_lists: {:?}", @@ -115,7 +116,7 @@ where ) })?; - let rev_reg_map = if let Some(ref lists) = rev_status_lists { + let rev_reg_map = if let Some(lists) = rev_status_lists.clone() { let mut map: HashMap> = HashMap::new(); @@ -128,7 +129,7 @@ where .timestamp() .ok_or_else(|| err_msg!(Unexpected, "RevStatusList missing timestamp"))?; - let rev_reg: Option = (*list).into(); + let rev_reg: Option = list.into(); let rev_reg = rev_reg.ok_or_else(|| { err_msg!(Unexpected, "Revocation status list missing accumulator") })?; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 60bfbf60..34248eed 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -10,4 +10,4 @@ pub mod query; #[macro_use] pub mod macros; -pub mod map; +pub mod ref_map; diff --git a/src/utils/map.rs b/src/utils/ref_map.rs similarity index 100% rename from src/utils/map.rs rename to src/utils/ref_map.rs diff --git a/tests/anoncreds_demos.rs b/tests/anoncreds_demos.rs index 7b7db1de..9406393c 100644 --- a/tests/anoncreds_demos.rs +++ b/tests/anoncreds_demos.rs @@ -181,7 +181,7 @@ fn anoncreds_demo_works_for_single_issuer_single_prover() { &schemas, &cred_defs, None::<&HashMap>, - None, + None::<&[_; 0]>, None::<&HashMap>>, ) .expect("Error verifying presentation"); @@ -578,7 +578,7 @@ fn anoncreds_demo_works_for_multiple_issuer_single_prover() { &schemas, &cred_defs, None::<&HashMap>, - None, + None::<&[_; 0]>, None::<&HashMap>>, ) .expect("Error verifying presentation"); @@ -707,7 +707,7 @@ fn anoncreds_demo_proof_does_not_verify_with_wrong_attr_and_predicates() { &schemas, &cred_defs, None::<&HashMap>, - None, + None::<&[_; 0]>, None::<&HashMap>>, ); @@ -879,7 +879,7 @@ fn anoncreds_demo_works_for_requested_attribute_in_upper_case() { &schemas, &cred_defs, None::<&HashMap>, - None, + None::<&[_; 0]>, None::<&HashMap>>, ) .expect("Error verifying presentation"); @@ -1062,7 +1062,7 @@ fn anoncreds_demo_works_for_twice_entry_of_attribute_from_different_credential() &schemas, &cred_defs, None::<&HashMap>, - None, + None::<&[_; 0]>, None::<&HashMap>>, ) .expect("Error verifying presentation"); From 6e1a3414c7444890c78a3105a86dba6887175312 Mon Sep 17 00:00:00 2001 From: Bogdan Mircea Date: Tue, 15 Aug 2023 19:29:15 +0300 Subject: [PATCH 4/7] Updated Rust toolchain version Signed-off-by: Bogdan Mircea --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 62b589d7..7446d6b5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,7 @@ name: 'Anoncreds' env: - RUST_VERSION: '1.64.0' + RUST_VERSION: '1.65.0' CROSS_VERSION: '0.2.4' on: From bc10e76a59917756b408907d88942f4ab7db73ed Mon Sep 17 00:00:00 2001 From: Bogdan Mircea Date: Wed, 16 Aug 2023 11:02:25 +0300 Subject: [PATCH 5/7] Moved handling of BorrowMutError to TailsFileReader::read Signed-off-by: Bogdan Mircea --- src/error.rs | 6 ------ src/services/tails.rs | 7 ++++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/error.rs b/src/error.rs index 46c4af54..12141a3f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -140,12 +140,6 @@ impl From for Error { } } -impl From for Error { - fn from(err: std::cell::BorrowMutError) -> Self { - Self::from(ErrorKind::IOError).with_cause(err) - } -} - impl From for Error { fn from(err: serde_json::Error) -> Self { // FIXME could be input or output... diff --git a/src/services/tails.rs b/src/services/tails.rs index 2b2d5d06..572ae250 100644 --- a/src/services/tails.rs +++ b/src/services/tails.rs @@ -13,6 +13,7 @@ use crate::cl::{ }; use crate::error::Error; use crate::utils::base58; +use crate::ErrorKind; const TAILS_BLOB_TAG_SZ: u8 = 2; const TAIL_SIZE: usize = Tail::BYTES_REPR_SIZE; @@ -35,7 +36,11 @@ impl TailsFileReader { fn read(&self, size: usize, offset: usize) -> Result, Error> { let mut buf = vec![0u8; size]; - let mut file = self.file.try_borrow_mut()?; + let mut file = self + .file + .try_borrow_mut() + .map_err(|err| Error::from(ErrorKind::IOError).with_cause(err))?; + file.seek(SeekFrom::Start(offset as u64))?; file.read_exact(buf.as_mut_slice())?; From 9f49ef0fcafe23ee3b2efdaf3b70edb78cf66508 Mon Sep 17 00:00:00 2001 From: Bogdan Mircea Date: Wed, 16 Aug 2023 19:34:49 +0300 Subject: [PATCH 6/7] Simplified the ReferencesMap iterators Signed-off-by: Bogdan Mircea --- src/utils/ref_map.rs | 61 +++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/utils/ref_map.rs b/src/utils/ref_map.rs index 68acf31f..b37e24de 100644 --- a/src/utils/ref_map.rs +++ b/src/utils/ref_map.rs @@ -1,4 +1,8 @@ -use std::{borrow::Borrow, collections::HashMap, hash::Hash}; +use std::{ + borrow::Borrow, + collections::{hash_map, HashMap}, + hash::{self, Hash}, +}; /// Trait primarily added to accommodate both native and FFI usage of maps. /// @@ -10,7 +14,7 @@ use std::{borrow::Borrow, collections::HashMap, hash::Hash}; /// references from the one we already have. pub trait ReferencesMap where - K: std::hash::Hash + Eq, + K: hash::Hash + Eq, { type Iter<'a>: IntoIterator where @@ -29,9 +33,9 @@ where impl ReferencesMap for HashMap where - K: std::hash::Hash + Eq, + K: hash::Hash + Eq, { - type Iter<'a> = std::collections::hash_map::Iter<'a, K, V> + type Iter<'a> = hash_map::Iter<'a, K, V> where K: 'a, V: 'a, @@ -51,14 +55,21 @@ where } } -type MapFnBothRef<'a, K, V> = fn((&'a &'a K, &'a &'a V)) -> (&'a K, &'a V); -type MapIterBothRef<'a, K, V> = std::collections::hash_map::Iter<'a, &'a K, &'a V>; +pub struct MapIterBothRef<'a, K, V>(hash_map::Iter<'a, &'a K, &'a V>); + +impl<'a, K, V> Iterator for MapIterBothRef<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option { + self.0.next().map(|(k, v)| (*k, *v)) + } +} impl ReferencesMap for HashMap<&K, &V> where - K: std::hash::Hash + Eq, + K: hash::Hash + Eq, { - type Iter<'a> = std::iter::Map, MapFnBothRef<'a, K, V>> + type Iter<'a> = MapIterBothRef<'a, K, V> where K: 'a, V: 'a, @@ -74,18 +85,25 @@ where } fn iter_ref(&self) -> Self::Iter<'_> { - self.iter().map(|(k, v)| (*k, *v)) + MapIterBothRef(self.iter()) } } -type MapFnKeyRef<'a, K, V> = fn((&'a &'a K, &'a V)) -> (&'a K, &'a V); -type MapIterKeyRef<'a, K, V> = std::collections::hash_map::Iter<'a, &'a K, V>; +pub struct MapIterKeyRef<'a, K, V>(hash_map::Iter<'a, &'a K, V>); + +impl<'a, K, V> Iterator for MapIterKeyRef<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option { + self.0.next().map(|(k, v)| (*k, v)) + } +} impl ReferencesMap for HashMap<&K, V> where - K: std::hash::Hash + Eq, + K: hash::Hash + Eq, { - type Iter<'a> = std::iter::Map, MapFnKeyRef<'a, K, V>> + type Iter<'a> = MapIterKeyRef<'a, K, V> where K: 'a, V: 'a, @@ -101,18 +119,25 @@ where } fn iter_ref(&self) -> Self::Iter<'_> { - self.iter().map(|(k, v)| (*k, v)) + MapIterKeyRef(self.iter()) } } -type MapFnValueRef<'a, K, V> = fn((&'a K, &'a &'a V)) -> (&'a K, &'a V); -type MapIterValueRef<'a, K, V> = std::collections::hash_map::Iter<'a, K, &'a V>; +pub struct MapIterValueRef<'a, K, V>(hash_map::Iter<'a, K, &'a V>); + +impl<'a, K, V> Iterator for MapIterValueRef<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option { + self.0.next().map(|(k, v)| (k, *v)) + } +} impl ReferencesMap for HashMap where K: std::hash::Hash + Eq, { - type Iter<'a> = std::iter::Map, MapFnValueRef<'a, K, V>> + type Iter<'a> = MapIterValueRef<'a, K ,V> where K: 'a, V: 'a, @@ -128,6 +153,6 @@ where } fn iter_ref(&self) -> Self::Iter<'_> { - self.iter().map(|(k, v)| (k, *v)) + MapIterValueRef(self.iter()) } } From 9a3a79f24bfa8d1dc033fd8ba5e7cdaffe7d6c81 Mon Sep 17 00:00:00 2001 From: Bogdan Mircea Date: Tue, 22 Aug 2023 01:01:39 +0300 Subject: [PATCH 7/7] Removed ReferencesMap trait in favor of cloning Signed-off-by: Bogdan Mircea --- src/data_types/cred_def.rs | 15 ++++ src/ffi/presentation.rs | 33 +++++-- src/services/prover.rs | 21 ++--- src/services/verifier.rs | 63 ++++++-------- src/utils/mod.rs | 2 - src/utils/ref_map.rs | 158 ---------------------------------- tests/anoncreds_demos.rs | 73 ++++++++-------- tests/multiple-credentials.rs | 2 +- tests/utils/fixtures.rs | 4 +- tests/utils/mock.rs | 52 ++++++++--- 10 files changed, 152 insertions(+), 271 deletions(-) delete mode 100644 src/utils/ref_map.rs diff --git a/src/data_types/cred_def.rs b/src/data_types/cred_def.rs index 88f0d17e..caf6fd30 100644 --- a/src/data_types/cred_def.rs +++ b/src/data_types/cred_def.rs @@ -56,6 +56,21 @@ impl CredentialDefinition { .map_err(|e| e.to_string())?; Ok(key) } + + pub fn try_clone(&self) -> Result { + let cred_data = CredentialDefinitionData { + primary: self.value.primary.try_clone()?, + revocation: self.value.revocation.clone(), + }; + + Ok(Self { + schema_id: self.schema_id.clone(), + signature_type: self.signature_type, + tag: self.tag.clone(), + value: cred_data, + issuer_id: self.issuer_id.clone(), + }) + } } impl Validatable for CredentialDefinition { diff --git a/src/ffi/presentation.rs b/src/ffi/presentation.rs index f039837f..ed83f0f7 100644 --- a/src/ffi/presentation.rs +++ b/src/ffi/presentation.rs @@ -177,11 +177,18 @@ pub extern "C" fn anoncreds_create_presentation( } let schemas = AnoncredsObjectList::load(schemas.as_slice())?; - let schemas = schemas.refs_map::(&schema_identifiers)?; + let schemas = schemas + .refs_map::(&schema_identifiers)? + .into_iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect(); let cred_defs = AnoncredsObjectList::load(cred_defs.as_slice())?; let cred_defs = cred_defs - .refs_map::(&cred_def_identifiers)?; + .refs_map::(&cred_def_identifiers)? + .into_iter() + .map(|(k, v)| v.try_clone().map(|v| (k.clone(), v))) + .collect::>()?; let presentation = create_presentation( pres_req.load()?.cast_ref()?, @@ -292,17 +299,27 @@ pub extern "C" fn anoncreds_verify_presentation( } let schemas = AnoncredsObjectList::load(schemas.as_slice())?; - let schemas = schemas.refs_map::(&schema_identifiers)?; + let schemas = schemas + .refs_map::(&schema_identifiers)? + .into_iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect(); let cred_defs = AnoncredsObjectList::load(cred_defs.as_slice())?; let cred_defs = cred_defs - .refs_map::(&cred_def_identifiers)?; + .refs_map::(&cred_def_identifiers)? + .into_iter() + .map(|(k, v)| v.try_clone().map(|v| (k.clone(), v))) + .collect::>()?; let rev_reg_defs = AnoncredsObjectList::load(rev_reg_defs.as_slice())?; let rev_reg_defs = rev_reg_defs .refs_map::( &rev_reg_def_identifiers, - )?; + )? + .into_iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect::>(); let rev_reg_defs = if rev_reg_defs.is_empty() { None @@ -328,12 +345,14 @@ pub extern "C" fn anoncreds_verify_presentation( let mut map_nonrevoked_interval_override = HashMap::new(); for (id, req_timestamp, override_timestamp) in &override_entries { map_nonrevoked_interval_override - .entry(id) + .entry(id.clone()) .or_insert_with(HashMap::new) .insert(*req_timestamp, *override_timestamp); } - let rev_status_lists = rev_status_list.as_ref().map(|v| v.iter().copied()); + let rev_status_lists = rev_status_list + .as_ref() + .map(|v| v.iter().copied().cloned().collect()); let verify = verify_presentation( presentation.load()?.cast_ref()?, diff --git a/src/services/prover.rs b/src/services/prover.rs index 245f4bae..f80849ad 100644 --- a/src/services/prover.rs +++ b/src/services/prover.rs @@ -27,7 +27,6 @@ use crate::services::helpers::{ get_revealed_attributes_for_credential, new_nonce, }; use crate::types::{CredentialRevocationState, PresentCredentials}; -use crate::utils::ref_map::ReferencesMap; use crate::utils::validation::Validatable; use bitvec::bitvec; use std::collections::{HashMap, HashSet}; @@ -375,11 +374,11 @@ pub fn process_credential( /// /// let mut schemas = HashMap::new(); /// let schema_id = SchemaId::new_unchecked("did:web:xyz/resource/schema"); -/// schemas.insert(&schema_id, &schema); +/// schemas.insert(schema_id, schema); /// /// let mut cred_defs = HashMap::new(); /// let cred_def_id = CredentialDefinitionId::new_unchecked("did:web:xyz/resource/cred-def"); -/// cred_defs.insert(&cred_def_id, &cred_def); +/// cred_defs.insert(cred_def_id, cred_def); /// /// let mut present = PresentCredentials::default(); /// let mut cred1 = present.add_credential( @@ -399,18 +398,14 @@ pub fn process_credential( /// &cred_defs /// ).expect("Unable to create presentation"); /// ``` -pub fn create_presentation( +pub fn create_presentation( pres_req: &PresentationRequest, credentials: PresentCredentials, self_attested: Option>, link_secret: &LinkSecret, - schemas: &T, - cred_defs: &U, -) -> Result -where - T: ReferencesMap + std::fmt::Debug, - U: ReferencesMap + std::fmt::Debug, -{ + schemas: &HashMap, + cred_defs: &HashMap, +) -> Result { trace!("create_proof >>> credentials: {:?}, pres_req: {:?}, credentials: {:?}, self_attested: {:?}, link_secret: {:?}, schemas: {:?}, cred_defs: {:?}", credentials, pres_req, credentials, &self_attested, secret!(&link_secret), schemas, cred_defs); @@ -442,11 +437,11 @@ where let credential = present.cred; let schema = schemas - .get_ref(&credential.schema_id) + .get(&credential.schema_id) .ok_or_else(|| err_msg!("Schema not provided for ID: {}", credential.schema_id))?; let cred_def_id = CredentialDefinitionId::new(credential.cred_def_id.clone())?; - let cred_def = cred_defs.get_ref(&cred_def_id).ok_or_else(|| { + let cred_def = cred_defs.get(&cred_def_id).ok_or_else(|| { err_msg!( "Credential Definition not provided for ID: {}", credential.cred_def_id diff --git a/src/services/verifier.rs b/src/services/verifier.rs index f55182e8..1db07f9c 100644 --- a/src/services/verifier.rs +++ b/src/services/verifier.rs @@ -23,7 +23,6 @@ use crate::services::helpers::build_sub_proof_request; use crate::services::helpers::get_predicates_for_credential; use crate::services::helpers::get_revealed_attributes_for_credential; use crate::utils::query::Query; -use crate::utils::ref_map::ReferencesMap; use crate::utils::validation::LEGACY_DID_IDENTIFIER; use once_cell::sync::Lazy; @@ -44,23 +43,17 @@ static INTERNAL_TAG_MATCHER: Lazy = Lazy::new(|| Regex::new("^attr::([^:]+)::(value|marker)$").unwrap()); /// Verify an incoming proof presentation -pub fn verify_presentation<'a, T, U, V, I, Z>( +pub fn verify_presentation( presentation: &Presentation, pres_req: &PresentationRequest, - schemas: &T, - cred_defs: &U, - rev_reg_defs: Option<&V>, - rev_status_lists: Option, - nonrevoke_interval_override: Option<&Z>, -) -> Result -where - T: ReferencesMap + std::fmt::Debug, - U: ReferencesMap + std::fmt::Debug, - V: ReferencesMap - + std::fmt::Debug, - I: IntoIterator + Clone + std::fmt::Debug, - Z: ReferencesMap> + std::fmt::Debug, -{ + schemas: &HashMap, + cred_defs: &HashMap, + rev_reg_defs: Option<&HashMap>, + rev_status_lists: Option>, + nonrevoke_interval_override: Option< + &HashMap>, + >, +) -> Result { trace!("verify >>> presentation: {:?}, pres_req: {:?}, schemas: {:?}, cred_defs: {:?}, rev_reg_defs: {:?} rev_status_lists: {:?}", presentation, pres_req, schemas, cred_defs, rev_reg_defs, rev_status_lists); @@ -105,11 +98,11 @@ where let identifier = presentation.identifiers[sub_proof_index].clone(); let schema = schemas - .get_ref(&identifier.schema_id) + .get(&identifier.schema_id) .ok_or_else(|| err_msg!("Schema not provided for ID: {:?}", identifier.schema_id))?; let cred_def_id = CredentialDefinitionId::new(identifier.cred_def_id.clone())?; - let cred_def = cred_defs.get_ref(&cred_def_id).ok_or_else(|| { + let cred_def = cred_defs.get(&cred_def_id).ok_or_else(|| { err_msg!( "Credential Definition not provided for ID: {:?}", identifier.cred_def_id @@ -129,7 +122,7 @@ where .timestamp() .ok_or_else(|| err_msg!(Unexpected, "RevStatusList missing timestamp"))?; - let rev_reg: Option = list.into(); + let rev_reg: Option = (&list).into(); let rev_reg = rev_reg.ok_or_else(|| { err_msg!(Unexpected, "Revocation status list missing accumulator") })?; @@ -210,7 +203,7 @@ where // Override Interval if an earlier `from` value is accepted by the verifier nonrevoke_interval_override.map(|maps| { - maps.get_ref(&rev_reg_def_id).map(|map| { + maps.get(&rev_reg_def_id).map(|map| { cred_nonrevoked_interval .as_mut() .map(|int| int.update_with_override(map)) @@ -225,7 +218,7 @@ where let rev_reg_def = Some( rev_reg_defs .ok_or_else(|| err_msg!("Could not load the Revocation Registry Definition"))? - .get_ref(&rev_reg_def_id) + .get(&rev_reg_def_id) .ok_or_else(|| { err_msg!( "Revocation Registry Definition not provided for ID: {:?}", @@ -500,20 +493,16 @@ fn verify_revealed_attribute_value( } #[allow(clippy::too_many_arguments)] -fn verify_requested_restrictions( +fn verify_requested_restrictions( pres_req: &PresentationRequestPayload, - schemas: &T, - cred_defs: &U, + schemas: &HashMap, + cred_defs: &HashMap, requested_proof: &RequestedProof, received_revealed_attrs: &HashMap, received_unrevealed_attrs: &HashMap, received_predicates: &HashMap, self_attested_attrs: &HashSet, -) -> Result<()> -where - T: ReferencesMap, - U: ReferencesMap, -{ +) -> Result<()> { let proof_attr_identifiers: HashMap = received_revealed_attrs .iter() .chain(received_unrevealed_attrs) @@ -671,16 +660,12 @@ fn is_self_attested( } } -fn gather_filter_info( +fn gather_filter_info( referent: &str, identifiers: &HashMap, - schemas: &T, - cred_defs: &U, -) -> Result -where - T: ReferencesMap, - U: ReferencesMap, -{ + schemas: &HashMap, + cred_defs: &HashMap, +) -> Result { let identifier = identifiers.get(referent).ok_or_else(|| { err_msg!( InvalidState, @@ -693,11 +678,11 @@ where let cred_def_id = &identifier.cred_def_id; let schema = schemas - .get_ref(schema_id) + .get(schema_id) .ok_or_else(|| err_msg!("schema_id {schema_id} could not be found in the schemas"))?; let cred_def = cred_defs - .get_ref(cred_def_id) + .get(cred_def_id) .ok_or_else(|| err_msg!("cred_def_id {cred_def_id} could not be found in the cred_defs"))?; Ok(Filter { diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 34248eed..d1956f23 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -9,5 +9,3 @@ pub mod query; #[macro_use] pub mod macros; - -pub mod ref_map; diff --git a/src/utils/ref_map.rs b/src/utils/ref_map.rs deleted file mode 100644 index b37e24de..00000000 --- a/src/utils/ref_map.rs +++ /dev/null @@ -1,158 +0,0 @@ -use std::{ - borrow::Borrow, - collections::{hash_map, HashMap}, - hash::{self, Hash}, -}; - -/// Trait primarily added to accommodate both native and FFI usage of maps. -/// -/// In FFI, only object references are available. So, if something like a [`HashMap`] is required, -/// then it has to be constructed from those references. -/// -/// In native Rust code, the tendency is to already have the [`HashMap`] containing owned values -/// so it would be great to be able to work with that rather tha construct a new [`HashMap`] with -/// references from the one we already have. -pub trait ReferencesMap -where - K: hash::Hash + Eq, -{ - type Iter<'a>: IntoIterator - where - K: 'a, - V: 'a, - Self: 'a; - - fn get_ref(&self, key: &Q) -> Option<&V> - where - for<'a> &'a K: Borrow, - K: Borrow, - Q: Hash + Eq; - - fn iter_ref(&self) -> Self::Iter<'_>; -} - -impl ReferencesMap for HashMap -where - K: hash::Hash + Eq, -{ - type Iter<'a> = hash_map::Iter<'a, K, V> - where - K: 'a, - V: 'a, - Self: 'a; - - fn get_ref(&self, key: &Q) -> Option<&V> - where - for<'a> &'a K: Borrow, - K: Borrow, - Q: Hash + Eq, - { - self.get(key) - } - - fn iter_ref(&self) -> Self::Iter<'_> { - self.iter() - } -} - -pub struct MapIterBothRef<'a, K, V>(hash_map::Iter<'a, &'a K, &'a V>); - -impl<'a, K, V> Iterator for MapIterBothRef<'a, K, V> { - type Item = (&'a K, &'a V); - - fn next(&mut self) -> Option { - self.0.next().map(|(k, v)| (*k, *v)) - } -} - -impl ReferencesMap for HashMap<&K, &V> -where - K: hash::Hash + Eq, -{ - type Iter<'a> = MapIterBothRef<'a, K, V> - where - K: 'a, - V: 'a, - Self: 'a; - - fn get_ref(&self, key: &Q) -> Option<&V> - where - for<'a> &'a K: Borrow, - K: Borrow, - Q: Hash + Eq, - { - self.get(key).copied() - } - - fn iter_ref(&self) -> Self::Iter<'_> { - MapIterBothRef(self.iter()) - } -} - -pub struct MapIterKeyRef<'a, K, V>(hash_map::Iter<'a, &'a K, V>); - -impl<'a, K, V> Iterator for MapIterKeyRef<'a, K, V> { - type Item = (&'a K, &'a V); - - fn next(&mut self) -> Option { - self.0.next().map(|(k, v)| (*k, v)) - } -} - -impl ReferencesMap for HashMap<&K, V> -where - K: hash::Hash + Eq, -{ - type Iter<'a> = MapIterKeyRef<'a, K, V> - where - K: 'a, - V: 'a, - Self: 'a; - - fn get_ref(&self, key: &Q) -> Option<&V> - where - for<'a> &'a K: Borrow, - K: Borrow, - Q: Hash + Eq, - { - self.get(key) - } - - fn iter_ref(&self) -> Self::Iter<'_> { - MapIterKeyRef(self.iter()) - } -} - -pub struct MapIterValueRef<'a, K, V>(hash_map::Iter<'a, K, &'a V>); - -impl<'a, K, V> Iterator for MapIterValueRef<'a, K, V> { - type Item = (&'a K, &'a V); - - fn next(&mut self) -> Option { - self.0.next().map(|(k, v)| (k, *v)) - } -} - -impl ReferencesMap for HashMap -where - K: std::hash::Hash + Eq, -{ - type Iter<'a> = MapIterValueRef<'a, K ,V> - where - K: 'a, - V: 'a, - Self: 'a; - - fn get_ref(&self, key: &Q) -> Option<&V> - where - for<'a> &'a K: Borrow, - K: Borrow, - Q: Hash + Eq, - { - self.get(key).copied() - } - - fn iter_ref(&self) -> Self::Iter<'_> { - MapIterValueRef(self.iter()) - } -} diff --git a/tests/anoncreds_demos.rs b/tests/anoncreds_demos.rs index 9406393c..d13594b4 100644 --- a/tests/anoncreds_demos.rs +++ b/tests/anoncreds_demos.rs @@ -5,7 +5,6 @@ use anoncreds::data_types::schema::SchemaId; use anoncreds::issuer; use anoncreds::prover; use anoncreds::tails::TailsFileWriter; -use anoncreds::types::RevocationRegistryDefinition; use anoncreds::types::{CredentialRevocationConfig, PresentCredentials}; use anoncreds::verifier; use serde_json::json; @@ -116,11 +115,11 @@ fn anoncreds_demo_works_for_single_issuer_single_prover() { let mut schemas = HashMap::new(); let gvt_schema_id = SchemaId::new_unchecked(gvt_schema_id); - schemas.insert(&gvt_schema_id, &gvt_schema); + schemas.insert(gvt_schema_id, gvt_schema.clone()); let mut cred_defs = HashMap::new(); let gvt_cred_def_id = CredentialDefinitionId::new_unchecked(gvt_cred_def_id); - cred_defs.insert(&gvt_cred_def_id, &gvt_cred_def); + cred_defs.insert(gvt_cred_def_id, gvt_cred_def.try_clone().unwrap()); let presentation = prover::create_presentation( &pres_request, @@ -180,9 +179,9 @@ fn anoncreds_demo_works_for_single_issuer_single_prover() { &pres_request, &schemas, &cred_defs, - None::<&HashMap>, - None::<&[_; 0]>, - None::<&HashMap>>, + None, + None, + None, ) .expect("Error verifying presentation"); @@ -327,13 +326,13 @@ fn anoncreds_demo_works_with_revocation_for_single_issuer_single_prover() { let mut schemas = HashMap::new(); let gvt_schema_id = SchemaId::new_unchecked(gvt_schema_id); - schemas.insert(&gvt_schema_id, &gvt_schema); + schemas.insert(gvt_schema_id, gvt_schema.clone()); let mut cred_defs = HashMap::new(); let gvt_cred_def_id = CredentialDefinitionId::new_unchecked(gvt_cred_def_id); - cred_defs.insert(&gvt_cred_def_id, &gvt_cred_def); + cred_defs.insert(gvt_cred_def_id, gvt_cred_def.try_clone().unwrap()); - let mut rev_status_list = vec![&issued_rev_status_list]; + let mut rev_status_list = vec![issued_rev_status_list.clone()]; // Prover creates presentation let presentation = fixtures::create_presentation( @@ -346,7 +345,7 @@ fn anoncreds_demo_works_with_revocation_for_single_issuer_single_prover() { ); // Verifier verifies presentation of not Revoked rev_state - let rev_reg_def_map = HashMap::from([(&gvt_rev_reg_def_id, &gvt_rev_reg_def)]); + let rev_reg_def_map = HashMap::from([(gvt_rev_reg_def_id, gvt_rev_reg_def.clone())]); let valid = verifier::verify_presentation( &presentation, &pres_request, @@ -354,7 +353,7 @@ fn anoncreds_demo_works_with_revocation_for_single_issuer_single_prover() { &cred_defs, Some(&rev_reg_def_map), Some(rev_status_list.clone()), - None::<&HashMap>>, + None, ) .expect("Error verifying presentation"); assert!(valid); @@ -373,7 +372,7 @@ fn anoncreds_demo_works_with_revocation_for_single_issuer_single_prover() { .unwrap(); // update rev_status_lists - rev_status_list.push(&revoked_status_list); + rev_status_list.push(revoked_status_list.clone()); let rev_state = prover::create_or_update_revocation_state( &tails_location, @@ -402,7 +401,7 @@ fn anoncreds_demo_works_with_revocation_for_single_issuer_single_prover() { &cred_defs, Some(&rev_reg_def_map), Some(rev_status_list), - None::<&HashMap>>, + None, ) .expect("Error verifying presentation"); assert!(!valid); @@ -544,14 +543,14 @@ fn anoncreds_demo_works_for_multiple_issuer_single_prover() { let mut schemas = HashMap::new(); let gvt_schema_id = SchemaId::new_unchecked(gvt_schema_id); let emp_schema_id = SchemaId::new_unchecked(emp_schema_id); - schemas.insert(&gvt_schema_id, &gvt_schema); - schemas.insert(&emp_schema_id, &emp_schema); + schemas.insert(gvt_schema_id, gvt_schema.clone()); + schemas.insert(emp_schema_id, emp_schema.clone()); let mut cred_defs = HashMap::new(); let gvt_cred_def_id = CredentialDefinitionId::new_unchecked(gvt_cred_def_id); let emp_cred_def_id = CredentialDefinitionId::new_unchecked(emp_cred_def_id); - cred_defs.insert(&gvt_cred_def_id, &gvt_cred_def); - cred_defs.insert(&emp_cred_def_id, &emp_cred_def); + cred_defs.insert(gvt_cred_def_id, gvt_cred_def.try_clone().unwrap()); + cred_defs.insert(emp_cred_def_id, emp_cred_def.try_clone().unwrap()); let mut present = PresentCredentials::default(); let mut gvt_cred = present.add_credential(&prover_wallet.credentials[0], None, None); @@ -577,9 +576,9 @@ fn anoncreds_demo_works_for_multiple_issuer_single_prover() { &pres_request, &schemas, &cred_defs, - None::<&HashMap>, - None::<&[_; 0]>, - None::<&HashMap>>, + None, + None, + None, ) .expect("Error verifying presentation"); assert!(valid); @@ -685,11 +684,11 @@ fn anoncreds_demo_proof_does_not_verify_with_wrong_attr_and_predicates() { let mut schemas = HashMap::new(); let gvt_schema_id = SchemaId::new_unchecked(gvt_schema_id); - schemas.insert(&gvt_schema_id, &gvt_schema); + schemas.insert(gvt_schema_id, gvt_schema.clone()); let mut cred_defs = HashMap::new(); let gvt_cred_def_id = CredentialDefinitionId::new_unchecked(gvt_cred_def_id); - cred_defs.insert(&gvt_cred_def_id, &gvt_cred_def); + cred_defs.insert(gvt_cred_def_id, gvt_cred_def.try_clone().unwrap()); let presentation = prover::create_presentation( &pres_request, @@ -706,9 +705,9 @@ fn anoncreds_demo_proof_does_not_verify_with_wrong_attr_and_predicates() { &pres_request, &schemas, &cred_defs, - None::<&HashMap>, - None::<&[_; 0]>, - None::<&HashMap>>, + None, + None, + None, ); assert!(valid.is_err()) @@ -814,11 +813,11 @@ fn anoncreds_demo_works_for_requested_attribute_in_upper_case() { let mut schemas = HashMap::new(); let gvt_schema_id = SchemaId::new_unchecked(gvt_schema_id); - schemas.insert(&gvt_schema_id, &gvt_schema); + schemas.insert(gvt_schema_id, gvt_schema.clone()); let mut cred_defs = HashMap::new(); let gvt_cred_def_id = CredentialDefinitionId::new_unchecked(gvt_cred_def_id); - cred_defs.insert(&gvt_cred_def_id, &gvt_cred_def); + cred_defs.insert(gvt_cred_def_id, gvt_cred_def.try_clone().unwrap()); let presentation = prover::create_presentation( &pres_request, @@ -878,9 +877,9 @@ fn anoncreds_demo_works_for_requested_attribute_in_upper_case() { &pres_request, &schemas, &cred_defs, - None::<&HashMap>, - None::<&[_; 0]>, - None::<&HashMap>>, + None, + None, + None, ) .expect("Error verifying presentation"); @@ -1027,14 +1026,14 @@ fn anoncreds_demo_works_for_twice_entry_of_attribute_from_different_credential() let mut schemas = HashMap::new(); let gvt_schema_id = SchemaId::new_unchecked(gvt_schema_id); let emp_schema_id = SchemaId::new_unchecked(emp_schema_id); - schemas.insert(&gvt_schema_id, &gvt_schema); - schemas.insert(&emp_schema_id, &emp_schema); + schemas.insert(gvt_schema_id, gvt_schema.clone()); + schemas.insert(emp_schema_id, emp_schema.clone()); let mut cred_defs = HashMap::new(); let gvt_cred_def_id = CredentialDefinitionId::new_unchecked(gvt_cred_def_id); let emp_cred_def_id = CredentialDefinitionId::new_unchecked(emp_cred_def_id); - cred_defs.insert(&gvt_cred_def_id, &gvt_cred_def); - cred_defs.insert(&emp_cred_def_id, &emp_cred_def); + cred_defs.insert(gvt_cred_def_id, gvt_cred_def.try_clone().unwrap()); + cred_defs.insert(emp_cred_def_id, emp_cred_def.try_clone().unwrap()); let mut present = PresentCredentials::default(); let mut gvt_cred = present.add_credential(&prover_wallet.credentials[0], None, None); @@ -1061,9 +1060,9 @@ fn anoncreds_demo_works_for_twice_entry_of_attribute_from_different_credential() &pres_request, &schemas, &cred_defs, - None::<&HashMap>, - None::<&[_; 0]>, - None::<&HashMap>>, + None, + None, + None, ) .expect("Error verifying presentation"); assert!(valid); diff --git a/tests/multiple-credentials.rs b/tests/multiple-credentials.rs index 00a19a0b..14f8474c 100644 --- a/tests/multiple-credentials.rs +++ b/tests/multiple-credentials.rs @@ -285,7 +285,7 @@ fn anoncreds_with_multiple_credentials_per_request() { // Create overrides for timestamps let id = RevocationRegistryDefinitionId::new_unchecked(REV_REG_ID_1); - let override_rev1 = HashMap::from([(&id, HashMap::from([(LOCAL_FROM, OVERRIDE_LOCAL_FROM)]))]); + let override_rev1 = HashMap::from([(id, HashMap::from([(LOCAL_FROM, OVERRIDE_LOCAL_FROM)]))]); let overrides = vec![ None, Some(&override_rev1), diff --git a/tests/utils/fixtures.rs b/tests/utils/fixtures.rs index 65452dc9..223b9acf 100644 --- a/tests/utils/fixtures.rs +++ b/tests/utils/fixtures.rs @@ -185,8 +185,8 @@ pub fn create_revocation_status_list( } pub fn create_presentation( - schemas: &HashMap<&SchemaId, &Schema>, - cred_defs: &HashMap<&CredentialDefinitionId, &CredentialDefinition>, + schemas: &HashMap, + cred_defs: &HashMap, pres_request: &PresentationRequest, prover_wallet: &ProverWallet, rev_state_timestamp: Option, diff --git a/tests/utils/mock.rs b/tests/utils/mock.rs index 98905602..042d969b 100644 --- a/tests/utils/mock.rs +++ b/tests/utils/mock.rs @@ -40,7 +40,7 @@ pub type ProverValues<'a> = HashMap<&'a str, (Vec<&'a str>, Vec<&'a str>)>; // { rev_reg_def_id: {req_timestamp, override_timestamp} } #[allow(unused)] -pub type Override<'a> = HashMap<&'a RevocationRegistryDefinitionId, HashMap>; +pub type Override<'a> = HashMap>; #[derive(Debug)] pub struct Mock<'a> { @@ -85,16 +85,32 @@ impl<'a> Mock<'a> { overrides: &[Option<&Override>], ) -> Vec> { let mut results = vec![]; - let schemas: HashMap<&SchemaId, &Schema> = HashMap::from_iter(self.ledger.schemas.iter()); - let cred_defs: HashMap<&CredentialDefinitionId, &CredentialDefinition> = - HashMap::from_iter(self.ledger.cred_defs.iter()); + let schemas: HashMap = HashMap::from_iter( + self.ledger + .schemas + .iter() + .map(|(k, v)| (k.clone(), v.clone())), + ); + let cred_defs: HashMap = HashMap::from_iter( + self.ledger + .cred_defs + .iter() + .map(|(k, v)| v.try_clone().map(|v| (k.clone(), v))) + .collect::, anoncreds::Error>>() + .unwrap(), + ); let mut rev_status_lists = vec![]; - self.ledger - .revcation_list - .iter() - .for_each(|(_, v)| v.iter().for_each(|(_, list)| rev_status_lists.push(list))); - let rev_reg_def_map = HashMap::from_iter(self.ledger.rev_reg_defs.iter()); + self.ledger.revcation_list.iter().for_each(|(_, v)| { + v.iter() + .for_each(|(_, list)| rev_status_lists.push(list.clone())) + }); + let rev_reg_def_map = HashMap::from_iter( + self.ledger + .rev_reg_defs + .iter() + .map(|(k, v)| (k.clone(), v.clone())), + ); for (i, presentation) in presentations.iter().enumerate() { let valid = verifier::verify_presentation( @@ -426,9 +442,21 @@ impl<'a> Mock<'a> { self_attested: HashMap, req: &PresentationRequest, ) -> Presentation { - let schemas: HashMap<&SchemaId, &Schema> = HashMap::from_iter(self.ledger.schemas.iter()); - let cred_defs: HashMap<&CredentialDefinitionId, &CredentialDefinition> = - HashMap::from_iter(self.ledger.cred_defs.iter()); + let schemas: HashMap = HashMap::from_iter( + self.ledger + .schemas + .iter() + .map(|(k, v)| (k.clone(), v.clone())), + ); + + let cred_defs: HashMap = HashMap::from_iter( + self.ledger + .cred_defs + .iter() + .map(|(k, v)| v.try_clone().map(|v| (k.clone(), v))) + .collect::, anoncreds::Error>>() + .unwrap(), + ); let mut present = PresentCredentials::default(); for cred in self.prover_wallets[prover_id].credentials.iter() {