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

Prover: fix credx credential retrieval #961

Merged
merged 10 commits into from
Aug 30, 2023
1 change: 0 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,6 @@ jobs:
run: |
cargo test --manifest-path="wallet_migrator/Cargo.toml";
RUST_TEST_THREADS=1 CARGO_INCREMENTAL=0 TEST_POOL_IP=127.0.0.1 cargo test --manifest-path="aries_vcx/Cargo.toml" -F migration --test test_creds_proofs -- --include-ignored;
RUST_TEST_THREADS=1 CARGO_INCREMENTAL=0 TEST_POOL_IP=127.0.0.1 cargo test --manifest-path="aries_vcx/Cargo.toml" -F migration --test test_creds_proofs_revocations -- --include-ignored;
Patrik-Stas marked this conversation as resolved.
Show resolved Hide resolved

test-integration-libvcx:
needs: workflow-setup
Expand Down
2 changes: 1 addition & 1 deletion aries_vcx/src/handlers/proof_presentation/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?)
}

Expand Down
72 changes: 59 additions & 13 deletions aries_vcx/tests/test_creds_proofs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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() {
Expand All @@ -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,
Expand All @@ -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;
}
Expand Down
69 changes: 16 additions & 53 deletions aries_vcx/tests/utils/scenarios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -1131,70 +1131,33 @@ 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),
};

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(
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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
Expand Down
20 changes: 12 additions & 8 deletions aries_vcx_core/src/anoncreds/credx_anoncreds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down Expand Up @@ -750,7 +754,7 @@ impl BaseAnonCreds for IndyCredxAnonCreds {
.map(|v| v.try_as_str().map(_normalize_attr_name))
.collect::<Result<_, _>>()?,
_ => Err(AriesVcxCoreError::from_msg(
AriesVcxCoreErrorKind::InvalidAttributesStructure,
AriesVcxCoreErrorKind::InvalidInput,
"exactly one of 'name' or 'names' must be present",
))?,
};
Expand Down
Loading