From f5fcf2a13dd32bfb1105aeb608c1f00d55ccff5e Mon Sep 17 00:00:00 2001 From: Patrik Date: Wed, 30 Aug 2023 13:24:42 +0200 Subject: [PATCH] Prover: fix credx credential retrieval (#961) * Test code adjustments Signed-off-by: Patrik Stas * wip Signed-off-by: Patrik Stas * Rename 'requested_credentials' to 'preselected_credentials' Signed-off-by: Patrik Stas * Remove prover_select_credentials_and_fail_to_generate_proof in favor of simpler testing approach Signed-off-by: Patrik Stas * Simplify common testing case of sending proof Signed-off-by: Patrik Stas * Add test test_agency_pool_it_should_select_credentials_for_satisfiable_restriction Signed-off-by: Patrik Stas * Fix credential retrieval by prover Signed-off-by: Patrik Stas * Do not run test_agency_pool_it_should_fail_to_select_credentials_for_predicate for credx implementation Signed-off-by: Patrik Stas * Address code review Signed-off-by: Patrik Stas * Revert CI change Signed-off-by: Patrik Stas --------- Signed-off-by: Patrik Stas Signed-off-by: Bogdan Mircea --- .../src/handlers/proof_presentation/prover.rs | 2 +- aries_vcx/tests/test_creds_proofs.rs | 72 +++++++++++++++---- aries_vcx/tests/utils/scenarios.rs | 69 +++++------------- .../src/anoncreds/credx_anoncreds.rs | 20 +++--- 4 files changed, 88 insertions(+), 75 deletions(-) diff --git a/aries_vcx/src/handlers/proof_presentation/prover.rs b/aries_vcx/src/handlers/proof_presentation/prover.rs index ea078fbf12..bd84de6881 100644 --- a/aries_vcx/src/handlers/proof_presentation/prover.rs +++ b/aries_vcx/src/handlers/proof_presentation/prover.rs @@ -58,7 +58,7 @@ impl Prover { let json_retrieved_credentials = anoncreds .prover_get_credentials_for_proof_req(&presentation_request) .await?; - + trace!("Prover::retrieve_credentials >>> presentation_request: {presentation_request}, json_retrieved_credentials: {json_retrieved_credentials}"); Ok(serde_json::from_str(&json_retrieved_credentials)?) } diff --git a/aries_vcx/tests/test_creds_proofs.rs b/aries_vcx/tests/test_creds_proofs.rs index ba2cf1b478..d3ca1df5b5 100644 --- a/aries_vcx/tests/test_creds_proofs.rs +++ b/aries_vcx/tests/test_creds_proofs.rs @@ -587,10 +587,10 @@ mod tests { accept_cred_proposal, accept_cred_proposal_1, accept_offer, accept_proof_proposal, attr_names, create_and_send_nonrevocable_cred_offer, create_connected_connections, create_proof, decline_offer, generate_and_send_proof, issue_address_credential, prover_select_credentials, - prover_select_credentials_and_fail_to_generate_proof, prover_select_credentials_and_send_proof, - receive_proof_proposal_rejection, reject_proof_proposal, retrieved_to_selected_credentials_simple, - send_cred_proposal, send_cred_proposal_1, send_cred_req, send_credential, send_proof_proposal, - send_proof_proposal_1, send_proof_request, verifier_create_proof_and_send_request, verify_proof, + prover_select_credentials_and_send_proof, receive_proof_proposal_rejection, reject_proof_proposal, + retrieved_to_selected_credentials_simple, send_cred_proposal, send_cred_proposal_1, send_cred_req, + send_credential, send_proof_proposal, send_proof_proposal_1, send_proof_request, + verifier_create_proof_and_send_request, verify_proof, }; #[tokio::test] @@ -733,6 +733,8 @@ mod tests { .await; } + // todo: credx implementation does not support checking credential value in respect to predicate + #[cfg(not(feature = "modular_libs"))] #[tokio::test] #[ignore] async fn test_agency_pool_it_should_fail_to_select_credentials_for_predicate() { @@ -753,19 +755,13 @@ mod tests { #[cfg(feature = "migration")] institution.migrate().await; - let requested_preds_string = serde_json::to_string(&json!([ - { + let requested_preds_string = serde_json::to_string(&json!([{ "name": "zip", "p_type": ">=", "p_value": 85000 }])) .unwrap(); - info!( - "test_basic_proof :: Going to seng proof request with attributes {}", - &requested_preds_string - ); - send_proof_request( &mut institution, &institution_to_consumer, @@ -779,8 +775,58 @@ mod tests { #[cfg(feature = "migration")] consumer.migrate().await; - prover_select_credentials_and_fail_to_generate_proof(&mut consumer, &consumer_to_institution, None, None) - .await; + let mut prover = create_proof(&mut consumer, &consumer_to_institution, None).await; + let selected_credentials = + prover_select_credentials(&mut prover, &mut consumer, &consumer_to_institution, None).await; + + assert!(selected_credentials.credential_for_referent.is_empty()); + }) + .await; + } + + #[tokio::test] + #[ignore] + async fn test_agency_pool_it_should_select_credentials_for_satisfiable_restriction() { + SetupPoolDirectory::run(|setup| async move { + let mut institution = create_faber_trustee(setup.genesis_file_path.clone()).await; + let mut consumer = create_alice(setup.genesis_file_path).await; + + let (consumer_to_institution, institution_to_consumer) = + create_connected_connections(&mut consumer, &mut institution).await; + issue_address_credential( + &mut consumer, + &mut institution, + &consumer_to_institution, + &institution_to_consumer, + ) + .await; + + let requested_attrs_string = serde_json::to_string(&json!([ + { + "name": "address1", + "restrictions": [{ + "issuer_did": "abcdef0000000000000000", + }, + { + "issuer_did": institution.institution_did, + }] + }])) + .unwrap(); + + send_proof_request( + &mut institution, + &institution_to_consumer, + &requested_attrs_string, + "[]", + "{}", + None, + ) + .await; + + let mut prover = create_proof(&mut consumer, &consumer_to_institution, None).await; + let selected_credentials = + prover_select_credentials(&mut prover, &mut consumer, &consumer_to_institution, None).await; + assert_eq!(selected_credentials.credential_for_referent.is_empty(), false); }) .await; } diff --git a/aries_vcx/tests/utils/scenarios.rs b/aries_vcx/tests/utils/scenarios.rs index a0b6cf2c46..9171fb07ab 100644 --- a/aries_vcx/tests/utils/scenarios.rs +++ b/aries_vcx/tests/utils/scenarios.rs @@ -1121,7 +1121,7 @@ pub mod test_utils { prover: &mut Prover, alice: &mut Alice, connection: &MediatedConnection, - requested_values: Option<&str>, + preselected_credentials: Option<&str>, ) -> SelectedCredentials { prover_update_with_mediator(prover, &alice.agency_client, connection) .await @@ -1131,15 +1131,11 @@ pub mod test_utils { .retrieve_credentials(&alice.profile.inject_anoncreds()) .await .unwrap(); - let selected_credentials = match requested_values { - Some(requested_values) => { + info!("prover_select_credentials >> retrieved_credentials: {retrieved_credentials:?}"); + let selected_credentials = match preselected_credentials { + Some(preselected_credentials) => { let credential_data = prover.presentation_request_data().unwrap(); - retrieved_to_selected_credentials_specific( - &retrieved_credentials, - requested_values, - &credential_data, - true, - ) + match_preselected_credentials(&retrieved_credentials, preselected_credentials, &credential_data, true) } _ => retrieved_to_selected_credentials_simple(&retrieved_credentials, true), }; @@ -1147,54 +1143,21 @@ pub mod test_utils { selected_credentials } - pub async fn prover_select_credentials_and_send_proof_and_assert( + pub async fn prover_select_credentials_and_send_proof( alice: &mut Alice, consumer_to_institution: &MediatedConnection, request_name: Option<&str>, - requested_values: Option<&str>, - expected_prover_state: ProverState, + preselected_credentials: Option<&str>, ) { let mut prover = create_proof(alice, consumer_to_institution, request_name).await; let selected_credentials = - prover_select_credentials(&mut prover, alice, consumer_to_institution, requested_values).await; + prover_select_credentials(&mut prover, alice, consumer_to_institution, preselected_credentials).await; info!( "Prover :: Retrieved credential converted to selected: {:?}", &selected_credentials ); generate_and_send_proof(alice, &mut prover, consumer_to_institution, selected_credentials).await; - assert_eq!(expected_prover_state, prover.get_state()); - } - - pub async fn prover_select_credentials_and_send_proof( - consumer: &mut Alice, - consumer_to_institution: &MediatedConnection, - request_name: Option<&str>, - requested_values: Option<&str>, - ) { - prover_select_credentials_and_send_proof_and_assert( - consumer, - consumer_to_institution, - request_name, - requested_values, - ProverState::PresentationSent, - ) - .await - } - - pub async fn prover_select_credentials_and_fail_to_generate_proof( - consumer: &mut Alice, - consumer_to_institution: &MediatedConnection, - request_name: Option<&str>, - requested_values: Option<&str>, - ) { - prover_select_credentials_and_send_proof_and_assert( - consumer, - consumer_to_institution, - request_name, - requested_values, - ProverState::PresentationPreparationFailed, - ) - .await + assert_eq!(ProverState::PresentationSent, prover.get_state()); } pub async fn connect_using_request_sent_to_public_agent( @@ -1373,7 +1336,7 @@ pub mod test_utils { with_tails: bool, ) -> SelectedCredentials { info!( - "test_real_proof >>> retrieved matching credentials {:?}", + "retrieved_to_selected_credentials_simple >>> retrieved matching credentials {:?}", retrieved_credentials ); let mut selected_credentials = SelectedCredentials::default(); @@ -1392,18 +1355,18 @@ pub mod test_utils { return selected_credentials; } - pub fn retrieved_to_selected_credentials_specific( + pub fn match_preselected_credentials( retrieved_credentials: &RetrievedCredentials, - requested_values: &str, + preselected_credentials: &str, credential_data: &str, with_tails: bool, ) -> SelectedCredentials { info!( - "test_real_proof >>> retrieved matching credentials {:?}", + "retrieved_to_selected_credentials_specific >>> retrieved matching credentials {:?}", retrieved_credentials ); let credential_data: Value = serde_json::from_str(credential_data).unwrap(); - let requested_values: Value = serde_json::from_str(requested_values).unwrap(); + let preselected_credentials: Value = serde_json::from_str(preselected_credentials).unwrap(); let requested_attributes: &Value = &credential_data["requested_attributes"]; let mut selected_credentials = SelectedCredentials::default(); @@ -1414,8 +1377,8 @@ pub mod test_utils { .into_iter() .filter_map(|cred| { let attribute_name = requested_attributes[referent]["name"].as_str().unwrap(); - let requested_value = requested_values[attribute_name].as_str().unwrap(); - if cred.cred_info.attributes[attribute_name] == requested_value { + let preselected_credential = preselected_credentials[attribute_name].as_str().unwrap(); + if cred.cred_info.attributes[attribute_name] == preselected_credential { Some(cred) } else { None diff --git a/aries_vcx_core/src/anoncreds/credx_anoncreds.rs b/aries_vcx_core/src/anoncreds/credx_anoncreds.rs index 5d2fc34479..1fc8239a59 100644 --- a/aries_vcx_core/src/anoncreds/credx_anoncreds.rs +++ b/aries_vcx_core/src/anoncreds/credx_anoncreds.rs @@ -160,18 +160,22 @@ impl IndyCredxAnonCreds { let wql_query = if let Some(restrictions) = restrictions { match restrictions { - Value::Array(mut arr) => { - arr.extend(attrs); - json!({ "$and": arr }) + Value::Array(restrictions) => { + let restrictions_wql = json!({ "$or": restrictions }); + attrs.push(restrictions_wql); + json!({ "$and": attrs }) } - Value::Object(obj) => { - attrs.push(Value::Object(obj)); + Value::Object(restriction) => { + attrs.push(Value::Object(restriction)); json!({ "$and": attrs }) } - _ => json!(attrs), + _ => Err(AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::InvalidInput, + "Invalid attribute restrictions (must be array or an object)", + ))?, } } else { - json!(attrs) + json!({ "$and": attrs }) }; let wql_query = serde_json::to_string(&wql_query)?; @@ -750,7 +754,7 @@ impl BaseAnonCreds for IndyCredxAnonCreds { .map(|v| v.try_as_str().map(_normalize_attr_name)) .collect::>()?, _ => Err(AriesVcxCoreError::from_msg( - AriesVcxCoreErrorKind::InvalidAttributesStructure, + AriesVcxCoreErrorKind::InvalidInput, "exactly one of 'name' or 'names' must be present", ))?, };