Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update revocation registry definition #56

76 changes: 33 additions & 43 deletions anoncreds/src/data_types/anoncreds/rev_reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,87 +10,77 @@ 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<RevocationRegistryId>,
#[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<ursa::cl::RevocationRegistry>,
#[serde(skip_serializing_if = "Option::is_none")]
timestamp: Option<u64>,
}

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<ursa::cl::RevocationRegistry> {
fn from(rev_status_list: &RevocationStatusList) -> Option<ursa::cl::RevocationRegistry> {
rev_status_list.registry.clone()
}
}

impl RevocationStatusList {
pub(crate) fn timestamp(&self) -> u64 {
pub(crate) fn timestamp(&self) -> Option<u64> {
self.timestamp
}

pub(crate) fn state(&self) -> &bitvec::vec::BitVec {
&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<bool> {
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<ursa::cl::RevocationRegistry>,
timestamp: Option<u64>,
) -> Result<Self, error::Error> {
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,
Expand Down Expand Up @@ -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
Expand Down
73 changes: 5 additions & 68 deletions anoncreds/src/data_types/anoncreds/rev_reg_def.rs
Original file line number Diff line number Diff line change
@@ -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<Self, Self::Err> {
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<IssuanceType> 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 {
Expand All @@ -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,
Expand All @@ -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()
}
Expand All @@ -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<IssuanceType>,
pub max_cred_num: Option<u32>,
}

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(())
}
}
3 changes: 3 additions & 0 deletions anoncreds/src/ffi/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -135,13 +136,15 @@ 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()?,
cred_offer.load()?.cast_ref()?,
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)
Expand Down
44 changes: 15 additions & 29 deletions anoncreds/src/ffi/revocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,18 @@ 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,
},
};

#[no_mangle]
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,
Expand All @@ -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"))?,
Expand Down Expand Up @@ -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::<RevocationRegistryDefinition>()?;
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) };
Expand Down Expand Up @@ -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()
Expand All @@ -265,15 +251,15 @@ 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"))?,
prev_rev_state
.as_ref()
.map(AnonCredsObject::cast_ref)
.transpose()?,
prev_rev_reg_list
prev_rev_status_list
.as_ref()
.map(AnonCredsObject::cast_ref)
.transpose()?,
Expand Down
Loading