diff --git a/anoncreds/src/data_types/anoncreds/rev_reg.rs b/anoncreds/src/data_types/anoncreds/rev_reg.rs index c4f20fa0..ca84201b 100644 --- a/anoncreds/src/data_types/anoncreds/rev_reg.rs +++ b/anoncreds/src/data_types/anoncreds/rev_reg.rs @@ -10,68 +10,50 @@ use crate::{data_types::Validatable, error, impl_anoncreds_object_identifier}; impl_anoncreds_object_identifier!(RevocationRegistryId); #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(tag = "ver")] -pub enum RevocationRegistry { - #[serde(rename = "1.0")] - RevocationRegistryV1(RevocationRegistryV1), +pub struct RevocationRegistry { + pub value: ursa::cl::RevocationRegistry, } impl RevocationRegistry { pub fn initial_delta(&self) -> RevocationRegistryDelta { - match self { - Self::RevocationRegistryV1(v1) => { - RevocationRegistryDelta::RevocationRegistryDeltaV1(RevocationRegistryDeltaV1 { - value: { - let empty = HashSet::new(); - ursa::cl::RevocationRegistryDelta::from_parts( - None, &v1.value, &empty, &empty, - ) - }, - }) - } + RevocationRegistryDelta { + value: { + let empty = HashSet::new(); + ursa::cl::RevocationRegistryDelta::from_parts(None, &self.value, &empty, &empty) + }, } } } -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RevocationRegistryV1 { - pub value: ursa::cl::RevocationRegistry, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(tag = "ver")] -pub enum RevocationRegistryDelta { - #[serde(rename = "1.0")] - RevocationRegistryDeltaV1(RevocationRegistryDeltaV1), -} - -impl Validatable for RevocationRegistryDelta {} - #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct RevocationRegistryDeltaV1 { +pub struct RevocationRegistryDelta { pub value: ursa::cl::RevocationRegistryDelta, } +impl Validatable for RevocationRegistryDelta {} + #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RevocationStatusList { - rev_reg_id: RevocationRegistryId, + #[serde(skip_serializing_if = "Option::is_none")] + rev_reg_def_id: Option, #[serde(with = "serde_revocation_list")] revocation_list: bitvec::vec::BitVec, - #[serde(flatten)] - registry: ursa::cl::RevocationRegistry, - timestamp: u64, + #[serde(flatten, skip_serializing_if = "Option::is_none")] + registry: Option, + #[serde(skip_serializing_if = "Option::is_none")] + timestamp: Option, } -impl From<&RevocationStatusList> for ursa::cl::RevocationRegistry { - fn from(rev_reg_list: &RevocationStatusList) -> ursa::cl::RevocationRegistry { - rev_reg_list.registry.clone() +impl From<&RevocationStatusList> for Option { + fn from(rev_status_list: &RevocationStatusList) -> Option { + rev_status_list.registry.clone() } } impl RevocationStatusList { - pub(crate) fn timestamp(&self) -> u64 { + pub(crate) fn timestamp(&self) -> Option { self.timestamp } @@ -79,18 +61,26 @@ impl RevocationStatusList { &self.revocation_list } + pub fn set_registry(&mut self, registry: ursa::cl::RevocationRegistry) { + self.registry = Some(registry) + } + pub(crate) fn state_owned(&self) -> bitvec::vec::BitVec { self.revocation_list.clone() } + pub(crate) fn get(&self, idx: usize) -> Option { + self.revocation_list.get(idx).as_deref().copied() + } + pub fn new( - rev_reg_id: &str, + rev_reg_def_id: Option<&str>, revocation_list: bitvec::vec::BitVec, - registry: ursa::cl::RevocationRegistry, - timestamp: u64, + registry: Option, + timestamp: Option, ) -> Result { Ok(RevocationStatusList { - rev_reg_id: RevocationRegistryId::new(rev_reg_id)?, + rev_reg_def_id: rev_reg_def_id.map(RevocationRegistryId::new).transpose()?, revocation_list, registry, timestamp, @@ -157,7 +147,7 @@ mod tests { const REVOCATION_LIST: &str = r#" { - "revRegId": "reg", + "revRegDefId": "reg", "revocationList": [1, 1, 1, 1], "accum": "1 1379509F4D411630D308A5ABB4F422FCE6737B330B1C5FD286AA5C26F2061E60 1 235535CC45D4816C7686C5A402A230B35A62DDE82B4A652E384FD31912C4E4BB 1 0C94B61595FCAEFC892BB98A27D524C97ED0B7ED1CC49AD6F178A59D4199C9A4 1 172482285606DEE8500FC8A13E6A35EC071F8B84F0EB4CD3DD091C0B4CD30E5E 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000", "timestamp": 1234 diff --git a/anoncreds/src/data_types/anoncreds/rev_reg_def.rs b/anoncreds/src/data_types/anoncreds/rev_reg_def.rs index cfa19d93..e0d84479 100644 --- a/anoncreds/src/data_types/anoncreds/rev_reg_def.rs +++ b/anoncreds/src/data_types/anoncreds/rev_reg_def.rs @@ -1,55 +1,16 @@ use std::str::FromStr; use crate::{ - data_types::{invalid, ConversionError, Validatable, ValidationError}, + data_types::{ConversionError, Validatable, ValidationError}, impl_anoncreds_object_identifier, }; -use super::cred_def::CredentialDefinitionId; +use super::{cred_def::CredentialDefinitionId, issuer_id::IssuerId}; pub const CL_ACCUM: &str = "CL_ACCUM"; -pub const ISSUANCE_BY_DEFAULT: &str = "ISSUANCE_BY_DEFAULT"; -pub const ISSUANCE_ON_DEMAND: &str = "ISSUANCE_ON_DEMAND"; - impl_anoncreds_object_identifier!(RevocationRegistryDefinitionId); -#[allow(non_camel_case_types)] -#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] -pub enum IssuanceType { - #[default] - ISSUANCE_BY_DEFAULT, - ISSUANCE_ON_DEMAND, -} - -impl FromStr for IssuanceType { - type Err = ConversionError; - - fn from_str(s: &str) -> Result { - match s { - ISSUANCE_BY_DEFAULT => Ok(Self::ISSUANCE_BY_DEFAULT), - ISSUANCE_ON_DEMAND => Ok(Self::ISSUANCE_ON_DEMAND), - _ => Err(ConversionError::from_msg("Invalid issuance type")), - } - } -} - -impl From for usize { - fn from(value: IssuanceType) -> usize { - match value { - // Credentials are by default revoked - IssuanceType::ISSUANCE_ON_DEMAND => 1, - // Credentials are by default not revoked - IssuanceType::ISSUANCE_BY_DEFAULT => 0, - } - } -} - -impl IssuanceType { - pub fn to_bool(&self) -> bool { - *self == IssuanceType::ISSUANCE_BY_DEFAULT - } -} #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub enum RegistryType { @@ -70,7 +31,6 @@ impl FromStr for RegistryType { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct RevocationRegistryDefinitionValue { - pub issuance_type: IssuanceType, pub max_cred_num: u32, pub public_keys: RevocationRegistryDefinitionValuePublicKeys, pub tails_hash: String, @@ -83,23 +43,17 @@ pub struct RevocationRegistryDefinitionValuePublicKeys { pub accum_key: ursa::cl::RevocationKeyPublic, } -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(tag = "ver")] -pub enum RevocationRegistryDefinition { - #[serde(rename = "1.0")] - RevocationRegistryDefinitionV1(RevocationRegistryDefinitionV1), -} - #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct RevocationRegistryDefinitionV1 { +pub struct RevocationRegistryDefinition { + pub issuer_id: IssuerId, pub revoc_def_type: RegistryType, pub tag: String, pub cred_def_id: CredentialDefinitionId, pub value: RevocationRegistryDefinitionValue, } -impl Validatable for RevocationRegistryDefinitionV1 { +impl Validatable for RevocationRegistryDefinition { fn validate(&self) -> Result<(), ValidationError> { self.cred_def_id.validate() } @@ -109,20 +63,3 @@ impl Validatable for RevocationRegistryDefinitionV1 { pub struct RevocationRegistryDefinitionPrivate { pub value: ursa::cl::RevocationKeyPrivate, } - -#[derive(Deserialize, Debug, Serialize)] -pub struct RevocationRegistryConfig { - pub issuance_type: Option, - pub max_cred_num: Option, -} - -impl Validatable for RevocationRegistryConfig { - fn validate(&self) -> Result<(), ValidationError> { - if let Some(num_) = self.max_cred_num { - if num_ == 0 { - return Err(invalid!("RevocationRegistryConfig validation failed: `max_cred_num` must be greater than 0")); - } - } - Ok(()) - } -} diff --git a/anoncreds/src/ffi/credential.rs b/anoncreds/src/ffi/credential.rs index 3fd17675..757e06ca 100644 --- a/anoncreds/src/ffi/credential.rs +++ b/anoncreds/src/ffi/credential.rs @@ -60,6 +60,7 @@ pub extern "C" fn anoncreds_create_credential( attr_raw_values: FfiStrList, attr_enc_values: FfiStrList, rev_reg_id: FfiStr, + rev_status_list: ObjectHandle, revocation: *const FfiCredRevInfo, cred_p: *mut ObjectHandle, rev_reg_p: *mut ObjectHandle, @@ -135,6 +136,7 @@ pub extern "C" fn anoncreds_create_credential( } else { None }; + let (cred, rev_reg, rev_delta) = create_credential( cred_def.load()?.cast_ref()?, cred_def_private.load()?.cast_ref()?, @@ -142,6 +144,7 @@ pub extern "C" fn anoncreds_create_credential( cred_request.load()?.cast_ref()?, cred_values.into(), rev_reg_id, + rev_status_list.load()?.cast_ref().ok(), revocation_config .as_ref() .map(RevocationConfig::as_ref_config) diff --git a/anoncreds/src/ffi/revocation.rs b/anoncreds/src/ffi/revocation.rs index 9b908d26..266cee1c 100644 --- a/anoncreds/src/ffi/revocation.rs +++ b/anoncreds/src/ffi/revocation.rs @@ -16,9 +16,8 @@ use crate::services::{ prover::create_or_update_revocation_state, tails::{TailsFileReader, TailsFileWriter}, types::{ - CredentialRevocationState, IssuanceType, RegistryType, RevocationRegistry, - RevocationRegistryDefinition, RevocationRegistryDefinitionPrivate, RevocationRegistryDelta, - RevocationStatusList, + CredentialRevocationState, RegistryType, RevocationRegistry, RevocationRegistryDefinition, + RevocationRegistryDefinitionPrivate, RevocationRegistryDelta, RevocationStatusList, }, }; @@ -26,9 +25,9 @@ use crate::services::{ pub extern "C" fn anoncreds_create_revocation_registry( cred_def: ObjectHandle, cred_def_id: FfiStr, + issuer_id: FfiStr, tag: FfiStr, rev_reg_type: FfiStr, - issuance_type: FfiStr, max_cred_num: i64, tails_dir_path: FfiStr, reg_def_p: *mut ObjectHandle, @@ -45,23 +44,22 @@ pub extern "C" fn anoncreds_create_revocation_registry( let cred_def_id = cred_def_id .as_opt_str() .ok_or_else(|| err_msg!("Missing cred def id"))?; + let issuer_id = issuer_id + .as_opt_str() + .ok_or_else(|| err_msg!("Missing issuer id"))?; let rev_reg_type = { let rtype = rev_reg_type .as_opt_str() .ok_or_else(|| err_msg!("Missing registry type"))?; RegistryType::from_str(rtype).map_err(err_map!(Input))? }; - let issuance_type = match issuance_type.as_opt_str() { - Some(s) => IssuanceType::from_str(s).map_err(err_map!(Input))?, - None => IssuanceType::default(), - }; let mut tails_writer = TailsFileWriter::new(tails_dir_path.into_opt_string()); let (reg_def, reg_def_private, reg_entry, reg_init_delta) = create_revocation_registry( cred_def.load()?.cast_ref()?, cred_def_id, + issuer_id, tag, rev_reg_type, - issuance_type, max_cred_num .try_into() .map_err(|_| err_msg!("Invalid maximum credential count"))?, @@ -180,21 +178,9 @@ pub extern "C" fn anoncreds_revocation_registry_definition_get_attribute( let reg_def = handle.load()?; let reg_def = reg_def.cast_ref::()?; let val = match name.as_opt_str().unwrap_or_default() { - "max_cred_num" => match reg_def { - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(r) => { - r.value.max_cred_num.to_string() - } - }, - "tails_hash" => match reg_def { - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(r) => { - r.value.tails_hash.to_string() - } - }, - "tails_location" => match reg_def { - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(r) => { - r.value.tails_location.to_string() - } - }, + "max_cred_num" => reg_def.value.max_cred_num.to_string(), + "tails_hash" => reg_def.value.tails_hash.to_string(), + "tails_location" => reg_def.value.tails_location.to_string(), s => return Err(err_msg!("Unsupported attribute: {}", s)), }; unsafe { *result_p = rust_string_to_c(val) }; @@ -246,17 +232,17 @@ impl_anoncreds_object_from_json!(RevocationStatusList, anoncreds_revocation_list #[no_mangle] pub extern "C" fn anoncreds_create_or_update_revocation_state( rev_reg_def: ObjectHandle, - rev_reg_list: ObjectHandle, + rev_status_list: ObjectHandle, rev_reg_index: i64, tails_path: FfiStr, rev_state: ObjectHandle, - old_rev_reg_list: ObjectHandle, + old_rev_status_list: ObjectHandle, rev_state_p: *mut ObjectHandle, ) -> ErrorCode { catch_error(|| { check_useful_c_ptr!(rev_state_p); let prev_rev_state = rev_state.opt_load()?; - let prev_rev_reg_list = old_rev_reg_list.opt_load()?; + let prev_rev_status_list = old_rev_status_list.opt_load()?; let tails_reader = TailsFileReader::new_tails_reader( tails_path .as_opt_str() @@ -265,7 +251,7 @@ pub extern "C" fn anoncreds_create_or_update_revocation_state( let rev_state = create_or_update_revocation_state( tails_reader, rev_reg_def.load()?.cast_ref()?, - rev_reg_list.load()?.cast_ref()?, + rev_status_list.load()?.cast_ref()?, rev_reg_index .try_into() .map_err(|_| err_msg!("Invalid credential revocation index"))?, @@ -273,7 +259,7 @@ pub extern "C" fn anoncreds_create_or_update_revocation_state( .as_ref() .map(AnonCredsObject::cast_ref) .transpose()?, - prev_rev_reg_list + prev_rev_status_list .as_ref() .map(AnonCredsObject::cast_ref) .transpose()?, diff --git a/anoncreds/src/services/issuer.rs b/anoncreds/src/services/issuer.rs index 88568dc3..c0f27513 100644 --- a/anoncreds/src/services/issuer.rs +++ b/anoncreds/src/services/issuer.rs @@ -13,11 +13,8 @@ use crate::data_types::anoncreds::schema::SchemaId; use crate::data_types::anoncreds::{ cred_def::{CredentialDefinition, CredentialDefinitionData}, nonce::Nonce, - rev_reg::{RevocationRegistryDeltaV1, RevocationRegistryV1}, - rev_reg_def::{ - RevocationRegistryDefinitionV1, RevocationRegistryDefinitionValue, - RevocationRegistryDefinitionValuePublicKeys, - }, + rev_reg::RevocationRegistryDelta, + rev_reg_def::{RevocationRegistryDefinitionValue, RevocationRegistryDefinitionValuePublicKeys}, schema::Schema, }; use crate::error::Result; @@ -122,9 +119,9 @@ where pub fn create_revocation_registry( cred_def: &CredentialDefinition, cred_def_id: impl TryInto, + issuer_id: impl TryInto, tag: &str, rev_reg_type: RegistryType, - issuance_type: IssuanceType, max_cred_num: u32, tails_writer: &mut TW, ) -> Result<( @@ -136,9 +133,10 @@ pub fn create_revocation_registry( where TW: TailsWriter, { - trace!("create_revocation_registry >>> cred_def: {:?}, tag: {:?}, max_cred_num: {:?}, rev_reg_type: {:?}, issuance_type: {:?}", - cred_def, tag, max_cred_num, rev_reg_type, issuance_type); + trace!("create_revocation_registry >>> cred_def: {:?}, tag: {:?}, max_cred_num: {:?}, rev_reg_type: {:?}", + cred_def, tag, max_cred_num, rev_reg_type); let cred_def_id = cred_def_id.try_into()?; + let issuer_id = issuer_id.try_into()?; let credential_pub_key = cred_def.get_public_key().map_err(err_map!( Unexpected, @@ -158,27 +156,25 @@ where let revoc_reg_def_value = RevocationRegistryDefinitionValue { max_cred_num, - issuance_type, public_keys: rev_keys_pub, tails_location: tails_location.clone(), tails_hash, }; - let revoc_reg_def = RevocationRegistryDefinition::RevocationRegistryDefinitionV1( - RevocationRegistryDefinitionV1 { - revoc_def_type: rev_reg_type, - tag: tag.to_string(), - cred_def_id, - value: revoc_reg_def_value, - }, - ); + let revoc_reg_def = RevocationRegistryDefinition { + revoc_def_type: rev_reg_type, + issuer_id, + tag: tag.to_string(), + cred_def_id, + value: revoc_reg_def_value, + }; - let revoc_reg = RevocationRegistry::RevocationRegistryV1(RevocationRegistryV1 { + let revoc_reg = RevocationRegistry { value: revoc_registry, - }); + }; // now update registry to reflect issuance-by-default - let (revoc_reg, revoc_init_delta) = if issuance_type == IssuanceType::ISSUANCE_BY_DEFAULT { + let (revoc_reg, revoc_init_delta) = { let tails_reader = TailsFileReader::new_tails_reader(&tails_location); let issued = BTreeSet::from_iter(1..=max_cred_num); update_revocation_registry( @@ -188,9 +184,6 @@ where BTreeSet::new(), &tails_reader, )? - } else { - let delta = revoc_reg.initial_delta(); - (revoc_reg, delta) }; let revoc_def_priv = RevocationRegistryDefinitionPrivate { @@ -214,10 +207,8 @@ pub fn update_revocation_registry( revoked: BTreeSet, tails_reader: &TailsReader, ) -> Result<(RevocationRegistry, RevocationRegistryDelta)> { - let RevocationRegistryDefinition::RevocationRegistryDefinitionV1(rev_reg_def) = rev_reg_def; - let mut rev_reg = match rev_reg { - RevocationRegistry::RevocationRegistryV1(v1) => v1.value.clone(), - }; + let mut rev_reg = rev_reg.value.clone(); + let max_cred_num = rev_reg_def.value.max_cred_num; let delta = CryptoIssuer::update_revocation_registry( &mut rev_reg, @@ -227,10 +218,8 @@ pub fn update_revocation_registry( tails_reader, )?; Ok(( - RevocationRegistry::RevocationRegistryV1(RevocationRegistryV1 { value: rev_reg }), - RevocationRegistryDelta::RevocationRegistryDeltaV1(RevocationRegistryDeltaV1 { - value: delta, - }), + RevocationRegistry { value: rev_reg }, + RevocationRegistryDelta { value: delta }, )) } @@ -267,6 +256,7 @@ pub fn create_credential( cred_request: &CredentialRequest, cred_values: CredentialValues, rev_reg_id: Option, + rev_status_list: Option<&RevocationStatusList>, revocation_config: Option, ) -> Result<( Credential, @@ -288,14 +278,33 @@ pub fn create_credential( let prover_did = cred_request.prover_did.as_ref().unwrap_or(&rand_str); let (credential_signature, signature_correctness_proof, rev_reg, rev_reg_delta, witness) = - match revocation_config { - Some(revocation) => { - let rev_reg_def = match revocation.reg_def { - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(v1) => &v1.value, - }; - let mut rev_reg = match revocation.registry { - RevocationRegistry::RevocationRegistryV1(v1) => v1.value.clone(), - }; + match (revocation_config, rev_status_list) { + (Some(revocation_config), Some(rev_status_list)) => { + let rev_reg_def = &revocation_config.reg_def.value; + let mut rev_reg = revocation_config.registry.value.clone(); + + let status = rev_status_list + .get(revocation_config.registry_idx as usize) + .ok_or_else(|| { + err_msg!( + "Revocation status list does not have the index {}", + revocation_config.registry_idx + ) + })?; + + // This will be a temporary solution for the `issuance_on_demand` vs + // `issuance_by_default` state. Right now, we pass in the revcation status list and + // we check in this list whether the provided idx (revocation_config.registry_idx) + // is inside the revocation status list. If it is not in there we hit an edge case, + // which should not be possible within the happy flow. + // + // If the index is inside the revocation status list we check whether it is set to + // `true` or `false` within the bitvec. + // When it is set to `true`, or 1, we invert the value. This means that we use + // `issuance_on_demand`. + // When it is set to `false`, or 0, we invert the value. This means that we use + // `issuance_by_default`. + let issuance_type = !status; let (credential_signature, signature_correctness_proof, delta) = CryptoIssuer::sign_credential_with_revoc( @@ -307,33 +316,27 @@ pub fn create_credential( &credential_values, &cred_public_key, &cred_def_private.value, - revocation.registry_idx, + revocation_config.registry_idx, rev_reg_def.max_cred_num, - rev_reg_def.issuance_type.to_bool(), + issuance_type, &mut rev_reg, - &revocation.reg_def_private.value, - &revocation.tails_reader, + &revocation_config.reg_def_private.value, + &revocation_config.tails_reader, )?; let witness = { let empty = HashSet::new(); - let (by_default, issued, revoked) = match rev_reg_def.issuance_type { - IssuanceType::ISSUANCE_ON_DEMAND => { - (false, revocation.registry_used, &empty) - } - IssuanceType::ISSUANCE_BY_DEFAULT => { - (true, &empty, revocation.registry_used) - } - }; + let (by_default, issued, revoked) = + (true, &empty, revocation_config.registry_used); let rev_reg_delta = CryptoRevocationRegistryDelta::from_parts(None, &rev_reg, issued, revoked); Witness::new( - revocation.registry_idx, + revocation_config.registry_idx, rev_reg_def.max_cred_num, by_default, &rev_reg_delta, - &revocation.tails_reader, + &revocation_config.tails_reader, )? }; ( @@ -344,7 +347,7 @@ pub fn create_credential( Some(witness), ) } - None => { + _ => { let (signature, correctness_proof) = CryptoIssuer::sign_credential( prover_did, &cred_request.blinded_ms, @@ -370,13 +373,8 @@ pub fn create_credential( witness, }; - let rev_reg = rev_reg - .map(|reg| RevocationRegistry::RevocationRegistryV1(RevocationRegistryV1 { value: reg })); - let rev_reg_delta = rev_reg_delta.map(|delta| { - RevocationRegistryDelta::RevocationRegistryDeltaV1(RevocationRegistryDeltaV1 { - value: delta, - }) - }); + let rev_reg = rev_reg.map(|reg| RevocationRegistry { value: reg }); + let rev_reg_delta = rev_reg_delta.map(|delta| RevocationRegistryDelta { value: delta }); trace!( "create_credential <<< credential {:?}, rev_reg_delta {:?}", @@ -400,20 +398,15 @@ pub fn revoke_credential( secret!(&cred_rev_idx) ); - let max_cred_num = match rev_reg_def { - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(v1) => v1.value.max_cred_num, - }; - let mut rev_reg = match rev_reg { - RevocationRegistry::RevocationRegistryV1(v1) => v1.value.clone(), - }; + let max_cred_num = rev_reg_def.value.max_cred_num; + let mut rev_reg = rev_reg.value.clone(); let rev_reg_delta = CryptoIssuer::revoke_credential(&mut rev_reg, max_cred_num, cred_rev_idx, tails_reader)?; - let new_rev_reg = - RevocationRegistry::RevocationRegistryV1(RevocationRegistryV1 { value: rev_reg }); - let delta = RevocationRegistryDelta::RevocationRegistryDeltaV1(RevocationRegistryDeltaV1 { + let new_rev_reg = RevocationRegistry { value: rev_reg }; + let delta = RevocationRegistryDelta { value: rev_reg_delta, - }); + }; trace!("revoke <<< rev_reg_delta {:?}", delta); Ok((new_rev_reg, delta)) @@ -433,20 +426,16 @@ pub fn recover_credential( secret!(&cred_rev_idx) ); - let max_cred_num = match rev_reg_def { - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(v1) => v1.value.max_cred_num, - }; - let mut rev_reg = match rev_reg { - RevocationRegistry::RevocationRegistryV1(v1) => v1.value.clone(), - }; + let max_cred_num = rev_reg_def.value.max_cred_num; + let mut rev_reg = rev_reg.value.clone(); + let rev_reg_delta = CryptoIssuer::recovery_credential(&mut rev_reg, max_cred_num, cred_rev_idx, tails_reader)?; - let new_rev_reg = - RevocationRegistry::RevocationRegistryV1(RevocationRegistryV1 { value: rev_reg }); - let delta = RevocationRegistryDelta::RevocationRegistryDeltaV1(RevocationRegistryDeltaV1 { + let new_rev_reg = RevocationRegistry { value: rev_reg }; + let delta = RevocationRegistryDelta { value: rev_reg_delta, - }); + }; trace!("recover <<< rev_reg_delta {:?}", delta); Ok((new_rev_reg, delta)) @@ -456,16 +445,9 @@ pub fn merge_revocation_registry_deltas( rev_reg_delta: &RevocationRegistryDelta, other_delta: &RevocationRegistryDelta, ) -> Result { - match (rev_reg_delta, other_delta) { - ( - RevocationRegistryDelta::RevocationRegistryDeltaV1(v1), - RevocationRegistryDelta::RevocationRegistryDeltaV1(other), - ) => { - let mut result = v1.clone(); - result.value.merge(&other.value)?; - Ok(RevocationRegistryDelta::RevocationRegistryDeltaV1(result)) - } - } + let mut result = rev_reg_delta.clone(); + result.value.merge(&other_delta.value)?; + Ok(result) } #[cfg(test)] diff --git a/anoncreds/src/services/prover.rs b/anoncreds/src/services/prover.rs index c70dba78..9f087992 100644 --- a/anoncreds/src/services/prover.rs +++ b/anoncreds/src/services/prover.rs @@ -104,12 +104,7 @@ pub fn process_credential( )?; let credential_values = build_credential_values(&credential.values.0, Some(&master_secret.value))?; - let rev_pub_key = match rev_reg_def { - Some(RevocationRegistryDefinition::RevocationRegistryDefinitionV1(def)) => { - Some(&def.value.public_keys.accum_key) - } - _ => None, - }; + let rev_pub_key = rev_reg_def.map(|d| &d.value.public_keys.accum_key); CryptoProver::process_credential_signature( &mut credential.signature, @@ -254,74 +249,92 @@ pub fn create_presentation( pub fn create_or_update_revocation_state( tails_reader: TailsReader, revoc_reg_def: &RevocationRegistryDefinition, - rev_reg_list: &RevocationStatusList, + rev_status_list: &RevocationStatusList, rev_reg_idx: u32, rev_state: Option<&CredentialRevocationState>, // for witness update - old_rev_reg_list: Option<&RevocationStatusList>, // for witness update + old_rev_status_list: Option<&RevocationStatusList>, // for witness update ) -> Result { trace!( "create_or_update_revocation_state >>> , tails_reader: {:?}, revoc_reg_def: {:?}, \ - rev_reg_list: {:?}, rev_reg_idx: {}, rev_state: {:?}, old_rev_reg_list {:?}", + rev_status_list: {:?}, rev_reg_idx: {}, rev_state: {:?}, old_rev_status_list {:?}", tails_reader, revoc_reg_def, - rev_reg_list, + rev_status_list, rev_reg_idx, rev_state, - old_rev_reg_list, + old_rev_status_list, ); - let RevocationRegistryDefinition::RevocationRegistryDefinitionV1(revoc_reg_def) = revoc_reg_def; + let rev_reg: Option = rev_status_list.into(); + let rev_reg = rev_reg.ok_or(err_msg!( + "revocation registry is required to create or update the revocation state" + ))?; + + let timestamp = rev_status_list.timestamp().ok_or_else(|| { + err_msg!("Timestamp is required to create or update the revocation state") + })?; + let mut issued = HashSet::::new(); let mut revoked = HashSet::::new(); - let witness = - if let (Some(source_rev_state), Some(source_rev_list)) = (rev_state, old_rev_reg_list) { - _create_index_deltas( - rev_reg_list.state_owned().bitxor(source_rev_list.state()), - rev_reg_list.state(), - &mut issued, - &mut revoked, - ); + let witness = if let (Some(source_rev_state), Some(source_rev_list)) = + (rev_state, old_rev_status_list) + { + _create_index_deltas( + rev_status_list + .state_owned() + .bitxor(source_rev_list.state()), + rev_status_list.state(), + &mut issued, + &mut revoked, + ); - let rev_reg_delta = RevocationRegistryDelta::from_parts( - Some(&source_rev_list.into()), - &rev_reg_list.into(), - &issued, - &revoked, - ); - let mut witness = source_rev_state.witness.clone(); - witness.update( - rev_reg_idx, - revoc_reg_def.value.max_cred_num, - &rev_reg_delta, - &tails_reader, - )?; - witness - } else { - let list_size = usize::try_from(revoc_reg_def.value.max_cred_num) - .map_err(|e| Error::from_msg(crate::ErrorKind::InvalidState, e.to_string()))?; - let bit: usize = revoc_reg_def.value.issuance_type.into(); - let list = bitvec![bit; list_size]; - _create_index_deltas( - rev_reg_list.state_owned().bitxor(list), - rev_reg_list.state(), - &mut issued, - &mut revoked, - ); - let rev_reg_delta = - RevocationRegistryDelta::from_parts(None, &rev_reg_list.into(), &issued, &revoked); - Witness::new( - rev_reg_idx, - revoc_reg_def.value.max_cred_num, - revoc_reg_def.value.issuance_type.to_bool(), - &rev_reg_delta, - &tails_reader, - )? - }; + let source_rev_reg: Option = source_rev_list.into(); + + let rev_reg_delta = RevocationRegistryDelta::from_parts( + source_rev_reg.as_ref(), + &rev_reg, + &issued, + &revoked, + ); + let mut witness = source_rev_state.witness.clone(); + witness.update( + rev_reg_idx, + revoc_reg_def.value.max_cred_num, + &rev_reg_delta, + &tails_reader, + )?; + witness + } else { + let list_size = usize::try_from(revoc_reg_def.value.max_cred_num) + .map_err(|e| Error::from_msg(crate::ErrorKind::InvalidState, e.to_string()))?; + // Issuance by default + let bit: usize = 0; + let list = bitvec![bit; list_size]; + _create_index_deltas( + rev_status_list.state_owned().bitxor(list), + rev_status_list.state(), + &mut issued, + &mut revoked, + ); + let rev_reg: Option = rev_status_list.into(); + let rev_reg = rev_reg.ok_or(err_msg!( + "revocation registry is not inside the revocation status list" + ))?; + let rev_reg_delta = RevocationRegistryDelta::from_parts(None, &rev_reg, &issued, &revoked); + Witness::new( + rev_reg_idx, + revoc_reg_def.value.max_cred_num, + // issuance by default + true, + &rev_reg_delta, + &tails_reader, + )? + }; Ok(CredentialRevocationState { witness, - rev_reg: rev_reg_list.into(), - timestamp: rev_reg_list.timestamp(), + rev_reg, + timestamp, }) } diff --git a/anoncreds/src/services/types.rs b/anoncreds/src/services/types.rs index f792f258..27d89146 100644 --- a/anoncreds/src/services/types.rs +++ b/anoncreds/src/services/types.rs @@ -11,8 +11,7 @@ pub use crate::data_types::anoncreds::{ presentation::Presentation, rev_reg::{RevocationRegistry, RevocationRegistryDelta, RevocationStatusList}, rev_reg_def::{ - IssuanceType, RegistryType, RevocationRegistryDefinition, - RevocationRegistryDefinitionPrivate, + RegistryType, RevocationRegistryDefinition, RevocationRegistryDefinitionPrivate, }, schema::AttributeNames, }; diff --git a/anoncreds/src/services/verifier.rs b/anoncreds/src/services/verifier.rs index ec973c44..bf85b598 100644 --- a/anoncreds/src/services/verifier.rs +++ b/anoncreds/src/services/verifier.rs @@ -173,14 +173,8 @@ pub fn verify_presentation( cred_def.value.revocation.as_ref(), )?; - let rev_key_pub = rev_reg_def.as_ref().map(|r_reg_def| match r_reg_def { - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(reg_def) => { - ®_def.value.public_keys.accum_key - } - }); - let rev_reg = rev_reg.as_ref().map(|r_reg| match r_reg { - RevocationRegistry::RevocationRegistryV1(reg_def) => ®_def.value, - }); + let rev_key_pub = rev_reg_def.map(|d| &d.value.public_keys.accum_key); + let rev_reg = rev_reg.map(|r| &r.value); proof_verifier.add_sub_proof_request( &sub_pres_request, diff --git a/anoncreds/tests/anoncreds_demos.rs b/anoncreds/tests/anoncreds_demos.rs index 8af3aae8..0e65d30c 100644 --- a/anoncreds/tests/anoncreds_demos.rs +++ b/anoncreds/tests/anoncreds_demos.rs @@ -15,8 +15,8 @@ use anoncreds::{ tails::{TailsFileReader, TailsFileWriter}, types::{ CredentialDefinitionConfig, CredentialRevocationConfig, CredentialRevocationState, - IssuanceType, MakeCredentialValues, PresentCredentials, PresentationRequest, RegistryType, - RevocationRegistry, RevocationRegistryDefinition, RevocationStatusList, SignatureType, + MakeCredentialValues, PresentCredentials, PresentationRequest, RegistryType, + RevocationStatusList, SignatureType, }, verifier, }; @@ -111,6 +111,7 @@ fn anoncreds_works_for_single_issuer_single_prover() { cred_values.into(), None, None, + None, ) .expect("Error creating credential"); @@ -284,9 +285,9 @@ fn anoncreds_with_revocation_works_for_single_issuer_single_prover() { let (rev_reg_def_pub, rev_reg_def_priv, rev_reg, _) = issuer::create_revocation_registry( &cred_def_pub, CRED_DEF_ID, + ISSUER_ID, "some_tag", RegistryType::CL_ACCUM, - IssuanceType::ISSUANCE_BY_DEFAULT, MAX_CRED_NUM, &mut tf, ) @@ -339,16 +340,17 @@ fn anoncreds_with_revocation_works_for_single_issuer_single_prover() { let rev_reg_id = RevocationRegistryId::new_unchecked(REV_REG_ID); // Get the location of the tails_file so it can be read - let location = match rev_reg_def_pub.clone() { - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(value) => { - value.value.tails_location - } - }; + let location = rev_reg_def_pub.clone().value.tails_location; + let tr = TailsFileReader::new_tails_reader(location.as_str()); // The Prover's index in the revocation list is REV_IDX let registry_used = HashSet::from([REV_IDX]); + let list = bitvec![0; MAX_CRED_NUM as usize ]; + let revocation_status_list = + RevocationStatusList::new(None, list, None, None).expect("Error creating status list"); + // TODO: Here Delta is not needed but is it used elsewhere? let (issue_cred, cred_rev_reg, _) = issuer::create_credential( &*gvt_cred_def, @@ -357,6 +359,7 @@ fn anoncreds_with_revocation_works_for_single_issuer_single_prover() { &cred_request, cred_values.into(), Some(rev_reg_id.clone()), + Some(&revocation_status_list), Some(CredentialRevocationConfig { reg_def: &rev_reg_def_pub, reg_def_private: &rev_reg_def_priv, @@ -414,9 +417,8 @@ fn anoncreds_with_revocation_works_for_single_issuer_single_prover() { // Prover: here we deliberately do not put in the same timestamp as the global non_revoked time interval, // this shows that it is not used let prover_timestamp = 1234u64; - let rev_reg = match cred_rev_reg.clone() { - RevocationRegistry::RevocationRegistryV1(r) => r.value, - }; + let rev_reg = cred_rev_reg.clone().value; + let rev_state = CredentialRevocationState { timestamp: prover_timestamp, rev_reg: rev_reg.clone(), @@ -452,6 +454,8 @@ fn anoncreds_with_revocation_works_for_single_issuer_single_prover() { // Create the map that contines the registries let rev_timestamp_map = HashMap::from([(prover_timestamp, &cred_rev_reg)]); + + let rev_reg_id = RevocationRegistryId::new_unchecked(REV_REG_ID); let mut rev_reg_map = HashMap::from([(rev_reg_id.clone(), rev_timestamp_map.clone())]); let valid = verifier::verify_presentation( @@ -477,12 +481,15 @@ fn anoncreds_with_revocation_works_for_single_issuer_single_prover() { // revoked_bit is not a reference so can drop drop(revoked_bit); - let ursa_rev_reg = match revoked_rev_reg.clone() { - RevocationRegistry::RevocationRegistryV1(v) => v.value, - }; + let ursa_rev_reg = revoked_rev_reg.clone().value; - let revocation_list = - RevocationStatusList::new(REV_REG_ID, list, ursa_rev_reg, prover_timestamp).unwrap(); + let revocation_list = RevocationStatusList::new( + Some(REV_REG_ID), + list, + Some(ursa_rev_reg), + Some(prover_timestamp), + ) + .unwrap(); let new_rev_state = prover::create_or_update_revocation_state( tr, &rev_reg_def_pub,