From 9f2e922667bee27a4261c05e511d2a014df8af82 Mon Sep 17 00:00:00 2001 From: Miroslav Kovar Date: Thu, 25 May 2023 12:55:32 +0200 Subject: [PATCH 1/4] Split BaseLedger trait (#861) Signed-off-by: Miroslav Kovar --- .../aries-vcx-agent/src/services/schema.rs | 2 +- aries_vcx/src/common/anoncreds.rs | 2 +- aries_vcx/src/common/keys.rs | 18 +-- aries_vcx/src/common/ledger/transactions.rs | 16 +- .../primitives/credential_definition.rs | 35 +++-- .../common/primitives/credential_schema.rs | 8 +- aries_vcx/src/common/primitives/mod.rs | 10 +- .../common/primitives/revocation_registry.rs | 6 +- .../primitives/revocation_registry_delta.rs | 2 +- .../common/proofs/prover/prover_internal.rs | 6 +- .../proofs/verifier/verifier_internal.rs | 8 +- aries_vcx/src/common/test_utils.rs | 8 +- .../src/core/profile/modular_libs_profile.rs | 28 +++- aries_vcx/src/core/profile/profile.rs | 12 +- .../src/core/profile/vdr_proxy_profile.rs | 28 +++- .../src/core/profile/vdrtools_profile.rs | 33 +++- aries_vcx/src/global/author_agreement.rs | 2 +- .../issuance/holder/state_machine.rs | 4 +- aries_vcx/src/protocols/issuance/mod.rs | 2 +- aries_vcx/src/utils/mockdata/mock_settings.rs | 2 +- .../src/utils/mockdata/profile/mock_ledger.rs | 69 +++++---- .../utils/mockdata/profile/mock_profile.rs | 18 ++- aries_vcx/tests/test_agency.rs | 1 - aries_vcx/tests/test_creds_proofs.rs | 5 +- .../tests/test_creds_proofs_revocations.rs | 2 - aries_vcx/tests/test_pool.rs | 5 +- aries_vcx/tests/utils/devsetup_agent.rs | 1 + aries_vcx/tests/utils/scenarios.rs | 3 +- .../src/global/mockdata/mock_settings.rs | 2 +- .../src/indy/credentials/issuer/mod.rs | 2 +- .../indy/primitives/revocation_registry.rs | 8 +- aries_vcx_core/src/ledger/base_ledger.rs | 97 +++--------- aries_vcx_core/src/ledger/indy_ledger.rs | 80 +++++----- aries_vcx_core/src/ledger/indy_vdr_ledger.rs | 142 ++++++++++-------- aries_vcx_core/src/utils/mod.rs | 2 - did_resolver_sov/src/reader/mod.rs | 8 +- did_resolver_sov/tests/resolution.rs | 4 +- libvcx_core/src/api_vcx/api_global/ledger.rs | 6 +- libvcx_core/src/api_vcx/api_global/pool.rs | 2 +- libvcx_core/src/api_vcx/api_global/profile.rs | 2 +- libvcx_core/src/api_vcx/api_handle/schema.rs | 1 - 41 files changed, 361 insertions(+), 331 deletions(-) diff --git a/agents/rust/aries-vcx-agent/src/services/schema.rs b/agents/rust/aries-vcx-agent/src/services/schema.rs index e1b6589a7e..5ca5eaeb55 100644 --- a/agents/rust/aries-vcx-agent/src/services/schema.rs +++ b/agents/rust/aries-vcx-agent/src/services/schema.rs @@ -34,7 +34,7 @@ impl ServiceSchemas { } pub async fn schema_json(&self, thread_id: &str) -> AgentResult { - let ledger = Arc::clone(&self.profile).inject_ledger(); + let ledger = Arc::clone(&self.profile).inject_anoncreds_ledger_read(); Ok(ledger.get_schema(thread_id, None).await?) } diff --git a/aries_vcx/src/common/anoncreds.rs b/aries_vcx/src/common/anoncreds.rs index 7648a5af6c..a6e7a42ba6 100644 --- a/aries_vcx/src/common/anoncreds.rs +++ b/aries_vcx/src/common/anoncreds.rs @@ -71,7 +71,7 @@ pub mod integration_tests { ) .await; - let ledger = Arc::clone(&holder_setup.profile).inject_ledger(); + let ledger = Arc::clone(&holder_setup.profile).inject_anoncreds_ledger_read(); let (_, first_rev_reg_delta, first_timestamp) = ledger.get_rev_reg_delta_json(&rev_reg_id, None, None).await.unwrap(); diff --git a/aries_vcx/src/common/keys.rs b/aries_vcx/src/common/keys.rs index 22f4bed3d8..7d1b938de2 100644 --- a/aries_vcx/src/common/keys.rs +++ b/aries_vcx/src/common/keys.rs @@ -6,7 +6,7 @@ use crate::core::profile::profile::Profile; use crate::errors::error::prelude::*; pub async fn rotate_verkey_apply(profile: &Arc, did: &str, temp_vk: &str) -> VcxResult<()> { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_write(); let nym_result = ledger.publish_nym(did, did, Some(temp_vk), None, None).await?; @@ -41,7 +41,7 @@ pub async fn rotate_verkey(profile: &Arc, did: &str) -> VcxResult<( } pub async fn get_verkey_from_ledger(profile: &Arc, did: &str) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_read(); let nym_response: String = ledger.get_nym(did).await?; let nym_json: Value = serde_json::from_str(&nym_response).map_err(|err| { @@ -75,17 +75,17 @@ pub async fn get_verkey_from_ledger(profile: &Arc, did: &str) -> Vc #[cfg(test)] #[allow(clippy::unwrap_used)] mod test { - use aries_vcx_core::indy::utils::mocks::pool_mocks::{enable_pool_mocks, PoolMocks}; - - use crate::utils::devsetup::*; - use crate::utils::mockdata::mockdata_pool; - - use super::*; - #[tokio::test] #[ignore] #[cfg(not(feature = "vdr_proxy_ledger"))] async fn test_pool_rotate_verkey_fails() { + use super::*; + + use aries_vcx_core::indy::utils::mocks::pool_mocks::{enable_pool_mocks, PoolMocks}; + + use crate::utils::devsetup::*; + use crate::utils::mockdata::mockdata_pool; + SetupProfile::run_indy(|setup| async move { enable_pool_mocks(); diff --git a/aries_vcx/src/common/ledger/transactions.rs b/aries_vcx/src/common/ledger/transactions.rs index 864046692e..d7f187ce69 100644 --- a/aries_vcx/src/common/ledger/transactions.rs +++ b/aries_vcx/src/common/ledger/transactions.rs @@ -78,7 +78,7 @@ pub async fn add_new_did( ) -> VcxResult<(String, String)> { let (did, verkey) = profile.inject_wallet().create_and_store_my_did(None, None).await?; - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_write(); let res = ledger .publish_nym(submitter_did, &did, Some(&verkey), None, role) @@ -190,7 +190,7 @@ pub async fn get_service(profile: &Arc, did: &String) -> VcxResult< None => did_raw, Some((_, value)) => value.to_string(), }; - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_read(); let attr_resp = ledger.get_attr(&did_raw, "endpoint").await?; let data = get_data_from_response(&attr_resp)?; if data["endpoint"].is_object() { @@ -207,7 +207,7 @@ pub async fn get_service(profile: &Arc, did: &String) -> VcxResult< } pub async fn parse_legacy_endpoint_attrib(profile: &Arc, did_raw: &str) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_read(); let attr_resp = ledger.get_attr(did_raw, "service").await?; let data = get_data_from_response(&attr_resp)?; let ser_service = match data["service"].as_str() { @@ -227,7 +227,7 @@ pub async fn parse_legacy_endpoint_attrib(profile: &Arc, did_raw: & pub async fn write_endpoint_legacy(profile: &Arc, did: &str, service: &AriesService) -> VcxResult { let attrib_json = json!({ "service": service }).to_string(); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_write(); let res = ledger.add_attr(did, &attrib_json).await?; check_response(&res)?; Ok(res) @@ -235,20 +235,20 @@ pub async fn write_endpoint_legacy(profile: &Arc, did: &str, servic pub async fn write_endpoint(profile: &Arc, did: &str, service: &EndpointDidSov) -> VcxResult { let attrib_json = json!({ "endpoint": service }).to_string(); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_write(); let res = ledger.add_attr(did, &attrib_json).await?; check_response(&res)?; Ok(res) } pub async fn add_attr(profile: &Arc, did: &str, attr: &str) -> VcxResult<()> { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_write(); let res = ledger.add_attr(did, &attr).await?; check_response(&res) } pub async fn get_attr(profile: &Arc, did: &str, attr_name: &str) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_read(); let attr_resp = ledger.get_attr(did, attr_name).await?; let data = get_data_from_response(&attr_resp)?; match data.get(attr_name) { @@ -259,7 +259,7 @@ pub async fn get_attr(profile: &Arc, did: &str, attr_name: &str) -> } pub async fn clear_attr(profile: &Arc, did: &str, attr_name: &str) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_indy_ledger_write(); ledger .add_attr(did, &json!({ attr_name: Value::Null }).to_string()) diff --git a/aries_vcx/src/common/primitives/credential_definition.rs b/aries_vcx/src/common/primitives/credential_definition.rs index cfbd6481c7..a18f417196 100644 --- a/aries_vcx/src/common/primitives/credential_definition.rs +++ b/aries_vcx/src/common/primitives/credential_definition.rs @@ -1,5 +1,5 @@ use aries_vcx_core::errors::error::AriesVcxCoreErrorKind; -use aries_vcx_core::ledger::base_ledger::BaseLedger; +use aries_vcx_core::ledger::base_ledger::AnoncredsLedgerRead; use crate::core::profile::profile::Profile; use crate::errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}; @@ -104,7 +104,7 @@ impl Default for PublicEntityStateType { } async fn _try_get_cred_def_from_ledger( - ledger: &Arc, + ledger: &Arc, issuer_did: &str, cred_def_id: &str, ) -> VcxResult> { @@ -140,7 +140,7 @@ impl CredentialDef { schema_id, tag, } = config; - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let schema_json = ledger.get_schema(&schema_id, Some(&issuer_did)).await?; let (cred_def_id, cred_def_json) = generate_cred_def(profile, &issuer_did, &schema_json, &tag, None, Some(support_revocation)).await?; @@ -170,8 +170,10 @@ impl CredentialDef { self.issuer_did, self.id ); - let ledger = Arc::clone(profile).inject_ledger(); - if let Some(ledger_cred_def_json) = _try_get_cred_def_from_ledger(&ledger, &self.issuer_did, &self.id).await? { + let ledger_read = Arc::clone(profile).inject_anoncreds_ledger_read(); + if let Some(ledger_cred_def_json) = + _try_get_cred_def_from_ledger(&ledger_read, &self.issuer_did, &self.id).await? + { return Err(AriesVcxError::from_msg( AriesVcxErrorKind::CredDefAlreadyCreated, format!( @@ -180,6 +182,7 @@ impl CredentialDef { ), )); } + let ledger = Arc::clone(profile).inject_anoncreds_ledger_write(); ledger.publish_cred_def(&self.cred_def_json, &self.issuer_did).await?; Ok(Self { state: PublicEntityStateType::Published, @@ -230,7 +233,7 @@ impl CredentialDef { } pub async fn update_state(&mut self, profile: &Arc) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); if (ledger.get_cred_def(&self.id, None).await).is_ok() { self.state = PublicEntityStateType::Published } @@ -289,8 +292,9 @@ pub mod integration_tests { let (schema_id, _) = create_and_write_test_schema(&setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS).await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); - let schema_json = ledger.get_schema(&schema_id, None).await.unwrap(); + let ledger_read = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); + let ledger_write = Arc::clone(&setup.profile).inject_anoncreds_ledger_write(); + let schema_json = ledger_read.get_schema(&schema_id, None).await.unwrap(); let (cred_def_id, cred_def_json_local) = generate_cred_def( &setup.profile, @@ -303,14 +307,14 @@ pub mod integration_tests { .await .unwrap(); - ledger + ledger_write .publish_cred_def(&cred_def_json_local, &setup.institution_did) .await .unwrap(); std::thread::sleep(std::time::Duration::from_secs(2)); - let cred_def_json_ledger = ledger + let cred_def_json_ledger = ledger_read .get_cred_def(&cred_def_id, Some(&setup.institution_did)) .await .unwrap(); @@ -327,8 +331,9 @@ pub mod integration_tests { SetupProfile::run_indy(|setup| async move { let (schema_id, _) = create_and_write_test_schema(&setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS).await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); - let schema_json = ledger.get_schema(&schema_id, None).await.unwrap(); + let ledger_read = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); + let ledger_write = Arc::clone(&setup.profile).inject_anoncreds_ledger_write(); + let schema_json = ledger_read.get_schema(&schema_id, None).await.unwrap(); let (cred_def_id, cred_def_json) = generate_cred_def( &setup.profile, @@ -340,7 +345,7 @@ pub mod integration_tests { ) .await .unwrap(); - ledger + ledger_write .publish_cred_def(&cred_def_json, &setup.institution_did) .await .unwrap(); @@ -355,11 +360,11 @@ pub mod integration_tests { ) .await .unwrap(); - ledger + ledger_write .publish_rev_reg_def(&json!(rev_reg_def_json).to_string(), &setup.institution_did) .await .unwrap(); - ledger + ledger_write .publish_rev_reg_delta(&rev_reg_def_id, &rev_reg_entry_json, &setup.institution_did) .await .unwrap(); diff --git a/aries_vcx/src/common/primitives/credential_schema.rs b/aries_vcx/src/common/primitives/credential_schema.rs index 760a4c2fc9..aba57dd989 100644 --- a/aries_vcx/src/common/primitives/credential_schema.rs +++ b/aries_vcx/src/common/primitives/credential_schema.rs @@ -90,7 +90,7 @@ impl Schema { source_id: &str, schema_id: &str, ) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let schema_json = ledger.get_schema(schema_id, None).await?; let schema_data: SchemaData = serde_json::from_str(&schema_json).map_err(|err| { AriesVcxError::from_msg( @@ -121,7 +121,7 @@ impl Schema { }); } - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_write(); ledger .publish_schema(&self.schema_json, &self.submitter_did, endorser_did) .await?; @@ -153,7 +153,7 @@ impl Schema { } pub async fn update_state(&mut self, profile: &Arc) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); if ledger.get_schema(&self.schema_id, None).await.is_ok() { self.state = PublicEntityStateType::Published } @@ -164,7 +164,7 @@ impl Schema { if !self.schema_json.is_empty() { Ok(self.schema_json.clone()) } else { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); Ok(ledger.get_schema(&self.schema_id, None).await?) } } diff --git a/aries_vcx/src/common/primitives/mod.rs b/aries_vcx/src/common/primitives/mod.rs index 4220c19fbd..5ad11365cf 100644 --- a/aries_vcx/src/common/primitives/mod.rs +++ b/aries_vcx/src/common/primitives/mod.rs @@ -54,7 +54,7 @@ pub mod integration_tests { let (_, _, _, _, rev_reg_id, _, _) = create_and_store_credential_def(&setup.profile, &setup.institution_did, attrs).await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); + let ledger = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); let _json = ledger.get_rev_reg_def_json(&rev_reg_id).await.unwrap(); }) .await; @@ -68,7 +68,7 @@ pub mod integration_tests { let (_, _, _, _, rev_reg_id, _, _) = create_and_store_credential_def(&setup.profile, &setup.institution_did, attrs).await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); + let ledger = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); let (id, _delta, _timestamp) = ledger.get_rev_reg_delta_json(&rev_reg_id, None, None).await.unwrap(); assert_eq!(id, rev_reg_id); @@ -84,7 +84,7 @@ pub mod integration_tests { let (_, _, _, _, rev_reg_id, _, _) = create_and_store_credential_def(&setup.profile, &setup.institution_did, attrs).await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); + let ledger = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); let (id, _rev_reg, _timestamp) = ledger .get_rev_reg(&rev_reg_id, time::OffsetDateTime::now_utc().unix_timestamp() as u64) .await @@ -103,7 +103,7 @@ pub mod integration_tests { let (_, _, cred_def_id, cred_def_json, _) = create_and_store_nonrevocable_credential_def(&setup.profile, &setup.institution_did, attrs).await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); + let ledger = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); let cred_def = ledger.get_cred_def(&cred_def_id, None).await.unwrap(); assert_eq!( @@ -121,7 +121,7 @@ pub mod integration_tests { let (schema_id, _schema_json) = create_and_write_test_schema(&setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS).await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); + let ledger = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); let rc = ledger.get_schema(&schema_id, None).await; let retrieved_schema = rc.unwrap(); diff --git a/aries_vcx/src/common/primitives/revocation_registry.rs b/aries_vcx/src/common/primitives/revocation_registry.rs index 107d2769bd..b8c7e8b01b 100644 --- a/aries_vcx/src/common/primitives/revocation_registry.rs +++ b/aries_vcx/src/common/primitives/revocation_registry.rs @@ -101,7 +101,7 @@ impl RevocationRegistry { &self.rev_reg_def ); self.rev_reg_def.value.tails_location = String::from(tails_url); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_write(); ledger .publish_rev_reg_def(&json!(self.rev_reg_def).to_string(), issuer_did) .await @@ -121,7 +121,7 @@ impl RevocationRegistry { issuer_did, self.rev_reg_id ); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_write(); ledger .publish_rev_reg_delta(&self.rev_reg_id, &self.rev_reg_entry, issuer_did) .await @@ -196,7 +196,7 @@ impl RevocationRegistry { pub async fn publish_local_revocations(&self, profile: &Arc, submitter_did: &str) -> VcxResult<()> { let anoncreds = Arc::clone(profile).inject_anoncreds(); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_write(); if let Some(delta) = anoncreds.get_rev_reg_delta(&self.rev_reg_id).await? { ledger diff --git a/aries_vcx/src/common/primitives/revocation_registry_delta.rs b/aries_vcx/src/common/primitives/revocation_registry_delta.rs index f51f1fe964..75d15f648b 100644 --- a/aries_vcx/src/common/primitives/revocation_registry_delta.rs +++ b/aries_vcx/src/common/primitives/revocation_registry_delta.rs @@ -38,7 +38,7 @@ impl RevocationRegistryDelta { from: Option, to: Option, ) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let (_, rev_reg_delta_json, _) = ledger.get_rev_reg_delta_json(rev_reg_id, from, to).await?; serde_json::from_str(&rev_reg_delta_json).map_err(|err| { AriesVcxError::from_msg( diff --git a/aries_vcx/src/common/proofs/prover/prover_internal.rs b/aries_vcx/src/common/proofs/prover/prover_internal.rs index 182d62e144..df450d5ddd 100644 --- a/aries_vcx/src/common/proofs/prover/prover_internal.rs +++ b/aries_vcx/src/common/proofs/prover/prover_internal.rs @@ -31,7 +31,7 @@ pub async fn build_schemas_json_prover( "build_schemas_json_prover >>> credentials_identifiers: {:?}", credentials_identifiers ); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let mut rtn: Value = json!({}); for cred_info in credentials_identifiers { @@ -62,7 +62,7 @@ pub async fn build_cred_defs_json_prover( "build_cred_defs_json_prover >>> credentials_identifiers: {:?}", credentials_identifiers ); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let mut rtn: Value = json!({}); for cred_info in credentials_identifiers { @@ -167,7 +167,7 @@ pub async fn build_rev_states_json( "build_rev_states_json >> credentials_identifiers: {:?}", credentials_identifiers ); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let anoncreds = Arc::clone(profile).inject_anoncreds(); let mut rtn: Value = json!({}); let mut timestamps: HashMap = HashMap::new(); diff --git a/aries_vcx/src/common/proofs/verifier/verifier_internal.rs b/aries_vcx/src/common/proofs/verifier/verifier_internal.rs index 331005a4ac..737f510835 100644 --- a/aries_vcx/src/common/proofs/verifier/verifier_internal.rs +++ b/aries_vcx/src/common/proofs/verifier/verifier_internal.rs @@ -101,7 +101,7 @@ pub async fn build_cred_defs_json_verifier( credential_data: &[CredInfoVerifier], ) -> VcxResult { debug!("building credential_def_json for proof validation"); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let mut credential_json = json!({}); for cred_info in credential_data.iter() { @@ -129,7 +129,7 @@ pub async fn build_schemas_json_verifier( ) -> VcxResult { debug!("building schemas json for proof validation"); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let mut schemas_json = json!({}); for cred_info in credential_data.iter() { @@ -158,7 +158,7 @@ pub async fn build_rev_reg_defs_json( ) -> VcxResult { debug!("building rev_reg_def_json for proof validation"); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let mut rev_reg_defs_json = json!({}); for cred_info in credential_data.iter() { @@ -183,7 +183,7 @@ pub async fn build_rev_reg_defs_json( pub async fn build_rev_reg_json(profile: &Arc, credential_data: &[CredInfoVerifier]) -> VcxResult { debug!("building rev_reg_json for proof validation"); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let mut rev_regs_json = json!({}); for cred_info in credential_data.iter() { diff --git a/aries_vcx/src/common/test_utils.rs b/aries_vcx/src/common/test_utils.rs index ced9a42187..95fdd7d9a1 100644 --- a/aries_vcx/src/common/test_utils.rs +++ b/aries_vcx/src/common/test_utils.rs @@ -37,7 +37,7 @@ pub async fn create_and_write_test_schema( attr_list: &str, ) -> (String, String) { let (schema_id, schema_json) = create_schema(profile, attr_list, submitter_did).await; - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_write(); let _response = ledger.publish_schema(&schema_json, submitter_did, None).await.unwrap(); tokio::time::sleep(Duration::from_millis(1000)).await; (schema_id, schema_json) @@ -65,7 +65,7 @@ pub async fn create_and_store_nonrevocable_credential_def( let cred_def_id = cred_def.get_cred_def_id(); tokio::time::sleep(Duration::from_millis(1000)).await; - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let cred_def_json = ledger.get_cred_def(&cred_def_id, None).await.unwrap(); (schema_id, schema_json, cred_def_id, cred_def_json, cred_def) } @@ -115,7 +115,7 @@ pub async fn create_and_store_credential_def( tokio::time::sleep(Duration::from_millis(1000)).await; let cred_def_id = cred_def.get_cred_def_id(); tokio::time::sleep(Duration::from_millis(1000)).await; - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let cred_def_json = ledger.get_cred_def(&cred_def_id, None).await.unwrap(); ( schema_id, @@ -178,7 +178,7 @@ pub async fn create_and_store_credential( /* create cred */ let credential_data = r#"{"address1": ["123 Main St"], "address2": ["Suite 3"], "city": ["Draper"], "state": ["UT"], "zip": ["84000"]}"#; let encoded_attributes = encode_attributes(&credential_data).unwrap(); - let ledger = Arc::clone(issuer).inject_ledger(); + let ledger = Arc::clone(issuer).inject_anoncreds_ledger_read(); let rev_def_json = ledger.get_rev_reg_def_json(&rev_reg_id).await.unwrap(); let tails_file = get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_string(); diff --git a/aries_vcx/src/core/profile/modular_libs_profile.rs b/aries_vcx/src/core/profile/modular_libs_profile.rs index cf8f820ea6..a96dcbe5fe 100644 --- a/aries_vcx/src/core/profile/modular_libs_profile.rs +++ b/aries_vcx/src/core/profile/modular_libs_profile.rs @@ -3,7 +3,7 @@ use std::time::Duration; use aries_vcx_core::anoncreds::base_anoncreds::BaseAnonCreds; use aries_vcx_core::anoncreds::credx_anoncreds::IndyCredxAnonCreds; -use aries_vcx_core::ledger::base_ledger::BaseLedger; +use aries_vcx_core::ledger::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}; use aries_vcx_core::ledger::indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerConfig}; use aries_vcx_core::ledger::request_signer::base_wallet::BaseWalletRequestSigner; use aries_vcx_core::ledger::request_submitter::vdr_ledger::{IndyVdrLedgerPool, IndyVdrSubmitter, LedgerPoolConfig}; @@ -19,8 +19,11 @@ use super::profile::Profile; #[derive(Debug)] pub struct ModularLibsProfile { wallet: Arc, - ledger: Arc, anoncreds: Arc, + anoncreds_ledger_read: Arc, + anoncreds_ledger_write: Arc, + indy_ledger_read: Arc, + indy_ledger_write: Arc, } impl ModularLibsProfile { @@ -44,21 +47,36 @@ impl ModularLibsProfile { let ledger = Arc::new(IndyVdrLedger::new(config)); Ok(ModularLibsProfile { wallet, - ledger, anoncreds, + anoncreds_ledger_read: ledger.clone(), + anoncreds_ledger_write: ledger.clone(), + indy_ledger_read: ledger.clone(), + indy_ledger_write: ledger, }) } } impl Profile for ModularLibsProfile { - fn inject_ledger(self: Arc) -> Arc { - Arc::clone(&self.ledger) + fn inject_indy_ledger_read(self: Arc) -> Arc { + Arc::clone(&self.indy_ledger_read) + } + + fn inject_indy_ledger_write(self: Arc) -> Arc { + Arc::clone(&self.indy_ledger_write) } fn inject_anoncreds(self: Arc) -> Arc { Arc::clone(&self.anoncreds) } + fn inject_anoncreds_ledger_read(self: Arc) -> Arc { + Arc::clone(&self.anoncreds_ledger_read) + } + + fn inject_anoncreds_ledger_write(self: Arc) -> Arc { + Arc::clone(&self.anoncreds_ledger_write) + } + fn inject_wallet(&self) -> Arc { Arc::clone(&self.wallet) } diff --git a/aries_vcx/src/core/profile/profile.rs b/aries_vcx/src/core/profile/profile.rs index 0609c748be..52017dea86 100644 --- a/aries_vcx/src/core/profile/profile.rs +++ b/aries_vcx/src/core/profile/profile.rs @@ -1,13 +1,21 @@ use std::sync::Arc; use aries_vcx_core::{ - anoncreds::base_anoncreds::BaseAnonCreds, ledger::base_ledger::BaseLedger, wallet::base_wallet::BaseWallet, + anoncreds::base_anoncreds::BaseAnonCreds, + ledger::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}, + wallet::base_wallet::BaseWallet, }; pub trait Profile: std::fmt::Debug + Send + Sync { - fn inject_ledger(self: Arc) -> Arc; + fn inject_indy_ledger_read(self: Arc) -> Arc; + + fn inject_indy_ledger_write(self: Arc) -> Arc; fn inject_anoncreds(self: Arc) -> Arc; + fn inject_anoncreds_ledger_read(self: Arc) -> Arc; + + fn inject_anoncreds_ledger_write(self: Arc) -> Arc; + fn inject_wallet(&self) -> Arc; } diff --git a/aries_vcx/src/core/profile/vdr_proxy_profile.rs b/aries_vcx/src/core/profile/vdr_proxy_profile.rs index 59d76d0590..f2e240bb58 100644 --- a/aries_vcx/src/core/profile/vdr_proxy_profile.rs +++ b/aries_vcx/src/core/profile/vdr_proxy_profile.rs @@ -3,7 +3,7 @@ use std::{sync::Arc, time::Duration}; use aries_vcx_core::{ anoncreds::{base_anoncreds::BaseAnonCreds, indy_anoncreds::IndySdkAnonCreds}, ledger::{ - base_ledger::BaseLedger, + base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}, indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerConfig}, request_signer::base_wallet::BaseWalletRequestSigner, request_submitter::vdr_proxy::VdrProxySubmitter, @@ -20,8 +20,11 @@ use super::profile::Profile; #[derive(Debug)] pub struct VdrProxyProfile { wallet: Arc, - ledger: Arc, anoncreds: Arc, + anoncreds_ledger_read: Arc, + anoncreds_ledger_write: Arc, + indy_ledger_read: Arc, + indy_ledger_write: Arc, } impl VdrProxyProfile { @@ -45,21 +48,36 @@ impl VdrProxyProfile { let ledger = Arc::new(IndyVdrLedger::new(config)); Ok(VdrProxyProfile { wallet, - ledger, anoncreds, + anoncreds_ledger_read: ledger.clone(), + anoncreds_ledger_write: ledger.clone(), + indy_ledger_read: ledger.clone(), + indy_ledger_write: ledger, }) } } impl Profile for VdrProxyProfile { - fn inject_ledger(self: Arc) -> Arc { - Arc::clone(&self.ledger) + fn inject_indy_ledger_read(self: Arc) -> Arc { + Arc::clone(&self.indy_ledger_read) + } + + fn inject_indy_ledger_write(self: Arc) -> Arc { + Arc::clone(&self.indy_ledger_write) } fn inject_anoncreds(self: Arc) -> Arc { Arc::clone(&self.anoncreds) } + fn inject_anoncreds_ledger_read(self: Arc) -> Arc { + Arc::clone(&self.anoncreds_ledger_read) + } + + fn inject_anoncreds_ledger_write(self: Arc) -> Arc { + Arc::clone(&self.anoncreds_ledger_write) + } + fn inject_wallet(&self) -> Arc { Arc::clone(&self.wallet) } diff --git a/aries_vcx/src/core/profile/vdrtools_profile.rs b/aries_vcx/src/core/profile/vdrtools_profile.rs index 5c0bddc415..4a86ea87a0 100644 --- a/aries_vcx/src/core/profile/vdrtools_profile.rs +++ b/aries_vcx/src/core/profile/vdrtools_profile.rs @@ -2,7 +2,10 @@ use std::sync::Arc; use aries_vcx_core::{ anoncreds::{base_anoncreds::BaseAnonCreds, indy_anoncreds::IndySdkAnonCreds}, - ledger::{base_ledger::BaseLedger, indy_ledger::IndySdkLedger}, + ledger::{ + base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}, + indy_ledger::IndySdkLedger, + }, wallet::{base_wallet::BaseWallet, indy_wallet::IndySdkWallet}, PoolHandle, WalletHandle, }; @@ -12,32 +15,50 @@ use super::profile::Profile; #[derive(Debug)] pub struct VdrtoolsProfile { wallet: Arc, - ledger: Arc, anoncreds: Arc, + anoncreds_ledger_read: Arc, + anoncreds_ledger_write: Arc, + indy_ledger_read: Arc, + indy_ledger_write: Arc, } impl VdrtoolsProfile { pub fn new(indy_wallet_handle: WalletHandle, indy_pool_handle: PoolHandle) -> Self { let wallet = Arc::new(IndySdkWallet::new(indy_wallet_handle)); - let ledger = Arc::new(IndySdkLedger::new(indy_wallet_handle, indy_pool_handle)); let anoncreds = Arc::new(IndySdkAnonCreds::new(indy_wallet_handle)); + let ledger = Arc::new(IndySdkLedger::new(indy_wallet_handle, indy_pool_handle)); VdrtoolsProfile { wallet, - ledger, anoncreds, + anoncreds_ledger_read: ledger.clone(), + anoncreds_ledger_write: ledger.clone(), + indy_ledger_read: ledger.clone(), + indy_ledger_write: ledger, } } } impl Profile for VdrtoolsProfile { - fn inject_ledger(self: Arc) -> Arc { - Arc::clone(&self.ledger) + fn inject_indy_ledger_read(self: Arc) -> Arc { + Arc::clone(&self.indy_ledger_read) + } + + fn inject_indy_ledger_write(self: Arc) -> Arc { + Arc::clone(&self.indy_ledger_write) } fn inject_anoncreds(self: Arc) -> Arc { Arc::clone(&self.anoncreds) } + fn inject_anoncreds_ledger_read(self: Arc) -> Arc { + Arc::clone(&self.anoncreds_ledger_read) + } + + fn inject_anoncreds_ledger_write(self: Arc) -> Arc { + Arc::clone(&self.anoncreds_ledger_write) + } + fn inject_wallet(&self) -> Arc { Arc::clone(&self.wallet) } diff --git a/aries_vcx/src/global/author_agreement.rs b/aries_vcx/src/global/author_agreement.rs index fe030a589f..c904c63802 100644 --- a/aries_vcx/src/global/author_agreement.rs +++ b/aries_vcx/src/global/author_agreement.rs @@ -1,5 +1,5 @@ use crate::errors::error::VcxResult; -use aries_vcx_core::global::author_agreement::{set_txn_author_agreement, TxnAuthorAgreementAcceptanceData}; +use aries_vcx_core::global::author_agreement::set_txn_author_agreement; pub fn proxy_set_txn_author_agreement( text: Option, diff --git a/aries_vcx/src/protocols/issuance/holder/state_machine.rs b/aries_vcx/src/protocols/issuance/holder/state_machine.rs index afc8bce207..05efcaaf26 100644 --- a/aries_vcx/src/protocols/issuance/holder/state_machine.rs +++ b/aries_vcx/src/protocols/issuance/holder/state_machine.rs @@ -578,7 +578,7 @@ async fn _store_credential( cred_def_json ); - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let anoncreds = Arc::clone(profile).inject_anoncreds(); let credential_json = get_attach_as_string!(&credential.content.credentials_attach); @@ -619,7 +619,7 @@ pub async fn create_credential_request( prover_did: &str, cred_offer: &str, ) -> VcxResult<(String, String, String, String)> { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let anoncreds = Arc::clone(profile).inject_anoncreds(); let cred_def_json = ledger.get_cred_def(cred_def_id, None).await?; diff --git a/aries_vcx/src/protocols/issuance/mod.rs b/aries_vcx/src/protocols/issuance/mod.rs index d47654fc47..789b8afe75 100644 --- a/aries_vcx/src/protocols/issuance/mod.rs +++ b/aries_vcx/src/protocols/issuance/mod.rs @@ -23,7 +23,7 @@ pub fn verify_thread_id(thread_id: &str, message: &CredentialIssuanceAction) -> } pub async fn is_cred_def_revokable(profile: &Arc, cred_def_id: &str) -> VcxResult { - let ledger = Arc::clone(profile).inject_ledger(); + let ledger = Arc::clone(profile).inject_anoncreds_ledger_read(); let cred_def_json = ledger.get_cred_def(cred_def_id, None).await.map_err(|err| { AriesVcxError::from_msg( AriesVcxErrorKind::InvalidLedgerResponse, diff --git a/aries_vcx/src/utils/mockdata/mock_settings.rs b/aries_vcx/src/utils/mockdata/mock_settings.rs index c01e0f6e57..03467786db 100644 --- a/aries_vcx/src/utils/mockdata/mock_settings.rs +++ b/aries_vcx/src/utils/mockdata/mock_settings.rs @@ -1,5 +1,5 @@ +use std::collections::HashMap; use std::sync::RwLock; -use std::{collections::HashMap, sync::Mutex}; use crate::errors::error::{AriesVcxError, VcxResult}; diff --git a/aries_vcx/src/utils/mockdata/profile/mock_ledger.rs b/aries_vcx/src/utils/mockdata/profile/mock_ledger.rs index ebafa9891e..649bdc6749 100644 --- a/aries_vcx/src/utils/mockdata/profile/mock_ledger.rs +++ b/aries_vcx/src/utils/mockdata/profile/mock_ledger.rs @@ -1,32 +1,16 @@ use aries_vcx_core::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}; -use aries_vcx_core::ledger::base_ledger::BaseLedger; +use aries_vcx_core::ledger::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}; use async_trait::async_trait; -use crate::utils::{ - self, - constants::{rev_def_json, CRED_DEF_JSON, REV_REG_DELTA_JSON, REV_REG_ID, REV_REG_JSON, SCHEMA_JSON}, -}; +use crate::utils; +use crate::utils::constants::{rev_def_json, CRED_DEF_JSON, REV_REG_DELTA_JSON, REV_REG_ID, REV_REG_JSON, SCHEMA_JSON}; #[derive(Debug)] pub(crate) struct MockLedger; -// NOTE : currently matches the expected results if indy_mocks are enabled -/// Implementation of [BaseLedger] which responds with mock data #[allow(unused)] #[async_trait] -impl BaseLedger for MockLedger { - async fn submit_request(&self, request_json: &str) -> VcxCoreResult { - // not needed yet - Err(AriesVcxCoreError::from_msg( - AriesVcxCoreErrorKind::UnimplementedFeature, - "unimplemented mock method: submit_request", - )) - } - - async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { - Ok(()) - } - +impl IndyLedgerRead for MockLedger { async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult { Ok(utils::constants::REQUEST_WITH_ENDORSER.to_string()) } @@ -43,6 +27,22 @@ impl BaseLedger for MockLedger { )) } + async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult { + Ok(r#"{"rc":"success"}"#.to_string()) + } + + async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { + Ok(r#"{"rc":"success"}"#.to_string()) + } +} + +#[allow(unused)] +#[async_trait] +impl IndyLedgerWrite for MockLedger { + async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { + Ok(()) + } + async fn publish_nym( &self, submitter_did: &str, @@ -54,6 +54,14 @@ impl BaseLedger for MockLedger { Ok(r#"{"rc":"success"}"#.to_string()) } + async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult { + Ok(r#"{"rc":"success"}"#.to_string()) + } +} + +#[allow(unused)] +#[async_trait] +impl AnoncredsLedgerRead for MockLedger { async fn get_schema(&self, schema_id: &str, submitter_did: Option<&str>) -> VcxCoreResult { Ok(SCHEMA_JSON.to_string()) } @@ -62,14 +70,6 @@ impl BaseLedger for MockLedger { Ok(CRED_DEF_JSON.to_string()) } - async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult { - Ok(r#"{"rc":"success"}"#.to_string()) - } - - async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult { - Ok(r#"{"rc":"success"}"#.to_string()) - } - async fn get_rev_reg_def_json(&self, rev_reg_id: &str) -> VcxCoreResult { Ok(rev_def_json()) } @@ -86,11 +86,11 @@ impl BaseLedger for MockLedger { async fn get_rev_reg(&self, rev_reg_id: &str, timestamp: u64) -> VcxCoreResult<(String, String, u64)> { Ok((REV_REG_ID.to_string(), REV_REG_JSON.to_string(), 1)) } +} - async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { - Ok(r#"{"rc":"success"}"#.to_string()) - } - +#[allow(unused)] +#[async_trait] +impl AnoncredsLedgerWrite for MockLedger { async fn publish_schema( &self, schema_json: &str, @@ -124,7 +124,7 @@ mod unit_tests { use aries_vcx_core::{ errors::error::{AriesVcxCoreErrorKind, VcxCoreResult}, - ledger::base_ledger::BaseLedger, + ledger::base_ledger::IndyLedgerRead, }; use super::MockLedger; @@ -137,9 +137,8 @@ mod unit_tests { assert_eq!(result.unwrap_err().kind(), AriesVcxCoreErrorKind::UnimplementedFeature) } - let ledger: Box = Box::new(MockLedger); + let ledger: Box = Box::new(MockLedger); - assert_unimplemented(ledger.submit_request("").await); assert_unimplemented(ledger.get_nym("").await); } } diff --git a/aries_vcx/src/utils/mockdata/profile/mock_profile.rs b/aries_vcx/src/utils/mockdata/profile/mock_profile.rs index 2b7919430b..68a66957a6 100644 --- a/aries_vcx/src/utils/mockdata/profile/mock_profile.rs +++ b/aries_vcx/src/utils/mockdata/profile/mock_profile.rs @@ -1,7 +1,9 @@ use std::sync::Arc; use aries_vcx_core::{ - anoncreds::base_anoncreds::BaseAnonCreds, ledger::base_ledger::BaseLedger, wallet::base_wallet::BaseWallet, + anoncreds::base_anoncreds::BaseAnonCreds, + ledger::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}, + wallet::base_wallet::BaseWallet, }; use crate::core::profile::profile::Profile; @@ -14,7 +16,11 @@ use super::{mock_anoncreds::MockAnoncreds, mock_ledger::MockLedger, mock_wallet: pub struct MockProfile; impl Profile for MockProfile { - fn inject_ledger(self: Arc) -> Arc { + fn inject_indy_ledger_write(self: Arc) -> Arc { + Arc::new(MockLedger {}) + } + + fn inject_indy_ledger_read(self: Arc) -> Arc { Arc::new(MockLedger {}) } @@ -25,4 +31,12 @@ impl Profile for MockProfile { fn inject_wallet(&self) -> Arc { Arc::new(MockWallet {}) } + + fn inject_anoncreds_ledger_read(self: Arc) -> Arc { + Arc::new(MockLedger {}) + } + + fn inject_anoncreds_ledger_write(self: Arc) -> Arc { + Arc::new(MockLedger {}) + } } diff --git a/aries_vcx/tests/test_agency.rs b/aries_vcx/tests/test_agency.rs index 2cb23265fd..d73dbf69b6 100644 --- a/aries_vcx/tests/test_agency.rs +++ b/aries_vcx/tests/test_agency.rs @@ -9,7 +9,6 @@ pub mod utils; #[cfg(test)] mod integration_tests { use std::sync::Arc; - use std::thread; use std::time::Duration; use agency_client::agency_client::AgencyClient; diff --git a/aries_vcx/tests/test_creds_proofs.rs b/aries_vcx/tests/test_creds_proofs.rs index 44f8ac69c0..5ee0d392f4 100644 --- a/aries_vcx/tests/test_creds_proofs.rs +++ b/aries_vcx/tests/test_creds_proofs.rs @@ -13,7 +13,6 @@ mod integration_tests { create_and_store_credential, create_and_store_nonrevocable_credential, create_and_store_nonrevocable_credential_def, create_indy_proof, }; - use aries_vcx::errors::error::VcxResult; use aries_vcx::handlers::proof_presentation::prover::Prover; use aries_vcx::handlers::proof_presentation::verifier::Verifier; use aries_vcx::handlers::util::AttachmentId; @@ -75,7 +74,7 @@ mod integration_tests { ) .await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); + let ledger = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); let r_cred_def_json = ledger.get_cred_def(&cred_def_id, None).await.unwrap(); let def1: serde_json::Value = serde_json::from_str(&cred_def_json).unwrap(); @@ -464,7 +463,6 @@ mod integration_tests { #[cfg(test)] mod tests { - use std::thread; use std::time::Duration; use messages::msg_fields::protocols::cred_issuance::offer_credential::OfferCredential; @@ -492,7 +490,6 @@ mod tests { 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, }; - use crate::utils::test_macros::ProofStateType; use super::*; diff --git a/aries_vcx/tests/test_creds_proofs_revocations.rs b/aries_vcx/tests/test_creds_proofs_revocations.rs index 5bdd4719c6..8b49b8abe0 100644 --- a/aries_vcx/tests/test_creds_proofs_revocations.rs +++ b/aries_vcx/tests/test_creds_proofs_revocations.rs @@ -7,7 +7,6 @@ pub mod utils; #[cfg(test)] mod integration_tests { - use std::thread; use std::time::Duration; use aries_vcx::protocols::proof_presentation::prover::state_machine::ProverState; @@ -23,7 +22,6 @@ mod integration_tests { revoke_credential_and_publish_accumulator, revoke_credential_local, rotate_rev_reg, send_proof_request, verifier_create_proof_and_send_request, }; - use crate::utils::test_macros::ProofStateType; use super::*; diff --git a/aries_vcx/tests/test_pool.rs b/aries_vcx/tests/test_pool.rs index 1cc3ef3aab..733b645cfc 100644 --- a/aries_vcx/tests/test_pool.rs +++ b/aries_vcx/tests/test_pool.rs @@ -12,9 +12,8 @@ mod integration_tests { use aries_vcx::common::ledger::transactions::{ add_attr, add_new_did, clear_attr, get_attr, get_service, write_endpoint, write_endpoint_legacy, }; - use aries_vcx::common::primitives::credential_schema::{Schema, SchemaData}; use aries_vcx::common::test_utils::create_and_store_nonrevocable_credential_def; - use aries_vcx::utils::constants::{DEFAULT_SCHEMA_ATTRS, SCHEMA_DATA}; + use aries_vcx::utils::constants::DEFAULT_SCHEMA_ATTRS; use aries_vcx::utils::devsetup::{SetupProfile, SetupWalletPool}; use diddoc_legacy::aries::service::AriesService; use std::sync::Arc; @@ -42,7 +41,7 @@ mod integration_tests { ) .await; - let ledger = Arc::clone(&setup.profile).inject_ledger(); + let ledger = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); let r_cred_def_json = ledger.get_cred_def(&cred_def_id, None).await.unwrap(); diff --git a/aries_vcx/tests/utils/devsetup_agent.rs b/aries_vcx/tests/utils/devsetup_agent.rs index 7a8f2b19bb..84a3358404 100644 --- a/aries_vcx/tests/utils/devsetup_agent.rs +++ b/aries_vcx/tests/utils/devsetup_agent.rs @@ -447,6 +447,7 @@ pub mod test_utils { } pub async fn create_test_alice_instance(setup: &SetupPool) -> Alice { + #[cfg(not(feature = "modular_libs"))] let (alice_profile, teardown) = { info!("create_test_alice_instance >> using indy profile"); Alice::setup_indy_profile(setup.pool_handle).await diff --git a/aries_vcx/tests/utils/scenarios.rs b/aries_vcx/tests/utils/scenarios.rs index 8ba3277554..db5279caa4 100644 --- a/aries_vcx/tests/utils/scenarios.rs +++ b/aries_vcx/tests/utils/scenarios.rs @@ -48,7 +48,6 @@ pub mod test_utils { use aries_vcx::utils::get_temp_dir_path; use crate::utils::devsetup_agent::test_utils::{Alice, Faber}; - use crate::utils::test_macros::ProofStateType; pub fn _send_message(sender: Sender) -> Option { Some(Box::new( @@ -769,7 +768,7 @@ pub mod test_utils { } pub async fn revoke_credential_local(faber: &mut Faber, issuer_credential: &Issuer, rev_reg_id: &str) { - let ledger = Arc::clone(&faber.profile).inject_ledger(); + let ledger = Arc::clone(&faber.profile).inject_anoncreds_ledger_read(); let (_, delta, timestamp) = ledger.get_rev_reg_delta_json(&rev_reg_id, None, None).await.unwrap(); info!("revoking credential locally"); issuer_credential.revoke_credential_local(&faber.profile).await.unwrap(); diff --git a/aries_vcx_core/src/global/mockdata/mock_settings.rs b/aries_vcx_core/src/global/mockdata/mock_settings.rs index 942a75f539..9050d454c5 100644 --- a/aries_vcx_core/src/global/mockdata/mock_settings.rs +++ b/aries_vcx_core/src/global/mockdata/mock_settings.rs @@ -1,5 +1,5 @@ +use std::collections::HashMap; use std::sync::RwLock; -use std::{collections::HashMap, sync::Mutex}; use crate::errors::error::VcxCoreResult; diff --git a/aries_vcx_core/src/indy/credentials/issuer/mod.rs b/aries_vcx_core/src/indy/credentials/issuer/mod.rs index b52d96a810..8ee22b8b53 100644 --- a/aries_vcx_core/src/indy/credentials/issuer/mod.rs +++ b/aries_vcx_core/src/indy/credentials/issuer/mod.rs @@ -1,6 +1,6 @@ use vdrtools::{CredentialOffer, CredentialRequest, CredentialValues, Locator, RevocationRegistryId}; -use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}; +use crate::errors::error::VcxCoreResult; use crate::global::settings; use crate::indy::anoncreds; use crate::indy::utils::parse_and_validate; diff --git a/aries_vcx_core/src/indy/primitives/revocation_registry.rs b/aries_vcx_core/src/indy/primitives/revocation_registry.rs index 2dd6e47840..a6528cee23 100644 --- a/aries_vcx_core/src/indy/primitives/revocation_registry.rs +++ b/aries_vcx_core/src/indy/primitives/revocation_registry.rs @@ -1,17 +1,13 @@ -use std::sync::Arc; - use vdrtools::{DidValue, Locator}; -use crate::anoncreds::base_anoncreds::BaseAnonCreds; -use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}; +use crate::errors::error::VcxCoreResult; use crate::global::settings; use crate::indy::anoncreds; use crate::indy::ledger::transactions::{ build_rev_reg_delta_request, build_rev_reg_request, check_response, sign_and_submit_to_ledger, }; use crate::indy::utils::parse_and_validate; -use crate::indy::wallet_non_secrets::{clear_rev_reg_delta, get_rev_reg_delta, set_rev_reg_delta}; -use crate::ledger::base_ledger::BaseLedger; +use crate::indy::wallet_non_secrets::{get_rev_reg_delta, set_rev_reg_delta}; use crate::{PoolHandle, WalletHandle}; pub const BLOB_STORAGE_TYPE: &str = "default"; diff --git a/aries_vcx_core/src/ledger/base_ledger.rs b/aries_vcx_core/src/ledger/base_ledger.rs index 17b2fe442a..49482d7648 100644 --- a/aries_vcx_core/src/ledger/base_ledger.rs +++ b/aries_vcx_core/src/ledger/base_ledger.rs @@ -1,25 +1,20 @@ +use std::fmt::Debug; + use async_trait::async_trait; use crate::errors::error::VcxCoreResult; -/// Trait defining standard 'ledger' related functionality. #[async_trait] -pub trait BaseLedger: std::fmt::Debug + Send + Sync { - // returns request result as JSON - async fn submit_request(&self, request_json: &str) -> VcxCoreResult; - - // endorsers/multi signs a request, submits to ledger, and verifies successful result - async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()>; - - // adds endorser to request and signs with submitter_did, returns the transaction ready for endorser to take - async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult; - - async fn get_txn_author_agreement(&self) -> VcxCoreResult; - - // returns request result as JSON +pub trait IndyLedgerRead: Debug + Send + Sync { + async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult; async fn get_nym(&self, did: &str) -> VcxCoreResult; + async fn get_txn_author_agreement(&self) -> VcxCoreResult; + async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult; + async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult; +} - // returns request result as JSON +#[async_trait] +pub trait IndyLedgerWrite: Debug + Send + Sync { async fn publish_nym( &self, submitter_did: &str, @@ -28,90 +23,34 @@ pub trait BaseLedger: std::fmt::Debug + Send + Sync { data: Option<&str>, role: Option<&str>, ) -> VcxCoreResult; + async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()>; + async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult; +} - // Schema json. - // { - // id: identifier of schema - // attrNames: array of attribute name strings - // name: Schema's name string - // version: Schema's version string - // ver: Version of the Schema json - // } - // if submitter_did provided - use cache - // TO CONSIDER - do we need to return the schema ID in a tuple? is it ever different to the input? +#[async_trait] +pub trait AnoncredsLedgerRead: Debug + Send + Sync { async fn get_schema(&self, schema_id: &str, submitter_did: Option<&str>) -> VcxCoreResult; - - // if submitter_did provided, try use cache - // TO CONSIDER - do we need to return the cred def ID in a tuple? is it ever different to the input? async fn get_cred_def(&self, cred_def_id: &str, submitter_did: Option<&str>) -> VcxCoreResult; - - // returns request result as JSON - async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult; - - // returns request result as JSON - async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult; - - // # Returns - // Revocation Registry Definition Id and Revocation Registry Definition json. - // { - // "id": string - ID of the Revocation Registry, - // "revocDefType": string - Revocation Registry type (only CL_ACCUM is supported for now), - // "tag": string - Unique descriptive ID of the Registry, - // "credDefId": string - ID of the corresponding CredentialDefinition, - // "value": Registry-specific data { - // "issuanceType": string - Type of Issuance(ISSUANCE_BY_DEFAULT or ISSUANCE_ON_DEMAND), - // "maxCredNum": number - Maximum number of credentials the Registry can serve. - // "tailsHash": string - Hash of tails. - // "tailsLocation": string - Location of tails file. - // "publicKeys": - Registry's public key. - // }, - // "ver": string - version of revocation registry definition json. - // } - // TO CONSIDER - do we need to return the rev reg id in a tuple? is it ever different to the input? async fn get_rev_reg_def_json(&self, rev_reg_id: &str) -> VcxCoreResult; - - // # Returns - // Revocation Registry Definition Id, Revocation Registry Delta json and Timestamp. - // { - // "value": Registry-specific data { - // prevAccum: string - previous accumulator value. - // accum: string - current accumulator value. - // issued: array - an array of issued indices. - // revoked: array an array of revoked indices. - // }, - // "ver": string - version revocation registry delta json - // } async fn get_rev_reg_delta_json( &self, rev_reg_id: &str, from: Option, to: Option, ) -> VcxCoreResult<(String, String, u64)>; - - // # Returns - // Revocation Registry Definition Id, Revocation Registry json and Timestamp. - // { - // "value": Registry-specific data { - // "accum": string - current accumulator value. - // }, - // "ver": string - version revocation registry json - // } async fn get_rev_reg(&self, rev_reg_id: &str, timestamp: u64) -> VcxCoreResult<(String, String, u64)>; +} - // returns request result as JSON - async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult; - +#[async_trait] +pub trait AnoncredsLedgerWrite: Debug + Send + Sync { async fn publish_schema( &self, schema_json: &str, submitter_did: &str, endorser_did: Option, ) -> VcxCoreResult<()>; - async fn publish_cred_def(&self, cred_def_json: &str, submitter_did: &str) -> VcxCoreResult<()>; - async fn publish_rev_reg_def(&self, rev_reg_def: &str, submitter_did: &str) -> VcxCoreResult<()>; - async fn publish_rev_reg_delta( &self, rev_reg_id: &str, diff --git a/aries_vcx_core/src/ledger/indy_ledger.rs b/aries_vcx_core/src/ledger/indy_ledger.rs index ec57c96927..7efaa99c22 100644 --- a/aries_vcx_core/src/ledger/indy_ledger.rs +++ b/aries_vcx_core/src/ledger/indy_ledger.rs @@ -3,7 +3,7 @@ use async_trait::async_trait; use crate::errors::error::VcxCoreResult; use crate::{indy, PoolHandle, WalletHandle}; -use super::base_ledger::BaseLedger; +use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}; #[derive(Debug)] pub struct IndySdkLedger { @@ -21,34 +21,36 @@ impl IndySdkLedger { } #[async_trait] -impl BaseLedger for IndySdkLedger { - async fn submit_request(&self, request_json: &str) -> VcxCoreResult { - indy::ledger::transactions::libindy_submit_request(self.indy_pool_handle, request_json).await - } - - async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { - indy::ledger::transactions::endorse_transaction( - self.indy_wallet_handle, - self.indy_pool_handle, - endorser_did, - request_json, - ) - .await +impl IndyLedgerRead for IndySdkLedger { + async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult { + indy::ledger::transactions::get_attr(self.indy_pool_handle, target_did, attr_name).await } - async fn set_endorser(&self, submitter_did: &str, request_json: &str, endorser: &str) -> VcxCoreResult { - indy::ledger::transactions::set_endorser(self.indy_wallet_handle, submitter_did, request_json, endorser).await + async fn get_nym(&self, did: &str) -> VcxCoreResult { + indy::ledger::transactions::get_nym(self.indy_pool_handle, did).await } async fn get_txn_author_agreement(&self) -> VcxCoreResult { indy::ledger::transactions::libindy_get_txn_author_agreement(self.indy_pool_handle).await } - async fn get_nym(&self, did: &str) -> VcxCoreResult { - indy::ledger::transactions::get_nym(self.indy_pool_handle, did).await + async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult { + indy::ledger::transactions::set_endorser(self.indy_wallet_handle, submitter_did, request, endorser).await } - // returns request result as JSON + async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { + indy::ledger::transactions::get_ledger_txn( + self.indy_wallet_handle, + self.indy_pool_handle, + seq_no, + submitter_did, + ) + .await + } +} + +#[async_trait] +impl IndyLedgerWrite for IndySdkLedger { async fn publish_nym( &self, submitter_did: &str, @@ -71,6 +73,24 @@ impl BaseLedger for IndySdkLedger { .await } + async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { + indy::ledger::transactions::endorse_transaction( + self.indy_wallet_handle, + self.indy_pool_handle, + endorser_did, + request_json, + ) + .await + } + + async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult { + indy::ledger::transactions::add_attr(self.indy_wallet_handle, self.indy_pool_handle, target_did, attrib_json) + .await + } +} + +#[async_trait] +impl AnoncredsLedgerRead for IndySdkLedger { async fn get_schema(&self, schema_id: &str, submitter_did: Option<&str>) -> VcxCoreResult { if let Some(submitter_did) = submitter_did { // with cache if possible @@ -95,15 +115,6 @@ impl BaseLedger for IndySdkLedger { .map(|(_id, json)| json) } - async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult { - indy::ledger::transactions::get_attr(self.indy_pool_handle, target_did, attr_name).await - } - - async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult { - indy::ledger::transactions::add_attr(self.indy_wallet_handle, self.indy_pool_handle, target_did, attrib_json) - .await - } - async fn get_rev_reg_def_json(&self, rev_reg_id: &str) -> VcxCoreResult { indy::ledger::transactions::get_rev_reg_def_json(self.indy_pool_handle, rev_reg_id) .await @@ -122,17 +133,10 @@ impl BaseLedger for IndySdkLedger { async fn get_rev_reg(&self, rev_reg_id: &str, timestamp: u64) -> VcxCoreResult<(String, String, u64)> { indy::ledger::transactions::get_rev_reg(self.indy_pool_handle, rev_reg_id, timestamp).await } +} - async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { - indy::ledger::transactions::get_ledger_txn( - self.indy_wallet_handle, - self.indy_pool_handle, - seq_no, - submitter_did, - ) - .await - } - +#[async_trait] +impl AnoncredsLedgerWrite for IndySdkLedger { async fn publish_schema( &self, schema_json: &str, diff --git a/aries_vcx_core/src/ledger/indy_vdr_ledger.rs b/aries_vcx_core/src/ledger/indy_vdr_ledger.rs index 3f2210f2bc..6327337b10 100644 --- a/aries_vcx_core/src/ledger/indy_vdr_ledger.rs +++ b/aries_vcx_core/src/ledger/indy_vdr_ledger.rs @@ -22,7 +22,7 @@ use crate::errors::error::VcxCoreResult; use crate::global::author_agreement::get_txn_author_agreement; use crate::global::settings; -use super::base_ledger::BaseLedger; +use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}; use super::request_signer::RequestSigner; use super::request_submitter::RequestSubmitter; use super::response_cacher::ResponseCacher; @@ -223,31 +223,22 @@ where } #[async_trait] -impl BaseLedger for IndyVdrLedger +impl IndyLedgerRead for IndyVdrLedger where T: RequestSubmitter + Send + Sync, U: RequestSigner + Send + Sync, V: ResponseCacher + Send + Sync, { - async fn submit_request(&self, request_json: &str) -> VcxCoreResult { - let request = PreparedRequest::from_request_json(request_json)?; + async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult { + let request = self._build_get_attr_request(None, target_did, attr_name).await?; self._submit_request(request).await } - async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { - let mut request = PreparedRequest::from_request_json(&request_json)?; - verify_transaction_can_be_endorsed(request_json, endorser_did)?; - let signature_endorser = self._get_request_signature(endorser_did, &request).await?; - request.set_multi_signature(&DidValue::from_str(endorser_did)?, &signature_endorser)?; - self._submit_request(request).await.map(|_| ()) - } + async fn get_nym(&self, did: &str) -> VcxCoreResult { + let dest = DidValue::from_str(did)?; + let request = self.request_builder()?.build_get_nym_request(None, &dest)?; - async fn set_endorser(&self, submitter_did: &str, request_json: &str, endorser: &str) -> VcxCoreResult { - let mut request = PreparedRequest::from_request_json(request_json)?; - request.set_endorser(&DidValue::from_str(endorser)?)?; - let signature_submitter = self._get_request_signature(submitter_did, &request).await?; - request.set_multi_signature(&DidValue::from_str(submitter_did)?, &signature_submitter)?; - Ok(request.req_json.to_string()) + self._submit_request_cached(did, request).await } async fn get_txn_author_agreement(&self) -> VcxCoreResult { @@ -257,19 +248,34 @@ where self._submit_request(request).await } - async fn get_nym(&self, did: &str) -> VcxCoreResult { - let dest = DidValue::from_str(did)?; - let request = self.request_builder()?.build_get_nym_request(None, &dest)?; + async fn set_endorser(&self, submitter_did: &str, request_json: &str, endorser: &str) -> VcxCoreResult { + let mut request = PreparedRequest::from_request_json(request_json)?; + request.set_endorser(&DidValue::from_str(endorser)?)?; + let signature_submitter = self._get_request_signature(submitter_did, &request).await?; + request.set_multi_signature(&DidValue::from_str(submitter_did)?, &signature_submitter)?; + Ok(request.req_json.to_string()) + } - self._submit_request_cached(did, request).await + async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { + let request = self._build_get_txn_request(submitter_did, seq_no)?; + self._submit_request(request).await } +} +#[async_trait] +#[async_trait] +impl IndyLedgerWrite for IndyVdrLedger +where + T: RequestSubmitter + Send + Sync, + U: RequestSigner + Send + Sync, + V: ResponseCacher + Send + Sync, +{ async fn publish_nym( &self, submitter_did: &str, target_did: &str, verkey: Option<&str>, - alias: Option<&str>, + data: Option<&str>, role: Option<&str>, ) -> VcxCoreResult { let identifier = DidValue::from_str(submitter_did)?; @@ -278,13 +284,56 @@ where &identifier, &dest, verkey.map(String::from), - alias.map(String::from), + data.map(String::from), role.map(String::from), )?; self._sign_and_submit_request(submitter_did, request).await } + async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { + let mut request = PreparedRequest::from_request_json(&request_json)?; + verify_transaction_can_be_endorsed(request_json, endorser_did)?; + let signature_endorser = self._get_request_signature(endorser_did, &request).await?; + request.set_multi_signature(&DidValue::from_str(endorser_did)?, &signature_endorser)?; + self._submit_request(request).await.map(|_| ()) + } + + async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult { + let request = self._build_attrib_request(target_did, target_did, Some(attrib_json))?; + let request = _append_txn_author_agreement_to_request(request).await?; + self._sign_and_submit_request(target_did, request).await + } +} + +fn current_epoch_time() -> i64 { + OffsetDateTime::now_utc().unix_timestamp() as i64 +} + +async fn _append_txn_author_agreement_to_request(request: PreparedRequest) -> VcxCoreResult { + if let Some(taa) = get_txn_author_agreement()? { + let mut request = request; + let acceptance = TxnAuthrAgrmtAcceptanceData { + mechanism: taa.acceptance_mechanism_type, + // TODO - investigate default digest + taa_digest: taa.taa_digest.map_or(String::from(""), |v| v), + time: taa.time_of_acceptance, + }; + request.set_txn_author_agreement_acceptance(&acceptance)?; + + Ok(request) + } else { + Ok(request) + } +} + +#[async_trait] +impl AnoncredsLedgerRead for IndyVdrLedger +where + T: RequestSubmitter + Send + Sync, + U: RequestSigner + Send + Sync, + V: ResponseCacher + Send + Sync, +{ async fn get_schema(&self, schema_id: &str, _submitter_did: Option<&str>) -> VcxCoreResult { let request = self .request_builder()? @@ -301,19 +350,6 @@ where Ok(serde_json::to_string(&cred_def)?) } - async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult { - let request = self._build_get_attr_request(None, target_did, attr_name).await?; - - self._submit_request(request).await - } - - async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult { - let request = self._build_attrib_request(target_did, target_did, Some(attrib_json))?; - let request = _append_txn_author_agreement_to_request(request).await?; - - self._sign_and_submit_request(target_did, request).await - } - async fn get_rev_reg_def_json(&self, rev_reg_id: &str) -> VcxCoreResult { let id = RevocationRegistryId::from_str(rev_reg_id)?; let request = self.request_builder()?.build_get_revoc_reg_def_request(None, &id)?; @@ -376,12 +412,15 @@ where timestamp, )) } +} - async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { - let request = self._build_get_txn_request(submitter_did, seq_no)?; - self._submit_request(request).await - } - +#[async_trait] +impl AnoncredsLedgerWrite for IndyVdrLedger +where + T: RequestSubmitter + Send + Sync, + U: RequestSigner + Send + Sync, + V: ResponseCacher + Send + Sync, +{ async fn publish_schema( &self, schema_json: &str, @@ -422,24 +461,3 @@ where self._sign_and_submit_request(submitter_did, request).await.map(|_| ()) } } - -fn current_epoch_time() -> i64 { - OffsetDateTime::now_utc().unix_timestamp() as i64 -} - -async fn _append_txn_author_agreement_to_request(request: PreparedRequest) -> VcxCoreResult { - if let Some(taa) = get_txn_author_agreement()? { - let mut request = request; - let acceptance = TxnAuthrAgrmtAcceptanceData { - mechanism: taa.acceptance_mechanism_type, - // TODO - investigate default digest - taa_digest: taa.taa_digest.map_or(String::from(""), |v| v), - time: taa.time_of_acceptance, - }; - request.set_txn_author_agreement_acceptance(&acceptance)?; - - Ok(request) - } else { - Ok(request) - } -} diff --git a/aries_vcx_core/src/utils/mod.rs b/aries_vcx_core/src/utils/mod.rs index 876ff955e9..af887e822d 100644 --- a/aries_vcx_core/src/utils/mod.rs +++ b/aries_vcx_core/src/utils/mod.rs @@ -1,5 +1,3 @@ -use std::{env, path::PathBuf}; - pub mod async_fn_iterator; pub(crate) mod constants; pub(crate) mod json; diff --git a/did_resolver_sov/src/reader/mod.rs b/did_resolver_sov/src/reader/mod.rs index 605ff78646..7235a638af 100644 --- a/did_resolver_sov/src/reader/mod.rs +++ b/did_resolver_sov/src/reader/mod.rs @@ -5,7 +5,7 @@ pub mod vdr_reader; use std::sync::Arc; -use aries_vcx_core::ledger::base_ledger::BaseLedger; +use aries_vcx_core::ledger::base_ledger::IndyLedgerRead; use async_trait::async_trait; use crate::error::DidSovError; @@ -18,7 +18,7 @@ pub trait AttrReader: Send + Sync { } pub struct ConcreteAttrReader { - ledger: Arc, + ledger: Arc, } #[async_trait] @@ -35,8 +35,8 @@ impl AttrReader for ConcreteAttrReader { } } -impl From> for ConcreteAttrReader { - fn from(ledger: Arc) -> Self { +impl From> for ConcreteAttrReader { + fn from(ledger: Arc) -> Self { Self { ledger } } } diff --git a/did_resolver_sov/tests/resolution.rs b/did_resolver_sov/tests/resolution.rs index 8dfb10bfeb..4f02bef2c9 100644 --- a/did_resolver_sov/tests/resolution.rs +++ b/did_resolver_sov/tests/resolution.rs @@ -30,7 +30,7 @@ async fn write_service_on_ledger_and_resolve_did_doc() { let did = format!("did:sov:{}", init.institution_did); write_test_endpoint(&init.profile, &init.institution_did).await; let resolver = DidSovResolver::new(Arc::::new( - init.profile.inject_ledger().into(), + init.profile.inject_indy_ledger_read().into(), )); let did_doc = resolver .resolve( @@ -50,7 +50,7 @@ async fn test_error_handling_during_resolution() { let did = format!("did:unknownmethod:{}", init.institution_did); let resolver = DidSovResolver::new(Arc::::new( - init.profile.inject_ledger().into(), + init.profile.inject_indy_ledger_read().into(), )); let result = resolver diff --git a/libvcx_core/src/api_vcx/api_global/ledger.rs b/libvcx_core/src/api_vcx/api_global/ledger.rs index 5f69fdc274..823aa9da31 100644 --- a/libvcx_core/src/api_vcx/api_global/ledger.rs +++ b/libvcx_core/src/api_vcx/api_global/ledger.rs @@ -18,13 +18,13 @@ pub async fn endorse_transaction(transaction: &str) -> LibvcxResult<()> { let endorser_did = get_config_value(CONFIG_INSTITUTION_DID)?; let profile = get_main_profile()?; - let ledger = profile.inject_ledger(); + let ledger = profile.inject_indy_ledger_write(); map_ariesvcx_core_result(ledger.endorse_transaction(&endorser_did, transaction).await) } pub async fn get_ledger_txn(seq_no: i32, submitter_did: Option) -> LibvcxResult { let profile = get_main_profile()?; - let ledger = profile.inject_ledger(); + let ledger = profile.inject_indy_ledger_read(); map_ariesvcx_core_result(ledger.get_ledger_txn(seq_no, submitter_did.as_deref()).await) } @@ -94,7 +94,7 @@ pub async fn ledger_clear_attr(target_did: &str, attr: &str) -> LibvcxResult LibvcxResult { let profile = get_main_profile()?; - let ledger = profile.inject_ledger(); + let ledger = profile.inject_indy_ledger_read(); map_ariesvcx_core_result(ledger.get_txn_author_agreement().await) } diff --git a/libvcx_core/src/api_vcx/api_global/pool.rs b/libvcx_core/src/api_vcx/api_global/pool.rs index 3ada2bd53a..69c61be0fd 100644 --- a/libvcx_core/src/api_vcx/api_global/pool.rs +++ b/libvcx_core/src/api_vcx/api_global/pool.rs @@ -1,5 +1,5 @@ use aries_vcx::aries_vcx_core::indy::ledger::pool::{close, create_pool_ledger_config, open_pool_ledger, PoolConfig}; -use aries_vcx::aries_vcx_core::{PoolHandle, INVALID_POOL_HANDLE}; +use aries_vcx::aries_vcx_core::INVALID_POOL_HANDLE; use aries_vcx::global::settings::{indy_mocks_enabled, DEFAULT_POOL_NAME}; use std::sync::RwLock; diff --git a/libvcx_core/src/api_vcx/api_global/profile.rs b/libvcx_core/src/api_vcx/api_global/profile.rs index 444e9e0ac0..ec043078fc 100644 --- a/libvcx_core/src/api_vcx/api_global/profile.rs +++ b/libvcx_core/src/api_vcx/api_global/profile.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use crate::errors::error::LibvcxResult; use aries_vcx::aries_vcx_core::{ wallet::{base_wallet::BaseWallet, indy_wallet::IndySdkWallet}, - PoolHandle, WalletHandle, + WalletHandle, }; use aries_vcx::core::profile::{profile::Profile, vdrtools_profile::VdrtoolsProfile}; use aries_vcx::{global::settings::indy_mocks_enabled, utils::mockdata::profile::mock_profile::MockProfile}; diff --git a/libvcx_core/src/api_vcx/api_handle/schema.rs b/libvcx_core/src/api_vcx/api_handle/schema.rs index 940c7b3d39..05fd3561f7 100644 --- a/libvcx_core/src/api_vcx/api_handle/schema.rs +++ b/libvcx_core/src/api_vcx/api_handle/schema.rs @@ -1,5 +1,4 @@ use std::string::ToString; -use std::sync::Arc; use serde_json; From b54441dc2f9f4d6c93f9c3f47814bddd356c0697 Mon Sep 17 00:00:00 2001 From: George Mulhearn <57472912+gmulhearn@users.noreply.github.com> Date: Fri, 26 May 2023 01:35:32 +1000 Subject: [PATCH 2/4] Issue #847: Prover Handler Types (#848) * Refactoring, added Prover Handler Types Signed-off-by: gmulhearn --- .../aries-vcx-agent/src/services/prover.rs | 25 +- aries_vcx/src/common/proofs/prover/prover.rs | 8 +- .../common/proofs/prover/prover_internal.rs | 225 ++++++------------ .../src/handlers/proof_presentation/mod.rs | 1 + .../src/handlers/proof_presentation/prover.rs | 17 +- .../src/handlers/proof_presentation/types.rs | 144 +++++++++++ .../proof_presentation/prover/messages.rs | 9 +- .../prover/state_machine.rs | 5 +- .../states/presentation_request_received.rs | 6 +- aries_vcx/tests/test_creds_proofs.rs | 135 +++++++---- .../tests/test_creds_proofs_revocations.rs | 11 +- aries_vcx/tests/utils/devsetup_agent.rs | 18 +- aries_vcx/tests/utils/scenarios.rs | 89 +++---- .../src/api_vcx/api_handle/disclosed_proof.rs | 10 +- 14 files changed, 418 insertions(+), 285 deletions(-) create mode 100644 aries_vcx/src/handlers/proof_presentation/types.rs diff --git a/agents/rust/aries-vcx-agent/src/services/prover.rs b/agents/rust/aries-vcx-agent/src/services/prover.rs index b0c68d0554..d441ef6402 100644 --- a/agents/rust/aries-vcx-agent/src/services/prover.rs +++ b/agents/rust/aries-vcx-agent/src/services/prover.rs @@ -7,6 +7,7 @@ use crate::storage::object_cache::ObjectCache; use crate::storage::Storage; use aries_vcx::core::profile::profile::Profile; use aries_vcx::handlers::proof_presentation::prover::Prover; +use aries_vcx::handlers::proof_presentation::types::SelectedCredentials; use aries_vcx::handlers::util::PresentationProposalData; use aries_vcx::messages::msg_fields::protocols::present_proof::ack::AckPresentation; use aries_vcx::messages::msg_fields::protocols::present_proof::request::RequestPresentation; @@ -57,23 +58,23 @@ impl ServiceProver { Ok(connection_id) } - async fn get_credentials_for_presentation(&self, prover: &Prover, tails_dir: Option<&str>) -> AgentResult { + async fn get_credentials_for_presentation( + &self, + prover: &Prover, + tails_dir: Option<&str>, + ) -> AgentResult { let credentials = prover.retrieve_credentials(&self.profile).await?; - let credentials: HashMap = serde_json::from_str(&credentials).unwrap(); - let mut res_credentials = json!({}); + let mut res_credentials = SelectedCredentials::default(); - for (key, val) in credentials["attrs"].as_object().unwrap().iter() { - let cred_array = val.as_array().unwrap(); + for (referent, cred_array) in credentials.credentials_by_referent.into_iter() { if !cred_array.is_empty() { - let first_cred = &cred_array[0]; - res_credentials["attrs"][key]["credential"] = first_cred.clone(); - if let Some(tails_dir) = tails_dir { - res_credentials["attrs"][key]["tails_file"] = Value::from(tails_dir); - } + let first_cred = cred_array[0].clone(); + let tails_dir = tails_dir.map(|x| x.to_owned()); + res_credentials.select_credential_for_referent_from_retrieved(referent, first_cred, tails_dir); } } - Ok(res_credentials.to_string()) + Ok(res_credentials) } pub fn create_from_request(&self, connection_id: &str, request: RequestPresentation) -> AgentResult { @@ -117,7 +118,7 @@ impl ServiceProver { let connection = self.service_connections.get_by_id(&connection_id)?; let credentials = self.get_credentials_for_presentation(&prover, tails_dir).await?; prover - .generate_presentation(&self.profile, credentials, "{}".to_string()) + .generate_presentation(&self.profile, credentials, HashMap::new()) .await?; let wallet = self.profile.inject_wallet(); diff --git a/aries_vcx/src/common/proofs/prover/prover.rs b/aries_vcx/src/common/proofs/prover/prover.rs index 7e6cd96902..61c8c18759 100644 --- a/aries_vcx/src/common/proofs/prover/prover.rs +++ b/aries_vcx/src/common/proofs/prover/prover.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::sync::Arc; use crate::common::proofs::proof_request::ProofRequestData; @@ -8,16 +9,17 @@ use crate::common::proofs::prover::prover_internal::{ use crate::core::profile::profile::Profile; use crate::errors::error::prelude::*; use crate::global::settings; +use crate::handlers::proof_presentation::types::SelectedCredentials; use crate::utils::mockdata::mock_settings::get_mock_generate_indy_proof; pub async fn generate_indy_proof( profile: &Arc, - credentials: &str, - self_attested_attrs: &str, + credentials: &SelectedCredentials, + self_attested_attrs: &HashMap, proof_req_data_json: &str, ) -> VcxResult { trace!( - "generate_indy_proof >>> credentials: {}, self_attested_attrs: {}", + "generate_indy_proof >>> credentials: {:?}, self_attested_attrs: {:?}", secret!(&credentials), secret!(&self_attested_attrs) ); diff --git a/aries_vcx/src/common/proofs/prover/prover_internal.rs b/aries_vcx/src/common/proofs/prover/prover_internal.rs index df450d5ddd..50d82075af 100644 --- a/aries_vcx/src/common/proofs/prover/prover_internal.rs +++ b/aries_vcx/src/common/proofs/prover/prover_internal.rs @@ -4,6 +4,7 @@ use aries_vcx_core::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind}; use serde_json::Value; use crate::errors::error::prelude::*; +use crate::handlers::proof_presentation::types::SelectedCredentials; use crate::{ common::proofs::{proof_request::ProofRequestData, proof_request_internal::NonRevokedInterval}, core::profile::profile::Profile, @@ -11,8 +12,8 @@ use crate::{ #[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct CredInfoProver { - pub requested_attr: String, pub referent: String, + pub credential_referent: String, pub schema_id: String, pub cred_def_id: String, pub rev_reg_id: Option, @@ -87,7 +88,10 @@ pub async fn build_cred_defs_json_prover( Ok(rtn.to_string()) } -pub fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) -> VcxResult> { +pub fn credential_def_identifiers( + credentials: &SelectedCredentials, + proof_req: &ProofRequestData, +) -> VcxResult> { trace!( "credential_def_identifiers >>> credentials: {:?}, proof_req: {:?}", credentials, @@ -95,51 +99,20 @@ pub fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestDat ); let mut rtn = Vec::new(); - let credentials: Value = serde_json::from_str(credentials).map_err(|err| { - AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidJson, - format!("Cannot deserialize credentials: {}", err), - ) - })?; - - if let Value::Object(ref attrs) = credentials["attrs"] { - for (requested_attr, value) in attrs { - if let (Some(referent), Some(schema_id), Some(cred_def_id)) = ( - value["credential"]["cred_info"]["referent"].as_str(), - value["credential"]["cred_info"]["schema_id"].as_str(), - value["credential"]["cred_info"]["cred_def_id"].as_str(), - ) { - let rev_reg_id = value["credential"]["cred_info"]["rev_reg_id"] - .as_str() - .map(|x| x.to_string()); - - let cred_rev_id = value["credential"]["cred_info"]["cred_rev_id"] - .as_str() - .map(|x| x.to_string()); - - let tails_file = value["tails_file"].as_str().map(|x| x.to_string()); - - let revealed = value["credential"]["cred_info"]["revealed"].as_bool(); - - rtn.push(CredInfoProver { - requested_attr: requested_attr.to_string(), - referent: referent.to_string(), - schema_id: schema_id.to_string(), - cred_def_id: cred_def_id.to_string(), - revocation_interval: _get_revocation_interval(requested_attr, proof_req)?, - timestamp: None, - rev_reg_id, - cred_rev_id, - tails_file, - revealed, - }); - } else { - return Err(AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidProofCredentialData, - "Cannot get identifiers", - )); - } - } + for (referent, selected_cred) in credentials.credential_for_referent.iter() { + let cred_info = &selected_cred.credential.cred_info; + rtn.push(CredInfoProver { + referent: referent.clone(), + credential_referent: cred_info.referent.clone(), + schema_id: cred_info.schema_id.clone(), + cred_def_id: cred_info.cred_def_id.clone(), + revocation_interval: _get_revocation_interval(&referent, proof_req)?, + timestamp: None, + rev_reg_id: cred_info.rev_reg_id.clone(), + cred_rev_id: cred_info.cred_rev_id.clone(), + tails_file: selected_cred.tails_dir.clone(), + revealed: cred_info.revealed, + }); } Ok(rtn) @@ -228,7 +201,7 @@ pub async fn build_rev_states_json( pub fn build_requested_credentials_json( credentials_identifiers: &Vec, - self_attested_attrs: &str, + self_attested_attrs: &HashMap, proof_req: &ProofRequestData, ) -> VcxResult { trace!( @@ -245,24 +218,24 @@ pub fn build_requested_credentials_json( // do same for predicates and self_attested if let Value::Object(ref mut map) = rtn["requested_attributes"] { for cred_info in credentials_identifiers { - if proof_req.requested_attributes.get(&cred_info.requested_attr).is_some() { - let insert_val = json!({"cred_id": cred_info.referent, "revealed": cred_info.revealed.unwrap_or(true), "timestamp": cred_info.timestamp}); - map.insert(cred_info.requested_attr.to_owned(), insert_val); + if proof_req.requested_attributes.get(&cred_info.referent).is_some() { + let insert_val = json!({"cred_id": cred_info.credential_referent, "revealed": cred_info.revealed.unwrap_or(true), "timestamp": cred_info.timestamp}); + map.insert(cred_info.referent.to_owned(), insert_val); } } } if let Value::Object(ref mut map) = rtn["requested_predicates"] { for cred_info in credentials_identifiers { - if proof_req.requested_predicates.get(&cred_info.requested_attr).is_some() { - let insert_val = json!({"cred_id": cred_info.referent, "timestamp": cred_info.timestamp}); - map.insert(cred_info.requested_attr.to_owned(), insert_val); + if proof_req.requested_predicates.get(&cred_info.referent).is_some() { + let insert_val = json!({"cred_id": cred_info.credential_referent, "timestamp": cred_info.timestamp}); + map.insert(cred_info.referent.to_owned(), insert_val); } } } // handle if the attribute is not revealed - let self_attested_attrs: Value = serde_json::from_str(self_attested_attrs).map_err(|err| { + let self_attested_attrs: Value = serde_json::to_value(self_attested_attrs).map_err(|err| { AriesVcxError::from_msg( AriesVcxErrorKind::InvalidJson, format!("Cannot deserialize self attested attributes: {}", err), @@ -296,8 +269,8 @@ pub mod pool_tests { // no rev_reg_id let cred1 = CredInfoProver { - requested_attr: "height_1".to_string(), - referent: LICENCE_CRED_ID.to_string(), + referent: "height_1".to_string(), + credential_referent: LICENCE_CRED_ID.to_string(), schema_id: SCHEMA_ID.to_string(), cred_def_id: CRED_DEF_ID.to_string(), rev_reg_id: None, @@ -357,8 +330,8 @@ pub mod unit_tests { let _setup = SetupMocks::init(); let cred1 = CredInfoProver { - requested_attr: "height_1".to_string(), - referent: LICENCE_CRED_ID.to_string(), + referent: "height_1".to_string(), + credential_referent: LICENCE_CRED_ID.to_string(), schema_id: SCHEMA_ID.to_string(), cred_def_id: CRED_DEF_ID.to_string(), rev_reg_id: Some(REV_REG_ID.to_string()), @@ -369,8 +342,8 @@ pub mod unit_tests { revealed: None, }; let cred2 = CredInfoProver { - requested_attr: "zip_2".to_string(), - referent: ADDRESS_CRED_ID.to_string(), + referent: "zip_2".to_string(), + credential_referent: ADDRESS_CRED_ID.to_string(), schema_id: ADDRESS_SCHEMA_ID.to_string(), cred_def_id: ADDRESS_CRED_DEF_ID.to_string(), rev_reg_id: Some(ADDRESS_REV_REG_ID.to_string()), @@ -392,8 +365,8 @@ pub mod unit_tests { SetupLibraryWallet::run(|setup| async move { let profile = indy_handles_to_profile(setup.wallet_handle, INVALID_POOL_HANDLE); let credential_ids = vec![CredInfoProver { - requested_attr: "1".to_string(), - referent: "2".to_string(), + referent: "1".to_string(), + credential_referent: "2".to_string(), schema_id: "3".to_string(), cred_def_id: "3".to_string(), rev_reg_id: Some("4".to_string()), @@ -417,8 +390,8 @@ pub mod unit_tests { SetupLibraryWallet::run(|setup| async move { let profile = indy_handles_to_profile(setup.wallet_handle, INVALID_POOL_HANDLE); let credential_ids = vec![CredInfoProver { - requested_attr: "1".to_string(), - referent: "2".to_string(), + referent: "1".to_string(), + credential_referent: "2".to_string(), schema_id: "3".to_string(), cred_def_id: "3".to_string(), rev_reg_id: Some("4".to_string()), @@ -450,8 +423,8 @@ pub mod unit_tests { ); let cred1 = CredInfoProver { - requested_attr: "height_1".to_string(), - referent: LICENCE_CRED_ID.to_string(), + referent: "height_1".to_string(), + credential_referent: LICENCE_CRED_ID.to_string(), schema_id: SCHEMA_ID.to_string(), cred_def_id: CRED_DEF_ID.to_string(), rev_reg_id: Some(REV_REG_ID.to_string()), @@ -462,8 +435,8 @@ pub mod unit_tests { revealed: None, }; let cred2 = CredInfoProver { - requested_attr: "zip_2".to_string(), - referent: ADDRESS_CRED_ID.to_string(), + referent: "zip_2".to_string(), + credential_referent: ADDRESS_CRED_ID.to_string(), schema_id: ADDRESS_SCHEMA_ID.to_string(), cred_def_id: ADDRESS_CRED_DEF_ID.to_string(), rev_reg_id: Some(ADDRESS_REV_REG_ID.to_string()), @@ -485,8 +458,8 @@ pub mod unit_tests { let _setup = SetupDefaults::init(); let cred1 = CredInfoProver { - requested_attr: "height_1".to_string(), - referent: LICENCE_CRED_ID.to_string(), + referent: "height_1".to_string(), + credential_referent: LICENCE_CRED_ID.to_string(), schema_id: SCHEMA_ID.to_string(), cred_def_id: CRED_DEF_ID.to_string(), rev_reg_id: Some(REV_REG_ID.to_string()), @@ -500,8 +473,8 @@ pub mod unit_tests { revealed: None, }; let cred2 = CredInfoProver { - requested_attr: "zip_2".to_string(), - referent: ADDRESS_CRED_ID.to_string(), + referent: "zip_2".to_string(), + credential_referent: ADDRESS_CRED_ID.to_string(), schema_id: ADDRESS_SCHEMA_ID.to_string(), cred_def_id: ADDRESS_CRED_DEF_ID.to_string(), rev_reg_id: Some(ADDRESS_REV_REG_ID.to_string()), @@ -570,48 +543,33 @@ pub mod unit_tests { .to_string(); let creds = credential_def_identifiers( - &selected_credentials.to_string(), + &serde_json::from_value(selected_credentials).unwrap(), &serde_json::from_str(&proof_req).unwrap(), ) .unwrap(); - assert_eq!(creds, vec![cred1, cred2]); + assert_eq!(creds.len(), 2); + assert!(creds.contains(&cred1)); + assert!(creds.contains(&cred2)); } #[test] fn test_credential_def_identifiers_failure() { let _setup = SetupDefaults::init(); - // selected credentials has incorrect json - assert_eq!( - credential_def_identifiers("", &proof_req_no_interval()) - .unwrap_err() - .kind(), - AriesVcxErrorKind::InvalidJson - ); - // No Creds assert_eq!( - credential_def_identifiers("{}", &proof_req_no_interval()).unwrap(), + credential_def_identifiers(&serde_json::from_str("{}").unwrap(), &proof_req_no_interval()).unwrap(), Vec::new() ); assert_eq!( - credential_def_identifiers(r#"{"attrs":{}}"#, &proof_req_no_interval()).unwrap(), + credential_def_identifiers( + &serde_json::from_str(r#"{"attrs":{}}"#).unwrap(), + &proof_req_no_interval() + ) + .unwrap(), Vec::new() ); - // missing cred info - let selected_credentials: Value = json!({ - "attrs":{ - "height_1":{ "interval":null } - } - }); - assert_eq!( - credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()) - .unwrap_err() - .kind(), - AriesVcxErrorKind::InvalidProofCredentialData - ); - // Optional Revocation let mut selected_credentials: Value = json!({ "attrs":{ @@ -636,8 +594,8 @@ pub mod unit_tests { } }); let creds = vec![CredInfoProver { - requested_attr: "height_1".to_string(), - referent: LICENCE_CRED_ID.to_string(), + referent: "height_1".to_string(), + credential_referent: LICENCE_CRED_ID.to_string(), schema_id: SCHEMA_ID.to_string(), cred_def_id: CRED_DEF_ID.to_string(), rev_reg_id: None, @@ -648,55 +606,24 @@ pub mod unit_tests { revealed: None, }]; assert_eq!( - &credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()).unwrap(), + &credential_def_identifiers( + &serde_json::from_value(selected_credentials.clone()).unwrap(), + &proof_req_no_interval() + ) + .unwrap(), &creds ); // rev_reg_id is null selected_credentials["attrs"]["height_1"]["cred_info"]["rev_reg_id"] = serde_json::Value::Null; assert_eq!( - &credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()).unwrap(), + &credential_def_identifiers( + &serde_json::from_value(selected_credentials).unwrap(), + &proof_req_no_interval() + ) + .unwrap(), &creds ); - - // Missing schema ID - let mut selected_credentials: Value = json!({ - "attrs":{ - "height_1":{ - "credential": { - "cred_info":{ - "referent":LICENCE_CRED_ID, - "attrs":{ - "sex":"male", - "age":"111", - "name":"Bob", - "height":"4'11" - }, - "cred_def_id": CRED_DEF_ID, - "rev_reg_id":REV_REG_ID, - "cred_rev_id":CRED_REV_ID - }, - "interval":null - }, - "tails_file": get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_string() - }, - } - }); - assert_eq!( - credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()) - .unwrap_err() - .kind(), - AriesVcxErrorKind::InvalidProofCredentialData - ); - - // Schema Id is null - selected_credentials["attrs"]["height_1"]["cred_info"]["schema_id"] = serde_json::Value::Null; - assert_eq!( - credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()) - .unwrap_err() - .kind(), - AriesVcxErrorKind::InvalidProofCredentialData - ); } #[test] @@ -704,8 +631,8 @@ pub mod unit_tests { let _setup = SetupMocks::init(); let cred1 = CredInfoProver { - requested_attr: "height_1".to_string(), - referent: LICENCE_CRED_ID.to_string(), + referent: "height_1".to_string(), + credential_referent: LICENCE_CRED_ID.to_string(), schema_id: SCHEMA_ID.to_string(), cred_def_id: CRED_DEF_ID.to_string(), rev_reg_id: Some(REV_REG_ID.to_string()), @@ -716,8 +643,8 @@ pub mod unit_tests { revealed: None, }; let cred2 = CredInfoProver { - requested_attr: "zip_2".to_string(), - referent: ADDRESS_CRED_ID.to_string(), + referent: "zip_2".to_string(), + credential_referent: ADDRESS_CRED_ID.to_string(), schema_id: ADDRESS_SCHEMA_ID.to_string(), cred_def_id: ADDRESS_CRED_DEF_ID.to_string(), rev_reg_id: Some(ADDRESS_REV_REG_ID.to_string()), @@ -761,7 +688,9 @@ pub mod unit_tests { "non_revoked": {"from": 098, "to": 123} }); let proof_req: ProofRequestData = serde_json::from_value(proof_req).unwrap(); - let requested_credential = build_requested_credentials_json(&creds, &self_attested_attrs, &proof_req).unwrap(); + let requested_credential = + build_requested_credentials_json(&creds, &serde_json::from_str(&self_attested_attrs).unwrap(), &proof_req) + .unwrap(); assert_eq!(test.to_string(), requested_credential); } @@ -770,8 +699,8 @@ pub mod unit_tests { let _setup = SetupMocks::init(); let cred1 = CredInfoProver { - requested_attr: "height".to_string(), - referent: "abc".to_string(), + referent: "height".to_string(), + credential_referent: "abc".to_string(), schema_id: SCHEMA_ID.to_string(), cred_def_id: CRED_DEF_ID.to_string(), rev_reg_id: Some(REV_REG_ID.to_string()), diff --git a/aries_vcx/src/handlers/proof_presentation/mod.rs b/aries_vcx/src/handlers/proof_presentation/mod.rs index 96e9e18468..de46b54d40 100644 --- a/aries_vcx/src/handlers/proof_presentation/mod.rs +++ b/aries_vcx/src/handlers/proof_presentation/mod.rs @@ -1,2 +1,3 @@ pub mod prover; +pub mod types; pub mod verifier; diff --git a/aries_vcx/src/handlers/proof_presentation/prover.rs b/aries_vcx/src/handlers/proof_presentation/prover.rs index d469921fae..b8dbc4d9cd 100644 --- a/aries_vcx/src/handlers/proof_presentation/prover.rs +++ b/aries_vcx/src/handlers/proof_presentation/prover.rs @@ -17,6 +17,8 @@ use crate::protocols::proof_presentation::prover::messages::ProverMessages; use crate::protocols::proof_presentation::prover::state_machine::{ProverSM, ProverState}; use crate::protocols::SendClosure; +use super::types::{RetrievedCredentials, SelectedCredentials}; + #[derive(Serialize, Deserialize, Debug, Clone, Default)] pub struct Prover { prover_sm: ProverSM, @@ -49,24 +51,25 @@ impl Prover { self.prover_sm.get_presentation_status() } - pub async fn retrieve_credentials(&self, profile: &Arc) -> VcxResult { + pub async fn retrieve_credentials(&self, profile: &Arc) -> VcxResult { trace!("Prover::retrieve_credentials >>>"); let presentation_request = self.presentation_request_data()?; let anoncreds = Arc::clone(profile).inject_anoncreds(); - anoncreds + let json_retrieved_credentials = anoncreds .prover_get_credentials_for_proof_req(&presentation_request) - .await - .map_err(|err| err.into()) + .await?; + + Ok(serde_json::from_str(&json_retrieved_credentials)?) } pub async fn generate_presentation( &mut self, profile: &Arc, - credentials: String, - self_attested_attrs: String, + credentials: SelectedCredentials, + self_attested_attrs: HashMap, ) -> VcxResult<()> { trace!( - "Prover::generate_presentation >>> credentials: {}, self_attested_attrs: {:?}", + "Prover::generate_presentation >>> credentials: {:?}, self_attested_attrs: {:?}", credentials, self_attested_attrs ); diff --git a/aries_vcx/src/handlers/proof_presentation/types.rs b/aries_vcx/src/handlers/proof_presentation/types.rs new file mode 100644 index 0000000000..16b3f4432a --- /dev/null +++ b/aries_vcx/src/handlers/proof_presentation/types.rs @@ -0,0 +1,144 @@ +use std::collections::HashMap; + +/// Data structure representing the credentials in the wallet, which are suitable +/// for presentation against a proof request. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct RetrievedCredentials { + /// A map of the proof request's requested referents (predicates and attribute referents) + /// against a list of [RetrievedCredentialForReferent] items which represent credentials + /// suitable for the given referent. + #[serde(rename = "attrs", skip_serializing_if = "HashMap::is_empty", default)] + pub credentials_by_referent: HashMap>, +} + +/// Data structure containing information about the credential which is suitable for a given +/// referent (`cred_info`), and the `interval` of non-revocation that was requested in the +/// original proof request (if requested). +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct RetrievedCredentialForReferent { + pub cred_info: RetrievedCredentialInfo, + pub interval: Option, +} + +/// A convenience data structure showing the metadata details (information) of a credential +/// in a wallet that has been retrieved as being 'suitable' for a proof request referent. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct RetrievedCredentialInfo { + /// The unique identifier of the credential in the wallet + pub referent: String, + /// Map of string key values representing all the attributes this credential has + #[serde(rename = "attrs")] + pub attributes: HashMap, + pub schema_id: String, + pub cred_def_id: String, + pub rev_reg_id: Option, + pub cred_rev_id: Option, +} + +// NOTE: in the future this could probably be moved to a more common location. +// It is currently defined in `proof_request_internal`, but it feels wrong +// to be exposing a type from an `..._internal` file. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct NonRevokedInterval { + pub from: Option, + pub to: Option, +} + +/// Data structure presenting the credentials which have been selected for usage +/// in creating a proof presentation in response to a proof request. +/// +/// Typically [SelectedCredentials] is constructed by selecting credential items +/// from [RetrievedCredentials] for each referent, however manual construction +/// can be done if required (e.g. if credential data is managed elsewhere). +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default)] +pub struct SelectedCredentials { + /// Map of referents (predicate and attribute) from the original proof request + /// to the credential to use in proving that referent: [SelectedCredentialForReferent]. + #[serde(rename = "attrs", skip_serializing_if = "HashMap::is_empty", default)] + pub credential_for_referent: HashMap, +} + +/// Data structure nesting further details about the selected credential for a +/// proof request referent. Including the credential details and configuration +/// for tails files if a non-revocation proof is neccessary. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct SelectedCredentialForReferent { + pub credential: SelectedCredentialForReferentCredential, + /// If wanting to create a non-revocation proof, `tails_dir` should be provided + /// and point to the absolute file path for a directory containing the tails + /// file for the credential's revocation registry. Note that the files within this + /// dir should be pre-downloaded and named by the tailsFileHash (base58), as + /// specified in the revocation registry definition for the credential. + #[serde(rename = "tails_file")] // our APIs expect a directory, but the legacy API calls it tails_file + pub tails_dir: Option, +} + +// NOTE: the only reason this is in a nested data struct is for backwards compatible +// serialization reasons. It is nested as originally it made mapping the [RetrievedCredentialForReferent] +// JSON value into a [SelectedCredentialForReferentCredential] much more convenient. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct SelectedCredentialForReferentCredential { + pub cred_info: SelectedCredentialInfo, +} + +// NOTE: this type is very similar to [RetrievedCredentialInfo] above, +// with the exception of `revealed` field being added and `attrs` field being removed +/// Data structure with the details of the credential to be used. Can be easily +/// constructed using the [RetrievedCredentials]'s [RetrievedCredentialInfo] items data. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct SelectedCredentialInfo { + /// The unique identifier of the credential in the wallet + pub referent: String, + pub schema_id: String, + pub cred_def_id: String, + pub rev_reg_id: Option, + pub cred_rev_id: Option, + /// Whether the raw attribute value/s should be proven and sent to the verifier. + /// Selecting false will still produce a proof for this credential, but no details + /// about the attributes values will be revealed. + /// If [None] is selected, aries-vcx will choose a default. + /// Selecting a value other than [None] for a credential being used in a predicate + /// referent proof will have no effect. + pub revealed: Option, +} + +// Utility method for easily translating between a retrieved credential for referent +// into a selected credential for referent. +impl From for SelectedCredentialForReferentCredential { + fn from(value: RetrievedCredentialForReferent) -> Self { + SelectedCredentialForReferentCredential { + cred_info: SelectedCredentialInfo { + referent: value.cred_info.referent, + schema_id: value.cred_info.schema_id, + cred_def_id: value.cred_info.cred_def_id, + rev_reg_id: value.cred_info.rev_reg_id, + cred_rev_id: value.cred_info.cred_rev_id, + revealed: None, // default as no-preference for revealed + }, + } + } +} + +impl SelectedCredentials { + /// Utility builder method for [SelectedCredentials] attribute creds, used to allow easy translation + /// from items of [RetrievedCredentials] into [SelectedCredentials] items. + /// + /// for the given `referent`, the `retrieved_cred` (from [RetrievedCredentials]) is selected for + /// presentation. `with_tails_dir` should be provided if the `retrieved_cred` should be presented + /// with a non-revocation proof. `with_tails_dir` should point to the absolute path of a directory + /// containing the relevant tails file for the credential's revocation registry. + pub fn select_credential_for_referent_from_retrieved( + &mut self, + referent: String, + retrieved_cred: RetrievedCredentialForReferent, + with_tails_dir: Option, + ) { + self.credential_for_referent.insert( + referent.to_string(), + SelectedCredentialForReferent { + credential: SelectedCredentialForReferentCredential::from(retrieved_cred), + tails_dir: with_tails_dir, + }, + ); + } +} diff --git a/aries_vcx/src/protocols/proof_presentation/prover/messages.rs b/aries_vcx/src/protocols/proof_presentation/prover/messages.rs index 8c2701277e..96ad310968 100644 --- a/aries_vcx/src/protocols/proof_presentation/prover/messages.rs +++ b/aries_vcx/src/protocols/proof_presentation/prover/messages.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use messages::{ msg_fields::protocols::{ notification::Notification, @@ -14,7 +16,10 @@ use messages::{ AriesMessage, }; -use crate::handlers::util::{matches_opt_thread_id, matches_thread_id, PresentationProposalData}; +use crate::handlers::{ + proof_presentation::types::SelectedCredentials, + util::{matches_opt_thread_id, matches_thread_id, PresentationProposalData}, +}; #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] pub enum ProverMessages { @@ -22,7 +27,7 @@ pub enum ProverMessages { PresentationRequestReceived(RequestPresentation), RejectPresentationRequest(String), SetPresentation(Presentation), - PreparePresentation((String, String)), + PreparePresentation((SelectedCredentials, HashMap)), SendPresentation, PresentationAckReceived(AckPresentation), PresentationRejectReceived(ProblemReport), diff --git a/aries_vcx/src/protocols/proof_presentation/prover/state_machine.rs b/aries_vcx/src/protocols/proof_presentation/prover/state_machine.rs index 83076560da..76c7c6541a 100644 --- a/aries_vcx/src/protocols/proof_presentation/prover/state_machine.rs +++ b/aries_vcx/src/protocols/proof_presentation/prover/state_machine.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use crate::core::profile::profile::Profile; use crate::errors::error::prelude::*; +use crate::handlers::proof_presentation::types::SelectedCredentials; use crate::handlers::util::{ make_attach_from_str, matches_opt_thread_id, matches_thread_id, AttachmentId, PresentationProposalData, Status, }; @@ -206,8 +207,8 @@ impl ProverSM { pub async fn generate_presentation( self, profile: &Arc, - credentials: String, - self_attested_attrs: String, + credentials: SelectedCredentials, + self_attested_attrs: HashMap, ) -> VcxResult { let state = match self.state { ProverFullState::PresentationRequestReceived(state) => { diff --git a/aries_vcx/src/protocols/proof_presentation/prover/states/presentation_request_received.rs b/aries_vcx/src/protocols/proof_presentation/prover/states/presentation_request_received.rs index ab33a45cb9..6d35452a40 100644 --- a/aries_vcx/src/protocols/proof_presentation/prover/states/presentation_request_received.rs +++ b/aries_vcx/src/protocols/proof_presentation/prover/states/presentation_request_received.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::sync::Arc; use messages::msg_fields::protocols::present_proof::present::Presentation; @@ -10,6 +11,7 @@ use uuid::Uuid; use crate::common::proofs::prover::prover::generate_indy_proof; use crate::core::profile::profile::Profile; use crate::errors::error::prelude::*; +use crate::handlers::proof_presentation::types::SelectedCredentials; use crate::handlers::util::{get_attach_as_string, Status}; use crate::protocols::proof_presentation::prover::states::finished::FinishedState; use crate::protocols::proof_presentation::prover::states::presentation_preparation_failed::PresentationPreparationFailedState; @@ -40,8 +42,8 @@ impl PresentationRequestReceived { pub async fn build_presentation( &self, profile: &Arc, - credentials: &str, - self_attested_attrs: &str, + credentials: &SelectedCredentials, + self_attested_attrs: &HashMap, ) -> VcxResult { let proof_req_data_json = get_attach_as_string!(&self.presentation_request.content.request_presentations_attach); diff --git a/aries_vcx/tests/test_creds_proofs.rs b/aries_vcx/tests/test_creds_proofs.rs index 5ee0d392f4..f3c51dda6d 100644 --- a/aries_vcx/tests/test_creds_proofs.rs +++ b/aries_vcx/tests/test_creds_proofs.rs @@ -6,6 +6,7 @@ extern crate serde_json; pub mod utils; mod integration_tests { + use std::collections::HashMap; use std::sync::Arc; use aries_vcx::common::proofs::proof_request::PresentationRequestData; @@ -14,8 +15,10 @@ mod integration_tests { create_and_store_nonrevocable_credential_def, create_indy_proof, }; use aries_vcx::handlers::proof_presentation::prover::Prover; + use aries_vcx::handlers::proof_presentation::types::RetrievedCredentials; use aries_vcx::handlers::proof_presentation::verifier::Verifier; use aries_vcx::handlers::util::AttachmentId; + use aries_vcx::protocols::proof_presentation::prover::state_machine::ProverState; use aries_vcx::protocols::proof_presentation::verifier::verification_status::PresentationVerificationStatus; use aries_vcx::utils::constants::{DEFAULT_SCHEMA_ATTRS, TAILS_DIR}; use aries_vcx::utils::devsetup::{init_holder_setup_in_indy_context, SetupProfile}; @@ -58,7 +61,10 @@ mod integration_tests { let proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); let retrieved_creds = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); - assert!(retrieved_creds.len() > 500); + // assert number of cred matches for different requested referents + assert_eq!(retrieved_creds.credentials_by_referent["address1_1"].len(), 2); + assert_eq!(retrieved_creds.credentials_by_referent["zip_2"].len(), 2); + assert_eq!(retrieved_creds.credentials_by_referent["self_attest_3"].len(), 0); }) .await; } @@ -87,7 +93,8 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_retrieve_credentials_empty() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { + // create skeleton proof request attachment data let mut req = json!({ "nonce":"123432421212", "name":"proof_req_1", @@ -97,7 +104,6 @@ mod integration_tests { }); let pres_req_data: PresentationRequestData = serde_json::from_str(&req.to_string()).unwrap(); - let id = "test_id".to_owned(); let attach_type = messages::decorators::attachment::AttachmentType::Base64(base64::encode( &json!(pres_req_data).to_string(), @@ -110,15 +116,18 @@ mod integration_tests { let content = RequestPresentationContent::new(vec![attach]); let decorators = RequestPresentationDecorators::default(); + // test retrieving credentials for empty proof request returns "{}" + let id = "test_id".to_owned(); let proof_req = RequestPresentation::with_decorators(id, content, decorators); let proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); let retrieved_creds = proof.retrieve_credentials(&setup.profile).await.unwrap(); - assert_eq!(retrieved_creds, "{}".to_string()); + assert_eq!(serde_json::to_string(&retrieved_creds).unwrap(), "{}".to_string()); + assert!(retrieved_creds.credentials_by_referent.is_empty()); + // populate proof request with a single attribute referent request req["requested_attributes"]["address1_1"] = json!({"name": "address1"}); let pres_req_data: PresentationRequestData = serde_json::from_str(&req.to_string()).unwrap(); - let id = "test_id".to_owned(); let attach_type = messages::decorators::attachment::AttachmentType::Base64(base64::encode( &json!(pres_req_data).to_string(), @@ -131,11 +140,22 @@ mod integration_tests { let content = RequestPresentationContent::new(vec![attach]); let decorators = RequestPresentationDecorators::default(); + // test retrieving credentials for the proof request returns the referent with no cred matches + let id = "test_id".to_owned(); let proof_req = RequestPresentation::with_decorators(id, content, decorators); let proof: Prover = Prover::create_from_request("2", proof_req).unwrap(); let retrieved_creds = proof.retrieve_credentials(&setup.profile).await.unwrap(); - assert_eq!(retrieved_creds, json!({"attrs":{"address1_1":[]}}).to_string()); + assert_eq!( + serde_json::to_string(&retrieved_creds).unwrap(), + json!({"attrs":{"address1_1":[]}}).to_string() + ); + assert_eq!( + retrieved_creds, + RetrievedCredentials { + credentials_by_referent: HashMap::from([("address1_1".to_string(), vec![])]) + } + ) }) .await; } @@ -144,9 +164,11 @@ mod integration_tests { #[ignore] async fn test_agency_pool_case_for_proof_req_doesnt_matter_for_retrieve_creds() { SetupProfile::run_indy(|setup| async move { + let holder_setup = init_holder_setup_in_indy_context(&setup).await; + create_and_store_nonrevocable_credential( &setup.profile, - &setup.profile, + &holder_setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -183,11 +205,9 @@ mod integration_tests { let proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); // All lower case - let retrieved_creds = proof.retrieve_credentials(&setup.profile).await.unwrap(); - assert!(retrieved_creds.contains(r#""zip":"84000""#)); - let ret_creds_as_value: serde_json::Value = serde_json::from_str(&retrieved_creds).unwrap(); + let retrieved_creds = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); assert_eq!( - ret_creds_as_value["attrs"]["zip_1"][0]["cred_info"]["attrs"]["zip"], + retrieved_creds.credentials_by_referent["zip_1"][0].cred_info.attributes["zip"], "84000" ); @@ -209,8 +229,13 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let proof: Prover = Prover::create_from_request("2", proof_req).unwrap(); - let retrieved_creds2 = proof.retrieve_credentials(&setup.profile).await.unwrap(); - assert!(retrieved_creds2.contains(r#""zip":"84000""#)); + let retrieved_creds2 = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); + assert_eq!( + retrieved_creds2.credentials_by_referent["zip_1"][0] + .cred_info + .attributes["zip"], + "84000" + ); // Entire word upper req["requested_attributes"]["zip_1"]["name"] = json!("ZIP"); @@ -230,8 +255,13 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); - let retrieved_creds3 = proof.retrieve_credentials(&setup.profile).await.unwrap(); - assert!(retrieved_creds3.contains(r#""zip":"84000""#)); + let retrieved_creds3 = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); + assert_eq!( + retrieved_creds3.credentials_by_referent["zip_1"][0] + .cred_info + .attributes["zip"], + "84000" + ); }) .await; } @@ -240,9 +270,11 @@ mod integration_tests { #[ignore] async fn test_agency_pool_generate_proof() { SetupProfile::run_indy(|setup| async move { + let holder_setup = init_holder_setup_in_indy_context(&setup).await; + create_and_store_credential( &setup.profile, - &setup.profile, + &holder_setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -285,16 +317,15 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let mut proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); - let all_creds: serde_json::Value = - serde_json::from_str(&proof.retrieve_credentials(&setup.profile).await.unwrap()).unwrap(); + let all_creds = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); let selected_credentials: serde_json::Value = json!({ "attrs":{ "address1_1": { - "credential": all_creds["attrs"]["address1_1"][0], + "credential": all_creds.credentials_by_referent["address1_1"][0], "tails_file": get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_string() }, "zip_2": { - "credential": all_creds["attrs"]["zip_2"][0], + "credential": all_creds.credentials_by_referent["zip_2"][0], "tails_file": get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_string() }, } @@ -306,12 +337,13 @@ mod integration_tests { let generated_proof = proof .generate_presentation( - &setup.profile, - selected_credentials.to_string(), - self_attested.to_string(), + &holder_setup.profile, + serde_json::from_value(selected_credentials).unwrap(), + serde_json::from_value(self_attested).unwrap(), ) .await; assert!(generated_proof.is_ok()); + assert!(matches!(proof.get_state(), ProverState::PresentationPrepared)); }) .await; } @@ -319,10 +351,13 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_generate_proof_with_predicates() { - SetupProfile::run_indy(|setup| async move { + // todo - use SetupProfile::run after modular impls + SetupProfile::run_indy(|setup: SetupProfile| async move { + let holder_setup = init_holder_setup_in_indy_context(&setup).await; + create_and_store_credential( &setup.profile, - &setup.profile, + &holder_setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -338,7 +373,7 @@ mod integration_tests { "restrictions": [{"issuer_did": setup.institution_did}], "non_revoked": {"from": 123, "to": to} }, - "zip_2": { "name": "zip" } + "state_2": { "name": "state" } }, "self_attested_attr_3": json!({ "name":"self_attested_attr", @@ -367,20 +402,19 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let mut proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); - let all_creds: serde_json::Value = - serde_json::from_str(&proof.retrieve_credentials(&setup.profile).await.unwrap()).unwrap(); + let all_creds = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); let selected_credentials: serde_json::Value = json!({ "attrs":{ "address1_1": { - "credential": all_creds["attrs"]["address1_1"][0], + "credential": all_creds.credentials_by_referent["address1_1"][0], "tails_file": get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_string() }, - "zip_2": { - "credential": all_creds["attrs"]["zip_2"][0], + "state_2": { + "credential": all_creds.credentials_by_referent["state_2"][0], "tails_file": get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_string() }, "zip_3": { - "credential": all_creds["attrs"]["zip_3"][0], + "credential": all_creds.credentials_by_referent["zip_3"][0], "tails_file": get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_string() }, }, @@ -390,12 +424,14 @@ mod integration_tests { }); let generated_proof = proof .generate_presentation( - &setup.profile, - selected_credentials.to_string(), - self_attested.to_string(), + &holder_setup.profile, + serde_json::from_value(selected_credentials).unwrap(), + serde_json::from_value(self_attested).unwrap(), ) .await; assert!(generated_proof.is_ok()); + + assert!(matches!(proof.get_state(), ProverState::PresentationPrepared)); }) .await; } @@ -404,6 +440,8 @@ mod integration_tests { #[ignore] async fn test_agency_pool_generate_self_attested_proof() { SetupProfile::run_indy(|setup| async move { + let holder_setup = init_holder_setup_in_indy_context(&setup).await; + let indy_proof_req = json!({ "nonce":"123432421212", "name":"proof_req_1", @@ -434,9 +472,9 @@ mod integration_tests { }); proof .generate_presentation( - &setup.profile, - selected_credentials.to_string(), - self_attested.to_string(), + &holder_setup.profile, + serde_json::from_value(selected_credentials).unwrap(), + serde_json::from_value(self_attested).unwrap(), ) .await .unwrap(); @@ -463,6 +501,7 @@ mod integration_tests { #[cfg(test)] mod tests { + use std::collections::HashMap; use std::time::Duration; use messages::msg_fields::protocols::cred_issuance::offer_credential::OfferCredential; @@ -971,13 +1010,7 @@ mod tests { let selected_credentials = retrieved_to_selected_credentials_simple(&retrieved_credentials, false); info!("test_real_proof :: generating and sending proof"); - generate_and_send_proof( - &mut consumer, - &mut prover, - &consumer_to_issuer, - &serde_json::to_string(&selected_credentials).unwrap(), - ) - .await; + generate_and_send_proof(&mut consumer, &mut prover, &consumer_to_issuer, selected_credentials).await; assert_eq!(ProverState::PresentationSent, prover.get_state()); assert_eq!(presentation_thread_id, prover.get_thread_id().unwrap()); assert_eq!(presentation_thread_id, verifier.get_thread_id().unwrap()); @@ -1234,13 +1267,13 @@ mod tests { let mut prover = send_proof_proposal(&mut consumer, &consumer_to_institution, &cred_def_id).await; let mut verifier = Verifier::create("1").unwrap(); accept_proof_proposal(&mut institution, &mut verifier, &institution_to_consumer).await; - let selected_credentials_str = + let selected_credentials = prover_select_credentials(&mut prover, &mut consumer, &consumer_to_institution, None).await; generate_and_send_proof( &mut consumer, &mut prover, &consumer_to_institution, - &selected_credentials_str, + selected_credentials, ) .await; verify_proof(&mut institution, &mut verifier, &institution_to_consumer).await; @@ -1310,13 +1343,13 @@ mod tests { accept_proof_proposal(&mut institution, &mut verifier, &institution_to_consumer).await; send_proof_proposal_1(&mut consumer, &mut prover, &consumer_to_institution, &cred_def_id).await; accept_proof_proposal(&mut institution, &mut verifier, &institution_to_consumer).await; - let selected_credentials_str = + let selected_credentials = prover_select_credentials(&mut prover, &mut consumer, &consumer_to_institution, None).await; generate_and_send_proof( &mut consumer, &mut prover, &consumer_to_institution, - &selected_credentials_str, + selected_credentials, ) .await; verify_proof(&mut institution, &mut verifier, &institution_to_consumer).await; @@ -1427,7 +1460,7 @@ mod tests { alice .prover - .generate_presentation(&alice.profile, credentials.to_string(), String::from("{}")) + .generate_presentation(&alice.profile, credentials, HashMap::new()) .await .unwrap(); assert_eq!(ProverState::PresentationPrepared, alice.prover.get_state()); @@ -1525,7 +1558,7 @@ mod tests { alice .prover - .generate_presentation(&alice.profile, credentials.to_string(), String::from("{}")) + .generate_presentation(&alice.profile, credentials, HashMap::new()) .await .unwrap(); assert_eq!(ProverState::PresentationPrepared, alice.prover.get_state()); diff --git a/aries_vcx/tests/test_creds_proofs_revocations.rs b/aries_vcx/tests/test_creds_proofs_revocations.rs index 8b49b8abe0..992a80d174 100644 --- a/aries_vcx/tests/test_creds_proofs_revocations.rs +++ b/aries_vcx/tests/test_creds_proofs_revocations.rs @@ -505,21 +505,20 @@ mod integration_tests { let retrieved_credentials = prover.retrieve_credentials(&consumer.profile).await.unwrap(); info!( - "test_revoked_credential_might_still_work :: prover :: based on proof, retrieved credentials: {}", + "test_revoked_credential_might_still_work :: prover :: based on proof, retrieved credentials: {:?}", &retrieved_credentials ); - let selected_credentials_value = retrieved_to_selected_credentials_simple(&retrieved_credentials, true); - let selected_credentials_str = serde_json::to_string(&selected_credentials_value).unwrap(); + let selected_credentials = retrieved_to_selected_credentials_simple(&retrieved_credentials, true); info!( - "test_revoked_credential_might_still_work :: prover :: retrieved credential converted to selected: {}", - &selected_credentials_str + "test_revoked_credential_might_still_work :: prover :: retrieved credential converted to selected: {:?}", + &selected_credentials ); generate_and_send_proof( &mut consumer, &mut prover, &consumer_to_institution, - &selected_credentials_str, + selected_credentials, ) .await; assert_eq!(ProverState::PresentationSent, prover.get_state()); diff --git a/aries_vcx/tests/utils/devsetup_agent.rs b/aries_vcx/tests/utils/devsetup_agent.rs index 84a3358404..4d64d67ae5 100644 --- a/aries_vcx/tests/utils/devsetup_agent.rs +++ b/aries_vcx/tests/utils/devsetup_agent.rs @@ -1,11 +1,13 @@ #[cfg(test)] pub mod test_utils { + use std::collections::HashMap; use std::sync::Arc; #[cfg(feature = "modular_libs")] use aries_vcx::core::profile::modular_libs_profile::ModularLibsProfile; use aries_vcx::core::profile::profile::Profile; use aries_vcx::core::profile::vdrtools_profile::VdrtoolsProfile; + use aries_vcx::handlers::proof_presentation::types::SelectedCredentials; use aries_vcx::handlers::revocation_notification::receiver::RevocationNotificationReceiver; use aries_vcx::handlers::revocation_notification::sender::RevocationNotificationSender; use aries_vcx::handlers::util::{AnyInvitation, OfferInfo, Status}; @@ -692,17 +694,15 @@ pub mod test_utils { } } - pub async fn get_credentials_for_presentation(&mut self) -> serde_json::Value { + pub async fn get_credentials_for_presentation(&mut self) -> SelectedCredentials { let credentials = self.prover.retrieve_credentials(&self.profile).await.unwrap(); - let credentials: std::collections::HashMap = - serde_json::from_str(&credentials).unwrap(); - let mut use_credentials = json!({}); + let mut use_credentials = SelectedCredentials { + credential_for_referent: HashMap::new(), + }; - for (referent, credentials) in credentials["attrs"].as_object().unwrap().iter() { - use_credentials["attrs"][referent] = json!({ - "credential": credentials[0] - }) + for (referent, credentials) in credentials.credentials_by_referent { + use_credentials.select_credential_for_referent_from_retrieved(referent, credentials[0].clone(), None); } use_credentials @@ -716,7 +716,7 @@ pub mod test_utils { let credentials = self.get_credentials_for_presentation().await; self.prover - .generate_presentation(&self.profile, credentials.to_string(), String::from("{}")) + .generate_presentation(&self.profile, credentials, HashMap::new()) .await .unwrap(); assert_eq!(ProverState::PresentationPrepared, self.prover.get_state()); diff --git a/aries_vcx/tests/utils/scenarios.rs b/aries_vcx/tests/utils/scenarios.rs index db5279caa4..c5916a1e18 100644 --- a/aries_vcx/tests/utils/scenarios.rs +++ b/aries_vcx/tests/utils/scenarios.rs @@ -1,4 +1,5 @@ pub mod test_utils { + use std::collections::HashMap; use std::sync::Arc; use std::thread; use std::time::Duration; @@ -6,6 +7,9 @@ pub mod test_utils { use aries_vcx::common::test_utils::create_and_store_credential_def; use aries_vcx::core::profile::profile::Profile; use aries_vcx::errors::error::{AriesVcxError, AriesVcxErrorKind}; + use aries_vcx::handlers::proof_presentation::types::{ + RetrievedCredentialForReferent, RetrievedCredentials, SelectedCredentials, + }; use aries_vcx::handlers::util::{AnyInvitation, OfferInfo, PresentationProposalData}; use aries_vcx::protocols::SendClosureConnection; use async_channel::{bounded, Sender}; @@ -719,15 +723,15 @@ pub mod test_utils { alice: &mut Alice, prover: &mut Prover, connection: &MediatedConnection, - selected_credentials: &str, + selected_credentials: SelectedCredentials, ) { let thread_id = prover.get_thread_id().unwrap(); info!( - "generate_and_send_proof >>> generating proof using selected credentials {}", + "generate_and_send_proof >>> generating proof using selected credentials {:?}", selected_credentials ); prover - .generate_presentation(&alice.profile, selected_credentials.into(), "{}".to_string()) + .generate_presentation(&alice.profile, selected_credentials, HashMap::new()) .await .unwrap(); assert_eq!(thread_id, prover.get_thread_id().unwrap()); @@ -967,14 +971,14 @@ pub mod test_utils { alice: &mut Alice, connection: &MediatedConnection, requested_values: Option<&str>, - ) -> String { + ) -> SelectedCredentials { prover .update_state(&alice.profile, &alice.agency_client, connection) .await .unwrap(); assert_eq!(prover.get_state(), ProverState::PresentationRequestReceived); let retrieved_credentials = prover.retrieve_credentials(&alice.profile).await.unwrap(); - let selected_credentials_value = match requested_values { + let selected_credentials = match requested_values { Some(requested_values) => { let credential_data = prover.presentation_request_data().unwrap(); retrieved_to_selected_credentials_specific( @@ -986,7 +990,8 @@ pub mod test_utils { } _ => retrieved_to_selected_credentials_simple(&retrieved_credentials, true), }; - serde_json::to_string(&selected_credentials_value).unwrap() + + selected_credentials } pub async fn prover_select_credentials_and_send_proof_and_assert( @@ -997,13 +1002,13 @@ pub mod test_utils { expected_prover_state: ProverState, ) { let mut prover = create_proof(alice, consumer_to_institution, request_name).await; - let selected_credentials_str = + let selected_credentials = prover_select_credentials(&mut prover, alice, consumer_to_institution, requested_values).await; info!( - "Prover :: Retrieved credential converted to selected: {}", - &selected_credentials_str + "Prover :: Retrieved credential converted to selected: {:?}", + &selected_credentials ); - generate_and_send_proof(alice, &mut prover, consumer_to_institution, &selected_credentials_str).await; + generate_and_send_proof(alice, &mut prover, consumer_to_institution, selected_credentials).await; assert_eq!(expected_prover_state, prover.get_state()); } @@ -1202,66 +1207,68 @@ pub mod test_utils { (consumer_to_institution, institution_to_consumer) } - pub fn retrieved_to_selected_credentials_simple(retrieved_credentials: &str, with_tails: bool) -> Value { + pub fn retrieved_to_selected_credentials_simple( + retrieved_credentials: &RetrievedCredentials, + with_tails: bool, + ) -> SelectedCredentials { info!( - "test_real_proof >>> retrieved matching credentials {}", + "test_real_proof >>> retrieved matching credentials {:?}", retrieved_credentials ); - let data: Value = serde_json::from_str(retrieved_credentials).unwrap(); - let mut credentials_mapped: Value = json!({"attrs":{}}); + let mut selected_credentials = SelectedCredentials::default(); - for (key, val) in data["attrs"].as_object().unwrap().iter() { - let cred_array = val.as_array().unwrap(); + for (referent, cred_array) in retrieved_credentials.credentials_by_referent.iter() { if cred_array.len() > 0 { - let first_cred = &cred_array[0]; - credentials_mapped["attrs"][key]["credential"] = first_cred.clone(); - if with_tails { - credentials_mapped["attrs"][key]["tails_file"] = - Value::from(get_temp_dir_path(TAILS_DIR).to_str().unwrap()); - } + let first_cred = cred_array[0].clone(); + let tails_dir = with_tails.then_some(get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_owned()); + selected_credentials.select_credential_for_referent_from_retrieved( + referent.to_owned(), + first_cred, + tails_dir, + ); } } - return credentials_mapped; + return selected_credentials; } pub fn retrieved_to_selected_credentials_specific( - retrieved_credentials: &str, + retrieved_credentials: &RetrievedCredentials, requested_values: &str, credential_data: &str, with_tails: bool, - ) -> Value { + ) -> SelectedCredentials { info!( - "test_real_proof >>> retrieved matching credentials {}", + "test_real_proof >>> retrieved matching credentials {:?}", retrieved_credentials ); - let retrieved_credentials: Value = serde_json::from_str(retrieved_credentials).unwrap(); let credential_data: Value = serde_json::from_str(credential_data).unwrap(); let requested_values: Value = serde_json::from_str(requested_values).unwrap(); let requested_attributes: &Value = &credential_data["requested_attributes"]; - let mut credentials_mapped: Value = json!({"attrs":{}}); - for (key, val) in retrieved_credentials["attrs"].as_object().unwrap().iter() { - let filtered: Vec<&Value> = val - .as_array() - .unwrap() + let mut selected_credentials = SelectedCredentials::default(); + + for (referent, cred_array) in retrieved_credentials.credentials_by_referent.iter() { + let filtered: Vec = cred_array + .clone() .into_iter() .filter_map(|cred| { - let attribute_name = requested_attributes[key]["name"].as_str().unwrap(); + let attribute_name = requested_attributes[referent]["name"].as_str().unwrap(); let requested_value = requested_values[attribute_name].as_str().unwrap(); - if cred["cred_info"]["attrs"][attribute_name].as_str().unwrap() == requested_value { + if cred.cred_info.attributes[attribute_name] == requested_value { Some(cred) } else { None } }) .collect(); - let first_cred: &serde_json::Value = &filtered[0]; - credentials_mapped["attrs"][key]["credential"] = first_cred.clone(); - if with_tails { - credentials_mapped["attrs"][key]["tails_file"] = - Value::from(get_temp_dir_path(TAILS_DIR).to_str().unwrap()); - } + let first_cred = filtered[0].clone(); + let tails_dir = with_tails.then_some(get_temp_dir_path(TAILS_DIR).to_str().unwrap().to_owned()); + selected_credentials.select_credential_for_referent_from_retrieved( + referent.to_owned(), + first_cred, + tails_dir, + ); } - return credentials_mapped; + return selected_credentials; } } diff --git a/libvcx_core/src/api_vcx/api_handle/disclosed_proof.rs b/libvcx_core/src/api_vcx/api_handle/disclosed_proof.rs index a9dd13efb0..64b7feb771 100644 --- a/libvcx_core/src/api_vcx/api_handle/disclosed_proof.rs +++ b/libvcx_core/src/api_vcx/api_handle/disclosed_proof.rs @@ -178,7 +178,11 @@ pub async fn generate_proof(handle: u32, credentials: &str, self_attested_attrs: let mut proof = HANDLE_MAP.get_cloned(handle)?; let profile = get_main_profile()?; proof - .generate_presentation(&profile, credentials.to_string(), self_attested_attrs.to_string()) + .generate_presentation( + &profile, + serde_json::from_str(credentials)?, + serde_json::from_str(self_attested_attrs)?, + ) .await?; HANDLE_MAP.insert(handle, proof) } @@ -204,7 +208,9 @@ pub async fn decline_presentation_request( pub async fn retrieve_credentials(handle: u32) -> LibvcxResult { let proof = HANDLE_MAP.get_cloned(handle)?; let profile = get_main_profile_optional_pool(); // do not throw if pool not open - proof.retrieve_credentials(&profile).await.map_err(|err| err.into()) + let retrieved_creds = proof.retrieve_credentials(&profile).await?; + + Ok(serde_json::to_string(&retrieved_creds)?) } pub fn get_proof_request_data(handle: u32) -> LibvcxResult { From a6ad85a7c0c8ff0852535ef4f169b628636f23af Mon Sep 17 00:00:00 2001 From: Miroslav Kovar Date: Fri, 26 May 2023 12:48:49 +0200 Subject: [PATCH 3/4] Split IndyVdrLedger and IndySdkLedger (#862) Split IndyVdrLedger and IndySdkLedger (#862) Signed-off-by: Miroslav Kovar --- .github/workflows/main.yml | 20 ++ .../src/core/profile/modular_libs_profile.rs | 24 +- .../src/core/profile/vdr_proxy_profile.rs | 22 +- .../src/core/profile/vdrtools_profile.rs | 13 +- .../src/utils/mockdata/profile/mock_ledger.rs | 8 +- aries_vcx_core/src/ledger/base_ledger.rs | 2 +- aries_vcx_core/src/ledger/indy_ledger.rs | 37 ++- aries_vcx_core/src/ledger/indy_vdr_ledger.rs | 311 ++++++++---------- did_resolver_sov/src/reader/indy_reader.rs | 4 +- did_resolver_sov/src/reader/vdr_reader.rs | 13 +- 10 files changed, 222 insertions(+), 232 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 88a38a7183..b2d5ee8d91 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -154,6 +154,26 @@ jobs: run: | cd libvcx && cargo clippy + check-did-resolver-feature-variants: + runs-on: ubuntu-20.04 + steps: + - name: "Git checkout" + uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + toolchain: 1.65.0 + - name: "Install dependencies" + shell: bash + run: | + sudo apt-get update -y + sudo apt-get install -y libsodium-dev libssl-dev libzmq3-dev + - name: "Verify aries_vcx compiles with different dependency feature variants" + run: | + cd did_resolver_sov + cargo check + cargo check --features vdrtools --no-default-features + cargo check --features modular_libs --no-default-features + check-aries-vcx-feature-variants: runs-on: ubuntu-20.04 steps: diff --git a/aries_vcx/src/core/profile/modular_libs_profile.rs b/aries_vcx/src/core/profile/modular_libs_profile.rs index a96dcbe5fe..938d6b2fa3 100644 --- a/aries_vcx/src/core/profile/modular_libs_profile.rs +++ b/aries_vcx/src/core/profile/modular_libs_profile.rs @@ -4,7 +4,9 @@ use std::time::Duration; use aries_vcx_core::anoncreds::base_anoncreds::BaseAnonCreds; use aries_vcx_core::anoncreds::credx_anoncreds::IndyCredxAnonCreds; use aries_vcx_core::ledger::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}; -use aries_vcx_core::ledger::indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerConfig}; +use aries_vcx_core::ledger::indy_vdr_ledger::{ + IndyVdrLedgerRead, IndyVdrLedgerReadConfig, IndyVdrLedgerWrite, IndyVdrLedgerWriteConfig, +}; use aries_vcx_core::ledger::request_signer::base_wallet::BaseWalletRequestSigner; use aries_vcx_core::ledger::request_submitter::vdr_ledger::{IndyVdrLedgerPool, IndyVdrSubmitter, LedgerPoolConfig}; use aries_vcx_core::ledger::response_cacher::in_memory::{InMemoryResponseCacher, InMemoryResponseCacherConfig}; @@ -38,20 +40,24 @@ impl ModularLibsProfile { .capacity(1000)? .build(); let response_cacher = Arc::new(InMemoryResponseCacher::new(cacher_config)); - let config = IndyVdrLedgerConfig { - request_signer, - request_submitter, + let config_read = IndyVdrLedgerReadConfig { + request_submitter: request_submitter.clone(), response_parser, response_cacher, }; - let ledger = Arc::new(IndyVdrLedger::new(config)); + let config_write = IndyVdrLedgerWriteConfig { + request_signer, + request_submitter, + }; + let ledger_read = Arc::new(IndyVdrLedgerRead::new(config_read)); + let ledger_write = Arc::new(IndyVdrLedgerWrite::new(config_write)); Ok(ModularLibsProfile { wallet, anoncreds, - anoncreds_ledger_read: ledger.clone(), - anoncreds_ledger_write: ledger.clone(), - indy_ledger_read: ledger.clone(), - indy_ledger_write: ledger, + anoncreds_ledger_read: ledger_read.clone(), + anoncreds_ledger_write: ledger_write.clone(), + indy_ledger_read: ledger_read.clone(), + indy_ledger_write: ledger_write, }) } } diff --git a/aries_vcx/src/core/profile/vdr_proxy_profile.rs b/aries_vcx/src/core/profile/vdr_proxy_profile.rs index f2e240bb58..652730f938 100644 --- a/aries_vcx/src/core/profile/vdr_proxy_profile.rs +++ b/aries_vcx/src/core/profile/vdr_proxy_profile.rs @@ -4,7 +4,7 @@ use aries_vcx_core::{ anoncreds::{base_anoncreds::BaseAnonCreds, indy_anoncreds::IndySdkAnonCreds}, ledger::{ base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}, - indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerConfig}, + indy_vdr_ledger::{IndyVdrLedgerRead, IndyVdrLedgerReadConfig, IndyVdrLedgerWrite, IndyVdrLedgerWriteConfig}, request_signer::base_wallet::BaseWalletRequestSigner, request_submitter::vdr_proxy::VdrProxySubmitter, response_cacher::in_memory::{InMemoryResponseCacher, InMemoryResponseCacherConfig}, @@ -39,20 +39,24 @@ impl VdrProxyProfile { .capacity(1000)? .build(); let response_cacher = Arc::new(InMemoryResponseCacher::new(cacher_config)); - let config = IndyVdrLedgerConfig { - request_signer, - request_submitter, + let config_read = IndyVdrLedgerReadConfig { + request_submitter: request_submitter.clone(), response_parser, response_cacher, }; - let ledger = Arc::new(IndyVdrLedger::new(config)); + let config_write = IndyVdrLedgerWriteConfig { + request_submitter, + request_signer, + }; + let ledger_read = Arc::new(IndyVdrLedgerRead::new(config_read)); + let ledger_write = Arc::new(IndyVdrLedgerWrite::new(config_write)); Ok(VdrProxyProfile { wallet, anoncreds, - anoncreds_ledger_read: ledger.clone(), - anoncreds_ledger_write: ledger.clone(), - indy_ledger_read: ledger.clone(), - indy_ledger_write: ledger, + anoncreds_ledger_read: ledger_read.clone(), + anoncreds_ledger_write: ledger_write.clone(), + indy_ledger_read: ledger_read, + indy_ledger_write: ledger_write, }) } } diff --git a/aries_vcx/src/core/profile/vdrtools_profile.rs b/aries_vcx/src/core/profile/vdrtools_profile.rs index 4a86ea87a0..d4dc71e291 100644 --- a/aries_vcx/src/core/profile/vdrtools_profile.rs +++ b/aries_vcx/src/core/profile/vdrtools_profile.rs @@ -4,7 +4,7 @@ use aries_vcx_core::{ anoncreds::{base_anoncreds::BaseAnonCreds, indy_anoncreds::IndySdkAnonCreds}, ledger::{ base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}, - indy_ledger::IndySdkLedger, + indy_ledger::{IndySdkLedgerRead, IndySdkLedgerWrite}, }, wallet::{base_wallet::BaseWallet, indy_wallet::IndySdkWallet}, PoolHandle, WalletHandle, @@ -26,14 +26,15 @@ impl VdrtoolsProfile { pub fn new(indy_wallet_handle: WalletHandle, indy_pool_handle: PoolHandle) -> Self { let wallet = Arc::new(IndySdkWallet::new(indy_wallet_handle)); let anoncreds = Arc::new(IndySdkAnonCreds::new(indy_wallet_handle)); - let ledger = Arc::new(IndySdkLedger::new(indy_wallet_handle, indy_pool_handle)); + let ledger_read = Arc::new(IndySdkLedgerRead::new(indy_wallet_handle, indy_pool_handle)); + let ledger_write = Arc::new(IndySdkLedgerWrite::new(indy_wallet_handle, indy_pool_handle)); VdrtoolsProfile { wallet, anoncreds, - anoncreds_ledger_read: ledger.clone(), - anoncreds_ledger_write: ledger.clone(), - indy_ledger_read: ledger.clone(), - indy_ledger_write: ledger, + anoncreds_ledger_read: ledger_read.clone(), + anoncreds_ledger_write: ledger_write.clone(), + indy_ledger_read: ledger_read, + indy_ledger_write: ledger_write, } } } diff --git a/aries_vcx/src/utils/mockdata/profile/mock_ledger.rs b/aries_vcx/src/utils/mockdata/profile/mock_ledger.rs index 649bdc6749..2030fcebe7 100644 --- a/aries_vcx/src/utils/mockdata/profile/mock_ledger.rs +++ b/aries_vcx/src/utils/mockdata/profile/mock_ledger.rs @@ -11,10 +11,6 @@ pub(crate) struct MockLedger; #[allow(unused)] #[async_trait] impl IndyLedgerRead for MockLedger { - async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult { - Ok(utils::constants::REQUEST_WITH_ENDORSER.to_string()) - } - async fn get_txn_author_agreement(&self) -> VcxCoreResult { Ok(utils::constants::DEFAULT_AUTHOR_AGREEMENT.to_string()) } @@ -39,6 +35,10 @@ impl IndyLedgerRead for MockLedger { #[allow(unused)] #[async_trait] impl IndyLedgerWrite for MockLedger { + async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult { + Ok(utils::constants::REQUEST_WITH_ENDORSER.to_string()) + } + async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { Ok(()) } diff --git a/aries_vcx_core/src/ledger/base_ledger.rs b/aries_vcx_core/src/ledger/base_ledger.rs index 49482d7648..49b643173d 100644 --- a/aries_vcx_core/src/ledger/base_ledger.rs +++ b/aries_vcx_core/src/ledger/base_ledger.rs @@ -9,7 +9,6 @@ pub trait IndyLedgerRead: Debug + Send + Sync { async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult; async fn get_nym(&self, did: &str) -> VcxCoreResult; async fn get_txn_author_agreement(&self) -> VcxCoreResult; - async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult; async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult; } @@ -23,6 +22,7 @@ pub trait IndyLedgerWrite: Debug + Send + Sync { data: Option<&str>, role: Option<&str>, ) -> VcxCoreResult; + async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult; async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()>; async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult; } diff --git a/aries_vcx_core/src/ledger/indy_ledger.rs b/aries_vcx_core/src/ledger/indy_ledger.rs index 7efaa99c22..55c8bfa1ce 100644 --- a/aries_vcx_core/src/ledger/indy_ledger.rs +++ b/aries_vcx_core/src/ledger/indy_ledger.rs @@ -6,14 +6,29 @@ use crate::{indy, PoolHandle, WalletHandle}; use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}; #[derive(Debug)] -pub struct IndySdkLedger { +pub struct IndySdkLedgerRead { indy_wallet_handle: WalletHandle, indy_pool_handle: PoolHandle, } -impl IndySdkLedger { +impl IndySdkLedgerRead { pub fn new(indy_wallet_handle: WalletHandle, indy_pool_handle: PoolHandle) -> Self { - IndySdkLedger { + IndySdkLedgerRead { + indy_wallet_handle, + indy_pool_handle, + } + } +} + +#[derive(Debug)] +pub struct IndySdkLedgerWrite { + indy_wallet_handle: WalletHandle, + indy_pool_handle: PoolHandle, +} + +impl IndySdkLedgerWrite { + pub fn new(indy_wallet_handle: WalletHandle, indy_pool_handle: PoolHandle) -> Self { + IndySdkLedgerWrite { indy_wallet_handle, indy_pool_handle, } @@ -21,7 +36,7 @@ impl IndySdkLedger { } #[async_trait] -impl IndyLedgerRead for IndySdkLedger { +impl IndyLedgerRead for IndySdkLedgerRead { async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult { indy::ledger::transactions::get_attr(self.indy_pool_handle, target_did, attr_name).await } @@ -34,10 +49,6 @@ impl IndyLedgerRead for IndySdkLedger { indy::ledger::transactions::libindy_get_txn_author_agreement(self.indy_pool_handle).await } - async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult { - indy::ledger::transactions::set_endorser(self.indy_wallet_handle, submitter_did, request, endorser).await - } - async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { indy::ledger::transactions::get_ledger_txn( self.indy_wallet_handle, @@ -50,7 +61,7 @@ impl IndyLedgerRead for IndySdkLedger { } #[async_trait] -impl IndyLedgerWrite for IndySdkLedger { +impl IndyLedgerWrite for IndySdkLedgerWrite { async fn publish_nym( &self, submitter_did: &str, @@ -73,6 +84,10 @@ impl IndyLedgerWrite for IndySdkLedger { .await } + async fn set_endorser(&self, submitter_did: &str, request: &str, endorser: &str) -> VcxCoreResult { + indy::ledger::transactions::set_endorser(self.indy_wallet_handle, submitter_did, request, endorser).await + } + async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { indy::ledger::transactions::endorse_transaction( self.indy_wallet_handle, @@ -90,7 +105,7 @@ impl IndyLedgerWrite for IndySdkLedger { } #[async_trait] -impl AnoncredsLedgerRead for IndySdkLedger { +impl AnoncredsLedgerRead for IndySdkLedgerRead { async fn get_schema(&self, schema_id: &str, submitter_did: Option<&str>) -> VcxCoreResult { if let Some(submitter_did) = submitter_did { // with cache if possible @@ -136,7 +151,7 @@ impl AnoncredsLedgerRead for IndySdkLedger { } #[async_trait] -impl AnoncredsLedgerWrite for IndySdkLedger { +impl AnoncredsLedgerWrite for IndySdkLedgerWrite { async fn publish_schema( &self, schema_json: &str, diff --git a/aries_vcx_core/src/ledger/indy_vdr_ledger.rs b/aries_vcx_core/src/ledger/indy_vdr_ledger.rs index 6327337b10..e9e7c00e5f 100644 --- a/aries_vcx_core/src/ledger/indy_vdr_ledger.rs +++ b/aries_vcx_core/src/ledger/indy_vdr_ledger.rs @@ -27,39 +27,51 @@ use super::request_signer::RequestSigner; use super::request_submitter::RequestSubmitter; use super::response_cacher::ResponseCacher; -pub struct IndyVdrLedgerConfig +pub struct IndyVdrLedgerReadConfig where T: RequestSubmitter + Send + Sync, - U: RequestSigner + Send + Sync, V: ResponseCacher + Send + Sync, { - pub request_signer: Arc, pub request_submitter: Arc, pub response_parser: Arc, pub response_cacher: Arc, } -pub struct IndyVdrLedger +pub struct IndyVdrLedgerWriteConfig where T: RequestSubmitter + Send + Sync, U: RequestSigner + Send + Sync, +{ + pub request_signer: Arc, + pub request_submitter: Arc, +} + +pub struct IndyVdrLedgerRead +where + T: RequestSubmitter + Send + Sync, V: ResponseCacher + Send + Sync, { - request_signer: Arc, request_submitter: Arc, response_parser: Arc, response_cacher: Arc, } -impl IndyVdrLedger +pub struct IndyVdrLedgerWrite where T: RequestSubmitter + Send + Sync, U: RequestSigner + Send + Sync, +{ + request_signer: Arc, + request_submitter: Arc, +} + +impl IndyVdrLedgerRead +where + T: RequestSubmitter + Send + Sync, V: ResponseCacher + Send + Sync, { - pub fn new(config: IndyVdrLedgerConfig) -> Self { + pub fn new(config: IndyVdrLedgerReadConfig) -> Self { Self { - request_signer: config.request_signer, request_submitter: config.request_submitter, response_parser: config.response_parser, response_cacher: config.response_cacher, @@ -67,13 +79,12 @@ where } pub fn request_builder(&self) -> VcxCoreResult { - // TODO - confirm correct protocol version? let v = settings::get_protocol_version(); let version = ProtocolVersion::from_id(v as u64)?; Ok(RequestBuilder::new(version)) } - async fn _submit_request_cached(&self, id: &str, request: PreparedRequest) -> VcxCoreResult { + async fn submit_request_cached(&self, id: &str, request: PreparedRequest) -> VcxCoreResult { match self.response_cacher.get(id, None).await? { Some(response) => Ok(response), None => { @@ -83,192 +94,95 @@ where } } } +} - async fn _submit_request(&self, request: PreparedRequest) -> VcxCoreResult { - self.request_submitter.submit(request).await +impl IndyVdrLedgerWrite +where + T: RequestSubmitter + Send + Sync, + U: RequestSigner + Send + Sync, +{ + pub fn new(config: IndyVdrLedgerWriteConfig) -> Self { + Self { + request_signer: config.request_signer, + request_submitter: config.request_submitter, + } } - async fn _get_request_signature(&self, did: &str, request: &PreparedRequest) -> VcxCoreResult> { - self.request_signer.sign(did, request).await + pub fn request_builder(&self) -> VcxCoreResult { + let v = settings::get_protocol_version(); + let version = ProtocolVersion::from_id(v as u64)?; + Ok(RequestBuilder::new(version)) } - async fn _sign_and_submit_request(&self, submitter_did: &str, request: PreparedRequest) -> VcxCoreResult { + async fn sign_and_submit_request(&self, submitter_did: &str, request: PreparedRequest) -> VcxCoreResult { let mut request = request; - let signature = self._get_request_signature(submitter_did, &request).await?; + let signature = self.request_signer.sign(submitter_did, &request).await?; request.set_signature(&signature)?; - self._submit_request(request).await - } - - async fn _build_get_cred_def_request( - &self, - submitter_did: Option<&str>, - cred_def_id: &str, - ) -> VcxCoreResult { - let identifier = submitter_did.map(DidValue::from_str).transpose()?; - let id = CredentialDefinitionId::from_str(cred_def_id)?; - Ok(self - .request_builder()? - .build_get_cred_def_request(identifier.as_ref(), &id)?) - } - - async fn _build_get_attr_request( - &self, - submitter_did: Option<&str>, - target_did: &str, - attribute_name: &str, - ) -> VcxCoreResult { - let identifier = if let Some(did) = submitter_did { - Some(DidValue::from_str(did)?) - } else { - None - }; - let dest = DidValue::from_str(target_did)?; - Ok(self.request_builder()?.build_get_attrib_request( - identifier.as_ref(), - &dest, - Some(attribute_name.to_string()), - None, - None, - )?) - } - - fn _build_attrib_request( - &self, - submitter_did: &str, - target_did: &str, - attrib_json_str: Option<&str>, - ) -> VcxCoreResult { - let identifier = DidValue::from_str(submitter_did)?; - let dest = DidValue::from_str(target_did)?; - let attrib_json = if let Some(attrib) = attrib_json_str { - Some(serde_json::from_str::(attrib)?) - } else { - None - }; - - Ok(self - .request_builder()? - .build_attrib_request(&identifier, &dest, None, attrib_json.as_ref(), None)?) - } - - fn _build_schema_request(&self, submitter_did: &str, schema_data: &str) -> VcxCoreResult { - let identifier = DidValue::from_str(submitter_did)?; - let schema_data: SchemaV1 = serde_json::from_str(schema_data)?; - Ok(self - .request_builder()? - .build_schema_request(&identifier, Schema::SchemaV1(schema_data))?) - } - - fn _build_cred_def_request(&self, submitter_did: &str, cred_def_data: &str) -> VcxCoreResult { - let identifier = DidValue::from_str(submitter_did)?; - let cred_def_data: CredentialDefinitionV1 = serde_json::from_str(cred_def_data)?; - Ok(self - .request_builder()? - .build_cred_def_request(&identifier, CredentialDefinition::CredentialDefinitionV1(cred_def_data))?) - } - - fn _build_rev_reg_def_request( - &self, - submitter_did: &str, - rev_reg_def_data: &str, - ) -> VcxCoreResult { - let identifier = DidValue::from_str(submitter_did)?; - let rev_reg_def_data: RevocationRegistryDefinitionV1 = serde_json::from_str(rev_reg_def_data)?; - Ok(self.request_builder()?.build_revoc_reg_def_request( - &identifier, - RevocationRegistryDefinition::RevocationRegistryDefinitionV1(rev_reg_def_data), - )?) - } - - fn _build_rev_reg_delta_request( - &self, - submitter_did: &str, - rev_reg_id: &str, - rev_reg_delta_data: &str, - ) -> VcxCoreResult { - let identifier = DidValue::from_str(submitter_did)?; - let rev_reg_delta_data: RevocationRegistryDeltaV1 = serde_json::from_str(rev_reg_delta_data)?; - Ok(self.request_builder()?.build_revoc_reg_entry_request( - &identifier, - &RevocationRegistryId::from_str(rev_reg_id)?, - &RegistryType::CL_ACCUM, - RevocationRegistryDelta::RevocationRegistryDeltaV1(rev_reg_delta_data), - )?) - } - - fn _build_get_txn_request(&self, submitter_did: Option<&str>, seq_no: i32) -> VcxCoreResult { - let identifier = submitter_did.map(DidValue::from_str).transpose()?; - Ok(self - .request_builder()? - .build_get_txn_request(identifier.as_ref(), LedgerType::DOMAIN.to_id(), seq_no)?) + self.request_submitter.submit(request).await } +} - fn _build_taa_request(&self, submitter_did: Option<&str>) -> VcxCoreResult { - let submitter_did = submitter_did.map(DidValue::from_str).transpose()?; - Ok(self - .request_builder()? - .build_get_txn_author_agreement_request(submitter_did.as_ref(), None)?) +impl Debug for IndyVdrLedgerRead +where + T: RequestSubmitter + Send + Sync, + V: ResponseCacher + Send + Sync, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "IndyVdrLedgerRead instance") } } -impl Debug for IndyVdrLedger +impl Debug for IndyVdrLedgerWrite where T: RequestSubmitter + Send + Sync, U: RequestSigner + Send + Sync, - V: ResponseCacher + Send + Sync, { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "IndyVdrLedger instance") + write!(f, "IndyVdrLedgerWrite instance") } } #[async_trait] -impl IndyLedgerRead for IndyVdrLedger +impl IndyLedgerRead for IndyVdrLedgerRead where T: RequestSubmitter + Send + Sync, - U: RequestSigner + Send + Sync, V: ResponseCacher + Send + Sync, { async fn get_attr(&self, target_did: &str, attr_name: &str) -> VcxCoreResult { - let request = self._build_get_attr_request(None, target_did, attr_name).await?; - self._submit_request(request).await + let dest = DidValue::from_str(target_did)?; + let request = + self.request_builder()? + .build_get_attrib_request(None, &dest, Some(attr_name.to_string()), None, None)?; + self.request_submitter.submit(request).await } async fn get_nym(&self, did: &str) -> VcxCoreResult { let dest = DidValue::from_str(did)?; let request = self.request_builder()?.build_get_nym_request(None, &dest)?; - - self._submit_request_cached(did, request).await + self.submit_request_cached(did, request).await } async fn get_txn_author_agreement(&self) -> VcxCoreResult { let request = self .request_builder()? .build_get_txn_author_agreement_request(None, None)?; - self._submit_request(request).await - } - - async fn set_endorser(&self, submitter_did: &str, request_json: &str, endorser: &str) -> VcxCoreResult { - let mut request = PreparedRequest::from_request_json(request_json)?; - request.set_endorser(&DidValue::from_str(endorser)?)?; - let signature_submitter = self._get_request_signature(submitter_did, &request).await?; - request.set_multi_signature(&DidValue::from_str(submitter_did)?, &signature_submitter)?; - Ok(request.req_json.to_string()) + self.request_submitter.submit(request).await } async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { - let request = self._build_get_txn_request(submitter_did, seq_no)?; - self._submit_request(request).await + let identifier = submitter_did.map(DidValue::from_str).transpose()?; + let request = + self.request_builder()? + .build_get_txn_request(identifier.as_ref(), LedgerType::DOMAIN.to_id(), seq_no)?; + self.request_submitter.submit(request).await } } #[async_trait] -#[async_trait] -impl IndyLedgerWrite for IndyVdrLedger +impl IndyLedgerWrite for IndyVdrLedgerWrite where T: RequestSubmitter + Send + Sync, U: RequestSigner + Send + Sync, - V: ResponseCacher + Send + Sync, { async fn publish_nym( &self, @@ -288,21 +202,37 @@ where role.map(String::from), )?; - self._sign_and_submit_request(submitter_did, request).await + self.sign_and_submit_request(submitter_did, request).await + } + + async fn set_endorser(&self, submitter_did: &str, request_json: &str, endorser: &str) -> VcxCoreResult { + let mut request = PreparedRequest::from_request_json(request_json)?; + request.set_endorser(&DidValue::from_str(endorser)?)?; + let signature_submitter = self.request_signer.sign(submitter_did, &request).await?; + request.set_multi_signature(&DidValue::from_str(submitter_did)?, &signature_submitter)?; + Ok(request.req_json.to_string()) } async fn endorse_transaction(&self, endorser_did: &str, request_json: &str) -> VcxCoreResult<()> { let mut request = PreparedRequest::from_request_json(&request_json)?; verify_transaction_can_be_endorsed(request_json, endorser_did)?; - let signature_endorser = self._get_request_signature(endorser_did, &request).await?; + let signature_endorser = self.request_signer.sign(endorser_did, &request).await?; request.set_multi_signature(&DidValue::from_str(endorser_did)?, &signature_endorser)?; - self._submit_request(request).await.map(|_| ()) + self.request_submitter.submit(request).await.map(|_| ()) } async fn add_attr(&self, target_did: &str, attrib_json: &str) -> VcxCoreResult { - let request = self._build_attrib_request(target_did, target_did, Some(attrib_json))?; + let identifier = DidValue::from_str(target_did)?; + let dest = DidValue::from_str(target_did)?; + let request = self.request_builder()?.build_attrib_request( + &identifier, + &dest, + None, + Some(&serde_json::from_str::(attrib_json)?), + None, + )?; let request = _append_txn_author_agreement_to_request(request).await?; - self._sign_and_submit_request(target_did, request).await + self.sign_and_submit_request(target_did, request).await } } @@ -320,7 +250,6 @@ async fn _append_txn_author_agreement_to_request(request: PreparedRequest) -> Vc time: taa.time_of_acceptance, }; request.set_txn_author_agreement_acceptance(&acceptance)?; - Ok(request) } else { Ok(request) @@ -328,24 +257,27 @@ async fn _append_txn_author_agreement_to_request(request: PreparedRequest) -> Vc } #[async_trait] -impl AnoncredsLedgerRead for IndyVdrLedger +impl AnoncredsLedgerRead for IndyVdrLedgerRead where T: RequestSubmitter + Send + Sync, - U: RequestSigner + Send + Sync, V: ResponseCacher + Send + Sync, { async fn get_schema(&self, schema_id: &str, _submitter_did: Option<&str>) -> VcxCoreResult { let request = self .request_builder()? .build_get_schema_request(None, &SchemaId::from_str(schema_id)?)?; - let response = self._submit_request_cached(schema_id, request).await?; + let response = self.submit_request_cached(schema_id, request).await?; let schema = self.response_parser.parse_get_schema_response(&response, None)?; Ok(serde_json::to_string(&schema)?) } async fn get_cred_def(&self, cred_def_id: &str, submitter_did: Option<&str>) -> VcxCoreResult { - let request = self._build_get_cred_def_request(submitter_did, cred_def_id).await?; - let response = self._submit_request(request).await?; + let identifier = submitter_did.map(DidValue::from_str).transpose()?; + let id = CredentialDefinitionId::from_str(cred_def_id)?; + let request = self + .request_builder()? + .build_get_cred_def_request(identifier.as_ref(), &id)?; + let response = self.request_submitter.submit(request).await?; let cred_def = self.response_parser.parse_get_cred_def_response(&response, None)?; Ok(serde_json::to_string(&cred_def)?) } @@ -353,10 +285,8 @@ where async fn get_rev_reg_def_json(&self, rev_reg_id: &str) -> VcxCoreResult { let id = RevocationRegistryId::from_str(rev_reg_id)?; let request = self.request_builder()?.build_get_revoc_reg_def_request(None, &id)?; - let res = self._submit_request_cached(rev_reg_id, request).await?; - + let res = self.submit_request_cached(rev_reg_id, request).await?; let rev_reg_def = self.response_parser.parse_get_revoc_reg_def_response(&res)?; - Ok(serde_json::to_string(&rev_reg_def)?) } @@ -375,7 +305,7 @@ where let request = self .request_builder()? .build_get_revoc_reg_delta_request(None, &revoc_reg_def_id, from, to)?; - let res = self._submit_request(request).await?; + let res = self.request_submitter.submit(request).await?; let RevocationRegistryDeltaInfo { revoc_reg_def_id, @@ -398,7 +328,7 @@ where &revoc_reg_def_id, timestamp.try_into().unwrap(), )?; - let res = self._submit_request(request).await?; + let res = self.request_submitter.submit(request).await?; let RevocationRegistryInfo { revoc_reg_def_id, @@ -415,11 +345,10 @@ where } #[async_trait] -impl AnoncredsLedgerWrite for IndyVdrLedger +impl AnoncredsLedgerWrite for IndyVdrLedgerWrite where T: RequestSubmitter + Send + Sync, U: RequestSigner + Send + Sync, - V: ResponseCacher + Send + Sync, { async fn publish_schema( &self, @@ -427,27 +356,40 @@ where submitter_did: &str, endorser_did: Option, ) -> VcxCoreResult<()> { - let mut request = self._build_schema_request(submitter_did, schema_json)?; + let identifier = DidValue::from_str(submitter_did)?; + let schema_data: SchemaV1 = serde_json::from_str(schema_json)?; + let mut request = self + .request_builder()? + .build_schema_request(&identifier, Schema::SchemaV1(schema_data))?; request = _append_txn_author_agreement_to_request(request).await?; - if let Some(endorser_did) = endorser_did { - request = PreparedRequest::from_request_json( - self.set_endorser(submitter_did, &request.req_json.to_string(), &endorser_did) - .await?, - )? - } - self._sign_and_submit_request(submitter_did, request).await.map(|_| ()) + // if let Some(endorser_did) = endorser_did { + // request = PreparedRequest::from_request_json( + // self.set_endorser(submitter_did, &request.req_json.to_string(), &endorser_did) + // .await?, + // )? + // } + self.sign_and_submit_request(submitter_did, request).await.map(|_| ()) } async fn publish_cred_def(&self, cred_def_json: &str, submitter_did: &str) -> VcxCoreResult<()> { - let request = self._build_cred_def_request(submitter_did, cred_def_json)?; + let identifier = DidValue::from_str(submitter_did)?; + let cred_def_data: CredentialDefinitionV1 = serde_json::from_str(cred_def_json)?; + let request = self + .request_builder()? + .build_cred_def_request(&identifier, CredentialDefinition::CredentialDefinitionV1(cred_def_data))?; let request = _append_txn_author_agreement_to_request(request).await?; - self._sign_and_submit_request(submitter_did, request).await.map(|_| ()) + self.sign_and_submit_request(submitter_did, request).await.map(|_| ()) } async fn publish_rev_reg_def(&self, rev_reg_def: &str, submitter_did: &str) -> VcxCoreResult<()> { - let request = self._build_rev_reg_def_request(submitter_did, rev_reg_def)?; + let identifier = DidValue::from_str(submitter_did)?; + let rev_reg_def_data: RevocationRegistryDefinitionV1 = serde_json::from_str(rev_reg_def)?; + let request = self.request_builder()?.build_revoc_reg_def_request( + &identifier, + RevocationRegistryDefinition::RevocationRegistryDefinitionV1(rev_reg_def_data), + )?; let request = _append_txn_author_agreement_to_request(request).await?; - self._sign_and_submit_request(submitter_did, request).await.map(|_| ()) + self.sign_and_submit_request(submitter_did, request).await.map(|_| ()) } async fn publish_rev_reg_delta( @@ -456,8 +398,15 @@ where rev_reg_entry_json: &str, submitter_did: &str, ) -> VcxCoreResult<()> { - let request = self._build_rev_reg_delta_request(submitter_did, rev_reg_id, rev_reg_entry_json)?; + let identifier = DidValue::from_str(submitter_did)?; + let rev_reg_delta_data: RevocationRegistryDeltaV1 = serde_json::from_str(rev_reg_entry_json)?; + let request = self.request_builder()?.build_revoc_reg_entry_request( + &identifier, + &RevocationRegistryId::from_str(rev_reg_id)?, + &RegistryType::CL_ACCUM, + RevocationRegistryDelta::RevocationRegistryDeltaV1(rev_reg_delta_data), + )?; let request = _append_txn_author_agreement_to_request(request).await?; - self._sign_and_submit_request(submitter_did, request).await.map(|_| ()) + self.sign_and_submit_request(submitter_did, request).await.map(|_| ()) } } diff --git a/did_resolver_sov/src/reader/indy_reader.rs b/did_resolver_sov/src/reader/indy_reader.rs index 01cfbc5c77..fbe7fab7d3 100644 --- a/did_resolver_sov/src/reader/indy_reader.rs +++ b/did_resolver_sov/src/reader/indy_reader.rs @@ -1,13 +1,13 @@ use std::sync::Arc; -use aries_vcx_core::{ledger::indy_ledger::IndySdkLedger, PoolHandle, INVALID_WALLET_HANDLE}; +use aries_vcx_core::{ledger::indy_ledger::IndySdkLedgerRead, PoolHandle, INVALID_WALLET_HANDLE}; use super::ConcreteAttrReader; impl From for ConcreteAttrReader { fn from(pool_handle: PoolHandle) -> Self { Self { - ledger: Arc::new(IndySdkLedger::new(INVALID_WALLET_HANDLE, pool_handle)), + ledger: Arc::new(IndySdkLedgerRead::new(INVALID_WALLET_HANDLE, pool_handle)), } } } diff --git a/did_resolver_sov/src/reader/vdr_reader.rs b/did_resolver_sov/src/reader/vdr_reader.rs index a4b4eb6f75..35465b895c 100644 --- a/did_resolver_sov/src/reader/vdr_reader.rs +++ b/did_resolver_sov/src/reader/vdr_reader.rs @@ -3,13 +3,11 @@ use std::{sync::Arc, time::Duration}; use crate::error::DidSovError; use aries_vcx_core::{ ledger::{ - indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerConfig}, - request_signer::base_wallet::BaseWalletRequestSigner, + indy_vdr_ledger::{IndyVdrLedgerRead, IndyVdrLedgerReadConfig}, request_submitter::vdr_ledger::{IndyVdrLedgerPool, IndyVdrSubmitter, LedgerPoolConfig}, response_cacher::in_memory::{InMemoryResponseCacher, InMemoryResponseCacherConfig}, }, - wallet::{base_wallet::BaseWallet, indy_wallet::IndySdkWallet}, - ResponseParser, INVALID_WALLET_HANDLE, + ResponseParser, }; use super::ConcreteAttrReader; @@ -18,23 +16,20 @@ impl TryFrom for ConcreteAttrReader { type Error = DidSovError; fn try_from(pool_config: LedgerPoolConfig) -> Result { - let wallet = Arc::new(IndySdkWallet::new(INVALID_WALLET_HANDLE)) as Arc; let ledger_pool = Arc::new(IndyVdrLedgerPool::new(pool_config)?); let request_submitter = Arc::new(IndyVdrSubmitter::new(ledger_pool)); - let request_signer = Arc::new(BaseWalletRequestSigner::new(wallet.clone())); let response_parser = Arc::new(ResponseParser::new()); let cacher_config = InMemoryResponseCacherConfig::builder() .ttl(Duration::from_secs(60)) .capacity(1000)? .build(); let response_cacher = Arc::new(InMemoryResponseCacher::new(cacher_config)); - let config = IndyVdrLedgerConfig { - request_signer, + let config = IndyVdrLedgerReadConfig { request_submitter, response_parser, response_cacher, }; - let ledger = Arc::new(IndyVdrLedger::new(config)); + let ledger = Arc::new(IndyVdrLedgerRead::new(config)); Ok(Self { ledger }) } } From 1222ef7010e9cd9cacd06cb0d6c49c7dbb3bb455 Mon Sep 17 00:00:00 2001 From: Bogdan Mircea <98585737+bobozaur@users.noreply.github.com> Date: Mon, 29 May 2023 15:41:34 +0300 Subject: [PATCH 4/4] Feature/credx issuer (#854) * Implement anoncreds trait with credx Signed-off-by: Bogdan Mircea --- .github/actions/setup-codecov-rust/action.yml | 4 +- .github/workflows/main.yml | 12 + aries_vcx/Cargo.toml | 3 + aries_vcx/src/common/anoncreds.rs | 10 +- aries_vcx/src/common/credentials/mod.rs | 28 +- aries_vcx/src/common/keys.rs | 8 +- .../primitives/credential_definition.rs | 12 +- aries_vcx/src/common/primitives/mod.rs | 12 +- .../primitives/revocation_registry_delta.rs | 2 +- .../src/common/proofs/verifier/verifier.rs | 54 +-- aries_vcx/src/common/test_utils.rs | 6 +- .../src/core/profile/mixed_breed_profile.rs | 67 +++ aries_vcx/src/core/profile/mod.rs | 2 + aries_vcx/src/utils/devsetup.rs | 78 +-- .../src/utils/mockdata/profile/mock_wallet.rs | 4 + aries_vcx/tests/test_creds_proofs.rs | 53 +-- aries_vcx/tests/test_pool.rs | 3 +- .../src/anoncreds/credx_anoncreds.rs | 446 +++++++++++++++--- aries_vcx_core/src/errors/mapping_vdrtools.rs | 2 +- .../src/wallet/agency_client_wallet.rs | 4 + aries_vcx_core/src/wallet/base_wallet.rs | 2 + aries_vcx_core/src/wallet/indy_wallet.rs | 20 +- 22 files changed, 620 insertions(+), 212 deletions(-) create mode 100644 aries_vcx/src/core/profile/mixed_breed_profile.rs diff --git a/.github/actions/setup-codecov-rust/action.yml b/.github/actions/setup-codecov-rust/action.yml index 4f06843810..fee5adaacb 100644 --- a/.github/actions/setup-codecov-rust/action.yml +++ b/.github/actions/setup-codecov-rust/action.yml @@ -10,10 +10,10 @@ inputs: runs: using: "composite" steps: - - name: Install latest nightly + - name: Install nightly 1.71 uses: actions-rs/toolchain@v1 with: - toolchain: nightly + toolchain: nightly-2023-05-08 override: true - uses: Swatinem/rust-cache@v2 - name: "Install dependencies" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b2d5ee8d91..d5ba174747 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -196,6 +196,7 @@ jobs: cargo check --features vdrtools --no-default-features cargo check --features modular_libs --no-default-features cargo check --features vdr_proxy_ledger --no-default-features + cargo check --features mixed_breed ########################################################################################## ############################## DOCKER BUILD ########################################## @@ -500,6 +501,17 @@ jobs: - name: "Run aries-vcx tests: vdrproxy_test" run: cargo test --manifest-path="aries_vcx/Cargo.toml" -F vdr_proxy_ledger -- --ignored + test-integration-aries-vcx-mixed-breed: + needs: workflow-setup + runs-on: ubuntu-20.04 + steps: + - name: "Git checkout" + uses: actions/checkout@v3 + - name: "Setup rust testing environment" + uses: ./.github/actions/setup-testing-rust + - name: "Run aries-vcx tests: pool_tests agency_pool_tests" + run: RUST_TEST_THREADS=1 cargo test --manifest-path="aries_vcx/Cargo.toml" -F mixed_breed -- --include-ignored; + test-integration-libvcx: needs: workflow-setup if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} diff --git a/aries_vcx/Cargo.toml b/aries_vcx/Cargo.toml index 4ac2b0c9d3..0b6d57069b 100644 --- a/aries_vcx/Cargo.toml +++ b/aries_vcx/Cargo.toml @@ -18,6 +18,9 @@ modular_libs = ["aries_vcx_core/modular_libs"] # TODO: Remove using "vdrtools" feature flag for vdr_proxy_ledger once IndyCredxAnonCreds # is fully implemented vdr_proxy_ledger = ["aries_vcx_core/vdr_proxy_ledger", "vdrtools"] +# Temporary feature used for testing the full credx anoncreds impl +# using vdrtools ledger and wallet. +mixed_breed = ["vdrtools", "modular_libs"] [dependencies] agency_client = { path = "../agency_client" } diff --git a/aries_vcx/src/common/anoncreds.rs b/aries_vcx/src/common/anoncreds.rs index a6e7a42ba6..c74508050a 100644 --- a/aries_vcx/src/common/anoncreds.rs +++ b/aries_vcx/src/common/anoncreds.rs @@ -7,7 +7,7 @@ pub mod integration_tests { use crate::common::test_utils::create_and_store_credential; use crate::utils::constants::TAILS_DIR; - use crate::utils::devsetup::{init_holder_setup_in_indy_context, SetupProfile}; + use crate::utils::devsetup::SetupProfile; use crate::utils::get_temp_dir_path; #[tokio::test] @@ -60,18 +60,16 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_revoke_credential() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { let (_, _, _, _, _, _, _, _, rev_reg_id, cred_rev_id, _, rev_reg) = create_and_store_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, crate::utils::constants::DEFAULT_SCHEMA_ATTRS, ) .await; - let ledger = Arc::clone(&holder_setup.profile).inject_anoncreds_ledger_read(); + let ledger = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); let (_, first_rev_reg_delta, first_timestamp) = ledger.get_rev_reg_delta_json(&rev_reg_id, None, None).await.unwrap(); diff --git a/aries_vcx/src/common/credentials/mod.rs b/aries_vcx/src/common/credentials/mod.rs index c61bd5a8c3..04a73e0a26 100644 --- a/aries_vcx/src/common/credentials/mod.rs +++ b/aries_vcx/src/common/credentials/mod.rs @@ -48,17 +48,15 @@ mod integration_tests { use crate::common::test_utils::create_and_store_credential; use crate::utils::constants::DEFAULT_SCHEMA_ATTRS; - use crate::utils::devsetup::{init_holder_setup_in_indy_context, SetupProfile}; + use crate::utils::devsetup::SetupProfile; #[tokio::test] #[ignore] async fn test_pool_prover_get_credential() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { let res = create_and_store_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -69,7 +67,7 @@ mod integration_tests { let rev_reg_id = res.8; let cred_rev_id = res.9; - let anoncreds = Arc::clone(&holder_setup.profile).inject_anoncreds(); + let anoncreds = Arc::clone(&setup.profile).inject_anoncreds(); let cred_json = anoncreds.prover_get_credential(&cred_id).await.unwrap(); let prover_cred = serde_json::from_str::(&cred_json).unwrap(); @@ -85,12 +83,10 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_get_cred_rev_id() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { let res = create_and_store_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -98,7 +94,7 @@ mod integration_tests { let cred_id = res.7; let cred_rev_id = res.9; - let cred_rev_id_ = get_cred_rev_id(&holder_setup.profile, &cred_id).await.unwrap(); + let cred_rev_id_ = get_cred_rev_id(&setup.profile, &cred_id).await.unwrap(); assert_eq!(cred_rev_id, cred_rev_id_.to_string()); }) @@ -108,12 +104,10 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_is_cred_revoked() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { let res = create_and_store_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -123,7 +117,7 @@ mod integration_tests { let tails_file = res.10; let rev_reg = res.11; - assert!(!is_cred_revoked(&holder_setup.profile, &rev_reg_id, &cred_rev_id) + assert!(!is_cred_revoked(&setup.profile, &rev_reg_id, &cred_rev_id) .await .unwrap()); @@ -140,7 +134,7 @@ mod integration_tests { std::thread::sleep(std::time::Duration::from_millis(500)); - assert!(is_cred_revoked(&holder_setup.profile, &rev_reg_id, &cred_rev_id) + assert!(is_cred_revoked(&setup.profile, &rev_reg_id, &cred_rev_id) .await .unwrap()); }) diff --git a/aries_vcx/src/common/keys.rs b/aries_vcx/src/common/keys.rs index 7d1b938de2..36778edbaa 100644 --- a/aries_vcx/src/common/keys.rs +++ b/aries_vcx/src/common/keys.rs @@ -77,7 +77,11 @@ pub async fn get_verkey_from_ledger(profile: &Arc, did: &str) -> Vc mod test { #[tokio::test] #[ignore] - #[cfg(not(feature = "vdr_proxy_ledger"))] + #[cfg(all( + not(feature = "vdr_proxy_ledger"), + not(feature = "modular_libs"), + not(feature = "mixed_breed") + ))] async fn test_pool_rotate_verkey_fails() { use super::*; @@ -86,7 +90,7 @@ mod test { use crate::utils::devsetup::*; use crate::utils::mockdata::mockdata_pool; - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { enable_pool_mocks(); PoolMocks::set_next_pool_response(mockdata_pool::RESPONSE_REQNACK); diff --git a/aries_vcx/src/common/primitives/credential_definition.rs b/aries_vcx/src/common/primitives/credential_definition.rs index a18f417196..e912f42e81 100644 --- a/aries_vcx/src/common/primitives/credential_definition.rs +++ b/aries_vcx/src/common/primitives/credential_definition.rs @@ -282,13 +282,14 @@ pub mod integration_tests { use crate::common::primitives::credential_definition::generate_cred_def; use crate::common::primitives::revocation_registry::generate_rev_reg; use crate::common::test_utils::create_and_write_test_schema; - use crate::utils::constants::DEFAULT_SCHEMA_ATTRS; + use crate::utils::constants::{DEFAULT_SCHEMA_ATTRS, TAILS_DIR}; use crate::utils::devsetup::SetupProfile; + use crate::utils::get_temp_dir_path; #[tokio::test] #[ignore] async fn test_pool_create_cred_def_real() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let (schema_id, _) = create_and_write_test_schema(&setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS).await; @@ -328,7 +329,7 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_create_rev_reg_def() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let (schema_id, _) = create_and_write_test_schema(&setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS).await; let ledger_read = Arc::clone(&setup.profile).inject_anoncreds_ledger_read(); @@ -350,11 +351,14 @@ pub mod integration_tests { .await .unwrap(); + let path = get_temp_dir_path(TAILS_DIR); + std::fs::create_dir_all(&path).unwrap(); + let (rev_reg_def_id, rev_reg_def_json, rev_reg_entry_json) = generate_rev_reg( &setup.profile, &setup.institution_did, &cred_def_id, - "tails.txt", + path.to_str().unwrap(), 2, "tag1", ) diff --git a/aries_vcx/src/common/primitives/mod.rs b/aries_vcx/src/common/primitives/mod.rs index 5ad11365cf..a1ef6cd18a 100644 --- a/aries_vcx/src/common/primitives/mod.rs +++ b/aries_vcx/src/common/primitives/mod.rs @@ -21,7 +21,7 @@ pub mod integration_tests { #[ignore] async fn test_pool_rev_reg_def_fails_for_cred_def_created_without_revocation() { // todo: does not need agency setup - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { // Cred def is created with support_revocation=false, // revoc_reg_def will fail in libindy because cred_Def doesn't have revocation keys let (_, _, cred_def_id, _, _) = create_and_store_nonrevocable_credential_def( @@ -41,7 +41,7 @@ pub mod integration_tests { ) .await; - assert_eq!(rc.unwrap_err().kind(), AriesVcxErrorKind::LibindyInvalidStructure); + assert_eq!(rc.unwrap_err().kind(), AriesVcxErrorKind::InvalidInput); }) .await; } @@ -49,7 +49,7 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_get_rev_reg_def_json() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let attrs = r#"["address1","address2","city","state","zip"]"#; let (_, _, _, _, rev_reg_id, _, _) = create_and_store_credential_def(&setup.profile, &setup.institution_did, attrs).await; @@ -63,7 +63,7 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_get_rev_reg_delta_json() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let attrs = r#"["address1","address2","city","state","zip"]"#; let (_, _, _, _, rev_reg_id, _, _) = create_and_store_credential_def(&setup.profile, &setup.institution_did, attrs).await; @@ -79,7 +79,7 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_get_rev_reg() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let attrs = r#"["address1","address2","city","state","zip"]"#; let (_, _, _, _, rev_reg_id, _, _) = create_and_store_credential_def(&setup.profile, &setup.institution_did, attrs).await; @@ -98,7 +98,7 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_get_cred_def() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let attrs = r#"["address1","address2","city","state","zip"]"#; let (_, _, cred_def_id, cred_def_json, _) = create_and_store_nonrevocable_credential_def(&setup.profile, &setup.institution_did, attrs).await; diff --git a/aries_vcx/src/common/primitives/revocation_registry_delta.rs b/aries_vcx/src/common/primitives/revocation_registry_delta.rs index 75d15f648b..9a34b2ff6f 100644 --- a/aries_vcx/src/common/primitives/revocation_registry_delta.rs +++ b/aries_vcx/src/common/primitives/revocation_registry_delta.rs @@ -66,7 +66,7 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_create_rev_reg_delta_from_ledger() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let attrs = r#"["address1","address2","city","state","zip"]"#; let (_, _, _, _, rev_reg_id, _, _) = create_and_store_credential_def(&setup.profile, &setup.institution_did, attrs).await; diff --git a/aries_vcx/src/common/proofs/verifier/verifier.rs b/aries_vcx/src/common/proofs/verifier/verifier.rs index 0707f69f20..68313a5f94 100644 --- a/aries_vcx/src/common/proofs/verifier/verifier.rs +++ b/aries_vcx/src/common/proofs/verifier/verifier.rs @@ -60,7 +60,7 @@ pub mod unit_tests { use crate::common::proofs::proof_request::ProofRequestData; use crate::common::test_utils::create_and_store_nonrevocable_credential; use crate::utils; - use crate::utils::devsetup::{init_holder_setup_in_indy_context, SetupProfile}; + use crate::utils::devsetup::SetupProfile; use super::*; @@ -129,9 +129,7 @@ pub mod unit_tests { #[tokio::test] #[ignore] async fn test_pool_proof_restrictions() { - 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", @@ -165,7 +163,7 @@ pub mod unit_tests { let (schema_id, schema_json, cred_def_id, cred_def_json, _offer, _req, _req_meta, cred_id) = create_and_store_nonrevocable_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, utils::constants::DEFAULT_SCHEMA_ATTRS, ) @@ -173,7 +171,7 @@ pub mod unit_tests { let cred_def_json: serde_json::Value = serde_json::from_str(&cred_def_json).unwrap(); let schema_json: serde_json::Value = serde_json::from_str(&schema_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, @@ -196,7 +194,7 @@ pub mod unit_tests { .await .unwrap(); assert_eq!( - validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json) + validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json) .await .unwrap_err() .kind(), @@ -206,7 +204,7 @@ pub mod unit_tests { 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(&holder_setup.profile, &prover_proof_json, &proof_req_json.to_string()) + validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json.to_string()) .await .unwrap(), true @@ -218,9 +216,7 @@ pub mod unit_tests { #[tokio::test] #[ignore] async fn test_pool_proof_validate_attribute() { - 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", @@ -255,7 +251,7 @@ pub mod unit_tests { let (schema_id, schema_json, cred_def_id, cred_def_json, _offer, _req, _req_meta, cred_id) = create_and_store_nonrevocable_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, utils::constants::DEFAULT_SCHEMA_ATTRS, ) @@ -263,7 +259,7 @@ pub mod unit_tests { let cred_def_json: serde_json::Value = serde_json::from_str(&cred_def_json).unwrap(); let schema_json: serde_json::Value = serde_json::from_str(&schema_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, @@ -286,7 +282,7 @@ pub mod unit_tests { .await .unwrap(); assert_eq!( - validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json) + validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json) .await .unwrap(), true @@ -298,7 +294,7 @@ pub mod unit_tests { let prover_proof_json = serde_json::to_string(&proof_obj).unwrap(); assert_eq!( - validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json) + validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json) .await .unwrap_err() .kind(), @@ -311,7 +307,7 @@ pub mod unit_tests { let prover_proof_json = serde_json::to_string(&proof_obj).unwrap(); assert_eq!( - validate_indy_proof(&holder_setup.profile, &prover_proof_json, &proof_req_json) + validate_indy_proof(&setup.profile, &prover_proof_json, &proof_req_json) .await .unwrap_err() .kind(), @@ -329,18 +325,16 @@ pub mod integration_tests { use std::sync::Arc; use crate::common::test_utils::{create_indy_proof, create_proof_with_predicate}; - use crate::utils::devsetup::{init_holder_setup_in_indy_context, SetupProfile}; + use crate::utils::devsetup::SetupProfile; #[tokio::test] #[ignore] async fn test_pool_prover_verify_proof() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { let (schemas, cred_defs, proof_req, proof) = - create_indy_proof(&setup.profile, &holder_setup.profile, &setup.institution_did).await; + create_indy_proof(&setup.profile, &setup.profile, &setup.institution_did).await; - let anoncreds = Arc::clone(&holder_setup.profile).inject_anoncreds(); + let anoncreds = Arc::clone(&setup.profile).inject_anoncreds(); let proof_validation = anoncreds .verifier_verify_proof(&proof_req, &proof, &schemas, &cred_defs, "{}", "{}") .await @@ -354,13 +348,11 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_prover_verify_proof_with_predicate_success_case() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { let (schemas, cred_defs, proof_req, proof) = - create_proof_with_predicate(&setup.profile, &holder_setup.profile, &setup.institution_did, true).await; + create_proof_with_predicate(&setup.profile, &setup.profile, &setup.institution_did, true).await; - let anoncreds = Arc::clone(&holder_setup.profile).inject_anoncreds(); + let anoncreds = Arc::clone(&setup.profile).inject_anoncreds(); let proof_validation = anoncreds .verifier_verify_proof(&proof_req, &proof, &schemas, &cred_defs, "{}", "{}") .await @@ -374,13 +366,11 @@ pub mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_prover_verify_proof_with_predicate_fail_case() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { let (schemas, cred_defs, proof_req, proof) = - create_proof_with_predicate(&setup.profile, &holder_setup.profile, &setup.institution_did, false).await; + create_proof_with_predicate(&setup.profile, &setup.profile, &setup.institution_did, false).await; - let anoncreds = Arc::clone(&holder_setup.profile).inject_anoncreds(); + let anoncreds = Arc::clone(&setup.profile).inject_anoncreds(); anoncreds .verifier_verify_proof(&proof_req, &proof, &schemas, &cred_defs, "{}", "{}") .await diff --git a/aries_vcx/src/common/test_utils.rs b/aries_vcx/src/common/test_utils.rs index 95fdd7d9a1..0b53493ba8 100644 --- a/aries_vcx/src/common/test_utils.rs +++ b/aries_vcx/src/common/test_utils.rs @@ -97,11 +97,15 @@ pub async fn create_and_store_credential_def( .publish_cred_def(profile) .await .unwrap(); + + let path = get_temp_dir_path(TAILS_DIR); + std::fs::create_dir_all(&path).unwrap(); + let mut rev_reg = RevocationRegistry::create( profile, issuer_did, &cred_def.get_cred_def_id(), - get_temp_dir_path(TAILS_DIR).to_str().unwrap(), + path.to_str().unwrap(), 10, 1, ) diff --git a/aries_vcx/src/core/profile/mixed_breed_profile.rs b/aries_vcx/src/core/profile/mixed_breed_profile.rs new file mode 100644 index 0000000000..4ec7a0a63b --- /dev/null +++ b/aries_vcx/src/core/profile/mixed_breed_profile.rs @@ -0,0 +1,67 @@ +use std::sync::Arc; + +use aries_vcx_core::{ + anoncreds::{base_anoncreds::BaseAnonCreds, credx_anoncreds::IndyCredxAnonCreds}, + ledger::{ + base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}, + indy_ledger::{IndySdkLedgerRead, IndySdkLedgerWrite}, + }, + wallet::{base_wallet::BaseWallet, indy_wallet::IndySdkWallet}, + PoolHandle, WalletHandle, +}; + +use super::profile::Profile; + +#[derive(Debug)] +pub struct MixedBreedProfile { + wallet: Arc, + anoncreds: Arc, + anoncreds_ledger_read: Arc, + anoncreds_ledger_write: Arc, + indy_ledger_read: Arc, + indy_ledger_write: Arc, +} + +impl MixedBreedProfile { + pub fn new(indy_wallet_handle: WalletHandle, indy_pool_handle: PoolHandle) -> Self { + let wallet: Arc = Arc::new(IndySdkWallet::new(indy_wallet_handle)); + let anoncreds = Arc::new(IndyCredxAnonCreds::new(Arc::clone(&wallet))); + let ledger_read = Arc::new(IndySdkLedgerRead::new(indy_wallet_handle, indy_pool_handle)); + let ledger_write = Arc::new(IndySdkLedgerWrite::new(indy_wallet_handle, indy_pool_handle)); + + MixedBreedProfile { + wallet, + anoncreds, + anoncreds_ledger_read: ledger_read.clone(), + anoncreds_ledger_write: ledger_write.clone(), + indy_ledger_read: ledger_read, + indy_ledger_write: ledger_write, + } + } +} + +impl Profile for MixedBreedProfile { + fn inject_indy_ledger_read(self: Arc) -> Arc { + Arc::clone(&self.indy_ledger_read) + } + + fn inject_indy_ledger_write(self: Arc) -> Arc { + Arc::clone(&self.indy_ledger_write) + } + + fn inject_anoncreds(self: Arc) -> Arc { + Arc::clone(&self.anoncreds) + } + + fn inject_anoncreds_ledger_read(self: Arc) -> Arc { + Arc::clone(&self.anoncreds_ledger_read) + } + + fn inject_anoncreds_ledger_write(self: Arc) -> Arc { + Arc::clone(&self.anoncreds_ledger_write) + } + + fn inject_wallet(&self) -> Arc { + Arc::clone(&self.wallet) + } +} diff --git a/aries_vcx/src/core/profile/mod.rs b/aries_vcx/src/core/profile/mod.rs index 2264c82d07..db7093d86a 100644 --- a/aries_vcx/src/core/profile/mod.rs +++ b/aries_vcx/src/core/profile/mod.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "mixed_breed")] +pub mod mixed_breed_profile; #[cfg(feature = "modular_libs")] pub mod modular_libs_profile; pub mod profile; diff --git a/aries_vcx/src/utils/devsetup.rs b/aries_vcx/src/utils/devsetup.rs index 632c5375bd..db32e61652 100644 --- a/aries_vcx/src/utils/devsetup.rs +++ b/aries_vcx/src/utils/devsetup.rs @@ -29,6 +29,8 @@ use agency_client::agency_client::AgencyClient; use agency_client::configuration::AgentProvisionConfig; use agency_client::testing::mocking::{disable_agency_mocks, enable_agency_mocks, AgencyMockDecrypted}; +#[cfg(feature = "mixed_breed")] +use crate::core::profile::mixed_breed_profile::MixedBreedProfile; #[cfg(feature = "modular_libs")] use crate::core::profile::modular_libs_profile::ModularLibsProfile; use crate::core::profile::profile::Profile; @@ -365,15 +367,16 @@ impl SetupWalletPool { } impl SetupProfile { - pub(self) fn should_run_modular() -> bool { - cfg!(feature = "modular_libs") - } - - #[cfg(any(feature = "modular_libs", feature = "vdrtools"))] pub async fn init() -> SetupProfile { init_test_logging(); set_test_configs(); + #[cfg(feature = "mixed_breed")] + return { + info!("SetupProfile >> using mixed breed profile"); + SetupProfile::init_mixed_breed().await + }; + #[cfg(feature = "modular_libs")] return { info!("SetupProfile >> using modular profile"); @@ -451,6 +454,38 @@ impl SetupProfile { } } + #[cfg(feature = "mixed_breed")] + async fn init_mixed_breed() -> SetupProfile { + let (institution_did, wallet_handle) = setup_issuer_wallet().await; + + settings::set_config_value( + settings::CONFIG_GENESIS_PATH, + utils::get_temp_dir_path(settings::DEFAULT_GENESIS_PATH) + .to_str() + .unwrap(), + ) + .unwrap(); + let pool_handle = open_test_pool().await; + + let profile: Arc = Arc::new(MixedBreedProfile::new(wallet_handle, pool_handle.clone())); + + Arc::clone(&profile) + .inject_anoncreds() + .prover_create_link_secret(settings::DEFAULT_LINK_SECRET_ALIAS) + .await + .unwrap(); + + async fn indy_teardown(pool_handle: PoolHandle) { + delete_test_pool(pool_handle.clone()).await; + } + + SetupProfile { + institution_did, + profile, + teardown: Arc::new(move || Box::pin(indy_teardown(pool_handle))), + } + } + #[cfg(feature = "vdr_proxy_ledger")] async fn init_vdr_proxy_ledger() -> SetupProfile { use std::env; @@ -477,7 +512,6 @@ impl SetupProfile { } } - #[cfg(any(feature = "modular_libs", feature = "vdrtools", feature = "vdr_proxy_ledger"))] pub async fn run(f: impl FnOnce(Self) -> F) where F: Future, @@ -492,38 +526,6 @@ impl SetupProfile { reset_global_state(); } - - // FUTURE - ideally no tests should be using this method, they should be using the generic run - // after modular profile Anoncreds/Ledger methods have all been implemented, all tests should use run() - #[cfg(any(feature = "vdrtools", feature = "vdr_proxy_ledger"))] - pub async fn run_indy(f: impl FnOnce(Self) -> F) - where - F: Future, - { - #[cfg(feature = "vdr_proxy_ledger")] - let init = Self::init_vdr_proxy_ledger().await; - - #[cfg(all(feature = "vdrtools", not(feature = "vdr_proxy_ledger")))] - let init = Self::init_indy().await; - - let teardown = Arc::clone(&init.teardown); - - f(init).await; - - (teardown)().await; - - reset_global_state(); - } -} - -// TODO - FUTURE - delete this method after `SetupProfile::run_indy` is removed. The purpose of this helper method -// is to return a test profile for a prover/holder given an existing indy-based profile setup (i.e. returned by SetupProfile::run_indy) -#[cfg(any(feature = "modular_libs", feature = "vdrtools"))] -pub async fn init_holder_setup_in_indy_context(indy_issuer_setup: &SetupProfile) -> SetupProfile { - if SetupProfile::should_run_modular() { - return SetupProfile::init().await; // create a new modular profile - } - indy_issuer_setup.clone() // if indy runtime, just re-use the issuer setup } impl SetupInstitutionWallet { diff --git a/aries_vcx/src/utils/mockdata/profile/mock_wallet.rs b/aries_vcx/src/utils/mockdata/profile/mock_wallet.rs index b281542ae7..af79ddd9b9 100644 --- a/aries_vcx/src/utils/mockdata/profile/mock_wallet.rs +++ b/aries_vcx/src/utils/mockdata/profile/mock_wallet.rs @@ -47,6 +47,10 @@ impl BaseWallet for MockWallet { Ok(r#"{"id":"123","type":"record type","value":"record value","tags":null}"#.to_string()) } + async fn get_wallet_record_value(&self, xtype: &str, id: &str) -> VcxCoreResult { + Ok(r#""record value""#.to_owned()) + } + async fn delete_wallet_record(&self, xtype: &str, id: &str) -> VcxCoreResult<()> { Ok(()) } diff --git a/aries_vcx/tests/test_creds_proofs.rs b/aries_vcx/tests/test_creds_proofs.rs index f3c51dda6d..d2a7b316d4 100644 --- a/aries_vcx/tests/test_creds_proofs.rs +++ b/aries_vcx/tests/test_creds_proofs.rs @@ -21,7 +21,7 @@ mod integration_tests { use aries_vcx::protocols::proof_presentation::prover::state_machine::ProverState; use aries_vcx::protocols::proof_presentation::verifier::verification_status::PresentationVerificationStatus; use aries_vcx::utils::constants::{DEFAULT_SCHEMA_ATTRS, TAILS_DIR}; - use aries_vcx::utils::devsetup::{init_holder_setup_in_indy_context, SetupProfile}; + use aries_vcx::utils::devsetup::SetupProfile; use aries_vcx::utils::get_temp_dir_path; use messages::msg_fields::protocols::present_proof::request::{ RequestPresentation, RequestPresentationContent, RequestPresentationDecorators, @@ -31,17 +31,15 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_retrieve_credentials() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { create_and_store_nonrevocable_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) .await; - let (_, _, req, _) = create_indy_proof(&setup.profile, &holder_setup.profile, &setup.institution_did).await; + let (_, _, req, _) = create_indy_proof(&setup.profile, &setup.profile, &setup.institution_did).await; let pres_req_data: PresentationRequestData = serde_json::from_str(&req).unwrap(); let id = "test_id".to_owned(); @@ -60,7 +58,7 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); - let retrieved_creds = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); + let retrieved_creds = proof.retrieve_credentials(&setup.profile).await.unwrap(); // assert number of cred matches for different requested referents assert_eq!(retrieved_creds.credentials_by_referent["address1_1"].len(), 2); assert_eq!(retrieved_creds.credentials_by_referent["zip_2"].len(), 2); @@ -72,7 +70,7 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_get_credential_def() { - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let (_, _, cred_def_id, cred_def_json, _) = create_and_store_nonrevocable_credential_def( &setup.profile, &setup.institution_did, @@ -163,12 +161,10 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_case_for_proof_req_doesnt_matter_for_retrieve_creds() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { create_and_store_nonrevocable_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -205,7 +201,7 @@ mod integration_tests { let proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); // All lower case - let retrieved_creds = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); + let retrieved_creds = proof.retrieve_credentials(&setup.profile).await.unwrap(); assert_eq!( retrieved_creds.credentials_by_referent["zip_1"][0].cred_info.attributes["zip"], "84000" @@ -229,7 +225,7 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let proof: Prover = Prover::create_from_request("2", proof_req).unwrap(); - let retrieved_creds2 = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); + let retrieved_creds2 = proof.retrieve_credentials(&setup.profile).await.unwrap(); assert_eq!( retrieved_creds2.credentials_by_referent["zip_1"][0] .cred_info @@ -255,7 +251,7 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); - let retrieved_creds3 = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); + let retrieved_creds3 = proof.retrieve_credentials(&setup.profile).await.unwrap(); assert_eq!( retrieved_creds3.credentials_by_referent["zip_1"][0] .cred_info @@ -269,12 +265,10 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_generate_proof() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { create_and_store_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -317,7 +311,7 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let mut proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); - let all_creds = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); + let all_creds = proof.retrieve_credentials(&setup.profile).await.unwrap(); let selected_credentials: serde_json::Value = json!({ "attrs":{ "address1_1": { @@ -337,7 +331,7 @@ mod integration_tests { let generated_proof = proof .generate_presentation( - &holder_setup.profile, + &setup.profile, serde_json::from_value(selected_credentials).unwrap(), serde_json::from_value(self_attested).unwrap(), ) @@ -351,13 +345,10 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_generate_proof_with_predicates() { - // todo - use SetupProfile::run after modular impls - SetupProfile::run_indy(|setup: SetupProfile| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { create_and_store_credential( &setup.profile, - &holder_setup.profile, + &setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS, ) @@ -402,7 +393,7 @@ mod integration_tests { let proof_req = RequestPresentation::with_decorators(id, content, decorators); let mut proof: Prover = Prover::create_from_request("1", proof_req).unwrap(); - let all_creds = proof.retrieve_credentials(&holder_setup.profile).await.unwrap(); + let all_creds = proof.retrieve_credentials(&setup.profile).await.unwrap(); let selected_credentials: serde_json::Value = json!({ "attrs":{ "address1_1": { @@ -424,7 +415,7 @@ mod integration_tests { }); let generated_proof = proof .generate_presentation( - &holder_setup.profile, + &setup.profile, serde_json::from_value(selected_credentials).unwrap(), serde_json::from_value(self_attested).unwrap(), ) @@ -439,9 +430,7 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_generate_self_attested_proof() { - SetupProfile::run_indy(|setup| async move { - let holder_setup = init_holder_setup_in_indy_context(&setup).await; - + SetupProfile::run(|setup| async move { let indy_proof_req = json!({ "nonce":"123432421212", "name":"proof_req_1", @@ -472,7 +461,7 @@ mod integration_tests { }); proof .generate_presentation( - &holder_setup.profile, + &setup.profile, serde_json::from_value(selected_credentials).unwrap(), serde_json::from_value(self_attested).unwrap(), ) diff --git a/aries_vcx/tests/test_pool.rs b/aries_vcx/tests/test_pool.rs index 733b645cfc..7e5c5edc60 100644 --- a/aries_vcx/tests/test_pool.rs +++ b/aries_vcx/tests/test_pool.rs @@ -32,8 +32,7 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_pool_get_credential_def() { - // TODO - use SetupProfile::run after modular impls - SetupProfile::run_indy(|setup| async move { + SetupProfile::run(|setup| async move { let (_, _, cred_def_id, cred_def_json, _) = create_and_store_nonrevocable_credential_def( &setup.profile, &setup.institution_did, diff --git a/aries_vcx_core/src/anoncreds/credx_anoncreds.rs b/aries_vcx_core/src/anoncreds/credx_anoncreds.rs index e59d279757..aae049a2b3 100644 --- a/aries_vcx_core/src/anoncreds/credx_anoncreds.rs +++ b/aries_vcx_core/src/anoncreds/credx_anoncreds.rs @@ -16,10 +16,12 @@ use crate::{ use async_trait::async_trait; use credx::{ + tails::{TailsFileReader, TailsFileWriter}, types::{ - Credential as CredxCredential, CredentialDefinitionId, CredentialRequestMetadata, CredentialRevocationState, - DidValue, MasterSecret, PresentCredentials, Presentation, PresentationRequest, RevocationRegistry, - RevocationRegistryDefinition, RevocationRegistryDelta, RevocationRegistryId, Schema, SchemaId, + Credential as CredxCredential, CredentialDefinitionId, CredentialRequestMetadata, CredentialRevocationConfig, + CredentialRevocationState, DidValue, IssuanceType, MasterSecret, PresentCredentials, Presentation, + PresentationRequest, RegistryType, RevocationRegistry, RevocationRegistryDefinition, RevocationRegistryDelta, + RevocationRegistryId, Schema, SchemaId, SignatureType, }, ursa::bn::BigNumber, }; @@ -28,14 +30,36 @@ use credx::{ ursa::cl::MasterSecret as UrsaMasterSecret, }; use indy_credx as credx; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::Value; use uuid::Uuid; use super::base_anoncreds::BaseAnonCreds; -const CATEGORY_CREDENTIAL: &str = "VCX_CREDENTIAL"; const CATEGORY_LINK_SECRET: &str = "VCX_LINK_SECRET"; +const CATEGORY_CREDENTIAL: &str = "VCX_CREDENTIAL"; +const CATEGORY_CRED_DEF: &str = "VCX_CRED_DEF"; +const CATEGORY_CRED_KEY_CORRECTNESS_PROOF: &str = "VCX_CRED_KEY_CORRECTNESS_PROOF"; +const CATEGORY_CRED_DEF_PRIV: &str = "VCX_CRED_DEF_PRIV"; +const CATEGORY_CRED_SCHEMA: &str = "VCX_CRED_SCHEMA"; + +// Category used for mapping a cred_def_id to a schema_id +const CATEGORY_CRED_MAP_SCHEMA_ID: &str = "VCX_CRED_MAP_SCHEMA_ID"; + +const CATEGORY_REV_REG: &str = "VCX_REV_REG"; +const CATEGORY_REV_REG_DELTA: &str = "VCX_REV_REG_DELTA"; +const CATEGORY_REV_REG_INFO: &str = "VCX_REV_REG_INFO"; +const CATEGORY_REV_REG_DEF: &str = "VCX_REV_REG_DEF"; +const CATEGORY_REV_REG_DEF_PRIV: &str = "VCX_REV_REG_DEF_PRIV"; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct RevocationRegistryInfo { + pub id: RevocationRegistryId, + pub curr_id: u32, + pub used_ids: HashSet, +} + #[derive(Debug)] pub struct IndyCredxAnonCreds { wallet: Arc, @@ -46,6 +70,14 @@ impl IndyCredxAnonCreds { IndyCredxAnonCreds { wallet } } + async fn get_wallet_record_value(&self, category: &str, id: &str) -> VcxCoreResult + where + T: DeserializeOwned, + { + let str_record = self.wallet.get_wallet_record_value(category, id).await?; + serde_json::from_str(&str_record).map_err(From::from) + } + async fn get_link_secret(&self, link_secret_id: &str) -> VcxCoreResult { let record = self .wallet @@ -151,15 +183,6 @@ impl BaseAnonCreds for IndyCredxAnonCreds { rev_reg_defs_json: &str, rev_regs_json: &str, ) -> VcxCoreResult { - let _ = ( - proof_req_json, - proof_json, - schemas_json, - credential_defs_json, - rev_reg_defs_json, - rev_regs_json, - ); - let presentation: Presentation = serde_json::from_str(proof_json)?; let pres_req: PresentationRequest = serde_json::from_str(proof_req_json)?; @@ -199,8 +222,64 @@ impl BaseAnonCreds for IndyCredxAnonCreds { max_creds: u32, tag: &str, ) -> VcxCoreResult<(String, String, String)> { - let _ = (issuer_did, cred_def_id, tails_dir, max_creds, tag); - Err(unimplemented_method_err("credx issuer_create_and_store_revoc_reg")) + let issuer_did = issuer_did.to_owned().into(); + + let mut tails_writer = TailsFileWriter::new(Some(tails_dir.to_owned())); + + let cred_def = self.get_wallet_record_value(CATEGORY_CRED_DEF, cred_def_id).await?; + + let rev_reg_id = + credx::issuer::make_revocation_registry_id(&issuer_did, &cred_def, tag, RegistryType::CL_ACCUM)?; + + let res_rev_reg = self.get_wallet_record_value(CATEGORY_REV_REG, &rev_reg_id.0).await; + let res_rev_reg_def = self.get_wallet_record_value(CATEGORY_REV_REG_DEF, &rev_reg_id.0).await; + + if let (Ok(rev_reg), Ok(rev_reg_def)) = (res_rev_reg, res_rev_reg_def) { + return Ok((rev_reg_id.0, rev_reg, rev_reg_def)); + } + + let (rev_reg_def, rev_reg_def_priv, rev_reg, _rev_reg_delta) = credx::issuer::create_revocation_registry( + &issuer_did, + &cred_def, + tag, + RegistryType::CL_ACCUM, + IssuanceType::ISSUANCE_BY_DEFAULT, + max_creds, + &mut tails_writer, + )?; + + // Store stuff in wallet + let rev_reg_info = RevocationRegistryInfo { + id: rev_reg_id.clone(), + curr_id: 0, + used_ids: HashSet::new(), + }; + + let str_rev_reg_info = serde_json::to_string(&rev_reg_info)?; + + self.wallet + .add_wallet_record(CATEGORY_REV_REG_INFO, &rev_reg_id.0, &str_rev_reg_info, None) + .await?; + + let str_rev_reg_def = serde_json::to_string(&rev_reg_def)?; + + self.wallet + .add_wallet_record(CATEGORY_REV_REG_DEF, &rev_reg_id.0, &str_rev_reg_def, None) + .await?; + + let str_rev_reg_def_priv = serde_json::to_string(&rev_reg_def_priv)?; + + self.wallet + .add_wallet_record(CATEGORY_REV_REG_DEF_PRIV, &rev_reg_id.0, &str_rev_reg_def_priv, None) + .await?; + + let str_rev_reg = serde_json::to_string(&rev_reg)?; + + self.wallet + .add_wallet_record(CATEGORY_REV_REG, &rev_reg_id.0, &str_rev_reg, None) + .await?; + + Ok((rev_reg_id.0, str_rev_reg_def, str_rev_reg)) } async fn issuer_create_and_store_credential_def( @@ -211,13 +290,85 @@ impl BaseAnonCreds for IndyCredxAnonCreds { sig_type: Option<&str>, config_json: &str, ) -> VcxCoreResult<(String, String)> { - let _ = (issuer_did, schema_json, tag, sig_type, config_json); - Err(unimplemented_method_err("credx issuer_create_and_store_credential_def")) + let issuer_did = issuer_did.to_owned().into(); + let schema = serde_json::from_str(schema_json)?; + let sig_type = sig_type.map(serde_json::from_str).unwrap_or(Ok(SignatureType::CL))?; + let config = serde_json::from_str(config_json)?; + + let schema_seq_no = match &schema { + Schema::SchemaV1(s) => s.seq_no, + }; + + let cred_def_id = + credx::issuer::make_credential_definition_id(&issuer_did, schema.id(), schema_seq_no, tag, sig_type)?; + + // If cred def already exists, return it + if let Ok(cred_def) = self.get_wallet_record_value(CATEGORY_CRED_DEF, &cred_def_id.0).await { + return Ok((cred_def_id.0, cred_def)); + } + + // Otherwise, create cred def + let (cred_def, cred_def_priv, cred_key_correctness_proof) = + credx::issuer::create_credential_definition(&issuer_did, &schema, tag, sig_type, config)?; + + let str_cred_def = serde_json::to_string(&cred_def)?; + + // Store stuff in wallet + self.wallet + .add_wallet_record(CATEGORY_CRED_DEF, &cred_def_id.0, &str_cred_def, None) + .await?; + + let str_cred_def_priv = serde_json::to_string(&cred_def_priv)?; + + self.wallet + .add_wallet_record(CATEGORY_CRED_DEF_PRIV, &cred_def_id.0, &str_cred_def_priv, None) + .await?; + + let str_cred_key_proof = serde_json::to_string(&cred_key_correctness_proof)?; + + self.wallet + .add_wallet_record( + CATEGORY_CRED_KEY_CORRECTNESS_PROOF, + &cred_def_id.0, + &str_cred_key_proof, + None, + ) + .await?; + + let store_schema_res = self + .wallet + .add_wallet_record(CATEGORY_CRED_SCHEMA, schema.id(), schema_json, None) + .await; + + if let Err(e) = store_schema_res { + warn!("Storing schema {schema_json} failed - {e}. It's possible it is already stored.") + } + + let str_schema_id = serde_json::to_string(schema.id())?; + + self.wallet + .add_wallet_record(CATEGORY_CRED_MAP_SCHEMA_ID, &cred_def_id.0, &str_schema_id, None) + .await?; + + // Return the ID and the cred def + Ok((cred_def_id.0.to_owned(), str_cred_def)) } async fn issuer_create_credential_offer(&self, cred_def_id: &str) -> VcxCoreResult { - let _ = cred_def_id; - Err(unimplemented_method_err("credx issuer_create_credential_offer")) + let cred_def = self.get_wallet_record_value(CATEGORY_CRED_DEF, cred_def_id).await?; + + let correctness_proof = self + .get_wallet_record_value(CATEGORY_CRED_KEY_CORRECTNESS_PROOF, cred_def_id) + .await?; + + let schema_id = self + .get_wallet_record_value(CATEGORY_CRED_MAP_SCHEMA_ID, cred_def_id) + .await?; + + // If cred_def contains schema ID, why take it as an argument here...? + let offer = credx::issuer::create_credential_offer(&schema_id, &cred_def, &correctness_proof)?; + + serde_json::to_string(&offer).map_err(From::from) } async fn issuer_create_credential( @@ -228,8 +379,120 @@ impl BaseAnonCreds for IndyCredxAnonCreds { rev_reg_id: Option, tails_dir: Option, ) -> VcxCoreResult<(String, Option, Option)> { - let _ = (cred_offer_json, cred_req_json, cred_values_json, rev_reg_id, tails_dir); - Err(unimplemented_method_err("credx issuer_create_credential")) + let cred_offer: CredentialOffer = serde_json::from_str(cred_offer_json)?; + let cred_request = serde_json::from_str(cred_req_json)?; + let cred_values = serde_json::from_str(cred_values_json)?; + + let cred_def_id = &cred_offer.cred_def_id.0; + + let cred_def = self.get_wallet_record_value(CATEGORY_CRED_DEF, cred_def_id).await?; + + let cred_def_private = self + .get_wallet_record_value(CATEGORY_CRED_DEF_PRIV, cred_def_id) + .await?; + + let mut revocation_config_parts = match (tails_dir, &rev_reg_id) { + (Some(tails_dir), Some(rev_reg_id)) => { + let rev_reg_def = self.get_wallet_record_value(CATEGORY_REV_REG_DEF, rev_reg_id).await?; + + let rev_reg_def_priv = self + .get_wallet_record_value(CATEGORY_REV_REG_DEF_PRIV, rev_reg_id) + .await?; + + let rev_reg = self.get_wallet_record_value(CATEGORY_REV_REG, rev_reg_id).await?; + let rev_reg_info: RevocationRegistryInfo = + self.get_wallet_record_value(CATEGORY_REV_REG_INFO, rev_reg_id).await?; + + Some((rev_reg_def, rev_reg_def_priv, rev_reg, rev_reg_info, tails_dir)) + } + (None, None) => None, + (tails_dir, rev_reg_id) => { + warn!("Missing revocation config params: tails_dir: {tails_dir:?} - {rev_reg_id:?}; Issuing non revokable credential"); + None + } + }; + + let revocation_config = match &mut revocation_config_parts { + Some((rev_reg_def, rev_reg_def_priv, rev_reg, rev_reg_info, tails_dir)) => { + rev_reg_info.curr_id += 1; + + let tails_file_hash = match rev_reg_def { + RevocationRegistryDefinition::RevocationRegistryDefinitionV1(rev_reg_def) => { + if rev_reg_info.curr_id > rev_reg_def.value.max_cred_num { + return Err(AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::ActionNotSupported, + "The revocation registry is full", + )); + } + + if rev_reg_def.value.issuance_type == IssuanceType::ISSUANCE_ON_DEMAND { + rev_reg_info.used_ids.insert(rev_reg_info.curr_id); + } + + &rev_reg_def.value.tails_hash + } + }; + + let mut tails_file_path = std::path::PathBuf::new(); + tails_file_path.push(&tails_dir); + tails_file_path.push(tails_file_hash); + + let tails_path = tails_file_path.to_str().ok_or_else(|| { + AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::InvalidOption, + "tails file is not an unicode string", + ) + })?; + let tails_reader = TailsFileReader::new(tails_path); + + let revocation_config = CredentialRevocationConfig { + reg_def: rev_reg_def, + reg_def_private: rev_reg_def_priv, + registry: rev_reg, + registry_idx: rev_reg_info.curr_id, + registry_used: &rev_reg_info.used_ids, + tails_reader, + }; + + Some(revocation_config) + } + None => None, + }; + + let (cred, rev_reg, rev_reg_delta) = credx::issuer::create_credential( + &cred_def, + &cred_def_private, + &cred_offer, + &cred_request, + cred_values, + revocation_config, + )?; + + let str_rev_reg = rev_reg.as_ref().map(serde_json::to_string).transpose()?; + let str_rev_reg_delta = rev_reg_delta.as_ref().map(serde_json::to_string).transpose()?; + + let cred_rev_id = if let (Some(rev_reg_id), Some(str_rev_reg), Some((_, _, _, rev_reg_info, _))) = + (rev_reg_id, &str_rev_reg, revocation_config_parts) + { + let cred_rev_id = rev_reg_info.curr_id.to_string(); + let str_rev_reg_info = serde_json::to_string(&rev_reg_info)?; + + self.wallet + .update_wallet_record_value(CATEGORY_REV_REG, &rev_reg_id, str_rev_reg) + .await?; + + self.wallet + .update_wallet_record_value(CATEGORY_REV_REG_INFO, &rev_reg_id, &str_rev_reg_info) + .await?; + + Some(cred_rev_id) + } else { + None + }; + + let str_cred = serde_json::to_string(&cred)?; + + Ok((str_cred, cred_rev_id, str_rev_reg_delta)) } /// * `requested_credentials_json`: either a credential or self-attested attribute for each requested attribute @@ -519,8 +782,19 @@ impl BaseAnonCreds for IndyCredxAnonCreds { let tails_file_hash = match revoc_reg_def.borrow() { RevocationRegistryDefinition::RevocationRegistryDefinitionV1(r) => &r.value.tails_hash, }; - let tails_file_path = format!("{}/{}", tails_dir, tails_file_hash); - let tails_reader: credx::tails::TailsReader = credx::tails::TailsFileReader::new(&tails_file_path); + + let mut tails_file_path = std::path::PathBuf::new(); + tails_file_path.push(&tails_dir); + tails_file_path.push(tails_file_hash); + + let tails_path = tails_file_path.to_str().ok_or_else(|| { + AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::InvalidOption, + "tails file is not an unicode string", + ) + })?; + + let tails_reader = TailsFileReader::new(tails_path); let rev_reg_delta: RevocationRegistryDelta = serde_json::from_str(rev_reg_delta_json)?; let rev_reg_idx: u32 = cred_rev_id .parse() @@ -679,21 +953,98 @@ impl BaseAnonCreds for IndyCredxAnonCreds { let schema_json = serde_json::to_string(&schema)?; let schema_id = &schema.id().0; - // TODO - future - store as cache against issuer_did Ok((schema_id.to_string(), schema_json)) } async fn revoke_credential_local(&self, tails_dir: &str, rev_reg_id: &str, cred_rev_id: &str) -> VcxCoreResult<()> { - let _ = (tails_dir, rev_reg_id, cred_rev_id); - Err(unimplemented_method_err("credx revoke_credential_local")) + let cred_rev_id = cred_rev_id.parse().map_err(|e| { + AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::InvalidInput, + format!("Invalid cred_rev_id {cred_rev_id} - {e}"), + ) + })?; + + let rev_reg = self.get_wallet_record_value(CATEGORY_REV_REG, rev_reg_id).await?; + + let rev_reg_def = self.get_wallet_record_value(CATEGORY_REV_REG_DEF, rev_reg_id).await?; + + let tails_file_hash = match &rev_reg_def { + RevocationRegistryDefinition::RevocationRegistryDefinitionV1(r) => &r.value.tails_hash, + }; + + let tails_file_path = format!("{tails_dir}/{tails_file_hash}"); + let tails_reader = TailsFileReader::new(&tails_file_path); + + let (rev_reg, new_rev_reg_delta) = + credx::issuer::revoke_credential(&rev_reg_def, &rev_reg, cred_rev_id, &tails_reader)?; + + let old_str_rev_reg_delta = self.get_rev_reg_delta(rev_reg_id).await?; + + let rev_reg_delta = old_str_rev_reg_delta + .as_ref() + .map(|s| serde_json::from_str(s)) + .transpose()?; + + let rev_reg_delta = rev_reg_delta + .map(|rev_reg_delta| credx::issuer::merge_revocation_registry_deltas(&rev_reg_delta, &new_rev_reg_delta)) + .transpose()? + .unwrap_or(new_rev_reg_delta); + + let str_rev_reg = serde_json::to_string(&rev_reg)?; + let str_rev_reg_delta = serde_json::to_string(&rev_reg_delta)?; + + self.wallet + .update_wallet_record_value(CATEGORY_REV_REG, rev_reg_id, &str_rev_reg) + .await?; + + match old_str_rev_reg_delta { + Some(_) => { + self.wallet + .update_wallet_record_value(CATEGORY_REV_REG_DELTA, rev_reg_id, &str_rev_reg_delta) + .await? + } + None => { + self.wallet + .add_wallet_record(CATEGORY_REV_REG_DELTA, rev_reg_id, &str_rev_reg_delta, None) + .await? + } + } + + Ok(()) } async fn get_rev_reg_delta(&self, rev_reg_id: &str) -> VcxCoreResult> { - Err(unimplemented_method_err("credx get_rev_reg_delta")) + let res_rev_reg_delta = self + .get_wallet_record_value::(CATEGORY_REV_REG_DELTA, rev_reg_id) + .await; + + if let Err(err) = &res_rev_reg_delta { + warn!( + "get_rev_reg_delta >> Unable to get rev_reg_delta cache for rev_reg_id: {}, error: {}", + rev_reg_id, err + ); + } + + let res_rev_reg_delta = res_rev_reg_delta.ok().as_ref().map(serde_json::to_string).transpose(); + + if let Err(err) = &res_rev_reg_delta { + warn!( + "get_rev_reg_delta >> Unable to deserialize rev_reg_delta cache for rev_reg_id: {}, error: {}", + rev_reg_id, err + ); + } + + Ok(res_rev_reg_delta.ok().flatten()) } async fn clear_rev_reg_delta(&self, rev_reg_id: &str) -> VcxCoreResult<()> { - Err(unimplemented_method_err("credx clear_rev_reg_delta")) + if self.get_rev_reg_delta(rev_reg_id).await?.is_some() { + self.wallet + .delete_wallet_record(CATEGORY_REV_REG_DELTA, rev_reg_id) + .await?; + } + + Ok(()) } async fn generate_nonce(&self) -> VcxCoreResult { @@ -783,13 +1134,6 @@ fn _format_attribute_as_marker_tag_name(attribute_name: &str) -> String { format!("attr::{attribute_name}::marker") } -fn unimplemented_method_err(method_name: &str) -> AriesVcxCoreError { - AriesVcxCoreError::from_msg( - AriesVcxCoreErrorKind::UnimplementedFeature, - format!("method '{}' is not yet implemented in AriesVCX", method_name), - ) -} - // common transformation requirement in credx fn hashmap_as_ref<'a, T, U>(map: &'a HashMap) -> HashMap where @@ -804,35 +1148,3 @@ where new_map } - -#[cfg(test)] -#[cfg(feature = "general_test")] -mod unit_tests { - use crate::errors::error::{AriesVcxCoreErrorKind, VcxCoreResult}; - use crate::{common::test_utils::mock_profile, plugins::anoncreds::base_anoncreds::BaseAnonCreds}; - - use super::IndyCredxAnonCreds; - - #[tokio::test] - async fn test_unimplemented_methods() { - // test used to assert which methods are unimplemented currently, can be removed after all methods implemented - - fn assert_unimplemented(result: VcxCoreResult) { - assert_eq!(result.unwrap_err().kind(), AriesVcxCoreErrorKind::UnimplementedFeature) - } - - let profile = mock_profile(); - let anoncreds: Box = Box::new(IndyCredxAnonCreds::new(profile.inject_wallet())); - - assert_unimplemented(anoncreds.issuer_create_and_store_revoc_reg("", "", "", 0, "").await); - assert_unimplemented( - anoncreds - .issuer_create_and_store_credential_def("", "", "", None, "") - .await, - ); - assert_unimplemented(anoncreds.issuer_create_credential_offer("").await); - assert_unimplemented(anoncreds.issuer_create_credential("", "", "", None, None).await); - assert_unimplemented(anoncreds.revoke_credential_local("", "", "").await); - assert_unimplemented(anoncreds.publish_local_revocations("", "").await); - } -} diff --git a/aries_vcx_core/src/errors/mapping_vdrtools.rs b/aries_vcx_core/src/errors/mapping_vdrtools.rs index 0a0e6ba399..66fc281de0 100644 --- a/aries_vcx_core/src/errors/mapping_vdrtools.rs +++ b/aries_vcx_core/src/errors/mapping_vdrtools.rs @@ -21,7 +21,7 @@ impl From for AriesVcxCoreErrorKind { match indy { InvalidParam(_) => AriesVcxCoreErrorKind::InvalidLibindyParam, - InvalidStructure => AriesVcxCoreErrorKind::LibindyInvalidStructure, + InvalidStructure => AriesVcxCoreErrorKind::InvalidInput, IOError => AriesVcxCoreErrorKind::IOError, InvalidWalletHandle => AriesVcxCoreErrorKind::InvalidWalletHandle, WalletAlreadyExists => AriesVcxCoreErrorKind::DuplicationWallet, diff --git a/aries_vcx_core/src/wallet/agency_client_wallet.rs b/aries_vcx_core/src/wallet/agency_client_wallet.rs index 4736e4f598..ac1a3fa34d 100644 --- a/aries_vcx_core/src/wallet/agency_client_wallet.rs +++ b/aries_vcx_core/src/wallet/agency_client_wallet.rs @@ -52,6 +52,10 @@ impl BaseWallet for AgencyClientWallet { Err(unimplemented_agency_client_wallet_method("get_wallet_record")) } + async fn get_wallet_record_value(&self, xtype: &str, id: &str) -> VcxCoreResult { + Err(unimplemented_agency_client_wallet_method("get_wallet_record_value")) + } + async fn delete_wallet_record(&self, xtype: &str, id: &str) -> VcxCoreResult<()> { Err(unimplemented_agency_client_wallet_method("delete_wallet_record")) } diff --git a/aries_vcx_core/src/wallet/base_wallet.rs b/aries_vcx_core/src/wallet/base_wallet.rs index f83ce1c2b5..ac3256728e 100644 --- a/aries_vcx_core/src/wallet/base_wallet.rs +++ b/aries_vcx_core/src/wallet/base_wallet.rs @@ -31,6 +31,8 @@ pub trait BaseWallet: std::fmt::Debug + Send + Sync { async fn get_wallet_record(&self, xtype: &str, id: &str, options_json: &str) -> VcxCoreResult; + async fn get_wallet_record_value(&self, xtype: &str, id: &str) -> VcxCoreResult; + async fn delete_wallet_record(&self, xtype: &str, id: &str) -> VcxCoreResult<()>; async fn update_wallet_record_value(&self, xtype: &str, id: &str, value: &str) -> VcxCoreResult<()>; diff --git a/aries_vcx_core/src/wallet/indy_wallet.rs b/aries_vcx_core/src/wallet/indy_wallet.rs index 01cdd69ffb..fb101c6477 100644 --- a/aries_vcx_core/src/wallet/indy_wallet.rs +++ b/aries_vcx_core/src/wallet/indy_wallet.rs @@ -4,7 +4,8 @@ use async_trait::async_trait; use futures::executor::block_on; use serde_json::Value; -use crate::errors::error::{AriesVcxCoreError, VcxCoreResult}; +use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}; +use crate::indy::wallet::WalletRecord; use crate::{ indy, utils::{async_fn_iterator::AsyncFnIterator, json::TryGetIndex}, @@ -61,6 +62,23 @@ impl BaseWallet for IndySdkWallet { indy::wallet::get_wallet_record(self.wallet_handle, xtype, id, options_json).await } + async fn get_wallet_record_value(&self, xtype: &str, id: &str) -> VcxCoreResult { + let options = r#"{ + "retrieve_type": false, + "retrieve_value": true, + "retrieve_tags": false + }"#; + + let str_record = self.get_wallet_record(xtype, id, options).await?; + let wallet_record: WalletRecord = serde_json::from_str(&str_record)?; + wallet_record.value.ok_or_else(|| { + AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::WalletRecordNotFound, + "The wallet record does not have a value", + ) + }) + } + async fn delete_wallet_record(&self, xtype: &str, id: &str) -> VcxCoreResult<()> { indy::wallet::delete_wallet_record(self.wallet_handle, xtype, id).await }