diff --git a/.github/workflows/mediator.pr.yml b/.github/workflows/mediator.pr.yml index e383c94023..f453be71df 100644 --- a/.github/workflows/mediator.pr.yml +++ b/.github/workflows/mediator.pr.yml @@ -26,7 +26,7 @@ jobs: test-integration-mediator: runs-on: ubuntu-22.04 - services: + services: mysql: image: mysql:latest env: @@ -53,4 +53,9 @@ jobs: - name: Setup database run: DATABASE_URL=${MYSQL_URL} sqlx migrate run --source aries/agents/rust/mediator/mediation/migrations - name: "Run mediator integration tests" - run: cargo run --bin mediator & sleep 5 && cargo test --verbose --package mediator -- --nocapture; \ No newline at end of file + run: cargo run --bin mediator & sleep 5 && cargo test --verbose --package mediator -- --nocapture; + - name: "Collect docker logs on failure" + if: failure() + uses: ./.github/actions/upload-docker-logs + with: + name: "docker-services-${{ github.job }}" diff --git a/Cargo.lock b/Cargo.lock index c91235f658..588235cb64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1554,6 +1554,7 @@ dependencies = [ name = "diddoc_legacy" version = "0.61.0" dependencies = [ + "display_as_json", "serde", "serde_derive", "serde_json", diff --git a/aries/agents/rust/aries-vcx-agent/Cargo.toml b/aries/agents/rust/aries-vcx-agent/Cargo.toml index a42beb31ff..8881564d4a 100644 --- a/aries/agents/rust/aries-vcx-agent/Cargo.toml +++ b/aries/agents/rust/aries-vcx-agent/Cargo.toml @@ -13,11 +13,11 @@ aries_vcx_core = { path = "../../../../aries_vcx_core", features = [ "vdrtools_wallet", ] } shared = { path = "../../../shared" } -did_resolver_registry = { path = "../../../did_resolver_registry" } -did_resolver_sov = { path = "../../../did_resolver_sov" } -did_peer = { path = "../../../did_peer" } -did_key = { path = "../../../did_key" } -public_key = { path = "../../../public_key" } +did_resolver_registry = { path = "../../../../did_resolver_registry" } +did_resolver_sov = { path = "../../../../did_resolver_sov" } +did_peer = { path = "../../../../did_peer" } +did_key = { path = "../../../../did_key" } +public_key = { path = "../../../../public_key" } async-trait = "0.1.64" derive_builder = "0.12.0" serde_json = "1.0.85" diff --git a/aries/agents/rust/aries-vcx-agent/src/agent/agent_struct.rs b/aries/agents/rust/aries-vcx-agent/src/agent/agent_struct.rs index 3cac501fbc..98f4f345e0 100644 --- a/aries/agents/rust/aries-vcx-agent/src/agent/agent_struct.rs +++ b/aries/agents/rust/aries-vcx-agent/src/agent/agent_struct.rs @@ -6,13 +6,12 @@ use aries_vcx_core::{ wallet::indy::IndySdkWallet, }; -use crate::services::did_exchange::ServiceDidExchange; -use crate::services::out_of_band::ServiceOutOfBand; use crate::{ agent::agent_config::AgentConfig, services::{ connection::ServiceConnections, credential_definition::ServiceCredentialDefinitions, - holder::ServiceCredentialsHolder, issuer::ServiceCredentialsIssuer, prover::ServiceProver, + did_exchange::ServiceDidExchange, holder::ServiceCredentialsHolder, + issuer::ServiceCredentialsIssuer, out_of_band::ServiceOutOfBand, prover::ServiceProver, revocation_registry::ServiceRevocationRegistries, schema::ServiceSchemas, verifier::ServiceVerifier, }, @@ -103,6 +102,6 @@ impl Agent { } pub fn public_did(&self) -> &str { - self.did_exchange.public_did().as_ref() + self.did_exchange.public_did() } } diff --git a/aries/agents/rust/aries-vcx-agent/src/agent/init.rs b/aries/agents/rust/aries-vcx-agent/src/agent/init.rs index 1269315211..78f036f87d 100644 --- a/aries/agents/rust/aries-vcx-agent/src/agent/init.rs +++ b/aries/agents/rust/aries-vcx-agent/src/agent/init.rs @@ -1,28 +1,38 @@ use std::sync::Arc; -use aries_vcx::global::settings::DEFAULT_LINK_SECRET_ALIAS; +use aries_vcx::{ + common::ledger::{ + service_didsov::{DidSovServiceType, EndpointDidSov}, + transactions::{add_new_did, write_endpoint}, + }, + global::settings::DEFAULT_LINK_SECRET_ALIAS, +}; use aries_vcx_core::{ self, anoncreds::{base_anoncreds::BaseAnonCreds, credx_anoncreds::IndyCredxAnonCreds}, + ledger::indy_vdr_ledger::DefaultIndyLedgerRead, wallet::indy::{ wallet::{create_and_open_wallet, wallet_configure_issuer}, IndySdkWallet, WalletConfig, }, }; +use did_peer::resolver::PeerDidResolver; +use did_resolver_registry::ResolverRegistry; +use did_resolver_sov::resolution::DidSovResolver; use crate::{ agent::{agent_config::AgentConfig, agent_struct::Agent}, error::AgentResult, services::{ - out_of_band::ServiceOutOfBand, connection::{ServiceConnections, ServiceEndpoint}, - did_exchange::ServiceDidExchange, - schema::ServiceSchemas, credential_definition::ServiceCredentialDefinitions, - revocation_registry::ServiceRevocationRegistries, + did_exchange::ServiceDidExchange, holder::ServiceCredentialsHolder, issuer::ServiceCredentialsIssuer, + out_of_band::ServiceOutOfBand, prover::ServiceProver, + revocation_registry::ServiceRevocationRegistries, + schema::ServiceSchemas, verifier::ServiceVerifier, }, }; @@ -75,7 +85,7 @@ impl Agent { }; let anoncreds = IndyCredxAnonCreds; - let (ledger_read, ledger_write) = build_ledger_components(vcx_pool_config).unwrap(); + let (ledger_read, ledger_write) = build_ledger_components(vcx_pool_config.clone()).unwrap(); let ledger_read = Arc::new(ledger_read); let ledger_write = Arc::new(ledger_write); @@ -88,24 +98,30 @@ impl Agent { // TODO: This setup should be easier // The default issuer did can't be used - its verkey is not in base58 - TODO: double-check let (public_did, _verkey) = add_new_did( - &wallet, - &profile.inject_indy_ledger_write(), + wallet.as_ref(), + ledger_write.as_ref(), &config_issuer.institution_did, None, ) - .await?; + .await?; let endpoint = EndpointDidSov::create() .set_service_endpoint(init_config.service_endpoint.clone()) .set_types(Some(vec![DidSovServiceType::DidCommunication])); - write_endpoint(&profile.inject_indy_ledger_write(), &public_did, &endpoint).await?; + write_endpoint( + wallet.as_ref(), + ledger_write.as_ref(), + &public_did, + &endpoint, + ) + .await?; let did_peer_resolver = PeerDidResolver::new(); - let did_sov_resolver = - DidSovResolver::new(Arc::::new(profile.inject_indy_ledger_read().into())); + let did_sov_resolver: DidSovResolver, DefaultIndyLedgerRead> = + DidSovResolver::new(ledger_read.clone()); let did_resolver_registry = Arc::new( ResolverRegistry::new() - .register_resolver::("peer".into(), did_peer_resolver.into()) - .register_resolver::("sov".into(), did_sov_resolver.into()), + .register_resolver("peer".into(), did_peer_resolver) + .register_resolver("sov".into(), did_sov_resolver), ); let connections = Arc::new(ServiceConnections::new( @@ -114,13 +130,14 @@ impl Agent { init_config.service_endpoint.clone(), )); let did_exchange = Arc::new(ServiceDidExchange::new( - Arc::clone(&profile), - did_resolver_registry.clone(), + ledger_read.clone(), + wallet.clone(), + did_resolver_registry, init_config.service_endpoint.clone(), public_did, )); let out_of_band = Arc::new(ServiceOutOfBand::new( - Arc::clone(&profile), + wallet.clone(), init_config.service_endpoint, )); let schemas = Arc::new(ServiceSchemas::new( diff --git a/aries/agents/rust/aries-vcx-agent/src/error/error_struct.rs b/aries/agents/rust/aries-vcx-agent/src/error/error_struct.rs index 9c9a5c6300..a2adc732f7 100644 --- a/aries/agents/rust/aries-vcx-agent/src/error/error_struct.rs +++ b/aries/agents/rust/aries-vcx-agent/src/error/error_struct.rs @@ -8,7 +8,7 @@ pub struct AgentError { impl std::fmt::Display for AgentError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> { - f.write_str(&format!("{}: {}", self.kind.to_string(), self.message.to_string())) + f.write_str(&format!("{}: {}", self.kind, self.message)) } } diff --git a/aries/agents/rust/aries-vcx-agent/src/helper.rs b/aries/agents/rust/aries-vcx-agent/src/helper.rs new file mode 100644 index 0000000000..c0c36bb368 --- /dev/null +++ b/aries/agents/rust/aries-vcx-agent/src/helper.rs @@ -0,0 +1,57 @@ +use aries_vcx::{ + did_doc_sov::{service::ServiceSov, DidDocumentSov}, + messages::AriesMessage, + utils::{encryption_envelope::EncryptionEnvelope, from_did_doc_sov_to_legacy}, +}; +use aries_vcx_core::wallet::base_wallet::BaseWallet; +use serde_json::json; +use url::Url; + +use crate::{AgentError, AgentErrorKind, AgentResult}; + +pub fn get_their_endpoint(did_document: &DidDocumentSov) -> AgentResult { + let service = did_document.service().first().ok_or(AgentError::from_msg( + AgentErrorKind::InvalidState, + "No service found", + ))?; + // todo: will get cleaned up after service is de-generified + let url: String = match service { + ServiceSov::Legacy(d) => d.service_endpoint().to_string(), + ServiceSov::AIP1(d) => d.service_endpoint().to_string(), + ServiceSov::DIDCommV1(d) => d.service_endpoint().to_string(), + ServiceSov::DIDCommV2(d) => d.service_endpoint().to_string(), + }; + Url::parse(&url).map_err(|err| { + AgentError::from_msg( + AgentErrorKind::InvalidState, + &format!("Failed to parse url found in did document due: {:?}", err), + ) + }) +} + +pub async fn pairwise_encrypt( + our_did_doc: &DidDocumentSov, + their_did_doc: &DidDocumentSov, + wallet: &impl BaseWallet, + message: &AriesMessage, +) -> AgentResult { + let sender_verkey = our_did_doc + .resolved_key_agreement() + .next() + .ok_or_else(|| { + AgentError::from_msg( + AgentErrorKind::InvalidState, + "No key agreement method found in our did document", + ) + })? + .public_key()? + .base58(); + EncryptionEnvelope::create( + wallet, + json!(message).to_string().as_bytes(), + Some(&sender_verkey), + &from_did_doc_sov_to_legacy(their_did_doc.clone())?, + ) + .await + .map_err(|err| err.into()) +} diff --git a/aries/agents/rust/aries-vcx-agent/src/lib.rs b/aries/agents/rust/aries-vcx-agent/src/lib.rs index a9cb543d33..558dc5c769 100644 --- a/aries/agents/rust/aries-vcx-agent/src/lib.rs +++ b/aries/agents/rust/aries-vcx-agent/src/lib.rs @@ -9,6 +9,7 @@ extern crate uuid; mod agent; mod error; +pub mod helper; mod http; mod services; mod storage; diff --git a/aries/agents/rust/aries-vcx-agent/src/services/did_exchange.rs b/aries/agents/rust/aries-vcx-agent/src/services/did_exchange.rs index 99fba3eda2..40dd0db3e7 100644 --- a/aries/agents/rust/aries-vcx-agent/src/services/did_exchange.rs +++ b/aries/agents/rust/aries-vcx-agent/src/services/did_exchange.rs @@ -1,36 +1,32 @@ use std::sync::Arc; use aries_vcx::{ - core::profile::profile::Profile, messages::msg_fields::protocols::{ - did_exchange::{complete::Complete, problem_report::ProblemReport, request::Request, response::Response}, - out_of_band::invitation::Invitation as OobInvitation, - }, - protocols::{ - connection::wrap_and_send_msg, did_exchange::{ - resolve_key_from_invitation, - state_machine::{ - generic::{GenericDidExchange, ThinState}, - requester::{ConstructRequestConfig, PairwiseConstructRequestConfig, PublicConstructRequestConfig}, - responder::ReceiveRequestConfig, - }, + complete::Complete, problem_report::ProblemReport, request::Request, response::Response, }, + out_of_band::invitation::Invitation as OobInvitation, + }, + protocols::did_exchange::{ + resolve_key_from_invitation, + state_machine::generic::{GenericDidExchange, ThinState}, }, - utils::from_did_doc_sov_to_legacy, + transport::Transport, }; +use aries_vcx_core::{ledger::indy_vdr_ledger::DefaultIndyLedgerRead, wallet::indy::IndySdkWallet}; use did_resolver_registry::ResolverRegistry; +use super::connection::ServiceEndpoint; use crate::{ - http_client::HttpClient, + helper::{get_their_endpoint, pairwise_encrypt}, + http::VcxHttpClient, storage::{object_cache::ObjectCache, Storage}, AgentError, AgentErrorKind, AgentResult, }; -use super::connection::ServiceEndpoint; - pub struct ServiceDidExchange { - profile: Arc, + ledger_read: Arc, + wallet: Arc, resolver_registry: Arc, service_endpoint: ServiceEndpoint, did_exchange: Arc>, @@ -39,13 +35,15 @@ pub struct ServiceDidExchange { impl ServiceDidExchange { pub fn new( - profile: Arc, + ledger_read: Arc, + wallet: Arc, resolver_registry: Arc, service_endpoint: ServiceEndpoint, public_did: String, ) -> Self { Self { - profile, + ledger_read, + wallet, service_endpoint, resolver_registry, did_exchange: Arc::new(ObjectCache::new("did-exchange")), @@ -54,67 +52,38 @@ impl ServiceDidExchange { } pub async fn send_request_public(&self, their_did: String) -> AgentResult { - let config = ConstructRequestConfig::Public(PublicConstructRequestConfig { - wallet: self.profile.inject_wallet(), - ledger: self.profile.inject_indy_ledger_read(), - their_did: format!("did:sov:{}", their_did).parse()?, - our_did: format!("did:sov:{}", self.public_did).parse()?, - }); - let (requester, request) = GenericDidExchange::construct_request(config).await?; - wrap_and_send_msg( - &self.profile.inject_wallet(), - &request.clone().into(), - &requester - .our_did_document() - .resolved_key_agreement() - .next() - .ok_or_else(|| AgentError::from_msg(AgentErrorKind::InvalidState, "No key agreement method found"))? - .public_key()? - .base58(), - &from_did_doc_sov_to_legacy(requester.their_did_doc().clone())?, - &HttpClient, - ) - .await?; - let request_id = request - .decorators - .thread - .ok_or_else(|| AgentError::from_msg(AgentErrorKind::InvalidState, "Request did not contain a thread id"))? - .thid; - self.did_exchange.insert(&request_id, requester.clone().into()) - } - - pub async fn send_request_pairwise(&self, invitation: OobInvitation) -> AgentResult { - let config = ConstructRequestConfig::Pairwise(PairwiseConstructRequestConfig { - wallet: self.profile.inject_wallet(), - invitation: invitation.clone(), - resolver_registry: self.resolver_registry.clone(), - service_endpoint: self.service_endpoint.clone(), - routing_keys: vec![], - }); - let (requester, request) = GenericDidExchange::construct_request(config).await?; - wrap_and_send_msg( - &self.profile.inject_wallet(), - &request.clone().into(), - &requester - .our_did_document() - .resolved_key_agreement() - .next() - .ok_or_else(|| AgentError::from_msg(AgentErrorKind::InvalidState, "No key agreement method found"))? - .public_key()? - .base58(), - &from_did_doc_sov_to_legacy(requester.their_did_doc().clone())?, - &HttpClient, + let (requester, request) = GenericDidExchange::construct_request_public( + self.ledger_read.as_ref(), + format!("did:sov:{}", their_did).parse()?, + format!("did:sov:{}", self.public_did).parse()?, ) .await?; let request_id = request + .clone() .decorators .thread - .ok_or_else(|| AgentError::from_msg(AgentErrorKind::InvalidState, "Request did not contain a thread id"))? + .ok_or_else(|| { + AgentError::from_msg( + AgentErrorKind::InvalidState, + "Request did not contain a thread id", + ) + })? .thid; - self.did_exchange.insert(&request_id, requester.clone().into()) + let ddo_their = requester.their_did_doc(); + let ddo_our = requester.our_did_document(); + let encryption_envelope = + pairwise_encrypt(ddo_our, ddo_their, self.wallet.as_ref(), &request.into()).await?; + VcxHttpClient + .send_message(encryption_envelope.0, get_their_endpoint(ddo_their)?) + .await?; + self.did_exchange.insert(&request_id, requester.clone()) } - pub async fn send_response(&self, request: Request, invitation: OobInvitation) -> AgentResult { + pub async fn send_response( + &self, + request: Request, + invitation: OobInvitation, + ) -> AgentResult { // TODO: We should fetch the out of band invite associated with the request. // We don't want to be sending response if we don't know if there is any invitation // associated with the request. @@ -122,63 +91,62 @@ impl ServiceDidExchange { .clone() .decorators .thread - .ok_or_else(|| AgentError::from_msg(AgentErrorKind::InvalidState, "Request did not contain a thread id"))? + .ok_or_else(|| { + AgentError::from_msg( + AgentErrorKind::InvalidState, + "Request did not contain a thread id", + ) + })? .thid; - let invitation_key = resolve_key_from_invitation(&invitation, &self.resolver_registry).await?; - let (responder, response) = GenericDidExchange::handle_request(ReceiveRequestConfig { - wallet: self.profile.inject_wallet(), - resolver_registry: self.resolver_registry.clone(), + let invitation_key = + resolve_key_from_invitation(&invitation, &self.resolver_registry).await?; + let (responder, response) = GenericDidExchange::handle_request( + self.wallet.as_ref(), + self.resolver_registry.clone(), request, - service_endpoint: self.service_endpoint.clone(), - routing_keys: vec![], - invitation_id: invitation.id.clone(), + self.service_endpoint.clone(), + vec![], + invitation.id.clone(), invitation_key, - }) - .await?; - wrap_and_send_msg( - &self.profile.inject_wallet(), - &response.clone().into(), - &responder - .our_did_document() - .resolved_key_agreement() - .next() - .ok_or_else(|| AgentError::from_msg(AgentErrorKind::InvalidState, "No key agreement method found"))? - .public_key()? - .base58(), - &from_did_doc_sov_to_legacy(responder.their_did_doc().clone())?, - &HttpClient, ) .await?; - self.did_exchange.insert(&request_id, responder.clone().into()) + let ddo_their = responder.their_did_doc(); + let ddo_our = responder.our_did_document(); + let encryption_envelope = + pairwise_encrypt(ddo_our, ddo_their, self.wallet.as_ref(), &response.into()).await?; + VcxHttpClient + .send_message(encryption_envelope.0, get_their_endpoint(ddo_their)?) + .await?; + self.did_exchange.insert(&request_id, responder.clone()) } pub async fn send_complete(&self, response: Response) -> AgentResult { let thread_id = response.decorators.thread.thid.clone(); - let (requester, complete) = self.did_exchange.get(&thread_id)?.handle_response(response).await?; - wrap_and_send_msg( - &self.profile.inject_wallet(), - &complete.clone().into(), - &requester - .our_did_document() - .resolved_key_agreement() - .next() - .ok_or_else(|| AgentError::from_msg(AgentErrorKind::InvalidState, "No key agreement method found"))? - .public_key()? - .base58(), - &from_did_doc_sov_to_legacy(requester.their_did_doc().clone())?, - &HttpClient, - ) - .await?; - self.did_exchange.insert(&thread_id, requester.clone().into()) + let (requester, complete) = self + .did_exchange + .get(&thread_id)? + .handle_response(response) + .await?; + let ddo_their = requester.their_did_doc(); + let ddo_our = requester.our_did_document(); + let encryption_envelope = + pairwise_encrypt(ddo_our, ddo_their, self.wallet.as_ref(), &complete.into()).await?; + VcxHttpClient + .send_message(encryption_envelope.0, get_their_endpoint(ddo_their)?) + .await?; + self.did_exchange.insert(&thread_id, requester.clone()) } pub fn receive_complete(&self, complete: Complete) -> AgentResult { let thread_id = complete.decorators.thread.thid.clone(); - let requester = self.did_exchange.get(&thread_id)?.handle_complete(complete)?; + let requester = self + .did_exchange + .get(&thread_id)? + .handle_complete(complete)?; self.did_exchange.insert(&thread_id, requester) } - pub fn receive_problem_report(&self, thread_id: &str, problem_report: ProblemReport) -> AgentResult { + pub fn receive_problem_report(&self, problem_report: ProblemReport) -> AgentResult { let thread_id = problem_report.decorators.thread.thid.clone(); let requester = self .did_exchange @@ -192,7 +160,11 @@ impl ServiceDidExchange { } pub fn invitation_id(&self, thread_id: &str) -> AgentResult { - Ok(self.did_exchange.get(thread_id)?.invitation_id().to_string()) + Ok(self + .did_exchange + .get(thread_id)? + .invitation_id() + .to_string()) } pub fn public_did(&self) -> &str { diff --git a/aries/agents/rust/aries-vcx-agent/src/services/out_of_band.rs b/aries/agents/rust/aries-vcx-agent/src/services/out_of_band.rs index 64709b10a8..39c1925a2d 100644 --- a/aries/agents/rust/aries-vcx-agent/src/services/out_of_band.rs +++ b/aries/agents/rust/aries-vcx-agent/src/services/out_of_band.rs @@ -1,12 +1,13 @@ use std::sync::Arc; use aries_vcx::{ - core::profile::profile::Profile, did_doc_sov::{ extra_fields::{didcommv1::ExtraFieldsDidCommV1, KeyKind}, service::{didcommv1::ServiceDidCommV1, ServiceSov}, }, - handlers::out_of_band::{receiver::OutOfBandReceiver, sender::OutOfBandSender, GenericOutOfBand}, + handlers::out_of_band::{ + receiver::OutOfBandReceiver, sender::OutOfBandSender, GenericOutOfBand, + }, messages::{ msg_fields::protocols::out_of_band::invitation::{Invitation as OobInvitation, OobService}, msg_types::{ @@ -17,33 +18,33 @@ use aries_vcx::{ }, protocols::did_exchange::state_machine::generate_keypair, }; +use aries_vcx_core::wallet::indy::IndySdkWallet; use public_key::KeyType; use uuid::Uuid; +use super::connection::ServiceEndpoint; use crate::{ storage::{object_cache::ObjectCache, Storage}, AgentResult, }; -use super::connection::ServiceEndpoint; - pub struct ServiceOutOfBand { - profile: Arc, + wallet: Arc, service_endpoint: ServiceEndpoint, out_of_band: Arc>, } impl ServiceOutOfBand { - pub fn new(profile: Arc, service_endpoint: ServiceEndpoint) -> Self { + pub fn new(wallet: Arc, service_endpoint: ServiceEndpoint) -> Self { Self { - profile, + wallet, service_endpoint, out_of_band: Arc::new(ObjectCache::new("out-of-band")), } } pub async fn create_invitation(&self) -> AgentResult { - let public_key = generate_keypair(&self.profile.inject_wallet(), KeyType::Ed25519).await?; + let public_key = generate_keypair(self.wallet.as_ref(), KeyType::Ed25519).await?; let service = { let service_id = Uuid::new_v4().to_string(); ServiceSov::DIDCommV1(ServiceDidCommV1::new( @@ -60,8 +61,10 @@ impl ServiceOutOfBand { DidExchangeTypeV1::new_v1_0(), )))?; - self.out_of_band - .insert(&sender.get_id(), GenericOutOfBand::Sender(sender.to_owned()))?; + self.out_of_band.insert( + &sender.get_id(), + GenericOutOfBand::Sender(sender.to_owned()), + )?; Ok(sender.to_aries_message()) } diff --git a/aries/agents/rust/mediator/src/aries_agent/client/mod.rs b/aries/agents/rust/mediator/src/aries_agent/client/mod.rs index 03cd832ebf..87117d52e5 100644 --- a/aries/agents/rust/mediator/src/aries_agent/client/mod.rs +++ b/aries/agents/rust/mediator/src/aries_agent/client/mod.rs @@ -9,6 +9,7 @@ use aries_vcx::{ InviteeConnection, }, mediated_connection::pairwise_info::PairwiseInfo, + oob::oob_invitation_to_legacy_did_doc, }, utils::encryption_envelope::EncryptionEnvelope, }; @@ -26,7 +27,7 @@ pub mod transports; use self::transports::AriesTransport; use super::Agent; -use crate::{aries_agent::utils::oob2did, utils::prelude::*}; +use crate::utils::prelude::*; // client role utilities impl Agent { @@ -114,8 +115,10 @@ impl Agent { "Sending Connection Request Envelope: {},", serde_json::to_string_pretty(&packed_aries_msg_json).unwrap() ); + let mock_ledger = MockLedger {}; // not good. to be dealt later + let legacy_did_doc = oob_invitation_to_legacy_did_doc(&mock_ledger, &oob_invite).await?; let response_envelope = aries_transport - .send_aries_envelope(packed_aries_msg_json, &oob2did(oob_invite)) + .send_aries_envelope(packed_aries_msg_json, &legacy_did_doc) .await?; info!( "Received Response envelope {:#?}, unpacking", diff --git a/aries/agents/rust/mediator/src/aries_agent/mod.rs b/aries/agents/rust/mediator/src/aries_agent/mod.rs index 7132f6ad8c..43c3697745 100644 --- a/aries/agents/rust/mediator/src/aries_agent/mod.rs +++ b/aries/agents/rust/mediator/src/aries_agent/mod.rs @@ -226,12 +226,15 @@ impl Agent { #[cfg(test)] mod test { - use aries_vcx::utils::encryption_envelope::EncryptionEnvelope; + use aries_vcx::{ + protocols::oob::oob_invitation_to_legacy_did_doc, + utils::encryption_envelope::EncryptionEnvelope, + }; use log::info; use serde_json::Value; + use test_utils::mockdata::mock_ledger::MockLedger; use super::AgentBuilder; - use crate::aries_agent::utils::oob2did; #[tokio::test] pub async fn test_pack_unpack() { @@ -245,7 +248,11 @@ mod test { ) .await .unwrap(); - let their_diddoc = oob2did(agent.get_oob_invite().unwrap()); + let mock_ledger = MockLedger {}; // not good. to be dealt later + let their_diddoc = + oob_invitation_to_legacy_did_doc(&mock_ledger, &agent.get_oob_invite().unwrap()) + .await + .unwrap(); let our_service = agent.service.as_ref().unwrap(); let our_vk = our_service.recipient_keys.first().unwrap(); let EncryptionEnvelope(packed) = agent diff --git a/aries/agents/rust/mediator/src/aries_agent/utils.rs b/aries/agents/rust/mediator/src/aries_agent/utils.rs index c3759ed407..fbefebdd12 100644 --- a/aries/agents/rust/mediator/src/aries_agent/utils.rs +++ b/aries/agents/rust/mediator/src/aries_agent/utils.rs @@ -6,12 +6,9 @@ use axum::async_trait; use diddoc_legacy::aries::diddoc::AriesDidDoc; use messages::{ decorators::thread::Thread, - msg_fields::protocols::{ - connection::{ - response::{Response, ResponseContent, ResponseDecorators}, - ConnectionData, - }, - out_of_band::invitation::{Invitation as OOBInvitation, OobService}, + msg_fields::protocols::connection::{ + response::{Response, ResponseContent, ResponseDecorators}, + ConnectionData, }, }; use uuid::Uuid; @@ -54,27 +51,6 @@ pub async fn build_response_content( .build()) } -pub fn oob2did(oob: OOBInvitation) -> AriesDidDoc { - let mut did_doc: AriesDidDoc = AriesDidDoc::default(); - did_doc.set_id(oob.id.clone()); - let oob_service = oob - .content - .services - .first() - .expect("OOB needs a service") - .clone(); - - match oob_service { - OobService::AriesService(service) => { - did_doc.set_service_endpoint(service.service_endpoint); - did_doc.set_recipient_keys(service.recipient_keys); - did_doc.set_routing_keys(service.routing_keys); - } - _ => panic!("Assuming fully clean AriesService variant only"), - } - did_doc -} - pub struct MockTransport; #[async_trait] diff --git a/aries/agents/rust/mediator/tests/common/agent_and_transport_utils.rs b/aries/agents/rust/mediator/tests/common/agent_and_transport_utils.rs index db163117de..3d46063337 100644 --- a/aries/agents/rust/mediator/tests/common/agent_and_transport_utils.rs +++ b/aries/agents/rust/mediator/tests/common/agent_and_transport_utils.rs @@ -1,7 +1,10 @@ use std::collections::VecDeque; use aries_vcx::{ - protocols::connection::invitee::{states::completed::Completed, InviteeConnection}, + protocols::{ + connection::invitee::{states::completed::Completed, InviteeConnection}, + oob::oob_invitation_to_legacy_did_doc, + }, utils::encryption_envelope::EncryptionEnvelope, }; use aries_vcx_core::wallet::base_wallet::BaseWallet; @@ -10,7 +13,6 @@ use mediation::storage::MediatorPersistence; use mediator::{ aries_agent::{ client::transports::{AriesReqwest, AriesTransport}, - utils::oob2did, Agent, }, utils::{structs::VerKey, GenericStringError}, @@ -27,6 +29,7 @@ use messages::{ AriesMessage, }; use reqwest::header::ACCEPT; +use test_utils::mockdata::mock_ledger::MockLedger; use super::prelude::*; @@ -109,7 +112,10 @@ pub async fn gen_and_register_recipient_key( let agent_invite: OOBInvitation = agent .get_oob_invite() .map_err(|e| GenericStringError { msg: e.to_string() })?; - let agent_diddoc = oob2did(agent_invite); + let mock_ledger = MockLedger {}; + let agent_diddoc = oob_invitation_to_legacy_did_doc(&mock_ledger, &agent_invite) + .await + .unwrap(); let agent_recipient_key = agent_diddoc .recipient_keys() .unwrap() diff --git a/aries/agents/rust/mediator/tests/mediator-aries-connection.rs b/aries/agents/rust/mediator/tests/mediator-aries-connection.rs index 8644e847fe..1a801e9915 100644 --- a/aries/agents/rust/mediator/tests/mediator-aries-connection.rs +++ b/aries/agents/rust/mediator/tests/mediator-aries-connection.rs @@ -26,7 +26,10 @@ async fn didcomm_connection_succeeds() -> Result<()> { .error_for_status()? .json() .await?; - info!("Got invitation from register endpoint {:?}", oobi); + info!( + "Got invitation from register endpoint {}", + serde_json::to_string_pretty(&oobi.clone()).unwrap() + ); let agent = mediator::aries_agent::AgentBuilder::new_demo_agent().await?; let mut aries_transport = AriesReqwest { response_queue: VecDeque::new(), diff --git a/aries/legacy/diddoc_legacy/Cargo.toml b/aries/legacy/diddoc_legacy/Cargo.toml index 5ec94faa93..8430bbdafe 100644 --- a/aries/legacy/diddoc_legacy/Cargo.toml +++ b/aries/legacy/diddoc_legacy/Cargo.toml @@ -15,6 +15,7 @@ serde_derive = "1.0.97" url = { version = "2.3", features = ["serde"] } thiserror = "1.0.37" shared = { path = "../../shared" } +display_as_json = { path = "../../../tools/display_as_json" } [dev-dependencies] serde_json = "1.0.91" diff --git a/aries/legacy/diddoc_legacy/src/aries/service.rs b/aries/legacy/diddoc_legacy/src/aries/service.rs index 8ffc2b4050..ed90dbf298 100644 --- a/aries/legacy/diddoc_legacy/src/aries/service.rs +++ b/aries/legacy/diddoc_legacy/src/aries/service.rs @@ -1,3 +1,4 @@ +use display_as_json::Display; use url::Url; pub const SERVICE_SUFFIX: &str = "indy"; @@ -6,7 +7,7 @@ pub const SERVICE_TYPE: &str = "IndyAgent"; // Service object as defined https://github.com/hyperledger/aries-rfcs/blob/main/features/0434-outofband/README.md#the-services-item // Note that is divergence from w3c spec https://w3c.github.io/did-core/#service-properties -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, Display)] pub struct AriesService { pub id: String, #[serde(rename = "type")] diff --git a/aries/legacy/libvcx_core/src/api_vcx/api_handle/mediated_connection.rs b/aries/legacy/libvcx_core/src/api_vcx/api_handle/mediated_connection.rs index d62b15da32..48d60de9b8 100644 --- a/aries/legacy/libvcx_core/src/api_vcx/api_handle/mediated_connection.rs +++ b/aries/legacy/libvcx_core/src/api_vcx/api_handle/mediated_connection.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; use aries_vcx::{ agency_client::{api::downloaded_message::DownloadedMessage, MessageStatusCode}, - common::ledger::transactions::into_did_doc, handlers::{mediated_connection::MediatedConnection, util::AnyInvitation}, messages::{ msg_fields::protocols::connection::{ @@ -11,7 +10,10 @@ use aries_vcx::{ }, AriesMessage, }, - protocols::mediated_connection::pairwise_info::PairwiseInfo, + protocols::{ + connection::invitee::any_invitation_into_did_doc, + mediated_connection::pairwise_info::PairwiseInfo, + }, }; use serde_json; use uuid::Uuid; @@ -152,7 +154,8 @@ pub async fn create_connection(source_id: &str) -> LibvcxResult { pub async fn create_connection_with_invite(source_id: &str, details: &str) -> LibvcxResult { debug!("create connection {} with invite {}", source_id, details); if let Ok(invitation) = serde_json::from_str::(details) { - let ddo = into_did_doc(get_main_ledger_read()?.as_ref(), &invitation).await?; + let ddo = + any_invitation_into_did_doc(get_main_ledger_read()?.as_ref(), &invitation).await?; let connection = MediatedConnection::create_with_invite( source_id, get_main_wallet()?.as_ref(), diff --git a/aries_vcx/src/common/ledger/transactions.rs b/aries_vcx/src/common/ledger/transactions.rs index 6bce88f4f8..0d3271a912 100644 --- a/aries_vcx/src/common/ledger/transactions.rs +++ b/aries_vcx/src/common/ledger/transactions.rs @@ -7,18 +7,14 @@ use aries_vcx_core::{ }, wallet::base_wallet::BaseWallet, }; -use bs58; -use diddoc_legacy::aries::{diddoc::AriesDidDoc, service::AriesService}; -use messages::msg_fields::protocols::{ - connection::invitation::{Invitation, InvitationContent}, - out_of_band::invitation::OobService, -}; +use diddoc_legacy::aries::service::AriesService; +use messages::msg_fields::protocols::out_of_band::invitation::OobService; use serde_json::Value; + use crate::{ - utils::from_service_sov_to_legacy, common::{keys::get_verkey_from_ledger, ledger::service_didsov::EndpointDidSov}, errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}, - handlers::util::AnyInvitation, + utils::from_service_sov_to_legacy, }; #[derive(Deserialize, Debug)] @@ -57,7 +53,7 @@ pub enum Reply { #[derive(Debug, Deserialize)] pub struct ReplyV0 { - pub result: serde_json::Value, + pub result: Value, } #[derive(Debug, Deserialize)] @@ -67,12 +63,9 @@ pub struct ReplyV1 { #[derive(Debug, Deserialize)] pub struct ReplyDataV1 { - pub result: serde_json::Value, + pub result: Value, } -const DID_KEY_PREFIX: &str = "did:key:"; -const ED25519_MULTIBASE_CODEC: [u8; 2] = [0xed, 0x01]; - pub async fn resolve_service( indy_ledger: &impl IndyLedgerRead, service: &OobService, @@ -100,197 +93,6 @@ pub async fn add_new_did( Ok((did, verkey)) } -pub async fn resolve_oob_invitation( - resolver_registry: &Arc, - invitation: OobInvitation, -) -> VcxResult { - let mut builder = DidDocumentSov::builder(Default::default()); - - let mut resolved_services = vec![]; - let mut resolved_vms = vec![]; - let mut resolved_kas = vec![]; - let mut resolved_dids = vec![]; - - for service in invitation.content.services { - match service { - OobService::SovService(service) => { - builder = builder.add_service(service.clone()); - } - OobService::Did(did) => { - let parsed_did = Did::parse(did)?; - let DidResolutionOutput { did_document, .. } = - resolver_registry.resolve(&parsed_did, &Default::default()).await?; - resolved_services.extend( - did_document - .service() - .iter() - .map(|s| ServiceSov::try_from(s.clone())) - .collect::, _>>()?, - ); - resolved_vms.extend_from_slice(did_document.verification_method()); - resolved_kas.extend_from_slice(did_document.key_agreement()); - resolved_dids.push(parsed_did); - } - OobService::AriesService(service) => { - resolved_services.push(from_legacy_service_to_service_sov(service.clone())?) - } - } - } - - for service in resolved_services { - builder = builder.add_service(service); - } - - for vm in resolved_vms { - builder = builder.add_verification_method(vm.clone()); - } - - for ka in resolved_kas { - builder = builder.add_key_agreement(ka.clone()); - } - - for did in resolved_dids { - builder = builder.add_controller(did); - } - - Ok(builder.build()) -} - -pub async fn into_did_doc( - indy_ledger: &impl IndyLedgerRead, - invitation: &AnyInvitation, -) -> VcxResult { - let mut did_doc: AriesDidDoc = AriesDidDoc::default(); - let (service_endpoint, recipient_keys, routing_keys) = match invitation { - AnyInvitation::Con(Invitation { - content: InvitationContent::Public(content), - .. - }) => { - did_doc.set_id(content.did.to_string()); - let service = get_service(indy_ledger, &content.did) - .await - .unwrap_or_else(|err| { - error!( - "Failed to obtain service definition from the ledger: {}", - err - ); - AriesService::default() - }); - ( - service.service_endpoint, - service.recipient_keys, - service.routing_keys, - ) - } - AnyInvitation::Con(Invitation { - id, - content: InvitationContent::Pairwise(content), - .. - }) => { - did_doc.set_id(id.clone()); - ( - content.service_endpoint.clone(), - content.recipient_keys.clone(), - content.routing_keys.clone(), - ) - } - AnyInvitation::Con(Invitation { - content: InvitationContent::PairwiseDID(_content), - .. - }) => { - return Err(AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidDid, - "PairwiseDID invitation not supported yet!", - )) - } - AnyInvitation::Oob(invitation) => { - did_doc.set_id(invitation.id.clone()); - let service = resolve_service(indy_ledger, &invitation.content.services[0]) - .await - .unwrap_or_else(|err| { - error!( - "Failed to obtain service definition from the ledger: {}", - err - ); - AriesService::default() - }); - let recipient_keys = - normalize_keys_as_naked(service.recipient_keys).unwrap_or_else(|err| { - error!("Is not did valid: {}", err); - Vec::new() - }); - ( - service.service_endpoint, - recipient_keys, - service.routing_keys, - ) - } - }; - did_doc.set_service_endpoint(service_endpoint); - did_doc.set_recipient_keys(recipient_keys); - did_doc.set_routing_keys(routing_keys); - Ok(did_doc) -} - -fn _ed25519_public_key_to_did_key(public_key_base58: &str) -> VcxResult { - let public_key_bytes = bs58::decode(public_key_base58).into_vec().map_err(|_| { - AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidDid, - format!( - "Could not base58 decode a did:key fingerprint: {}", - public_key_base58 - ), - ) - })?; - let mut did_key_bytes = ED25519_MULTIBASE_CODEC.to_vec(); - did_key_bytes.extend_from_slice(&public_key_bytes); - let did_key_bytes_bs58 = bs58::encode(&did_key_bytes).into_string(); - let did_key = format!("{DID_KEY_PREFIX}z{did_key_bytes_bs58}"); - Ok(did_key) -} - -fn normalize_keys_as_naked(keys_list: Vec) -> VcxResult> { - let mut result = Vec::new(); - for key in keys_list { - if let Some(stripped_didkey) = key.strip_prefix(DID_KEY_PREFIX) { - let stripped = if let Some(stripped) = stripped_didkey.strip_prefix('z') { - stripped - } else { - Err(AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidDid, - format!("z prefix is missing: {}", key), - ))? - }; - let decoded_value = bs58::decode(stripped).into_vec().map_err(|_| { - AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidDid, - format!( - "Could not decode base58: {} as portion of {}", - stripped, key - ), - ) - })?; - let verkey = if let Some(public_key_bytes) = - decoded_value.strip_prefix(&ED25519_MULTIBASE_CODEC) - { - Ok(bs58::encode(public_key_bytes).into_string()) - } else { - Err(AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidDid, - format!( - "Only Ed25519-based did:keys are currently supported, got key: {}", - key - ), - )) - }?; - result.push(verkey); - } else { - result.push(key); - } - } - Ok(result) -} - pub async fn get_service(ledger: &impl IndyLedgerRead, did: &String) -> VcxResult { let did_raw = did.to_string(); let did_raw = match did_raw.rsplit_once(':') { diff --git a/aries_vcx/src/handlers/out_of_band/sender.rs b/aries_vcx/src/handlers/out_of_band/sender.rs index 12c22369e2..5ff935f7c0 100644 --- a/aries_vcx/src/handlers/out_of_band/sender.rs +++ b/aries_vcx/src/handlers/out_of_band/sender.rs @@ -70,7 +70,9 @@ impl OutOfBandSender { pub fn append_handshake_protocol(mut self, protocol: Protocol) -> VcxResult { let new_protocol = match protocol { - Protocol::ConnectionType(_) | Protocol::DidExchangeType(_) => MaybeKnown::Known(protocol), + Protocol::ConnectionType(_) | Protocol::DidExchangeType(_) => { + MaybeKnown::Known(protocol) + } _ => { return Err(AriesVcxError::from_msg( AriesVcxErrorKind::ActionNotSupported, diff --git a/aries_vcx/src/handlers/util.rs b/aries_vcx/src/handlers/util.rs index b751f7daf9..e9b7898286 100644 --- a/aries_vcx/src/handlers/util.rs +++ b/aries_vcx/src/handlers/util.rs @@ -240,10 +240,14 @@ pub fn verify_thread_id(thread_id: &str, message: &AriesMessage) -> VcxResult<() AriesMessage::CoordinateMediation(CoordinateMediation::Keylist(msg)) => { matches_opt_thread_id!(msg, thread_id) } - AriesMessage::DidExchange(DidExchange::Request(msg)) => matches_opt_thread_id!(msg, thread_id), + AriesMessage::DidExchange(DidExchange::Request(msg)) => { + matches_opt_thread_id!(msg, thread_id) + } AriesMessage::DidExchange(DidExchange::Response(msg)) => matches_thread_id!(msg, thread_id), AriesMessage::DidExchange(DidExchange::Complete(msg)) => matches_thread_id!(msg, thread_id), - AriesMessage::DidExchange(DidExchange::ProblemReport(msg)) => matches_thread_id!(msg, thread_id), + AriesMessage::DidExchange(DidExchange::ProblemReport(msg)) => { + matches_thread_id!(msg, thread_id) + } }; if !is_match { diff --git a/aries_vcx/src/lib.rs b/aries_vcx/src/lib.rs index b16f42358d..27f586e805 100644 --- a/aries_vcx/src/lib.rs +++ b/aries_vcx/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::result_large_err)] #![allow(clippy::large_enum_variant)] #![allow(clippy::diverging_sub_expression)] //this is needed for some large json macro invocations diff --git a/aries_vcx/src/protocols/connection/invitee/mod.rs b/aries_vcx/src/protocols/connection/invitee/mod.rs index 352d47e3a8..fef35c760d 100644 --- a/aries_vcx/src/protocols/connection/invitee/mod.rs +++ b/aries_vcx/src/protocols/connection/invitee/mod.rs @@ -2,12 +2,12 @@ pub mod states; use aries_vcx_core::{ledger::base_ledger::IndyLedgerRead, wallet::base_wallet::BaseWallet}; use chrono::Utc; -use diddoc_legacy::aries::diddoc::AriesDidDoc; +use diddoc_legacy::aries::{diddoc::AriesDidDoc, service::AriesService}; use messages::{ decorators::{thread::Thread, timing::Timing}, msg_fields::protocols::{ connection::{ - invitation::InvitationContent, + invitation::{Invitation, InvitationContent}, request::{Request, RequestContent, RequestDecorators}, response::Response, ConnectionData, @@ -26,10 +26,10 @@ use super::{ Connection, }; use crate::{ - common::{ledger::transactions::into_did_doc, signing::decode_signed_connection_response}, + common::{ledger::transactions::get_service, signing::decode_signed_connection_response}, errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}, handlers::util::{matches_thread_id, AnyInvitation}, - protocols::connection::trait_bounds::ThreadId, + protocols::{connection::trait_bounds::ThreadId, oob::oob_invitation_to_legacy_did_doc}, }; /// Convenience alias @@ -61,7 +61,7 @@ impl InviteeConnection { &invitation ); - let did_doc = into_did_doc(indy_ledger, &invitation).await?; + let did_doc = any_invitation_into_did_doc(indy_ledger, &invitation).await?; let state = Invited::new(did_doc, invitation); // Convert to `InvitedState` @@ -240,3 +240,60 @@ where self.state.bootstrap_did_doc() } } + +pub async fn any_invitation_into_did_doc( + indy_ledger: &impl IndyLedgerRead, + invitation: &AnyInvitation, +) -> VcxResult { + let mut did_doc: AriesDidDoc = AriesDidDoc::default(); + let (service_endpoint, recipient_keys, routing_keys) = match invitation { + AnyInvitation::Con(Invitation { + content: InvitationContent::Public(content), + .. + }) => { + did_doc.set_id(content.did.to_string()); + let service = get_service(indy_ledger, &content.did) + .await + .unwrap_or_else(|err| { + error!( + "Failed to obtain service definition from the ledger: {}", + err + ); + AriesService::default() + }); + ( + service.service_endpoint, + service.recipient_keys, + service.routing_keys, + ) + } + AnyInvitation::Con(Invitation { + id, + content: InvitationContent::Pairwise(content), + .. + }) => { + did_doc.set_id(id.clone()); + ( + content.service_endpoint.clone(), + content.recipient_keys.clone(), + content.routing_keys.clone(), + ) + } + AnyInvitation::Con(Invitation { + content: InvitationContent::PairwiseDID(_content), + .. + }) => { + return Err(AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidDid, + "PairwiseDID invitation not supported yet!", + )) + } + AnyInvitation::Oob(invitation) => { + return oob_invitation_to_legacy_did_doc(indy_ledger, invitation).await + } + }; + did_doc.set_service_endpoint(service_endpoint); + did_doc.set_recipient_keys(recipient_keys); + did_doc.set_routing_keys(routing_keys); + Ok(did_doc) +} diff --git a/aries_vcx/src/protocols/did_exchange/mod.rs b/aries_vcx/src/protocols/did_exchange/mod.rs index a15ee56e6c..b1d9cfb573 100644 --- a/aries_vcx/src/protocols/did_exchange/mod.rs +++ b/aries_vcx/src/protocols/did_exchange/mod.rs @@ -3,7 +3,9 @@ use std::sync::Arc; use did_doc_sov::extra_fields::KeyKind; use did_resolver::traits::resolvable::resolution_output::DidResolutionOutput; use did_resolver_registry::ResolverRegistry; -use messages::msg_fields::protocols::out_of_band::invitation::{Invitation as OobInvitation, OobService}; +use messages::msg_fields::protocols::out_of_band::invitation::{ + Invitation as OobInvitation, OobService, +}; use public_key::{Key, KeyType}; use crate::errors::error::{AriesVcxError, AriesVcxErrorKind}; @@ -35,7 +37,10 @@ pub async fn resolve_key_from_invitation( .resolve(&did.clone().try_into()?, &Default::default()) .await .map_err(|err| { - AriesVcxError::from_msg(AriesVcxErrorKind::InvalidDid, format!("DID resolution failed: {err}")) + AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidDid, + format!("DID resolution failed: {err}"), + ) })?; Ok(did_document .verification_method() diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/generic/conversions.rs b/aries_vcx/src/protocols/did_exchange/state_machine/generic/conversions.rs index 32d4b7d4fa..7d6e829a7e 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/generic/conversions.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/generic/conversions.rs @@ -1,10 +1,12 @@ +use super::{GenericDidExchange, RequesterState, ResponderState}; use crate::protocols::did_exchange::{ state_machine::{requester::DidExchangeRequester, responder::DidExchangeResponder}, - states::{completed::Completed, requester::request_sent::RequestSent, responder::response_sent::ResponseSent}, + states::{ + completed::Completed, requester::request_sent::RequestSent, + responder::response_sent::ResponseSent, + }, }; -use super::{GenericDidExchange, RequesterState, ResponderState}; - impl From> for GenericDidExchange { fn from(state: DidExchangeRequester) -> Self { Self::Requester(RequesterState::RequestSent(state)) diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs b/aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs index 2afdf7c79b..da40c87678 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs @@ -1,11 +1,20 @@ -mod conversions; -mod thin_state; +use std::sync::Arc; +use aries_vcx_core::{ledger::base_ledger::IndyLedgerRead, wallet::base_wallet::BaseWallet}; use did_doc_sov::DidDocumentSov; -use messages::msg_fields::protocols::did_exchange::{ - complete::Complete, problem_report::ProblemReport, request::Request, response::Response, +use did_parser::Did; +use did_resolver_registry::ResolverRegistry; +use messages::msg_fields::protocols::{ + did_exchange::{ + complete::Complete, problem_report::ProblemReport, request::Request, response::Response, + }, + out_of_band::invitation::Invitation, }; +use public_key::Key; +pub use thin_state::ThinState; +use url::Url; +use super::{requester::DidExchangeRequester, responder::DidExchangeResponder}; use crate::{ errors::error::{AriesVcxError, AriesVcxErrorKind}, protocols::did_exchange::{ @@ -17,12 +26,8 @@ use crate::{ }, }; -use super::{ - requester::{ConstructRequestConfig, DidExchangeRequester}, - responder::{DidExchangeResponder, ReceiveRequestConfig}, -}; - -pub use thin_state::ThinState; +mod conversions; +mod thin_state; #[derive(Debug, Clone)] pub enum GenericDidExchange { @@ -50,12 +55,14 @@ impl GenericDidExchange { GenericDidExchange::Requester(requester_state) => match requester_state { RequesterState::RequestSent(request_sent_state) => request_sent_state.our_did_doc(), RequesterState::Completed(completed_state) => completed_state.our_did_doc(), - RequesterState::Abandoned(abandoned_state) => todo!(), + RequesterState::Abandoned(_abandoned_state) => todo!(), }, GenericDidExchange::Responder(responder_state) => match responder_state { - ResponderState::ResponseSent(response_sent_state) => response_sent_state.our_did_doc(), + ResponderState::ResponseSent(response_sent_state) => { + response_sent_state.our_did_doc() + } ResponderState::Completed(completed_state) => completed_state.our_did_doc(), - ResponderState::Abandoned(abandoned_state) => todo!(), + ResponderState::Abandoned(_abandoned_state) => todo!(), }, } } @@ -63,14 +70,18 @@ impl GenericDidExchange { pub fn their_did_doc(&self) -> &DidDocumentSov { match self { GenericDidExchange::Requester(requester_state) => match requester_state { - RequesterState::RequestSent(request_sent_state) => request_sent_state.their_did_doc(), + RequesterState::RequestSent(request_sent_state) => { + request_sent_state.their_did_doc() + } RequesterState::Completed(completed_state) => completed_state.their_did_doc(), - RequesterState::Abandoned(abandoned_state) => todo!(), + RequesterState::Abandoned(_abandoned_state) => todo!(), }, GenericDidExchange::Responder(responder_state) => match responder_state { - ResponderState::ResponseSent(response_sent_state) => response_sent_state.their_did_doc(), + ResponderState::ResponseSent(response_sent_state) => { + response_sent_state.their_did_doc() + } ResponderState::Completed(completed_state) => completed_state.their_did_doc(), - ResponderState::Abandoned(abandoned_state) => todo!(), + ResponderState::Abandoned(_abandoned_state) => todo!(), }, } } @@ -78,45 +89,102 @@ impl GenericDidExchange { pub fn invitation_id(&self) -> &str { match self { GenericDidExchange::Requester(requester_state) => match requester_state { - RequesterState::RequestSent(request_sent_state) => request_sent_state.get_invitation_id(), + RequesterState::RequestSent(request_sent_state) => { + request_sent_state.get_invitation_id() + } RequesterState::Completed(completed_state) => completed_state.get_invitation_id(), RequesterState::Abandoned(_) => todo!(), }, GenericDidExchange::Responder(responder_state) => match responder_state { - ResponderState::ResponseSent(response_sent_state) => response_sent_state.get_invitation_id(), + ResponderState::ResponseSent(response_sent_state) => { + response_sent_state.get_invitation_id() + } ResponderState::Completed(completed_state) => completed_state.get_invitation_id(), - ResponderState::Abandoned(abandoned_state) => todo!(), + ResponderState::Abandoned(_abandoned_state) => todo!(), }, } } - pub async fn construct_request(config: ConstructRequestConfig) -> Result<(Self, Request), AriesVcxError> { - let TransitionResult { state, output } = DidExchangeRequester::::construct_request(config).await?; + pub async fn construct_request_public( + ledger: &impl IndyLedgerRead, + their_did: Did, + our_did: Did, + ) -> Result<(Self, Request), AriesVcxError> { + let TransitionResult { state, output } = + DidExchangeRequester::::construct_request_public( + ledger, their_did, our_did, + ) + .await?; Ok(( GenericDidExchange::Requester(RequesterState::RequestSent(state)), output, )) } - pub async fn handle_request(config: ReceiveRequestConfig) -> Result<(Self, Response), AriesVcxError> { - let TransitionResult { state, output } = DidExchangeResponder::::receive_request(config).await?; + pub async fn construct_request_pairwise( + wallet: &impl BaseWallet, + invitation: Invitation, + resolver_registry: Arc, + service_endpoint: Url, + routing_keys: Vec, + ) -> Result<(Self, Request), AriesVcxError> { + let TransitionResult { state, output } = + DidExchangeRequester::::construct_request_pairwise( + wallet, + invitation, + resolver_registry, + service_endpoint, + routing_keys, + ) + .await?; + Ok(( + GenericDidExchange::Requester(RequesterState::RequestSent(state)), + output, + )) + } + + pub async fn handle_request( + wallet: &impl BaseWallet, + resolver_registry: Arc, + request: Request, + service_endpoint: Url, + routing_keys: Vec, + invitation_id: String, + invitation_key: Key, + ) -> Result<(Self, Response), AriesVcxError> { + let TransitionResult { state, output } = + DidExchangeResponder::::receive_request( + wallet, + resolver_registry, + request, + service_endpoint, + routing_keys, + invitation_id, + invitation_key, + ) + .await?; Ok(( GenericDidExchange::Responder(ResponderState::ResponseSent(state)), output, )) } - pub async fn handle_response(self, response: Response) -> Result<(Self, Complete), (Self, AriesVcxError)> { + pub async fn handle_response( + self, + response: Response, + ) -> Result<(Self, Complete), (Self, AriesVcxError)> { match self { GenericDidExchange::Requester(requester_state) => match requester_state { RequesterState::RequestSent(request_sent_state) => { match request_sent_state.receive_response(response).await { - Ok(TransitionResult { state, output }) => { - Ok((GenericDidExchange::Requester(RequesterState::Completed(state)), output)) - } - Err(TransitionError { state, error }) => { - Err((GenericDidExchange::Requester(RequesterState::RequestSent(state)), error)) - } + Ok(TransitionResult { state, output }) => Ok(( + GenericDidExchange::Requester(RequesterState::Completed(state)), + output, + )), + Err(TransitionError { state, error }) => Err(( + GenericDidExchange::Requester(RequesterState::RequestSent(state)), + error, + )), } } RequesterState::Completed(completed_state) => Err(( @@ -149,7 +217,9 @@ impl GenericDidExchange { GenericDidExchange::Responder(responder_state) => match responder_state { ResponderState::ResponseSent(response_sent_state) => { match response_sent_state.receive_complete(complete) { - Ok(state) => Ok(GenericDidExchange::Responder(ResponderState::Completed(state))), + Ok(state) => Ok(GenericDidExchange::Responder(ResponderState::Completed( + state, + ))), Err(TransitionError { state, error }) => Err(( GenericDidExchange::Responder(ResponderState::ResponseSent(state)), error, @@ -181,12 +251,17 @@ impl GenericDidExchange { } } - pub fn handle_problem_report(self, problem_report: ProblemReport) -> Result { + pub fn handle_problem_report( + self, + problem_report: ProblemReport, + ) -> Result { match self { GenericDidExchange::Requester(requester_state) => match requester_state { - RequesterState::RequestSent(request_sent_state) => Ok(GenericDidExchange::Requester( - RequesterState::Abandoned(request_sent_state.receive_problem_report(problem_report)), - )), + RequesterState::RequestSent(request_sent_state) => { + Ok(GenericDidExchange::Requester(RequesterState::Abandoned( + request_sent_state.receive_problem_report(problem_report), + ))) + } RequesterState::Completed(completed_state) => Err(( GenericDidExchange::Requester(RequesterState::Completed(completed_state)), AriesVcxError::from_msg( @@ -199,9 +274,11 @@ impl GenericDidExchange { )), }, GenericDidExchange::Responder(responder_state) => match responder_state { - ResponderState::ResponseSent(response_sent_state) => Ok(GenericDidExchange::Responder( - ResponderState::Abandoned(response_sent_state.receive_problem_report(problem_report)), - )), + ResponderState::ResponseSent(response_sent_state) => { + Ok(GenericDidExchange::Responder(ResponderState::Abandoned( + response_sent_state.receive_problem_report(problem_report), + ))) + } ResponderState::Completed(completed_state) => Err(( GenericDidExchange::Responder(ResponderState::Completed(completed_state)), AriesVcxError::from_msg( diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/generic/thin_state.rs b/aries_vcx/src/protocols/did_exchange/state_machine/generic/thin_state.rs index 5996c23e8f..fef38af111 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/generic/thin_state.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/generic/thin_state.rs @@ -1,5 +1,3 @@ -use std::fmt::Display; - #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ThinState { #[serde(rename = "RequestSent")] diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs b/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs index d813f6de30..97ffe3f21f 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs @@ -1,6 +1,7 @@ -use std::{collections::HashMap, sync::Arc}; +use std::collections::HashMap; use aries_vcx_core::wallet::base_wallet::BaseWallet; +use base64::engine::general_purpose::URL_SAFE_NO_PAD; use did_doc::schema::{ types::uri::Uri, verification_method::{VerificationMethod, VerificationMethodKind, VerificationMethodType}, @@ -12,8 +13,7 @@ use did_doc_sov::{ }; use did_key::DidKey; use did_parser::{Did, DidUrl}; -use did_peer::peer_did::generate::generate_numalgo2; -use diddoc_legacy::aries::diddoc::AriesDidDoc; +use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}; use messages::decorators::attachment::{Attachment, AttachmentData, AttachmentType}; use public_key::{Key, KeyType}; use serde_json::Value; @@ -22,12 +22,15 @@ use url::Url; use crate::{ errors::error::{AriesVcxError, AriesVcxErrorKind}, protocols::{ - did_exchange::transition::transition_error::TransitionError, mediated_connection::pairwise_info::PairwiseInfo, + did_exchange::transition::transition_error::TransitionError, + mediated_connection::pairwise_info::PairwiseInfo, }, - utils::from_legacy_did_doc_to_sov, }; -pub async fn generate_keypair(wallet: &Arc, key_type: KeyType) -> Result { +pub async fn generate_keypair( + wallet: &impl BaseWallet, + key_type: KeyType, +) -> Result { let pairwise_info = PairwiseInfo::create(wallet).await?; Ok(Key::from_base58(&pairwise_info.pw_vk, key_type)?) } @@ -41,12 +44,16 @@ pub fn construct_service( .set_routing_keys(routing_keys) .set_recipient_keys(recipient_keys) .build(); - let service = ServiceSov::DIDCommV1(ServiceDidCommV1::new(Uri::new("#0")?, service_endpoint.into(), extra)?); + let service = ServiceSov::DIDCommV1(ServiceDidCommV1::new( + Uri::new("#0")?, + service_endpoint.into(), + extra, + )?); Ok(service) } pub async fn create_our_did_document( - wallet: &Arc, + wallet: &impl BaseWallet, service_endpoint: Url, routing_keys: Vec, ) -> Result<(DidDocumentSov, Key), AriesVcxError> { @@ -59,11 +66,16 @@ pub async fn create_our_did_document( )?; // TODO: Make it easier to generate peer did from keys and service, and generate DDO from it - let did_document_temp = did_doc_from_keys(Default::default(), key_ver.clone(), key_enc.clone(), service.clone())?; - let peer_did = generate_numalgo2(did_document_temp.into())?; + let did_document_temp = did_doc_from_keys( + Default::default(), + key_ver.clone(), + key_enc.clone(), + service.clone(), + )?; + let peer_did = PeerDid::::from_did_doc(did_document_temp.into())?; Ok(( - did_doc_from_keys(peer_did.clone().into(), key_ver, key_enc.clone(), service)?, + did_doc_from_keys(peer_did.into(), key_ver, key_enc.clone(), service)?, key_enc, )) } @@ -83,12 +95,16 @@ fn did_doc_from_keys( ) .add_public_key_base58(key_ver.base58()) .build(); - let vm_ka = VerificationMethod::builder(vm_ka_id, did.clone(), VerificationMethodType::X25519KeyAgreementKey2020) - .add_public_key_base58(key_enc.base58()) - .build(); + let vm_ka = VerificationMethod::builder( + vm_ka_id, + did.clone(), + VerificationMethodType::X25519KeyAgreementKey2020, + ) + .add_public_key_base58(key_enc.base58()) + .build(); Ok(DidDocumentSov::builder(did) .add_service(service) - .add_verification_method(vm_ver.clone()) + .add_verification_method(vm_ver) // TODO: Include just reference .add_key_agreement(VerificationMethodKind::Resolved(vm_ka)) .build()) @@ -96,9 +112,15 @@ fn did_doc_from_keys( pub fn ddo_sov_to_attach(ddo: DidDocumentSov) -> Result { // Interop note: acapy accepts unsigned when using peer dids? - Ok(Attachment::new(AttachmentData::new(AttachmentType::Base64( - base64::encode_config(&serde_json::to_string(&ddo)?, base64::URL_SAFE_NO_PAD), - )))) + let content_b64 = + base64::engine::Engine::encode(&URL_SAFE_NO_PAD, serde_json::to_string(&ddo)?); + Ok(Attachment::builder() + .data( + AttachmentData::builder() + .content(AttachmentType::Base64(content_b64)) + .build(), + ) + .build()) } // TODO: Obviously, extract attachment signing @@ -106,11 +128,12 @@ pub fn ddo_sov_to_attach(ddo: DidDocumentSov) -> Result, + wallet: &impl BaseWallet, ) -> Result { if let AttachmentType::Base64(attach_base64) = &attach.data.content { let did_key: DidKey = verkey.clone().try_into()?; - let verkey_b64 = base64::encode_config(verkey.key(), base64::URL_SAFE_NO_PAD); + let verkey_b64 = base64::engine::Engine::encode(&URL_SAFE_NO_PAD, verkey.key()); + let protected_header = json!({ "alg": "EdDSA", "jwk": { @@ -124,14 +147,15 @@ pub async fn jws_sign_attach( // TODO: Needs to be both protected and unprotected, does it make sense? "kid": did_key.to_string(), }); - let b64_protected = base64::encode_config(&protected_header.to_string(), base64::URL_SAFE_NO_PAD); + let b64_protected = + base64::engine::Engine::encode(&URL_SAFE_NO_PAD, protected_header.to_string()); let sign_input = format!("{}.{}", b64_protected, attach_base64).into_bytes(); let signed = wallet.sign(&verkey.base58(), &sign_input).await?; - let signature_base64 = base64::encode_config(&signed, base64::URL_SAFE_NO_PAD); + let signature_base64 = base64::engine::Engine::encode(&URL_SAFE_NO_PAD, signed); let jws = { let mut jws = HashMap::new(); - jws.insert("header".to_string(), Value::from(unprotected_header)); + jws.insert("header".to_string(), unprotected_header); jws.insert("protected".to_string(), Value::String(b64_protected)); jws.insert("signature".to_string(), Value::String(signature_base64)); jws @@ -150,10 +174,12 @@ pub fn attach_to_ddo_sov(attachment: Attachment) -> Result serde_json::from_value(value).map_err(Into::into), AttachmentType::Base64(ref value) => { - let bytes = base64::decode(&value).map_err(|err| { + let bytes = base64::Engine::decode(&URL_SAFE_NO_PAD, value).map_err(|err| { AriesVcxError::from_msg( AriesVcxErrorKind::SerializationError, - format!("Attachment base 64 decoding failed; attach: {attachment:?}, err: {err}"), + format!( + "Attachment base 64 decoding failed; attach: {attachment:?}, err: {err}" + ), ) })?; serde_json::from_slice::(&bytes).map_err(Into::into) diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/mod.rs b/aries_vcx/src/protocols/did_exchange/state_machine/mod.rs index c82b6e952b..74003b34a2 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/mod.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/mod.rs @@ -4,19 +4,19 @@ pub mod generic; pub mod requester; pub mod responder; +use std::marker::PhantomData; + +use chrono::Utc; +use did_doc_sov::DidDocumentSov; pub use helpers::generate_keypair; use messages::{ - decorators::thread::Thread, + decorators::{thread::Thread, timing::Timing}, msg_fields::protocols::did_exchange::problem_report::{ ProblemCode, ProblemReport, ProblemReportContent, ProblemReportDecorators, }, }; use uuid::Uuid; -use std::marker::PhantomData; - -use did_doc_sov::DidDocumentSov; - use super::{ states::{ abandoned::Abandoned, @@ -33,16 +33,6 @@ pub struct DidExchange { their_did_document: DidDocumentSov, } -impl DidExchange { - pub fn our_did_doc(&self) -> &DidDocumentSov { - &self.our_did_document - } - - pub fn their_did_doc(&self) -> &DidDocumentSov { - &self.their_did_document - } -} - impl DidExchange { pub fn get_thread_id(&self) -> &str { self.state.thread_id() @@ -53,20 +43,24 @@ impl DidExchange { reason: String, problem_code: Option, ) -> TransitionResult, ProblemReport> { - let problem_report = { - let id = Uuid::new_v4().to_string(); - let content = ProblemReportContent { - problem_code, - explain: Some(reason.clone()), - }; - let decorators = ProblemReportDecorators { - // TODO: Set thid of the conversation - thread: Thread::new(self.state.thread_id().to_string()), - localization: None, - timing: None, - }; - ProblemReport::with_decorators(id, content, decorators) - }; + let content = ProblemReportContent::builder() + .problem_code(problem_code) + .explain(Some(reason.clone())) + .build(); + let decorators = ProblemReportDecorators::builder() + .thread( + Thread::builder() + .thid(self.state.thread_id().to_string()) + .build(), + ) + .timing(Timing::builder().out_time(Utc::now()).build()) + .build(); + let problem_report = ProblemReport::builder() + .id(Uuid::new_v4().to_string()) + .content(content) + .decorators(decorators) + .build(); + TransitionResult { state: DidExchange { state: Abandoned { @@ -81,10 +75,13 @@ impl DidExchange { } } - pub fn receive_problem_report(self, problem_report: ProblemReport) -> DidExchange { + pub fn receive_problem_report( + self, + problem_report: ProblemReport, + ) -> DidExchange { DidExchange { state: Abandoned { - reason: problem_report.clone().content.explain.unwrap_or_default(), + reason: problem_report.content.explain.unwrap_or_default(), request_id: self.state.thread_id().to_string(), }, initiation_type: PhantomData, @@ -101,7 +98,11 @@ impl DidExchange { } impl DidExchange { - pub fn from_parts(state: S, their_did_document: DidDocumentSov, our_did_document: DidDocumentSov) -> Self { + pub fn from_parts( + state: S, + their_did_document: DidDocumentSov, + our_did_document: DidDocumentSov, + ) -> Self { Self { state, initiation_type: PhantomData, @@ -110,3 +111,13 @@ impl DidExchange { } } } + +impl DidExchange { + pub fn our_did_doc(&self) -> &DidDocumentSov { + &self.our_did_document + } + + pub fn their_did_doc(&self) -> &DidDocumentSov { + &self.their_did_document + } +} diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/requester/mod.rs b/aries_vcx/src/protocols/did_exchange/state_machine/requester/mod.rs index 249ba00de3..076f744208 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/requester/mod.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/requester/mod.rs @@ -2,8 +2,6 @@ mod request_sent; use super::DidExchange; -pub use request_sent::config::{ConstructRequestConfig, PairwiseConstructRequestConfig, PublicConstructRequestConfig}; - #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] pub struct Requester; diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/config.rs b/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/config.rs deleted file mode 100644 index 709a3a372b..0000000000 --- a/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/config.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::sync::Arc; - -use aries_vcx_core::{ledger::base_ledger::IndyLedgerRead, wallet::base_wallet::BaseWallet}; -use did_parser::Did; -use did_resolver_registry::ResolverRegistry; -use messages::msg_fields::protocols::out_of_band::invitation::Invitation as OobInvitation; -use url::Url; - -pub struct PairwiseConstructRequestConfig { - pub wallet: Arc, - pub invitation: OobInvitation, - pub resolver_registry: Arc, - pub service_endpoint: Url, - pub routing_keys: Vec, -} - -pub struct PublicConstructRequestConfig { - pub ledger: Arc, - pub wallet: Arc, - pub their_did: Did, - pub our_did: Did, -} - -pub enum ConstructRequestConfig { - Pairwise(PairwiseConstructRequestConfig), - Public(PublicConstructRequestConfig), -} diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/helpers.rs b/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/helpers.rs index cc8529cdeb..2a467cfb6f 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/helpers.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/helpers.rs @@ -1,28 +1,28 @@ use std::sync::Arc; use aries_vcx_core::ledger::base_ledger::IndyLedgerRead; +use chrono::Utc; use did_doc::schema::verification_method::{VerificationMethod, VerificationMethodType}; use did_doc_sov::{service::ServiceSov, DidDocumentSov}; use did_parser::{Did, DidUrl}; +use did_resolver::traits::resolvable::resolution_output::DidResolutionOutput; +use did_resolver_registry::ResolverRegistry; use messages::{ decorators::{ - attachment::Attachment, thread::{Thread, ThreadGoalCode}, + timing::Timing, }, msg_fields::protocols::{ - did_exchange::{ - complete::{Complete as CompleteMessage, CompleteDecorators}, - request::{Request, RequestContent, RequestDecorators}, - }, - out_of_band::invitation::{Invitation as OobInvitation, OobService}, + did_exchange::request::{Request, RequestContent, RequestDecorators}, + out_of_band::invitation::{Invitation as OobInvitation, Invitation, OobService}, }, }; -use shared_vcx::{maybe_known::MaybeKnown, misc::serde_ignored::SerdeIgnored as NoContent}; +use shared::maybe_known::MaybeKnown; use uuid::Uuid; use crate::{ common::ledger::transactions::resolve_service, - errors::error::{AriesVcxError, AriesVcxErrorKind}, + errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}, utils::from_legacy_service_to_service_sov, }; @@ -52,26 +52,30 @@ pub fn verify_handshake_protocol(invitation: OobInvitation) -> Result<(), AriesV } pub async fn did_doc_from_did( - ledger: &Arc, + ledger: &impl IndyLedgerRead, did: Did, ) -> Result<(DidDocumentSov, ServiceSov), AriesVcxError> { let service = resolve_service(ledger, &OobService::Did(did.id().to_string())).await?; - let did_url: DidUrl = format!("{}#vm-0", did.to_string()).try_into()?; - let vm = VerificationMethod::builder(did_url, did.clone(), VerificationMethodType::Ed25519VerificationKey2020) - .add_public_key_base58( - service - .recipient_keys - .first() - .ok_or_else(|| { - AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidState, - "No recipient keys found in resolved service", - ) - })? - .clone(), - ) - .build(); - let sov_service = from_legacy_service_to_service_sov(service.clone())?; + let did_url: DidUrl = format!("{}#vm-0", did).try_into()?; + let vm = VerificationMethod::builder( + did_url, + did.clone(), + VerificationMethodType::Ed25519VerificationKey2020, + ) + .add_public_key_base58( + service + .recipient_keys + .first() + .ok_or_else(|| { + AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidState, + "No recipient keys found in resolved service", + ) + })? + .clone(), + ) + .build(); + let sov_service = from_legacy_service_to_service_sov(service)?; let did_document = DidDocumentSov::builder(did.clone()) .add_service(sov_service.clone()) .add_controller(did) @@ -80,40 +84,84 @@ pub async fn did_doc_from_did( Ok((did_document, sov_service)) } -// TODO: Replace by a builder -pub fn construct_request(invitation_id: String, our_did: String) -> Result { +pub fn construct_request(invitation_id: String, our_did: String) -> Request { let request_id = Uuid::new_v4().to_string(); - let thread = { - let mut thread = Thread::new(request_id.clone()); - thread.pthid = Some(invitation_id.clone()); - thread - }; - let decorators = { - let mut decorators = RequestDecorators::default(); - decorators.thread = Some(thread); - decorators - }; - let content = RequestContent { - // TODO: Obviously, these fields should be more configurable - label: "".to_string(), - // Interop note: Rejected if non-empty by acapy (regardless of invite contents) - goal: Some("To establish a connection".to_string()), - // Interop note: Rejected if non-empty by acapy (regardless of invite contents) - goal_code: Some(MaybeKnown::Known(ThreadGoalCode::AriesRelBuild)), - // Interop note: Should not have to send both DID and DDO if did resolvable - did: our_did, - did_doc: None, - }; - Ok(Request::with_decorators(request_id.clone(), content, decorators)) + let decorators = RequestDecorators::builder() + .thread(Some( + Thread::builder() + .thid(request_id.clone()) + .pthid(invitation_id) + .build(), + )) + .timing(Timing::builder().out_time(Utc::now()).build()) + .build(); + let content = RequestContent::builder() + .label("".into()) + .did(our_did) + .did_doc(None) + .goal(Some("To establish a connection".into())) // Rejected if non-empty by acapy + .goal_code(Some(MaybeKnown::Known(ThreadGoalCode::AriesRelBuild))) // Rejected if non-empty by acapy + .build(); + Request::builder() + .id(request_id) + .content(content) + .decorators(decorators) + .build() } -// TODO: Replace by a builder -pub fn construct_complete_message(invitation_id: String, request_id: String) -> CompleteMessage { - let complete_id = Uuid::new_v4().to_string(); - let decorators = { - let mut thread = Thread::new(request_id); - thread.pthid = Some(invitation_id); - CompleteDecorators { thread, timing: None } - }; - CompleteMessage::with_decorators(complete_id, NoContent::default(), decorators) +pub async fn oob_invitation_to_diddoc( + resolver_registry: &Arc, + invitation: Invitation, +) -> VcxResult { + let mut builder = DidDocumentSov::builder(Default::default()); + + let mut resolved_services = vec![]; + let mut resolved_vms = vec![]; + let mut resolved_kas = vec![]; + let mut resolved_dids = vec![]; + + for service in invitation.content.services { + match service { + OobService::SovService(service) => { + builder = builder.add_service(service.clone()); + } + OobService::Did(did) => { + let parsed_did = Did::parse(did)?; + let DidResolutionOutput { did_document, .. } = resolver_registry + .resolve(&parsed_did, &Default::default()) + .await?; + resolved_services.extend( + did_document + .service() + .iter() + .map(|s| ServiceSov::try_from(s.clone())) + .collect::, _>>()?, + ); + resolved_vms.extend_from_slice(did_document.verification_method()); + resolved_kas.extend_from_slice(did_document.key_agreement()); + resolved_dids.push(parsed_did); + } + OobService::AriesService(service) => { + resolved_services.push(from_legacy_service_to_service_sov(service.clone())?) + } + } + } + + for service in resolved_services { + builder = builder.add_service(service); + } + + for vm in resolved_vms { + builder = builder.add_verification_method(vm.clone()); + } + + for ka in resolved_kas { + builder = builder.add_key_agreement(ka.clone()); + } + + for did in resolved_dids { + builder = builder.add_controller(did); + } + + Ok(builder.build()) } diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/mod.rs b/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/mod.rs index 280d3f5b66..9422cfe72a 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/mod.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/mod.rs @@ -1,46 +1,55 @@ -pub mod config; -mod helpers; +use std::sync::Arc; -use did_parser::ParseError; -use did_peer::peer_did_resolver::resolver::PeerDidResolver; -use did_resolver::{error::GenericError, traits::resolvable::DidResolvable}; -use messages::msg_fields::protocols::did_exchange::{ - complete::Complete as CompleteMessage, request::Request, response::Response, +use aries_vcx_core::{ledger::base_ledger::IndyLedgerRead, wallet::base_wallet::BaseWallet}; +use chrono::Utc; +use did_parser::Did; +use did_peer::resolver::PeerDidResolver; +use did_resolver::traits::resolvable::DidResolvable; +use did_resolver_registry::ResolverRegistry; +use helpers::{ + construct_request, did_doc_from_did, oob_invitation_to_diddoc, verify_handshake_protocol, +}; +use messages::{ + decorators::{thread::Thread, timing::Timing}, + msg_fields::protocols::{ + did_exchange::{ + complete::{Complete as CompleteMessage, Complete, CompleteDecorators}, + request::Request, + response::Response, + }, + out_of_band::invitation::Invitation, + }, }; +use url::Url; +use uuid::Uuid; +use super::DidExchangeRequester; use crate::{ - common::ledger::transactions::resolve_oob_invitation, errors::error::{AriesVcxError, AriesVcxErrorKind}, protocols::did_exchange::{ - state_machine::helpers::{ - attach_to_ddo_sov, create_our_did_document, ddo_sov_to_attach, jws_sign_attach, to_transition_error, - }, + state_machine::helpers::{attach_to_ddo_sov, create_our_did_document, to_transition_error}, states::{completed::Completed, requester::request_sent::RequestSent}, transition::{transition_error::TransitionError, transition_result::TransitionResult}, }, }; -use helpers::{construct_complete_message, construct_request, did_doc_from_did, verify_handshake_protocol}; - -use self::config::{ConstructRequestConfig, PairwiseConstructRequestConfig, PublicConstructRequestConfig}; - -use super::DidExchangeRequester; +mod helpers; impl DidExchangeRequester { - async fn construct_request_pairwise( - PairwiseConstructRequestConfig { - wallet, - service_endpoint, - routing_keys, - invitation, - resolver_registry, - }: PairwiseConstructRequestConfig, + pub async fn construct_request_pairwise( + wallet: &impl BaseWallet, + invitation: Invitation, + resolver_registry: Arc, + service_endpoint: Url, + routing_keys: Vec, ) -> Result, AriesVcxError> { verify_handshake_protocol(invitation.clone())?; - let (our_did_document, our_verkey) = create_our_did_document(&wallet, service_endpoint, routing_keys).await?; - let their_did_document = resolve_oob_invitation(&resolver_registry, invitation.clone()).await?; + let (our_did_document, _our_verkey) = + create_our_did_document(wallet, service_endpoint, routing_keys).await?; + let their_did_document = + oob_invitation_to_diddoc(&resolver_registry, invitation.clone()).await?; - let request = construct_request(invitation.id.clone(), our_did_document.id().to_string())?; + let request = construct_request(invitation.id.clone(), our_did_document.id().to_string()); Ok(TransitionResult { state: DidExchangeRequester::from_parts( @@ -55,27 +64,16 @@ impl DidExchangeRequester { }) } - async fn construct_request_public( - PublicConstructRequestConfig { - wallet, - ledger, - their_did, - our_did, - }: PublicConstructRequestConfig, + pub async fn construct_request_public( + ledger: &impl IndyLedgerRead, + their_did: Did, + our_did: Did, ) -> Result, AriesVcxError> { - let (their_did_document, service) = did_doc_from_did(&ledger, their_did.clone()).await?; - let (our_did_document, _) = did_doc_from_did(&ledger, our_did.clone()).await?; - let invitation_id = format!("{}#{}", their_did, service.id().to_string()); + let (their_did_document, service) = did_doc_from_did(ledger, their_did.clone()).await?; + let (our_did_document, _) = did_doc_from_did(ledger, our_did.clone()).await?; + let invitation_id = format!("{}#{}", their_did, service.id()); - let key = our_did_document - .verification_method() - .first() - .ok_or(AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidState, - "No verification method in requester's did document", - ))? - .public_key()?; - let request = construct_request(invitation_id.clone(), our_did.to_string())?; + let request = construct_request(invitation_id.clone(), our_did.to_string()); Ok(TransitionResult { state: DidExchangeRequester::from_parts( @@ -90,19 +88,13 @@ impl DidExchangeRequester { }) } - pub async fn construct_request( - config: ConstructRequestConfig, - ) -> Result, AriesVcxError> { - match config { - ConstructRequestConfig::Pairwise(config) => Self::construct_request_pairwise(config).await, - ConstructRequestConfig::Public(config) => Self::construct_request_public(config).await, - } - } - pub async fn receive_response( self, response: Response, - ) -> Result, CompleteMessage>, TransitionError> { + ) -> Result< + TransitionResult, CompleteMessage>, + TransitionError, + > { if response.decorators.thread.thid != self.state.request_id { return Err(TransitionError { error: AriesVcxError::from_msg( @@ -130,8 +122,20 @@ impl DidExchangeRequester { .to_owned() .into() }; - let complete_message = - construct_complete_message(self.state.invitation_id.clone(), self.state.request_id.clone()); + let decorators = CompleteDecorators::builder() + .thread( + Thread::builder() + .thid(self.state.request_id.clone()) + .pthid(self.state.invitation_id.clone()) + .build(), + ) + .timing(Timing::builder().out_time(Utc::now()).build()) + .build(); + let complete_message = Complete::builder() + .id(Uuid::new_v4().to_string()) + .decorators(decorators) + .build(); + Ok(TransitionResult { state: DidExchangeRequester::from_parts( Completed { diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/responder/mod.rs b/aries_vcx/src/protocols/did_exchange/state_machine/responder/mod.rs index b179de42bb..8357e22c5d 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/responder/mod.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/responder/mod.rs @@ -1,7 +1,5 @@ mod response_sent; -pub use response_sent::config::ReceiveRequestConfig; - use super::DidExchange; #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/config.rs b/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/config.rs deleted file mode 100644 index 9992bea606..0000000000 --- a/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/config.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::sync::Arc; - -use aries_vcx_core::wallet::base_wallet::BaseWallet; -use did_resolver_registry::ResolverRegistry; -use messages::msg_fields::protocols::did_exchange::request::Request; -use public_key::Key; -use url::Url; - -pub struct ReceiveRequestConfig { - pub wallet: Arc, - pub resolver_registry: Arc, - pub request: Request, - pub service_endpoint: Url, - pub routing_keys: Vec, - pub invitation_id: String, - pub invitation_key: Key, -} diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/helpers.rs b/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/helpers.rs deleted file mode 100644 index 8a47ac9b81..0000000000 --- a/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/helpers.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::sync::Arc; - -use did_doc_sov::DidDocumentSov; -use did_resolver_registry::ResolverRegistry; -use messages::{ - decorators::{attachment::Attachment, thread::Thread}, - msg_fields::protocols::did_exchange::{ - request::Request, - response::{Response, ResponseContent, ResponseDecorators}, - }, -}; - -use crate::{errors::error::AriesVcxError, protocols::did_exchange::state_machine::helpers::attach_to_ddo_sov}; - -pub async fn resolve_their_ddo( - resolver_registry: &Arc, - request: &Request, -) -> Result { - Ok(request - .content - .did_doc - .clone() - .map(attach_to_ddo_sov) - .transpose()? - .unwrap_or( - resolver_registry - .resolve(&request.content.did.parse()?, &Default::default()) - .await? - .did_document() - .to_owned() - .into(), - )) -} - -// TODO: Replace by a builder -pub fn construct_response( - our_did_document: DidDocumentSov, - invitation_id: String, - request_id: String, - attachment: Option, -) -> Result { - let content = ResponseContent { - did: our_did_document.id().to_string(), - did_doc: attachment, - }; - let thread = { - let mut thread = Thread::new(request_id.clone()); - thread.pthid = Some(invitation_id.clone()); - thread - }; - let decorators = ResponseDecorators { thread, timing: None }; - Ok(Response::with_decorators(request_id, content, decorators)) -} diff --git a/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/mod.rs b/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/mod.rs index 122adf3c05..d5034f79c4 100644 --- a/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/mod.rs +++ b/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/mod.rs @@ -1,38 +1,46 @@ -use messages::msg_fields::protocols::did_exchange::{complete::Complete, response::Response}; +use std::sync::Arc; +use aries_vcx_core::wallet::base_wallet::BaseWallet; +use chrono::Utc; +use did_doc_sov::DidDocumentSov; +use did_resolver_registry::ResolverRegistry; +use messages::{ + decorators::{thread::Thread, timing::Timing}, + msg_fields::protocols::did_exchange::{ + complete::Complete, + request::Request, + response::{Response, ResponseContent, ResponseDecorators}, + }, +}; +use public_key::Key; +use url::Url; +use uuid::Uuid; + +use super::DidExchangeResponder; use crate::{ errors::error::{AriesVcxError, AriesVcxErrorKind}, protocols::did_exchange::{ - state_machine::helpers::{create_our_did_document, ddo_sov_to_attach, jws_sign_attach}, + state_machine::helpers::{ + attach_to_ddo_sov, create_our_did_document, ddo_sov_to_attach, jws_sign_attach, + }, states::{completed::Completed, responder::response_sent::ResponseSent}, transition::{transition_error::TransitionError, transition_result::TransitionResult}, }, }; -use self::{ - config::ReceiveRequestConfig, - helpers::{construct_response, resolve_their_ddo}, -}; - -use super::DidExchangeResponder; - -pub mod config; -mod helpers; - impl DidExchangeResponder { pub async fn receive_request( - ReceiveRequestConfig { - wallet, - resolver_registry, - request, - service_endpoint, - routing_keys, - invitation_id, - invitation_key, - }: ReceiveRequestConfig, + wallet: &impl BaseWallet, + resolver_registry: Arc, + request: Request, + service_endpoint: Url, + routing_keys: Vec, + invitation_id: String, + invitation_key: Key, ) -> Result, Response>, AriesVcxError> { let their_ddo = resolve_their_ddo(&resolver_registry, &request).await?; - let (our_did_document, _enc_key) = create_our_did_document(&wallet, service_endpoint, routing_keys).await?; + let (our_did_document, _enc_key) = + create_our_did_document(wallet, service_endpoint, routing_keys).await?; if request.decorators.thread.and_then(|t| t.pthid) != Some(invitation_id.clone()) { return Err(AriesVcxError::from_msg( @@ -42,15 +50,31 @@ impl DidExchangeResponder { } // TODO: Response should sign the new *did* with invitation_key only if key was rotated - let signed_attach = - jws_sign_attach(ddo_sov_to_attach(our_did_document.clone())?, invitation_key, &wallet).await?; + let signed_attach = jws_sign_attach( + ddo_sov_to_attach(our_did_document.clone())?, + invitation_key, + wallet, + ) + .await?; - let response = construct_response( - our_did_document.clone(), - invitation_id.clone(), - request.id.clone(), - Some(signed_attach), - )?; + let content = ResponseContent::builder() + .did(our_did_document.id().to_string()) + .did_doc(Some(signed_attach)) + .build(); + let decorators = ResponseDecorators::builder() + .thread( + Thread::builder() + .thid(request.id.clone()) + .pthid(invitation_id.clone()) // todo: do we need to set this in Response? + .build(), + ) + .timing(Timing::builder().out_time(Utc::now()).build()) + .build(); + let response = Response::builder() + .id(Uuid::new_v4().to_string()) + .content(content) + .decorators(decorators) + .build(); Ok(TransitionResult { state: DidExchangeResponder::from_parts( @@ -97,3 +121,23 @@ impl DidExchangeResponder { )) } } + +async fn resolve_their_ddo( + resolver_registry: &Arc, + request: &Request, +) -> Result { + Ok(request + .content + .did_doc + .clone() + .map(attach_to_ddo_sov) + .transpose()? + .unwrap_or( + resolver_registry + .resolve(&request.content.did.parse()?, &Default::default()) + .await? + .did_document() + .to_owned() + .into(), + )) +} diff --git a/aries_vcx/src/protocols/oob/mod.rs b/aries_vcx/src/protocols/oob/mod.rs index d3f509d05b..ac44460650 100644 --- a/aries_vcx/src/protocols/oob/mod.rs +++ b/aries_vcx/src/protocols/oob/mod.rs @@ -1,4 +1,6 @@ +use aries_vcx_core::ledger::base_ledger::IndyLedgerRead; use chrono::Utc; +use diddoc_legacy::aries::{diddoc::AriesDidDoc, service::AriesService}; use messages::{ decorators::{thread::Thread, timing::Timing}, msg_fields::protocols::out_of_band::{ @@ -9,7 +11,13 @@ use messages::{ }; use uuid::Uuid; -use crate::errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}; +use crate::{ + common::ledger::transactions::resolve_service, + errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}, +}; + +const DID_KEY_PREFIX: &str = "did:key:"; +const ED25519_MULTIBASE_CODEC: [u8; 2] = [0xed, 0x01]; pub fn build_handshake_reuse_msg(oob_invitation: &Invitation) -> HandshakeReuse { let id = Uuid::new_v4().to_string(); @@ -56,6 +64,81 @@ pub fn build_handshake_reuse_accepted_msg( .build()) } +pub async fn oob_invitation_to_legacy_did_doc( + indy_ledger: &impl IndyLedgerRead, + invitation: &Invitation, +) -> VcxResult { + let mut did_doc: AriesDidDoc = AriesDidDoc::default(); + let (service_endpoint, recipient_keys, routing_keys) = { + did_doc.set_id(invitation.id.clone()); + let service = resolve_service(indy_ledger, &invitation.content.services[0]) + .await + .unwrap_or_else(|err| { + error!("Failed to obtain service definition from the ledger: {err}"); + AriesService::default() + }); + let recipient_keys = + normalize_keys_as_naked(&service.recipient_keys).unwrap_or_else(|err| { + error!( + "Failed to normalize keys of service {} as naked keys: {err}", + &service + ); + Vec::new() + }); + ( + service.service_endpoint, + recipient_keys, + service.routing_keys, + ) + }; + did_doc.set_service_endpoint(service_endpoint); + did_doc.set_recipient_keys(recipient_keys); + did_doc.set_routing_keys(routing_keys); + Ok(did_doc) +} + +fn normalize_keys_as_naked(keys_list: &Vec) -> VcxResult> { + let mut result = Vec::new(); + for key in keys_list { + if let Some(stripped_didkey) = key.strip_prefix(DID_KEY_PREFIX) { + let stripped = if let Some(stripped) = stripped_didkey.strip_prefix('z') { + stripped + } else { + Err(AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidDid, + format!("z prefix is missing: {}", key), + ))? + }; + let decoded_value = bs58::decode(stripped).into_vec().map_err(|_| { + AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidDid, + format!( + "Could not decode base58: {} as portion of {}", + stripped, key + ), + ) + })?; + let verkey = if let Some(public_key_bytes) = + decoded_value.strip_prefix(&ED25519_MULTIBASE_CODEC) + { + Ok(bs58::encode(public_key_bytes).into_string()) + } else { + Err(AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidDid, + format!( + "Only Ed25519-based did:keys are currently supported, got key: {}", + key + ), + )) + }?; + result.push(verkey); + } else { + result.push(key.clone()); + } + } + Ok(result) +} + // #[cfg(test)] // mod unit_tests { // use crate::protocols::oob::{build_handshake_reuse_accepted_msg, build_handshake_reuse_msg}; diff --git a/aries_vcx/src/utils/mod.rs b/aries_vcx/src/utils/mod.rs index 155ce0e307..a4cdd20271 100644 --- a/aries_vcx/src/utils/mod.rs +++ b/aries_vcx/src/utils/mod.rs @@ -1,19 +1,14 @@ -use aries_vcx_core::wallet::base_wallet::BaseWallet; -use diddoc_legacy::aries::diddoc::AriesDidDoc; use did_doc::schema::verification_method::{VerificationMethod, VerificationMethodType}; -use did_doc_sov::extra_fields::didcommv1::ExtraFieldsDidCommV1; -use did_doc_sov::extra_fields::KeyKind; -use did_doc_sov::service::didcommv1::ServiceDidCommV1; -use did_doc_sov::service::ServiceSov; -use did_doc_sov::DidDocumentSov; +use did_doc_sov::{ + extra_fields::{didcommv1::ExtraFieldsDidCommV1, KeyKind}, + service::{didcommv1::ServiceDidCommV1, ServiceSov}, + DidDocumentSov, +}; use did_key::DidKey; use did_parser::Did; -use diddoc_legacy::aries::service::AriesService; -use crate::errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}; +use diddoc_legacy::aries::{diddoc::AriesDidDoc, service::AriesService}; -#[macro_use] -#[cfg(feature = "vdrtools")] -pub mod devsetup; +use crate::errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}; #[cfg(debug_assertions)] #[macro_export] @@ -31,19 +26,6 @@ macro_rules! secret { }}; } -#[cfg(test)] -macro_rules! map ( - { $($key:expr => $value:expr),+ } => { - { - let mut m = std::collections::HashMap::new(); - $( - m.insert($key, $value); - )+ - m - } - }; -); - pub mod openssl; pub mod qualifier; @@ -52,17 +34,22 @@ pub mod encryption_envelope; pub mod serialization; pub mod validation; - -// TODO: Get rid of this please!!! +// TODO: Get rid of this, migrate off the legacy diddoc pub fn from_did_doc_sov_to_legacy(ddo: DidDocumentSov) -> VcxResult { - let mut new_ddo = AriesDidDoc::default(); - new_ddo.id = ddo.id().to_string(); + let mut new_ddo = AriesDidDoc { + id: ddo.id().to_string(), + ..Default::default() + }; new_ddo.set_service_endpoint( ddo.service() .first() - .ok_or_else(|| AriesVcxError::from_msg(AriesVcxErrorKind::InvalidState, "No service present in DDO"))? + .ok_or_else(|| { + AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidState, + "No service present in DDO", + ) + })? .service_endpoint() - .clone() .into(), ); let mut recipient_keys = vec![]; @@ -93,7 +80,7 @@ pub fn from_legacy_did_doc_to_sov(ddo: AriesDidDoc) -> VcxResult did.clone(), VerificationMethodType::Ed25519VerificationKey2020, ) - .add_public_key_base58( + .add_public_key_base58( ddo.recipient_keys()? .first() .ok_or_else(|| { @@ -104,17 +91,20 @@ pub fn from_legacy_did_doc_to_sov(ddo: AriesDidDoc) -> VcxResult })? .to_string(), ) - .build(); + .build(); let new_ddo = DidDocumentSov::builder(did.clone()) .add_service(from_legacy_service_to_service_sov( ddo.service .first() .ok_or_else(|| { - AriesVcxError::from_msg(AriesVcxErrorKind::InvalidState, "No service in the DDO being converted") + AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidState, + "No service in the DDO being converted", + ) })? .clone(), )?) - .add_controller(did.clone()) + .add_controller(did) .add_verification_method(vm) .build(); Ok(new_ddo) @@ -160,34 +150,66 @@ pub fn from_legacy_service_to_service_sov(service: AriesService) -> VcxResult AriesService { + info!( + "Converting AnyService to expanded AriesService: {:?}", + service + ); match service { ServiceSov::AIP1(service) => AriesService { id: service.id().to_string(), - service_endpoint: service.service_endpoint().clone().into(), + service_endpoint: service.service_endpoint().into(), ..Default::default() }, ServiceSov::DIDCommV1(service) => { let extra = service.extra(); - let recipient_keys = extra.recipient_keys().iter().map(|key| key.to_string()).collect(); - let routing_keys = extra.routing_keys().iter().map(|key| key.to_string()).collect(); + let recipient_keys = extra + .recipient_keys() + .iter() + .map(|key| key.to_string()) + .collect(); + let routing_keys = extra + .routing_keys() + .iter() + .map(|key| key.to_string()) + .collect(); AriesService { id: service.id().to_string(), recipient_keys, routing_keys, - service_endpoint: service.service_endpoint().clone().into(), + service_endpoint: service.service_endpoint().into(), ..Default::default() } } ServiceSov::DIDCommV2(service) => { let extra = service.extra(); - let routing_keys = extra.routing_keys().iter().map(|key| key.to_string()).collect(); + let routing_keys = extra + .routing_keys() + .iter() + .map(|key| key.to_string()) + .collect(); AriesService { id: service.id().to_string(), routing_keys, - service_endpoint: service.service_endpoint().clone().into(), + service_endpoint: service.service_endpoint().into(), ..Default::default() } } - ServiceSov::Legacy(_) => todo!(), + ServiceSov::Legacy(service) => AriesService { + id: service.id().to_string(), + recipient_keys: service + .extra() + .recipient_keys() + .iter() + .map(|key| key.to_string()) + .collect(), + routing_keys: service + .extra() + .routing_keys() + .iter() + .map(|key| key.to_string()) + .collect(), + service_endpoint: service.service_endpoint().into(), + ..Default::default() + }, } } diff --git a/aries_vcx/tests/fixtures/mod.rs b/aries_vcx/tests/fixtures/mod.rs deleted file mode 100644 index dd30d2323b..0000000000 --- a/aries_vcx/tests/fixtures/mod.rs +++ /dev/null @@ -1,84 +0,0 @@ -pub static OOB_INVITE: &str = r##" -{ - "@type": "https://didcomm.org/out-of-band/1.1/invitation", - "@id": "032fbd19-f6fd-48c5-9197-ba9a47040470", - "label": "Faber College", - "goal_code": "issue-vc", - "goal": "To issue a Faber College Graduate credential", - "accept": [ - "didcomm/aip2;env=rfc587", - "didcomm/aip2;env=rfc19" - ], - "handshake_protocols": [ - "https://didcomm.org/didexchange/1.0", - "https://didcomm.org/connections/1.0" - ], - "requests~attach": [], - "services": ["did:peer:2.Ez6LSpSrLxbAhg2SHwKk7kwpsH7DM7QjFS5iK6qP87eViohud.Vz6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V"] -} -"##; - -pub static REQUEST: &str = r##" -{ - "@id": "a46cdd0f-a2ca-4d12-afbf-2e78a6f1f3ef", - "@type": "https://didcomm.org/didexchange/1.0/request", - "~thread": { - "thid": "a46cdd0f-a2ca-4d12-afbf-2e78a6f1f3ef", - "pthid": "032fbd19-f6fd-48c5-9197-ba9a47040470" - }, - "label": "Bob", - "goal_code": "aries.rel.build", - "goal": "To create a relationship", - "did": "B.did@B:A", - "did_doc~attach": { - "@id": "d2ab6f2b-5646-4de3-8c02-762f553ab804", - "mime-type": "application/json", - "data": { - "base64": "eyJ0eXAiOiJKV1Qi... (bytes omitted)", - "jws": { - "header": { - "kid": "did:key:z6MkmjY8GnV5i9YTDtPETC2uUAW6ejw3nk5mXF5yci5ab7th" - }, - "protected": "eyJhbGciOiJFZERTQSIsImlhdCI6MTU4Mzg4... (bytes omitted)", - "signature": "3dZWsuru7QAVFUCtTd0s7uc1peYEijx4eyt5... (bytes omitted)" - } - } - } -} -"##; - -pub static RESPONSE: &str = r##" -{ - "@type": "https://didcomm.org/didexchange/1.0/response", - "@id": "12345678900987654321", - "~thread": { - "thid": "" - }, - "did": "B.did@B:A", - "did_doc~attach": { - "@id": "d2ab6f2b-5646-4de3-8c02-762f553ab804", - "mime-type": "application/json", - "data": { - "base64": "eyJ0eXAiOiJKV1Qi... (bytes omitted)", - "jws": { - "header": { - "kid": "did:key:z6MkmjY8GnV5i9YTDtPETC2uUAW6ejw3nk5mXF5yci5ab7th" - }, - "protected": "eyJhbGciOiJFZERTQSIsImlhdCI6MTU4Mzg4... (bytes omitted)", - "signature": "3dZWsuru7QAVFUCtTd0s7uc1peYEijx4eyt5... (bytes omitted)" - } - } - } -} -"##; - -pub static COMPLETE: &str = r##" -{ - "@type": "https://didcomm.org/didexchange/1.0/complete", - "@id": "12345678900987654321", - "~thread": { - "thid": "", - "pthid": "" - } -} -"##; diff --git a/aries_vcx/tests/test_did_exchange.rs b/aries_vcx/tests/test_did_exchange.rs index fa9f09eb97..0703f744df 100644 --- a/aries_vcx/tests/test_did_exchange.rs +++ b/aries_vcx/tests/test_did_exchange.rs @@ -1,163 +1,157 @@ -#[macro_use] extern crate log; -mod fixtures; -mod utils; use std::sync::Arc; -use aries_vcx::handlers::out_of_band::sender::OutOfBandSender; -use aries_vcx::protocols::did_exchange::resolve_key_from_invitation; -use aries_vcx::protocols::did_exchange::state_machine::generate_keypair; -use aries_vcx::protocols::did_exchange::state_machine::requester::{ - ConstructRequestConfig, DidExchangeRequester, PairwiseConstructRequestConfig, +use aries_vcx::{ + handlers::out_of_band::sender::OutOfBandSender, + protocols::did_exchange::{ + resolve_key_from_invitation, + state_machine::{ + generate_keypair, requester::DidExchangeRequester, responder::DidExchangeResponder, + }, + states::{requester::request_sent::RequestSent, responder::response_sent::ResponseSent}, + transition::transition_result::TransitionResult, + }, }; -use aries_vcx::protocols::did_exchange::state_machine::responder::{DidExchangeResponder, ReceiveRequestConfig}; -use aries_vcx::protocols::did_exchange::states::requester::request_sent::RequestSent; -use aries_vcx::protocols::did_exchange::states::responder::response_sent::ResponseSent; -use aries_vcx::protocols::did_exchange::transition::transition_result::TransitionResult; -use aries_vcx::utils::devsetup::SetupPoolDirectory; -use did_doc::schema::verification_method::{PublicKeyField, VerificationMethodType}; -use did_doc_sov::extra_fields::didcommv1::ExtraFieldsDidCommV1; -use did_doc_sov::extra_fields::didcommv2::ExtraFieldsDidCommV2; -use did_doc_sov::extra_fields::KeyKind; -use did_doc_sov::service::didcommv1::ServiceDidCommV1; -use did_doc_sov::service::didcommv2::ServiceDidCommV2; -use did_doc_sov::service::ServiceSov; -use did_peer::peer_did_resolver::resolver::PeerDidResolver; +use did_doc_sov::{ + extra_fields::{didcommv1::ExtraFieldsDidCommV1, KeyKind}, + service::{didcommv1::ServiceDidCommV1, ServiceSov}, +}; +use did_peer::resolver::PeerDidResolver; use did_resolver_registry::ResolverRegistry; -use messages::msg_fields::protocols::out_of_band::invitation::{Invitation, OobService}; -use messages::msg_types::protocols::did_exchange::{DidExchangeType, DidExchangeTypeV1}; -use messages::msg_types::Protocol; +use messages::{ + msg_fields::protocols::out_of_band::invitation::OobService, + msg_types::{ + protocols::did_exchange::{DidExchangeType, DidExchangeTypeV1}, + Protocol, + }, +}; use public_key::KeyType; +use test_utils::devsetup::SetupPoolDirectory; use url::Url; use uuid::Uuid; -use crate::utils::devsetup_alice::create_alice; -use crate::utils::devsetup_faber::create_faber; +use crate::utils::test_agent::{create_test_agent, create_test_agent_trustee}; + +pub mod utils; #[tokio::test] #[ignore] async fn did_exchange_test() { - SetupPoolDirectory::run(|setup| async move { - let institution = create_faber(setup.genesis_file_path.clone()).await; - let consumer = create_alice(setup.genesis_file_path).await; - - let did_peer_resolver = PeerDidResolver::new(); - let resolver_registry = Arc::new( - ResolverRegistry::new().register_resolver::("peer".into(), did_peer_resolver.into()), - ); - - let url: Url = "http://dummyurl.org".parse().unwrap(); + let setup = SetupPoolDirectory::init().await; + let institution = create_test_agent_trustee(setup.genesis_file_path.clone()).await; + let consumer = create_test_agent(setup.genesis_file_path).await; - let public_key = generate_keypair(&institution.profile.inject_wallet(), KeyType::Ed25519) - .await - .unwrap(); - let service = { - let service_id = Uuid::new_v4().to_string(); - ServiceSov::DIDCommV1( - ServiceDidCommV1::new( - service_id.parse().unwrap(), - url.clone().into(), - ExtraFieldsDidCommV1::builder() - .set_recipient_keys(vec![KeyKind::DidKey(public_key.try_into().unwrap())]) - .build(), - ) - .unwrap(), - ) - }; - let invitation = OutOfBandSender::create() - .append_service(&OobService::SovService(service)) - .append_handshake_protocol(Protocol::DidExchangeType(DidExchangeType::V1( - DidExchangeTypeV1::new_v1_0(), - ))) - .unwrap() - .oob - .clone(); + let did_peer_resolver = PeerDidResolver::new(); + let resolver_registry = Arc::new( + ResolverRegistry::new() + .register_resolver::("peer".into(), did_peer_resolver), + ); - let invitation_id = invitation.id.clone(); - let invitation_key = resolve_key_from_invitation(&invitation, &resolver_registry) - .await - .unwrap(); + let url: Url = "http://dummyurl.org".parse().unwrap(); - let TransitionResult { - state: requester, - output: request, - } = DidExchangeRequester::::construct_request(ConstructRequestConfig::Pairwise( - PairwiseConstructRequestConfig { - wallet: consumer.profile.inject_wallet(), - invitation, - service_endpoint: url.clone(), - routing_keys: vec![], - resolver_registry: resolver_registry.clone(), - }, - )) + let public_key = generate_keypair(&institution.wallet, KeyType::Ed25519) .await .unwrap(); + let service = { + let service_id = Uuid::new_v4().to_string(); + ServiceSov::DIDCommV1( + ServiceDidCommV1::new( + service_id.parse().unwrap(), + url.clone().into(), + ExtraFieldsDidCommV1::builder() + .set_recipient_keys(vec![KeyKind::DidKey(public_key.try_into().unwrap())]) + .build(), + ) + .unwrap(), + ) + }; + let invitation = OutOfBandSender::create() + .append_service(&OobService::SovService(service)) + .append_handshake_protocol(Protocol::DidExchangeType(DidExchangeType::V1( + DidExchangeTypeV1::new_v1_0(), + ))) + .unwrap() + .oob + .clone(); - let extra = ExtraFieldsDidCommV2::builder().build(); - let service = - ServiceSov::DIDCommV2(ServiceDidCommV2::new(Default::default(), url.clone().into(), extra).unwrap()); - let TransitionResult { - state: responder, - output: response, - } = DidExchangeResponder::::receive_request(ReceiveRequestConfig { - wallet: institution.profile.inject_wallet(), - resolver_registry, - request, - service_endpoint: url.clone(), - routing_keys: vec![], - invitation_id, - invitation_key, - }) + let invitation_id = invitation.id.clone(); + let invitation_key = resolve_key_from_invitation(&invitation, &resolver_registry) .await .unwrap(); - let TransitionResult { - state: requester, - output: complete, - } = requester.receive_response(response).await.unwrap(); + let TransitionResult { + state: requester, + output: request, + } = DidExchangeRequester::::construct_request_pairwise( + &consumer.wallet, + invitation, + resolver_registry.clone(), + url.clone(), + vec![], + ) + .await + .unwrap(); + + let TransitionResult { + state: responder, + output: response, + } = DidExchangeResponder::::receive_request( + &institution.wallet, + resolver_registry, + request, + url.clone(), + vec![], + invitation_id, + invitation_key, + ) + .await + .unwrap(); + + let TransitionResult { + state: requester, + output: complete, + } = requester.receive_response(response).await.unwrap(); - let responder = responder.receive_complete(complete).unwrap(); + let responder = responder.receive_complete(complete).unwrap(); - let responder_key = responder - .our_did_doc() + let responder_key = responder + .our_did_doc() + .verification_method() + .first() + .unwrap() + .public_key() + .unwrap() + .base58(); + assert_eq!( + requester + .their_did_doc() .verification_method() .first() .unwrap() .public_key() .unwrap() - .base58(); - assert_eq!( - requester - .their_did_doc() - .verification_method() - .first() - .unwrap() - .public_key() - .unwrap() - .base58(), - responder_key - ); + .base58(), + responder_key + ); - let requester_key = requester - .our_did_doc() + let requester_key = requester + .our_did_doc() + .verification_method() + .first() + .unwrap() + .public_key() + .unwrap() + .base58(); + assert_eq!( + responder + .their_did_doc() .verification_method() .first() .unwrap() .public_key() .unwrap() - .base58(); - assert_eq!( - responder - .their_did_doc() - .verification_method() - .first() - .unwrap() - .public_key() - .unwrap() - .base58(), - requester_key - ); - }) - .await; + .base58(), + requester_key + ); } diff --git a/aries_vcx/tests/test_pool.rs b/aries_vcx/tests/test_pool.rs index aee0a59ee9..e20f093139 100644 --- a/aries_vcx/tests/test_pool.rs +++ b/aries_vcx/tests/test_pool.rs @@ -290,6 +290,7 @@ async fn test_pool_multiple_service_formats() -> Result<(), Box> { .set_recipient_keys(vec!["did:sov:123".into()]) .set_routing_keys(vec!["did:sov:456".into()]); write_endpoint_legacy(&setup.wallet, &setup.ledger_write, &did, &service_1).await?; + thread::sleep(Duration::from_millis(50)); // Get service and verify it is in the old format let service = get_service(&setup.ledger_read, &did).await?; @@ -302,7 +303,6 @@ async fn test_pool_multiple_service_formats() -> Result<(), Box> { .set_service_endpoint(endpoint_url_2.parse()?) .set_routing_keys(Some(routing_keys_2.clone())); write_endpoint(&setup.wallet, &setup.ledger_write, &did, &service_2).await?; - thread::sleep(Duration::from_millis(50)); // Get service and verify it is in the new format diff --git a/aries_vcx/tests/utils/mod.rs b/aries_vcx/tests/utils/mod.rs index ee9c8e0e90..fb9ff8cd11 100644 --- a/aries_vcx/tests/utils/mod.rs +++ b/aries_vcx/tests/utils/mod.rs @@ -1,7 +1,5 @@ pub mod scenarios; pub mod test_agent; -pub mod test_macros; - use std::time::Duration; use aries_vcx::{ diff --git a/aries_vcx/tests/utils/scenarios/connection.rs b/aries_vcx/tests/utils/scenarios/connection.rs index c039c24a79..bbe3b50602 100644 --- a/aries_vcx/tests/utils/scenarios/connection.rs +++ b/aries_vcx/tests/utils/scenarios/connection.rs @@ -1,9 +1,8 @@ use aries_vcx::{ - common::ledger::transactions::into_did_doc, errors::error::VcxResult, handlers::{out_of_band::sender::OutOfBandSender, util::AnyInvitation}, protocols::{ - connection::{Connection, GenericConnection}, + connection::{invitee::any_invitation_into_did_doc, Connection, GenericConnection}, mediated_connection::pairwise_info::PairwiseInfo, }, transport::Transport, @@ -114,7 +113,9 @@ pub async fn create_connections_via_oob_invite( ))) .unwrap(); let invitation = AnyInvitation::Oob(oob_sender.oob.clone()); - let ddo = into_did_doc(&alice.ledger_read, &invitation).await.unwrap(); + let ddo = any_invitation_into_did_doc(&alice.ledger_read, &invitation) + .await + .unwrap(); // TODO: Create a key and write on ledger instead let inviter_pairwise_info = PairwiseInfo { pw_did: ddo.clone().id, @@ -148,7 +149,7 @@ pub async fn create_connections_via_public_invite( .content(content) .build(), ); - let ddo = into_did_doc(&alice.ledger_read, &public_invite) + let ddo = any_invitation_into_did_doc(&alice.ledger_read, &public_invite) .await .unwrap(); // TODO: Create a key and write on ledger instead diff --git a/aries_vcx/tests/utils/scenarios/proof_presentation.rs b/aries_vcx/tests/utils/scenarios/proof_presentation.rs index 8d07ffc2de..903bee8d65 100644 --- a/aries_vcx/tests/utils/scenarios/proof_presentation.rs +++ b/aries_vcx/tests/utils/scenarios/proof_presentation.rs @@ -260,6 +260,7 @@ pub async fn revoke_credential_and_publish_accumulator( .unwrap(); } +// todo: inline this pub async fn revoke_credential_local( faber: &mut TestAgent< impl IndyLedgerRead + AnoncredsLedgerRead, @@ -268,26 +269,12 @@ pub async fn revoke_credential_local( impl BaseWallet, >, issuer_credential: &Issuer, - rev_reg_id: &str, + _rev_reg_id: &str, ) { - let ledger = &faber.ledger_read; - let (_, delta, timestamp) = ledger - .get_rev_reg_delta_json(rev_reg_id, None, None) - .await - .unwrap(); - issuer_credential .revoke_credential_local(&faber.wallet, &faber.anoncreds) .await .unwrap(); - - let (_, delta_after_revoke, _) = ledger - .get_rev_reg_delta_json(rev_reg_id, Some(timestamp + 1), None) - .await - .unwrap(); - - assert_ne!(delta, delta_after_revoke); // They will not equal as we have saved the delta in - // cache } pub async fn rotate_rev_reg( diff --git a/aries_vcx/tests/utils/test_macros.rs b/aries_vcx/tests/utils/test_macros.rs deleted file mode 100644 index a2a2211fcb..0000000000 --- a/aries_vcx/tests/utils/test_macros.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::fmt; - -use aries_vcx::handlers::util::Status; - -macro_rules! enum_number { - ($name:ident { $($variant:ident = $value:expr, )* }) => { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - pub enum $name { - $($variant = $value,)* - } - - impl ::serde::Serialize for $name { - fn serialize(&self, serializer: S) -> Result - where S: ::serde::Serializer - { - // Serialize the enum as a u64. - serializer.serialize_u64(*self as u64) - } - } - - impl<'de> ::serde::Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result - where D: ::serde::Deserializer<'de> - { - struct Visitor; - - impl<'de> ::serde::de::Visitor<'de> for Visitor { - type Value = $name; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("positive integer") - } - - fn visit_u64(self, value: u64) -> Result<$name, E> - where E: ::serde::de::Error - { - // Rust does not come with a simple way of converting a - // number to an enum, so use a big `match`. - match value { - $( $value => Ok($name::$variant), )* - _ => Err(E::custom( - format!("unknown {} value: {}", - stringify!($name), value))), - } - } - } - - // Deserialize the enum from a u64. - deserializer.deserialize_u64(Visitor) - } - } - } -} - -enum_number!(ProofStateType -{ - ProofUndefined = 0, - ProofValidated = 1, - ProofInvalid = 2, -}); - -impl From for ProofStateType { - fn from(state: Status) -> Self { - match state { - Status::Success => ProofStateType::ProofValidated, - Status::Failed(_) => ProofStateType::ProofInvalid, - _ => ProofStateType::ProofUndefined, - } - } -} diff --git a/aries_vcx_core/src/ledger/indy_vdr_ledger.rs b/aries_vcx_core/src/ledger/indy_vdr_ledger.rs index 7b192bdd4c..bf2216962a 100644 --- a/aries_vcx_core/src/ledger/indy_vdr_ledger.rs +++ b/aries_vcx_core/src/ledger/indy_vdr_ledger.rs @@ -695,6 +695,7 @@ pub fn indyvdr_build_ledger_write( IndyVdrLedgerWrite::new(config_write) } +#[derive(Clone)] pub struct VcxPoolConfig { pub genesis_file_path: String, pub indy_vdr_config: Option, diff --git a/did_doc_sov/src/legacy/mod.rs b/did_doc_sov/src/legacy/mod.rs index 19bc5b46d9..96a4a742e3 100644 --- a/did_doc_sov/src/legacy/mod.rs +++ b/did_doc_sov/src/legacy/mod.rs @@ -201,7 +201,6 @@ where D: Deserializer<'de>, { let val = Value::deserialize(deserializer)?; - match serde_json::from_value::(val.clone()) { Ok(legacy_doc) => { Ok(convert_legacy_ddo_to_new(legacy_doc).map_err(serde::de::Error::custom)?) diff --git a/did_doc_sov/src/lib.rs b/did_doc_sov/src/lib.rs index 78dacd43ef..ed9db72ba6 100644 --- a/did_doc_sov/src/lib.rs +++ b/did_doc_sov/src/lib.rs @@ -61,11 +61,14 @@ impl DidDocumentSov { self.did_doc.key_agreement() } - pub fn resolved_key_agreement<'a>(&'a self) -> impl Iterator + 'a { - self.did_doc.key_agreement().iter().filter_map(|vm| match vm { - VerificationMethodKind::Resolved(resolved) => Some(resolved), - VerificationMethodKind::Resolvable(reference) => self.dereference_key(reference), - }) + pub fn resolved_key_agreement(&self) -> impl Iterator { + self.did_doc + .key_agreement() + .iter() + .filter_map(|vm| match vm { + VerificationMethodKind::Resolved(resolved) => Some(resolved), + VerificationMethodKind::Resolvable(reference) => self.dereference_key(reference), + }) } pub fn capability_invocation(&self) -> &[VerificationMethodKind] { diff --git a/did_doc_sov/src/service/aip1.rs b/did_doc_sov/src/service/aip1.rs index be46f7c653..c980382ba9 100644 --- a/did_doc_sov/src/service/aip1.rs +++ b/did_doc_sov/src/service/aip1.rs @@ -41,8 +41,8 @@ impl ServiceAIP1 { ServiceType::AIP1 } - pub fn service_endpoint(&self) -> &Url { - self.service.service_endpoint() + pub fn service_endpoint(&self) -> Url { + self.service.service_endpoint().clone() } pub fn extra(&self) -> &ExtraFieldsAIP1 { diff --git a/did_doc_sov/src/service/didcommv1.rs b/did_doc_sov/src/service/didcommv1.rs index f3ffb14195..735f0c743e 100644 --- a/did_doc_sov/src/service/didcommv1.rs +++ b/did_doc_sov/src/service/didcommv1.rs @@ -41,8 +41,8 @@ impl ServiceDidCommV1 { ServiceType::DIDCommV1 } - pub fn service_endpoint(&self) -> &Url { - self.service.service_endpoint() + pub fn service_endpoint(&self) -> Url { + self.service.service_endpoint().clone() } pub fn extra(&self) -> &ExtraFieldsDidCommV1 { diff --git a/did_doc_sov/src/service/didcommv2.rs b/did_doc_sov/src/service/didcommv2.rs index a1e947e387..06c62f94d6 100644 --- a/did_doc_sov/src/service/didcommv2.rs +++ b/did_doc_sov/src/service/didcommv2.rs @@ -41,8 +41,8 @@ impl ServiceDidCommV2 { ServiceType::DIDCommV2 } - pub fn service_endpoint(&self) -> &Url { - self.service.service_endpoint() + pub fn service_endpoint(&self) -> Url { + self.service.service_endpoint().clone() } pub fn extra(&self) -> &ExtraFieldsDidCommV2 { diff --git a/did_doc_sov/src/service/legacy.rs b/did_doc_sov/src/service/legacy.rs index f638ef7cbc..f0a989a5e7 100644 --- a/did_doc_sov/src/service/legacy.rs +++ b/did_doc_sov/src/service/legacy.rs @@ -44,8 +44,8 @@ impl ServiceLegacy { ServiceType::Legacy } - pub fn service_endpoint(&self) -> &Url { - &self.service_endpoint + pub fn service_endpoint(&self) -> Url { + self.service_endpoint.clone() } pub fn extra(&self) -> &ExtraFieldsLegacy { diff --git a/did_doc_sov/src/service/mod.rs b/did_doc_sov/src/service/mod.rs index 1b18c83229..a6d25349bd 100644 --- a/did_doc_sov/src/service/mod.rs +++ b/did_doc_sov/src/service/mod.rs @@ -72,7 +72,7 @@ impl ServiceSov { } } - pub fn service_endpoint(&self) -> &Url { + pub fn service_endpoint(&self) -> Url { match self { ServiceSov::AIP1(service) => service.service_endpoint(), ServiceSov::DIDCommV1(service) => service.service_endpoint(), @@ -129,28 +129,28 @@ impl TryFrom for Service { match service { ServiceSov::AIP1(service) => Ok(Service::builder( service.id().clone(), - service.service_endpoint().clone(), + service.service_endpoint(), ExtraFieldsSov::AIP1(service.extra().to_owned()), ) .add_service_type(service.service_type().to_string())? .build()), ServiceSov::DIDCommV1(service) => Ok(Service::builder( service.id().clone(), - service.service_endpoint().clone(), + service.service_endpoint(), ExtraFieldsSov::DIDCommV1(service.extra().to_owned()), ) .add_service_type(service.service_type().to_string())? .build()), ServiceSov::DIDCommV2(service) => Ok(Service::builder( service.id().clone(), - service.service_endpoint().clone(), + service.service_endpoint(), ExtraFieldsSov::DIDCommV2(service.extra().to_owned()), ) .add_service_type(service.service_type().to_string())? .build()), ServiceSov::Legacy(service) => Ok(Service::builder( service.id().clone(), - service.service_endpoint().clone(), + service.service_endpoint(), ExtraFieldsSov::Legacy(service.extra().to_owned()), ) .add_service_type(service.service_type().to_string())? diff --git a/did_doc_sov/tests/builder.rs b/did_doc_sov/tests/builder.rs index 37cc6bbdf2..57ec1e86e0 100644 --- a/did_doc_sov/tests/builder.rs +++ b/did_doc_sov/tests/builder.rs @@ -29,7 +29,7 @@ fn test_service_build_aip1() { let first_service = services.get(0).unwrap(); assert_eq!(first_service.id().clone(), ID.parse::().unwrap()); assert_eq!( - first_service.service_endpoint().clone(), + first_service.service_endpoint(), SERVICE_ENDPOINT.parse::().unwrap() ); let first_extra = first_service.extra(); @@ -59,7 +59,7 @@ fn test_service_build_didcommv1() { let first_service = services.get(0).unwrap(); assert_eq!(first_service.id().clone(), ID.parse::().unwrap()); assert_eq!( - first_service.service_endpoint().clone(), + first_service.service_endpoint(), SERVICE_ENDPOINT.parse::().unwrap() ); let first_extra = first_service.extra(); @@ -93,7 +93,7 @@ fn test_service_build_didcommv2() { let first_service = services.get(0).unwrap(); assert_eq!(first_service.id().clone(), ID.parse::().unwrap()); assert_eq!( - first_service.service_endpoint().clone(), + first_service.service_endpoint(), SERVICE_ENDPOINT.parse::().unwrap() ); let first_extra = first_service.extra(); diff --git a/did_doc_sov/tests/serde_legacy.rs b/did_doc_sov/tests/serde_legacy.rs index 6f17ea3fc4..e3bcdca794 100644 --- a/did_doc_sov/tests/serde_legacy.rs +++ b/did_doc_sov/tests/serde_legacy.rs @@ -2,7 +2,6 @@ use did_doc_sov::{extra_fields::KeyKind, DidDocumentSov}; const LEGACY_DID_DOC_JSON: &str = r#" { - "@context": "https://w3id.org/did/v1", "id": "2ZHFFhzA2XtTD6hJqzL7ux", "publicKey": [ { diff --git a/did_peer/src/resolver/mod.rs b/did_peer/src/resolver/mod.rs index 17ee58c9aa..04cc37b1d7 100644 --- a/did_peer/src/resolver/mod.rs +++ b/did_peer/src/resolver/mod.rs @@ -17,8 +17,15 @@ use crate::{ pub mod options; +#[derive(Default)] pub struct PeerDidResolver; +impl PeerDidResolver { + pub fn new() -> Self { + Self + } +} + #[async_trait] impl DidResolvable for PeerDidResolver { type ExtraFieldsService = ExtraFieldsSov; diff --git a/did_resolver_sov/src/dereferencing/dereferencer.rs b/did_resolver_sov/src/dereferencing/dereferencer.rs index 1494a39951..dcd85f07e0 100644 --- a/did_resolver_sov/src/dereferencing/dereferencer.rs +++ b/did_resolver_sov/src/dereferencing/dereferencer.rs @@ -1,4 +1,4 @@ -use std::io::Cursor; +use std::{borrow::Borrow, io::Cursor}; use async_trait::async_trait; use did_resolver::{ @@ -17,7 +17,11 @@ use super::utils::dereference_did_document; use crate::{reader::AttrReader, resolution::DidSovResolver}; #[async_trait] -impl<'a, T: AttrReader> DidDereferenceable for DidSovResolver<'a, T> { +impl DidDereferenceable for DidSovResolver +where + T: Borrow + Sync + Send, + A: AttrReader, +{ type Output = Cursor>; async fn dereference( diff --git a/did_resolver_sov/src/resolution/resolver.rs b/did_resolver_sov/src/resolution/resolver.rs index 2dda4adc70..cfdd1fb6a7 100644 --- a/did_resolver_sov/src/resolution/resolver.rs +++ b/did_resolver_sov/src/resolution/resolver.rs @@ -1,3 +1,5 @@ +use std::{borrow::Borrow, marker::PhantomData}; + use async_trait::async_trait; use did_doc_sov::extra_fields::ExtraFieldsSov; use did_resolver::{ @@ -17,18 +19,37 @@ use crate::{ reader::AttrReader, }; -pub struct DidSovResolver<'a, T: AttrReader> { - ledger: &'a T, +pub struct DidSovResolver +where + T: Borrow + Sync + Send, + A: AttrReader, +{ + ledger: T, + _marker: PhantomData, } -impl<'a, T: AttrReader> DidSovResolver<'a, T> { - pub fn new(ledger: &'a T) -> Self { - DidSovResolver { ledger } +impl DidSovResolver +where + T: Borrow + Sync + Send, + A: AttrReader, +{ + // todo: Creating instance can be non-ergonomic, as compiler will ask you to specify + // the full type of DidSovResolver explicitly, and the type can be quite long. + // Consider improving the DX in the future. + pub fn new(ledger: T) -> Self { + DidSovResolver { + ledger, + _marker: PhantomData, + } } } #[async_trait] -impl<'a, T: AttrReader> DidResolvable for DidSovResolver<'a, T> { +impl DidResolvable for DidSovResolver +where + T: Borrow + Sync + Send, + A: AttrReader, +{ type ExtraFieldsService = ExtraFieldsSov; type ExtraFieldsOptions = (); @@ -58,7 +79,7 @@ impl<'a, T: AttrReader> DidResolvable for DidSovResolver<'a, T> { ))); } let did = parsed_did.did(); - let ledger_response = self.ledger.get_attr(did, "endpoint").await?; + let ledger_response = self.ledger.borrow().get_attr(did, "endpoint").await?; let verkey = self.get_verkey(did).await?; ledger_response_to_ddo(did, &ledger_response, verkey) .await @@ -66,9 +87,13 @@ impl<'a, T: AttrReader> DidResolvable for DidSovResolver<'a, T> { } } -impl<'a, T: AttrReader> DidSovResolver<'a, T> { +impl DidSovResolver +where + T: Borrow + Sync + Send, + A: AttrReader, +{ async fn get_verkey(&self, did: &str) -> Result { - let nym_response = self.ledger.get_nym(did).await?; + let nym_response = self.ledger.borrow().get_nym(did).await?; let nym_json: Value = serde_json::from_str(&nym_response)?; let nym_data = nym_json["result"]["data"] .as_str() diff --git a/did_resolver_sov/tests/resolution.rs b/did_resolver_sov/tests/resolution.rs index 98acb4ff86..f889bf1f65 100644 --- a/did_resolver_sov/tests/resolution.rs +++ b/did_resolver_sov/tests/resolution.rs @@ -36,7 +36,7 @@ async fn write_service_on_ledger_and_resolve_did_doc() { &profile.institution_did, ) .await; - let resolver = DidSovResolver::new(&profile.ledger_read); + let resolver = DidSovResolver::new(profile.ledger_read); let did = format!("did:sov:{}", profile.institution_did); let did_doc = resolver @@ -53,7 +53,7 @@ async fn write_service_on_ledger_and_resolve_did_doc() { #[tokio::test] async fn test_error_handling_during_resolution() { let profile = build_setup_profile().await; - let resolver = DidSovResolver::new(&profile.ledger_read); + let resolver = DidSovResolver::new(profile.ledger_read); let did = format!("did:unknownmethod:{}", profile.institution_did); let result = resolver diff --git a/messages/src/lib.rs b/messages/src/lib.rs index 737b1f4365..53622ad869 100644 --- a/messages/src/lib.rs +++ b/messages/src/lib.rs @@ -15,8 +15,8 @@ pub mod msg_types; use derive_more::From; use misc::utils; use msg_fields::protocols::{ - did_exchange::DidExchange, cred_issuance::{v1::CredentialIssuanceV1, v2::CredentialIssuanceV2, CredentialIssuance}, + did_exchange::DidExchange, pickup::Pickup, present_proof::{v2::PresentProofV2, PresentProof}, }; diff --git a/messages/src/msg_fields/protocols/did_exchange/complete.rs b/messages/src/msg_fields/protocols/did_exchange/complete.rs index 79806a60af..d93e8086f2 100644 --- a/messages/src/msg_fields/protocols/did_exchange/complete.rs +++ b/messages/src/msg_fields/protocols/did_exchange/complete.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; -use shared_vcx::misc::serde_ignored::SerdeIgnored as NoContent; +use shared::misc::serde_ignored::SerdeIgnored as NoContent; +use typed_builder::TypedBuilder; use crate::{ decorators::{thread::Thread, timing::Timing}, @@ -9,10 +10,11 @@ use crate::{ pub type Complete = MsgParts; // TODO: Pthid is mandatory in this case! -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, TypedBuilder)] pub struct CompleteDecorators { #[serde(rename = "~thread")] pub thread: Thread, + #[builder(default, setter(strip_option))] #[serde(rename = "~timing")] #[serde(skip_serializing_if = "Option::is_none")] pub timing: Option, @@ -44,10 +46,13 @@ mod tests { } }); - let decorators = CompleteDecorators { thread, timing: None }; + let decorators = CompleteDecorators { + thread, + timing: None, + }; test_utils::test_msg( - NoContent::default(), + NoContent, decorators, DidExchangeTypeV1_0::Complete, expected, @@ -62,12 +67,12 @@ mod tests { }; let expected = json!({ - "~thread": serde_json::to_value(&make_extended_thread()).unwrap(), - "~timing": serde_json::to_value(&make_extended_timing()).unwrap() + "~thread": serde_json::to_value(make_extended_thread()).unwrap(), + "~timing": serde_json::to_value(make_extended_timing()).unwrap() }); test_utils::test_msg( - NoContent::default(), + NoContent, decorators, DidExchangeTypeV1_0::Complete, expected, diff --git a/messages/src/msg_fields/protocols/did_exchange/mod.rs b/messages/src/msg_fields/protocols/did_exchange/mod.rs index 960b136b8c..c7e676f06d 100644 --- a/messages/src/msg_fields/protocols/did_exchange/mod.rs +++ b/messages/src/msg_fields/protocols/did_exchange/mod.rs @@ -7,24 +7,25 @@ pub mod response; use derive_more::From; use serde::{de::Error, Deserialize, Serialize}; -use shared_vcx::misc::serde_ignored::SerdeIgnored as NoContent; +use shared::misc::serde_ignored::SerdeIgnored as NoContent; +use self::{ + complete::{Complete, CompleteDecorators}, + problem_report::{ProblemReport, ProblemReportContent, ProblemReportDecorators}, + request::{Request, RequestContent, RequestDecorators}, + response::{Response, ResponseContent, ResponseDecorators}, +}; use crate::{ misc::utils::{into_msg_with_type, transit_to_aries_msg}, msg_fields::traits::DelayedSerde, msg_types::{ - protocols::did_exchange::{DidExchangeType as DidExchangeKind, DidExchangeTypeV1, DidExchangeTypeV1_0}, + protocols::did_exchange::{ + DidExchangeType as DidExchangeKind, DidExchangeTypeV1, DidExchangeTypeV1_0, + }, MsgWithType, }, }; -use self::{ - complete::{Complete, CompleteDecorators}, - problem_report::{ProblemReport, ProblemReportContent, ProblemReportDecorators}, - request::{Request, RequestContent, RequestDecorators}, - response::{Response, ResponseContent, ResponseDecorators}, -}; - #[derive(Clone, Debug, From, PartialEq)] pub enum DidExchange { Request(Request), @@ -36,7 +37,10 @@ pub enum DidExchange { impl DelayedSerde for DidExchange { type MsgType<'a> = (DidExchangeKind, &'a str); - fn delayed_deserialize<'de, D>(msg_type: Self::MsgType<'de>, deserializer: D) -> Result + fn delayed_deserialize<'de, D>( + msg_type: Self::MsgType<'de>, + deserializer: D, + ) -> Result where D: serde::Deserializer<'de>, { @@ -49,7 +53,9 @@ impl DelayedSerde for DidExchange { match kind.map_err(D::Error::custom)? { DidExchangeTypeV1_0::Request => Request::deserialize(deserializer).map(From::from), DidExchangeTypeV1_0::Response => Response::deserialize(deserializer).map(From::from), - DidExchangeTypeV1_0::ProblemReport => ProblemReport::deserialize(deserializer).map(From::from), + DidExchangeTypeV1_0::ProblemReport => { + ProblemReport::deserialize(deserializer).map(From::from) + } DidExchangeTypeV1_0::Complete => Complete::deserialize(deserializer).map(From::from), } } diff --git a/messages/src/msg_fields/protocols/did_exchange/problem_report.rs b/messages/src/msg_fields/protocols/did_exchange/problem_report.rs index 82301e12d6..598cfba41a 100644 --- a/messages/src/msg_fields/protocols/did_exchange/problem_report.rs +++ b/messages/src/msg_fields/protocols/did_exchange/problem_report.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use typed_builder::TypedBuilder; use crate::{ decorators::{localization::MsgLocalization, thread::Thread, timing::Timing}, @@ -7,7 +8,7 @@ use crate::{ pub type ProblemReport = MsgParts; -#[derive(Clone, Debug, Deserialize, Serialize, Default, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, Default, PartialEq, TypedBuilder)] pub struct ProblemReportContent { #[serde(rename = "problem-code")] #[serde(skip_serializing_if = "Option::is_none")] @@ -25,13 +26,15 @@ pub enum ProblemCode { ResponseProcessingError, } -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, TypedBuilder)] pub struct ProblemReportDecorators { #[serde(rename = "~thread")] pub thread: Thread, + #[builder(default, setter(strip_option))] #[serde(rename = "~l10n")] #[serde(skip_serializing_if = "Option::is_none")] pub localization: Option, + #[builder(default, setter(strip_option))] #[serde(rename = "~timing")] #[serde(skip_serializing_if = "Option::is_none")] pub timing: Option, @@ -56,8 +59,8 @@ mod tests { use super::*; use crate::{ decorators::{ - localization::tests::make_extended_msg_localization, thread::tests::make_extended_thread, - timing::tests::make_extended_timing, + localization::tests::make_extended_msg_localization, + thread::tests::make_extended_thread, timing::tests::make_extended_timing, }, misc::test_utils, msg_types::protocols::did_exchange::DidExchangeTypeV1_0, @@ -73,7 +76,12 @@ mod tests { "~thread": decorators.thread }); - test_utils::test_msg(content, decorators, DidExchangeTypeV1_0::ProblemReport, expected); + test_utils::test_msg( + content, + decorators, + DidExchangeTypeV1_0::ProblemReport, + expected, + ); } #[test] @@ -94,6 +102,11 @@ mod tests { "~l10n": decorators.localization }); - test_utils::test_msg(content, decorators, DidExchangeTypeV1_0::ProblemReport, expected); + test_utils::test_msg( + content, + decorators, + DidExchangeTypeV1_0::ProblemReport, + expected, + ); } } diff --git a/messages/src/msg_fields/protocols/did_exchange/request.rs b/messages/src/msg_fields/protocols/did_exchange/request.rs index cc5ffe950e..749ce9332b 100644 --- a/messages/src/msg_fields/protocols/did_exchange/request.rs +++ b/messages/src/msg_fields/protocols/did_exchange/request.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; -use shared_vcx::maybe_known::MaybeKnown; +use shared::maybe_known::MaybeKnown; +use typed_builder::TypedBuilder; use crate::{ decorators::{ @@ -12,7 +13,7 @@ use crate::{ pub type Request = MsgParts; -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, TypedBuilder)] pub struct RequestContent { pub label: String, pub goal_code: Option>, @@ -22,11 +23,12 @@ pub struct RequestContent { pub did_doc: Option, } -#[derive(Clone, Debug, Deserialize, Serialize, Default, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, Default, PartialEq, TypedBuilder)] pub struct RequestDecorators { #[serde(rename = "~thread")] #[serde(skip_serializing_if = "Option::is_none")] pub thread: Option, + #[builder(default, setter(strip_option))] #[serde(rename = "~timing")] #[serde(skip_serializing_if = "Option::is_none")] pub timing: Option, @@ -57,9 +59,17 @@ mod tests { goal_code: Some(MaybeKnown::Known(ThreadGoalCode::AriesRelBuild)), goal: Some("test_goal".to_owned()), did: did_doc.id.clone(), - did_doc: Some(Attachment::new(AttachmentData::new(AttachmentType::Json( - serde_json::to_value(did_doc).unwrap(), - )))), + did_doc: Some( + Attachment::builder() + .data( + AttachmentData::builder() + .content(AttachmentType::Json( + serde_json::to_value(&did_doc).unwrap(), + )) + .build(), + ) + .build(), + ), } } diff --git a/messages/src/msg_fields/protocols/did_exchange/response.rs b/messages/src/msg_fields/protocols/did_exchange/response.rs index 408fee46e9..0779b114ac 100644 --- a/messages/src/msg_fields/protocols/did_exchange/response.rs +++ b/messages/src/msg_fields/protocols/did_exchange/response.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use typed_builder::TypedBuilder; use crate::{ decorators::{attachment::Attachment, thread::Thread, timing::Timing}, @@ -7,17 +8,18 @@ use crate::{ pub type Response = MsgParts; -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, TypedBuilder)] pub struct ResponseContent { pub did: String, // TODO: Use Did #[serde(rename = "did_doc~attach")] pub did_doc: Option, } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, TypedBuilder)] pub struct ResponseDecorators { #[serde(rename = "~thread")] pub thread: Thread, + #[builder(default, setter(strip_option))] #[serde(rename = "~timing")] #[serde(skip_serializing_if = "Option::is_none")] pub timing: Option, @@ -45,9 +47,17 @@ mod tests { let did_doc = AriesDidDoc::default(); ResponseContent { did: did_doc.id.clone(), - did_doc: Some(Attachment::new(AttachmentData::new(AttachmentType::Json( - serde_json::to_value(did_doc).unwrap(), - )))), + did_doc: Some( + Attachment::builder() + .data( + AttachmentData::builder() + .content(AttachmentType::Json( + serde_json::to_value(&did_doc).unwrap(), + )) + .build(), + ) + .build(), + ), } } diff --git a/messages/src/msg_types/protocols/did_exchange.rs b/messages/src/msg_types/protocols/did_exchange.rs index 9e7422ac0e..0c5fb7b3cb 100644 --- a/messages/src/msg_types/protocols/did_exchange.rs +++ b/messages/src/msg_types/protocols/did_exchange.rs @@ -46,7 +46,10 @@ mod tests { #[test] fn test_version_resolution_didexchange() { - test_utils::test_msg_type_resolution("https://didcomm.org/didexchange/1.255", DidExchangeTypeV1::new_v1_0()) + test_utils::test_msg_type_resolution( + "https://didcomm.org/didexchange/1.255", + DidExchangeTypeV1::new_v1_0(), + ) } #[test] diff --git a/messages/src/msg_types/protocols/mod.rs b/messages/src/msg_types/protocols/mod.rs index 34c5d5807e..77932c48c7 100644 --- a/messages/src/msg_types/protocols/mod.rs +++ b/messages/src/msg_types/protocols/mod.rs @@ -6,7 +6,8 @@ use shared::misc::utils::CowStr; use self::{ basic_message::BasicMessageType, connection::ConnectionType, - coordinate_mediation::CoordinateMediationType, did_exchange::DidExchangeType, cred_issuance::CredentialIssuanceType, discover_features::DiscoverFeaturesType, + coordinate_mediation::CoordinateMediationType, cred_issuance::CredentialIssuanceType, + did_exchange::DidExchangeType, discover_features::DiscoverFeaturesType, notification::NotificationType, out_of_band::OutOfBandType, pickup::PickupType, present_proof::PresentProofType, report_problem::ReportProblemType, revocation::RevocationType, routing::RoutingType, signature::SignatureType, trust_ping::TrustPingType, diff --git a/messages/src/msg_types/registry.rs b/messages/src/msg_types/registry.rs index f76ae7f74a..ddf5461bec 100644 --- a/messages/src/msg_types/registry.rs +++ b/messages/src/msg_types/registry.rs @@ -10,8 +10,8 @@ use crate::msg_types::{ basic_message::BasicMessageTypeV1, connection::ConnectionTypeV1, coordinate_mediation::CoordinateMediationTypeV1, - did_exchange::DidExchangeTypeV1, cred_issuance::{CredentialIssuanceTypeV1, CredentialIssuanceTypeV2}, + did_exchange::DidExchangeTypeV1, discover_features::DiscoverFeaturesTypeV1, notification::NotificationTypeV1, out_of_band::OutOfBandTypeV1, diff --git a/public_key/src/key.rs b/public_key/src/key.rs index 64479bf99c..6b8607d9fa 100644 --- a/public_key/src/key.rs +++ b/public_key/src/key.rs @@ -71,7 +71,10 @@ impl Key { // TODO: A better name? pub fn short_prefixless_fingerprint(&self) -> String { - self.prefixless_fingerprint().chars().take(8).collect::() + self.prefixless_fingerprint() + .chars() + .take(8) + .collect::() } fn strip_multicodec_prefix_if_present(key: Vec, key_type: &KeyType) -> Vec { diff --git a/uniffi_aries_vcx/core/src/core/profile.rs b/uniffi_aries_vcx/core/src/core/profile.rs index 5e9608695e..c55fe0117d 100644 --- a/uniffi_aries_vcx/core/src/core/profile.rs +++ b/uniffi_aries_vcx/core/src/core/profile.rs @@ -62,7 +62,7 @@ pub fn new_indy_profile( .build(); let ledger_pool = IndyVdrLedgerPool::new(genesis_file_path, indy_vdr_config, vec![])?; let request_submitter = IndyVdrSubmitter::new(ledger_pool); - let ledger_read = indyvdr_build_ledger_read(request_submitter.clone(), cache_config)?; + let ledger_read = indyvdr_build_ledger_read(request_submitter, cache_config)?; let wallet = IndySdkWallet::new(wh); let profile = UniffiProfile { anoncreds: IndyCredxAnonCreds,