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

CredxAnoncreds verifier functionality support #708

Merged
merged 9 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 13 additions & 16 deletions aries_vcx/src/common/proofs/verifier/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ pub mod unit_tests {

#[tokio::test]
async fn test_proof_self_attested_proof_validation() {
SetupProfile::run_indy(|setup| async move {
let holder_setup = init_holder_setup_in_indy_context(&setup).await;

SetupProfile::run(|setup| async move {
let requested_attrs = json!([
json!({
"name":"address1",
Expand All @@ -83,7 +81,7 @@ pub mod unit_tests {
let revocation_details = r#"{"support_revocation":false}"#.to_string();
let name = "Optional".to_owned();

let proof_req_json = ProofRequestData::create(&holder_setup.profile, &name)
let proof_req_json = ProofRequestData::create(&setup.profile, &name)
.await
.unwrap()
.set_requested_attributes_as_string(requested_attrs)
Expand All @@ -95,7 +93,7 @@ pub mod unit_tests {

let proof_req_json = serde_json::to_string(&proof_req_json).unwrap();

let anoncreds = Arc::clone(&holder_setup.profile).inject_anoncreds();
let anoncreds = Arc::clone(&setup.profile).inject_anoncreds();
let prover_proof_json = anoncreds
.prover_create_proof(
&proof_req_json,
Expand Down Expand Up @@ -194,19 +192,18 @@ pub mod unit_tests {
)
.await
.unwrap();
// TODO: should return a new AriesVcxErrorKind err instead of AriesVcxErrorKind::VdrToolsError
assert_eq!(
validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json)
validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json)
.await
.unwrap_err()
.kind(),
AriesVcxErrorKind::VdrToolsError(405)
); // AnoncredsProofRejected
AriesVcxErrorKind::ProofRejected
gmulhearn marked this conversation as resolved.
Show resolved Hide resolved
);

let mut proof_req_json: serde_json::Value = serde_json::from_str(&proof_req_json).unwrap();
proof_req_json["requested_attributes"]["attribute_0"]["restrictions"] = json!({});
assert_eq!(
validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json.to_string())
validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json.to_string())
.await
.unwrap(),
true
Expand Down Expand Up @@ -285,7 +282,7 @@ pub mod unit_tests {
.await
.unwrap();
assert_eq!(
validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json)
validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json)
.await
.unwrap(),
true
Expand All @@ -297,7 +294,7 @@ pub mod unit_tests {
let prover_proof_json = serde_json::to_string(&proof_obj).unwrap();

assert_eq!(
validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json)
validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json)
.await
.unwrap_err()
.kind(),
Expand All @@ -310,7 +307,7 @@ pub mod unit_tests {
let prover_proof_json = serde_json::to_string(&proof_obj).unwrap();

assert_eq!(
validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json)
validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json)
.await
.unwrap_err()
.kind(),
Expand Down Expand Up @@ -338,7 +335,7 @@ pub mod integration_tests {
let (schemas, cred_defs, proof_req, proof) =
create_indy_proof(&setup.profile, &holder_setup.profile, &setup.institution_did).await;

let anoncreds = Arc::clone(&setup.profile).inject_anoncreds();
let anoncreds = Arc::clone(&holder_setup.profile).inject_anoncreds();
let proof_validation = anoncreds
.verifier_verify_proof(&proof_req, &proof, &schemas, &cred_defs, "{}", "{}")
.await
Expand All @@ -357,7 +354,7 @@ pub mod integration_tests {
let (schemas, cred_defs, proof_req, proof) =
create_proof_with_predicate(&setup.profile, &holder_setup.profile, &setup.institution_did, true).await;

let anoncreds = Arc::clone(&setup.profile).inject_anoncreds();
let anoncreds = Arc::clone(&holder_setup.profile).inject_anoncreds();
let proof_validation = anoncreds
.verifier_verify_proof(&proof_req, &proof, &schemas, &cred_defs, "{}", "{}")
.await
Expand All @@ -376,7 +373,7 @@ pub mod integration_tests {
let (schemas, cred_defs, proof_req, proof) =
create_proof_with_predicate(&setup.profile, &holder_setup.profile, &setup.institution_did, false).await;

let anoncreds = Arc::clone(&setup.profile).inject_anoncreds();
let anoncreds = Arc::clone(&holder_setup.profile).inject_anoncreds();
anoncreds
.verifier_verify_proof(&proof_req, &proof, &schemas, &cred_defs, "{}", "{}")
.await
Expand Down
2 changes: 2 additions & 0 deletions aries_vcx/src/errors/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ pub enum AriesVcxErrorKind {
InvalidProofCredentialData,
#[error("Proof Request Passed into Libindy Call Was Invalid")]
InvalidProofRequest,
#[error("The proof was rejected")]
ProofRejected,

// Schema
#[error("No Schema for that schema sequence number")]
Expand Down
13 changes: 11 additions & 2 deletions aries_vcx/src/errors/mapping_credx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,23 @@ use indy_credx::Error as CredxError;

impl From<CredxError> for AriesVcxError {
fn from(err: CredxError) -> Self {
match err.kind() {
// Credx will occasionally wrap the real error within the `cause` of an ErrorKind::Input error type
// So we use this cause error if the cause exists and can be downcast to an credxerror
let cause = if err.kind() == indy_credx::ErrorKind::Input {
err.cause.as_ref().and_then(|x| x.downcast_ref::<CredxError>())
} else {
None
};
let e = cause.unwrap_or(&err);

match e.kind() {
indy_credx::ErrorKind::Input => AriesVcxError::from_msg(AriesVcxErrorKind::InvalidInput, err),
indy_credx::ErrorKind::IOError => AriesVcxError::from_msg(AriesVcxErrorKind::IOError, err),
indy_credx::ErrorKind::InvalidState => AriesVcxError::from_msg(AriesVcxErrorKind::InvalidState, err),
indy_credx::ErrorKind::Unexpected => AriesVcxError::from_msg(AriesVcxErrorKind::UnknownError, err),
indy_credx::ErrorKind::CredentialRevoked => AriesVcxError::from_msg(AriesVcxErrorKind::InvalidState, err),
indy_credx::ErrorKind::InvalidUserRevocId => AriesVcxError::from_msg(AriesVcxErrorKind::InvalidInput, err),
indy_credx::ErrorKind::ProofRejected => AriesVcxError::from_msg(AriesVcxErrorKind::InvalidState, err),
indy_credx::ErrorKind::ProofRejected => AriesVcxError::from_msg(AriesVcxErrorKind::ProofRejected, err),
indy_credx::ErrorKind::RevocationRegistryFull => {
AriesVcxError::from_msg(AriesVcxErrorKind::InvalidState, err)
}
Expand Down
1 change: 1 addition & 0 deletions aries_vcx/src/errors/mapping_vdrtools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl From<IndyErrorKind> for AriesVcxErrorKind {
UnknownWalletStorageType => AriesVcxErrorKind::InvalidConfiguration,
WalletStorageTypeAlreadyRegistered => AriesVcxErrorKind::InvalidConfiguration,
WalletAccessFailed => AriesVcxErrorKind::WalletAccessFailed,
ProofRejected => AriesVcxErrorKind::ProofRejected,
_ => {
let err_code = types::ErrorCode::from(indy) as u32;
AriesVcxErrorKind::VdrToolsError(err_code)
Expand Down
71 changes: 51 additions & 20 deletions aries_vcx/src/plugins/anoncreds/credx_anoncreds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use async_trait::async_trait;
use credx::{
types::{
Credential as CredxCredential, CredentialDefinitionId, CredentialRequestMetadata, CredentialRevocationState,
DidValue, MasterSecret, PresentCredentials, PresentationRequest, RevocationRegistryDefinition,
RevocationRegistryDelta, Schema, SchemaId,
DidValue, MasterSecret, PresentCredentials, Presentation, PresentationRequest, RevocationRegistry,
RevocationRegistryDefinition, RevocationRegistryDelta, RevocationRegistryId, Schema, SchemaId,
},
ursa::bn::BigNumber,
};
Expand Down Expand Up @@ -154,7 +154,36 @@ impl BaseAnonCreds for IndyCredxAnonCreds {
rev_reg_defs_json,
rev_regs_json,
);
Err(unimplemented_method_err("credx verifier_verify_proof"))

let presentation: Presentation = serde_json::from_str(proof_json)?;
let pres_req: PresentationRequest = serde_json::from_str(proof_req_json)?;

let schemas: HashMap<SchemaId, Schema> = serde_json::from_str(schemas_json)?;
let cred_defs: HashMap<CredentialDefinitionId, CredentialDefinition> =
serde_json::from_str(credential_defs_json)?;

let rev_reg_defs: Option<HashMap<RevocationRegistryId, RevocationRegistryDefinition>> =
serde_json::from_str(rev_reg_defs_json)?;

let rev_regs: Option<HashMap<RevocationRegistryId, HashMap<u64, RevocationRegistry>>> =
serde_json::from_str(rev_regs_json)?;
let rev_regs: Option<HashMap<RevocationRegistryId, HashMap<u64, &RevocationRegistry>>> =
rev_regs.as_ref().map(|regs| {
let mut new_regs: HashMap<RevocationRegistryId, HashMap<u64, &RevocationRegistry>> = HashMap::new();
for (k, v) in regs {
new_regs.insert(k.clone(), hashmap_as_ref(v));
}
new_regs
});

Ok(credx::verifier::verify_presentation(
&presentation,
&pres_req,
&hashmap_as_ref(&schemas),
&hashmap_as_ref(&cred_defs),
rev_reg_defs.as_ref().map(|regs| hashmap_as_ref(regs)).as_ref(),
rev_regs.as_ref(),
)?)
}

async fn issuer_create_and_store_revoc_reg(
Expand Down Expand Up @@ -234,8 +263,8 @@ impl BaseAnonCreds for IndyCredxAnonCreds {
None
};

let _schemas: HashMap<SchemaId, Schema> = serde_json::from_str(schemas_json)?;
let _cred_defs: HashMap<CredentialDefinitionId, CredentialDefinition> =
let schemas: HashMap<SchemaId, Schema> = serde_json::from_str(schemas_json)?;
let cred_defs: HashMap<CredentialDefinitionId, CredentialDefinition> =
serde_json::from_str(credential_defs_json)?;

let mut present_credentials: PresentCredentials = PresentCredentials::new();
Expand Down Expand Up @@ -334,25 +363,13 @@ impl BaseAnonCreds for IndyCredxAnonCreds {

let link_secret = self.get_link_secret(link_secret_id).await?;

let mut schemas: HashMap<SchemaId, &Schema> = HashMap::new();

for (k, v) in _schemas.iter() {
schemas.insert(k.clone(), v);
}

let mut cred_defs: HashMap<CredentialDefinitionId, &CredentialDefinition> = HashMap::new();

for (k, v) in _cred_defs.iter() {
cred_defs.insert(k.clone(), v);
}

let presentation = credx::prover::create_presentation(
&pres_req,
present_credentials,
self_attested,
&link_secret,
&schemas,
&cred_defs,
&hashmap_as_ref(&schemas),
&hashmap_as_ref(&cred_defs),
)?;

Ok(serde_json::to_string(&presentation)?)
Expand Down Expand Up @@ -748,6 +765,21 @@ fn unimplemented_method_err(method_name: &str) -> AriesVcxError {
)
}

// common transformation requirement in credx
fn hashmap_as_ref<'a, T, U>(map: &'a HashMap<T, U>) -> HashMap<T, &'a U>
where
T: std::hash::Hash,
T: std::cmp::Eq,
T: std::clone::Clone,
{
let mut new_map: HashMap<T, &U> = HashMap::new();
for (k, v) in map.iter() {
new_map.insert(k.clone(), v);
}

new_map
}

#[cfg(test)]
#[cfg(feature = "general_test")]
mod unit_tests {
Expand All @@ -767,7 +799,6 @@ mod unit_tests {
let profile = mock_profile();
let anoncreds: Box<dyn BaseAnonCreds> = Box::new(IndyCredxAnonCreds::new(profile));

assert_unimplemented(anoncreds.verifier_verify_proof("", "", "", "", "", "").await);
assert_unimplemented(anoncreds.issuer_create_and_store_revoc_reg("", "", "", 0, "").await);
assert_unimplemented(
anoncreds
Expand Down
6 changes: 2 additions & 4 deletions aries_vcx/src/utils/devsetup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ impl SetupProfile {
}

pub async fn init() -> SetupProfile {
init_test_logging();
set_test_configs();
if SetupProfile::should_run_modular() {
info!("SetupProfile >> using modular profile");
SetupProfile::init_modular().await
Expand All @@ -372,8 +374,6 @@ impl SetupProfile {
// FUTURE - ideally no tests should be using this method, they should be using the generic init
// after modular profile Anoncreds/Ledger methods have all been implemented, all tests should use init()
async fn init_indy() -> SetupProfile {
init_test_logging();
set_test_configs();
let (institution_did, wallet_handle) = setup_issuer_wallet().await;

settings::set_config_value(
Expand All @@ -399,8 +399,6 @@ impl SetupProfile {
}

async fn init_modular() -> SetupProfile {
init_test_logging();
set_test_configs();
let (institution_did, wallet_handle) = setup_issuer_wallet().await;

let genesis_file_path = create_tmp_genesis_txn_file();
Expand Down
2 changes: 2 additions & 0 deletions libvcx/src/errors/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ pub enum LibvcxErrorKind {
InvalidProofCredentialData,
#[error("Proof Request Passed into Libindy Call Was Invalid")]
InvalidProofRequest,
#[error("The proof was rejected")]
ProofRejected,

// Schema
#[error("Could not create schema")]
Expand Down
1 change: 1 addition & 0 deletions libvcx/src/errors/mapping_from_ariesvcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl From<AriesVcxErrorKind> for LibvcxErrorKind {
AriesVcxErrorKind::NoAgentInformation => LibvcxErrorKind::NoAgentInformation,
AriesVcxErrorKind::InvalidMessageFormat => LibvcxErrorKind::InvalidMessageFormat,
AriesVcxErrorKind::LedgerItemNotFound => LibvcxErrorKind::LedgerItemNotFound,
AriesVcxErrorKind::ProofRejected => LibvcxErrorKind::ProofRejected,
}
}
}