diff --git a/Cargo.lock b/Cargo.lock index c41442a9bf..f6621140af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -504,6 +504,7 @@ dependencies = [ "log", "messages", "num-bigint", + "pretty_assertions", "public_key", "rand 0.8.5", "regex", diff --git a/aries/agents/aath-backchannel/src/setup.rs b/aries/agents/aath-backchannel/src/setup.rs index 87fbbaf82c..8e626368f2 100644 --- a/aries/agents/aath-backchannel/src/setup.rs +++ b/aries/agents/aath-backchannel/src/setup.rs @@ -65,6 +65,7 @@ async fn download_genesis_file() -> std::result::Result { let mut f = std::fs::OpenOptions::new() .write(true) .create(true) + .truncate(true) .open(path.clone()) .expect("Unable to open file"); f.write_all(body.as_bytes()).expect("Unable to write data"); diff --git a/aries/agents/aries-vcx-agent/src/handlers/did_exchange.rs b/aries/agents/aries-vcx-agent/src/handlers/did_exchange.rs index cb81274fab..400fa33990 100644 --- a/aries/agents/aries-vcx-agent/src/handlers/did_exchange.rs +++ b/aries/agents/aries-vcx-agent/src/handlers/did_exchange.rs @@ -16,15 +16,14 @@ use aries_vcx::{ protocols::did_exchange::{ resolve_enc_key_from_invitation, state_machine::{ - create_our_did_document, generic::{GenericDidExchange, ThinState}, + helpers::create_peer_did_4, }, }, transport::Transport, utils::encryption_envelope::EncryptionEnvelope, }; use aries_vcx_core::wallet::base_wallet::BaseWallet; -use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}; use did_resolver_registry::ResolverRegistry; use did_resolver_sov::did_resolver::did_doc::schema::did_doc::DidDocument; use url::Url; @@ -66,12 +65,10 @@ impl DidcommHandlerDidExchange { invitation_id: Option, ) -> AgentResult<(String, Option)> { // todo: type the return type - let (our_did_document, _our_verkey) = - create_our_did_document(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]) - .await?; + let (our_peer_did, _our_verkey) = + create_peer_did_4(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]).await?; let their_did: Did = their_did.parse()?; - let our_peer_did = PeerDid::::from_did_doc(our_did_document.clone())?; let (requester, request) = GenericDidExchange::construct_request( self.resolver_registry.clone(), invitation_id, @@ -168,10 +165,8 @@ impl DidcommHandlerDidExchange { } }; - let (our_did_document, _our_verkey) = - create_our_did_document(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]) - .await?; - let peer_did_invitee = PeerDid::::from_did_doc(our_did_document.clone())?; + let (peer_did_4_invitee, _our_verkey) = + create_peer_did_4(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]).await?; let pthid = request .clone() @@ -190,7 +185,7 @@ impl DidcommHandlerDidExchange { self.wallet.as_ref(), self.resolver_registry.clone(), request, - &peer_did_invitee, + &peer_did_4_invitee, invitation_key, ) .await?; @@ -235,7 +230,9 @@ impl DidcommHandlerDidExchange { let (requester, _) = self.did_exchange.get(&thid)?; - let (requester, complete) = requester.handle_response(response).await?; + let (requester, complete) = requester + .handle_response(response, self.resolver_registry.clone()) + .await?; let ddo_their = requester.their_did_doc(); let ddo_our = requester.our_did_document(); let service = ddo_their.get_service_of_type(&ServiceType::DIDCommV1)?; diff --git a/aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs b/aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs index 1d473d1aa9..7716edeb72 100644 --- a/aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs +++ b/aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs @@ -12,10 +12,9 @@ use aries_vcx::{ }, AriesMessage, }, - protocols::did_exchange::state_machine::create_our_did_document, + protocols::did_exchange::state_machine::helpers::create_peer_did_4, }; use aries_vcx_core::wallet::base_wallet::BaseWallet; -use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}; use url::Url; use crate::{ @@ -39,10 +38,8 @@ impl ServiceOutOfBand { } pub async fn create_invitation(&self) -> AgentResult { - let (our_did_document, _our_verkey) = - create_our_did_document(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]) - .await?; - let peer_did = PeerDid::::from_did_doc(our_did_document)?; + let (peer_did, _our_verkey) = + create_peer_did_4(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]).await?; let sender = OutOfBandSender::create() .append_service(&OobService::Did(peer_did.to_string())) diff --git a/aries/aries_vcx/Cargo.toml b/aries/aries_vcx/Cargo.toml index d4ad97e267..df309953a3 100644 --- a/aries/aries_vcx/Cargo.toml +++ b/aries/aries_vcx/Cargo.toml @@ -81,3 +81,4 @@ test_utils = { path = "../misc/test_utils" } wallet_migrator = { path = "../misc/wallet_migrator" } async-channel = "1.7.1" tokio = { version = "1.20", features = ["rt", "macros", "rt-multi-thread"] } +pretty_assertions = "1.4.0" diff --git a/aries/aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs b/aries/aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs index 22de7d031c..7437bee542 100644 --- a/aries/aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs +++ b/aries/aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use aries_vcx_core::wallet::base_wallet::BaseWallet; use did_doc::schema::did_doc::DidDocument; use did_parser_nom::Did; -use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}; +use did_peer::peer_did::{numalgos::numalgo4::Numalgo4, PeerDid}; use did_resolver_registry::ResolverRegistry; use messages::msg_fields::protocols::did_exchange::{ complete::Complete, problem_report::ProblemReport, request::Request, response::Response, @@ -87,7 +87,7 @@ impl GenericDidExchange { resolver_registry: Arc, invitation_id: Option, their_did: &Did, - our_peer_did: &PeerDid, + our_peer_did: &PeerDid, ) -> Result<(Self, Request), AriesVcxError> { let TransitionResult { state, output } = DidExchangeRequester::::construct_request( @@ -107,7 +107,7 @@ impl GenericDidExchange { wallet: &impl BaseWallet, resolver_registry: Arc, request: Request, - our_peer_did: &PeerDid, + our_peer_did: &PeerDid, invitation_key: Option, ) -> Result<(Self, Response), AriesVcxError> { let TransitionResult { state, output } = @@ -128,11 +128,15 @@ impl GenericDidExchange { pub async fn handle_response( self, response: Response, + resolver_registry: Arc, ) -> 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 { + match request_sent_state + .receive_response(response, resolver_registry) + .await + { Ok(TransitionResult { state, output }) => Ok(( GenericDidExchange::Requester(RequesterState::Completed(state)), output, diff --git a/aries/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs b/aries/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs index 46f585d3e1..f484c83621 100644 --- a/aries/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs +++ b/aries/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs @@ -7,11 +7,17 @@ use did_doc::schema::{ did_doc::DidDocument, service::{service_key_kind::ServiceKeyKind, typed::didcommv1::ServiceDidCommV1, Service}, types::uri::Uri, - verification_method::{PublicKeyField, VerificationMethod, VerificationMethodType}, + verification_method::{PublicKeyField, VerificationMethodType}, }; use did_key::DidKey; -use did_parser_nom::{Did, DidUrl}; -use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}; +use did_parser_nom::DidUrl; +use did_peer::peer_did::{ + numalgos::numalgo4::{ + construction_did_doc::{DidPeer4ConstructionDidDocument, DidPeer4VerificationMethod}, + Numalgo4, + }, + PeerDid, +}; use messages::{ decorators::{ attachment::{Attachment, AttachmentData, AttachmentType}, @@ -35,7 +41,7 @@ use crate::{ }, }; -pub fn construct_response( +pub(crate) fn construct_response( request_id: String, our_did_document: &DidDocument, signed_attach: Attachment, @@ -55,7 +61,7 @@ pub fn construct_response( .build() } -pub async fn generate_keypair( +async fn generate_keypair( wallet: &impl BaseWallet, key_type: KeyType, ) -> Result { @@ -63,11 +69,11 @@ pub async fn generate_keypair( Ok(Key::from_base58(&pairwise_info.pw_vk, key_type)?) } -pub async fn create_our_did_document( +pub async fn create_peer_did_4( wallet: &impl BaseWallet, service_endpoint: Url, routing_keys: Vec, -) -> Result<(DidDocument, Key), AriesVcxError> { +) -> Result<(PeerDid, Key), AriesVcxError> { let key_enc = generate_keypair(wallet, KeyType::Ed25519).await?; let service: Service = ServiceDidCommV1::new( @@ -82,38 +88,29 @@ pub async fn create_our_did_document( ) .try_into()?; - info!("Prepared service for peer:did:2 generation: {} ", service); - let mut did_document = did_doc_from_keys(Default::default(), key_enc.clone(), service)?; - info!( - "Created did document for peer:did:2 generation: {} ", - did_document - ); - let peer_did = PeerDid::::from_did_doc(did_document.clone())?; - did_document.set_id(peer_did.did().clone()); - Ok((did_document, key_enc)) -} - -fn did_doc_from_keys( - did: Did, - key_enc: Key, - service: Service, -) -> Result { - let vm_ka_id = DidUrl::from_fragment(key_enc.short_prefixless_fingerprint())?; - let vm_ka = VerificationMethod::builder() - .id(vm_ka_id) - .controller(did.clone()) + info!("Prepared service for peer:did:4 generation: {} ", service); + let vm_ka = DidPeer4VerificationMethod::builder() + .id(DidUrl::from_fragment("key1".to_string())?) .verification_method_type(VerificationMethodType::Ed25519VerificationKey2020) .public_key(PublicKeyField::Base58 { public_key_base58: key_enc.base58(), }) .build(); - let mut did_doc = DidDocument::new(did); - did_doc.add_service(service); - did_doc.add_key_agreement(vm_ka); - Ok(did_doc) + let mut construction_did_doc = DidPeer4ConstructionDidDocument::new(); + construction_did_doc.add_key_agreement(vm_ka); + construction_did_doc.add_service(service); + + info!( + "Created did document for peer:did:4 generation: {} ", + construction_did_doc + ); + let peer_did = PeerDid::::new(construction_did_doc)?; + info!("Created peer did: {peer_did}"); + + Ok((peer_did, key_enc)) } -pub fn ddo_to_attach(ddo: DidDocument) -> Result { +pub(crate) fn ddo_to_attach(ddo: DidDocument) -> Result { // Interop note: acapy accepts unsigned when using peer dids? let content_b64 = base64::engine::Engine::encode(&URL_SAFE_NO_PAD, serde_json::to_string(&ddo)?); @@ -128,7 +125,7 @@ pub fn ddo_to_attach(ddo: DidDocument) -> Result { // TODO: Obviously, extract attachment signing // TODO: JWS verification -pub async fn jws_sign_attach( +pub(crate) async fn jws_sign_attach( mut attach: Attachment, verkey: Key, wallet: &impl BaseWallet, @@ -173,7 +170,7 @@ pub async fn jws_sign_attach( } } -pub fn attachment_to_diddoc(attachment: Attachment) -> Result { +pub(crate) fn attachment_to_diddoc(attachment: Attachment) -> Result { match attachment.data.content { AttachmentType::Json(value) => serde_json::from_value(value).map_err(Into::into), AttachmentType::Base64(ref value) => { @@ -194,7 +191,7 @@ pub fn attachment_to_diddoc(attachment: Attachment) -> Result(state: S) -> impl FnOnce(T) -> TransitionError +pub(crate) fn to_transition_error(state: S) -> impl FnOnce(T) -> TransitionError where T: Into, { @@ -203,69 +200,3 @@ where state, } } - -#[cfg(test)] -mod tests { - use did_doc::schema::{ - service::typed::ServiceType, utils::OneOrList, verification_method::VerificationMethodKind, - }; - - use super::*; - - #[tokio::test] - async fn test_did_doc_from_keys() { - let key_enc = Key::new( - "tyntrez7bCthPqvZUDGwhYB1bSe9HzpLdSeHFpuSwst".into(), - KeyType::Ed25519, - ) - .unwrap(); - - let service_endpoint = Url::parse("http://example.com").unwrap(); - let routing_keys = vec![ - ServiceKeyKind::Value("routing_key1".into()), - ServiceKeyKind::Value("routing_key2".into()), - ]; - let service: Service = ServiceDidCommV1::new( - Uri::new("#service-0").unwrap(), - service_endpoint.clone(), - 0, - vec![], - routing_keys, - ) - .try_into() - .unwrap(); - - let did = Did::default(); - - let result = did_doc_from_keys(did, key_enc.clone(), service); - - assert!(result.is_ok()); - let did_doc = result.unwrap(); - - assert_eq!(did_doc.service().len(), 1); - let ddo_service = did_doc.service().first().unwrap(); - assert_eq!(&ddo_service.id().to_string(), "#service-0"); - assert_eq!( - ddo_service.service_type(), - &OneOrList::One(ServiceType::DIDCommV1) - ); - assert_eq!(ddo_service.service_endpoint(), &service_endpoint); - assert_eq!( - ddo_service.extra_field_routing_keys().unwrap(), - vec![ - ServiceKeyKind::Value("routing_key1".into()), - ServiceKeyKind::Value("routing_key2".into()) - ] - ); - - assert_eq!(did_doc.key_agreement().len(), 1); - match did_doc.key_agreement().first().unwrap() { - VerificationMethodKind::Resolved(key_agreement) => { - assert_eq!(key_agreement.public_key().unwrap(), key_enc); - } - VerificationMethodKind::Resolvable(_) => { - panic!("Key agreement was expected to have embedded key"); - } - } - } -} diff --git a/aries/aries_vcx/src/protocols/did_exchange/state_machine/mod.rs b/aries/aries_vcx/src/protocols/did_exchange/state_machine/mod.rs index efc6f26322..896e0843be 100644 --- a/aries/aries_vcx/src/protocols/did_exchange/state_machine/mod.rs +++ b/aries/aries_vcx/src/protocols/did_exchange/state_machine/mod.rs @@ -1,4 +1,4 @@ -mod helpers; +pub mod helpers; pub mod generic; pub mod requester; @@ -8,7 +8,6 @@ use std::marker::PhantomData; use chrono::Utc; use did_doc::schema::did_doc::DidDocument; -pub use helpers::{create_our_did_document, generate_keypair}; use messages::{ decorators::{thread::Thread, timing::Timing}, msg_fields::protocols::did_exchange::problem_report::{ diff --git a/aries/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/mod.rs b/aries/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/mod.rs index be668153e5..fd04b83830 100644 --- a/aries/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/mod.rs +++ b/aries/aries_vcx/src/protocols/did_exchange/state_machine/requester/request_sent/mod.rs @@ -1,10 +1,8 @@ use std::sync::Arc; use did_parser_nom::Did; -use did_peer::{ - peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}, - resolver::options::PublicKeyEncoding, -}; +use did_peer::peer_did::{numalgos::numalgo4::Numalgo4, PeerDid}; +use did_resolver::traits::resolvable::resolution_output::DidResolutionOutput; use did_resolver_registry::ResolverRegistry; use messages::msg_fields::protocols::did_exchange::{ complete::Complete as CompleteMessage, request::Request, response::Response, @@ -21,7 +19,6 @@ use crate::{ states::{completed::Completed, requester::request_sent::RequestSent}, transition::{transition_error::TransitionError, transition_result::TransitionResult}, }, - utils::didcomm_utils::resolve_didpeer2, }; impl DidExchangeRequester { @@ -29,7 +26,7 @@ impl DidExchangeRequester { resolver_registry: Arc, invitation_id: Option, their_did: &Did, - our_peer_did: &PeerDid, + our_peer_did: &PeerDid, ) -> Result, AriesVcxError> { info!( "DidExchangeRequester::construct_request >> their_did: {}, our_peer_did: \ @@ -40,7 +37,7 @@ impl DidExchangeRequester { .resolve(their_did, &Default::default()) .await? .did_document; - let our_did_document = resolve_didpeer2(our_peer_did, PublicKeyEncoding::Base58).await?; + let our_did_document = our_peer_did.resolve_did_doc()?; let request = construct_request(invitation_id.clone(), our_peer_did.to_string()); info!( @@ -51,7 +48,6 @@ impl DidExchangeRequester { state: DidExchangeRequester::from_parts( RequestSent { request_id: request.id.clone(), - // invitation_id, }, their_did_document, our_did_document, @@ -63,6 +59,7 @@ impl DidExchangeRequester { pub async fn receive_response( self, response: Response, + resolver_registry: Arc, ) -> Result< TransitionResult, CompleteMessage>, TransitionError, @@ -91,16 +88,16 @@ impl DidExchangeRequester { "DidExchangeRequester::receive_response >> the Response message \ contains pairwise DID, resolving to DID Document" ); - let peer_did = PeerDid::::parse(response.content.did) - .map_err(to_transition_error(self.clone()))?; - resolve_didpeer2(&peer_did, PublicKeyEncoding::Base58) + let did = + &Did::parse(response.content.did).map_err(to_transition_error(self.clone()))?; + let DidResolutionOutput { did_document, .. } = resolver_registry + .resolve(did, &Default::default()) .await - .map_err(to_transition_error(self.clone()))? + .map_err(to_transition_error(self.clone()))?; + did_document }; - let complete_message = construct_didexchange_complete( - self.state.request_id.clone(), // self.state.invitation_id.clone(), - ); + let complete_message = construct_didexchange_complete(self.state.request_id.clone()); info!( "DidExchangeRequester::receive_response << complete_message: {}", complete_message @@ -111,7 +108,6 @@ impl DidExchangeRequester { Completed { request_id: self.state.request_id, }, - // TODO: Make sure to make the DDO identifier did:peer:3 for both did_document, self.our_did_document, ), diff --git a/aries/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/mod.rs b/aries/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/mod.rs index 81edfb0f03..3cd0b19a69 100644 --- a/aries/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/mod.rs +++ b/aries/aries_vcx/src/protocols/did_exchange/state_machine/responder/response_sent/mod.rs @@ -2,10 +2,7 @@ use std::sync::Arc; use aries_vcx_core::wallet::base_wallet::BaseWallet; use did_doc::schema::did_doc::DidDocument; -use did_peer::{ - peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}, - resolver::options::PublicKeyEncoding, -}; +use did_peer::peer_did::{numalgos::numalgo4::Numalgo4, PeerDid}; use did_resolver_registry::ResolverRegistry; use messages::msg_fields::protocols::did_exchange::{ complete::Complete, request::Request, response::Response, @@ -22,7 +19,6 @@ use crate::{ states::{completed::Completed, responder::response_sent::ResponseSent}, transition::{transition_error::TransitionError, transition_result::TransitionResult}, }, - utils::didcomm_utils::resolve_didpeer2, }; impl DidExchangeResponder { @@ -30,7 +26,7 @@ impl DidExchangeResponder { wallet: &impl BaseWallet, resolver_registry: Arc, request: Request, - our_peer_did: &PeerDid, + our_peer_did: &PeerDid, invitation_key: Option, ) -> Result, Response>, AriesVcxError> { info!( @@ -39,22 +35,22 @@ impl DidExchangeResponder { request, our_peer_did, invitation_key ); let their_ddo = resolve_ddo_from_request(&resolver_registry, &request).await?; - let our_did_document = resolve_didpeer2(our_peer_did, PublicKeyEncoding::Base58).await?; + let our_did_document = our_peer_did.resolve_did_doc()?; // TODO: Check amendment made to did-exchange protocol in terms of rotating keys. // When keys are rotated, there's a new decorator which conveys that let ddo_attachment_unsigned = ddo_to_attach(our_did_document.clone())?; let ddo_attachment = match invitation_key { None => { // TODO: not signing if invitation_key is not provided, that would be case for - // implicit invitations However we should probably sign with - // the key the request used as recipient_vk to anoncrypt the request + // implicit invitations. However we should probably sign with + // the key the request used as recipient_vk to anoncrypt the request // So argument "invitation_key" should be required ddo_attachment_unsigned } Some(invitation_key) => { // TODO: this must happen only if we rotate DID; We currently do that always // can skip signing if we don't rotate did document (unique p2p invitations - // with peer DIDs) + // with peer DIDs) jws_sign_attach(ddo_attachment_unsigned, invitation_key, wallet).await? } }; diff --git a/aries/aries_vcx/src/utils/didcomm_utils.rs b/aries/aries_vcx/src/utils/didcomm_utils.rs index c6a9fb0fcd..b044966659 100644 --- a/aries/aries_vcx/src/utils/didcomm_utils.rs +++ b/aries/aries_vcx/src/utils/didcomm_utils.rs @@ -2,33 +2,10 @@ use did_doc::schema::{ did_doc::DidDocument, service::service_key_kind::ServiceKeyKind, types::uri::Uri, verification_method::VerificationMethodType, }; -use did_peer::{ - peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}, - resolver::{options::PublicKeyEncoding, PeerDidResolutionOptions, PeerDidResolver}, -}; -use did_resolver::{ - error::GenericError, - traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}, -}; use public_key::Key; use crate::errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}; -pub(crate) async fn resolve_didpeer2( - did_peer: &PeerDid, - encoding: PublicKeyEncoding, -) -> Result { - let DidResolutionOutput { did_document, .. } = PeerDidResolver::new() - .resolve( - did_peer.did(), - &PeerDidResolutionOptions { - encoding: Some(encoding), - }, - ) - .await?; - Ok(did_document) -} - fn resolve_service_key_to_typed_key( key: &ServiceKeyKind, did_document: &DidDocument, diff --git a/aries/aries_vcx/tests/test_did_exchange.rs b/aries/aries_vcx/tests/test_did_exchange.rs index 46f9f88dbb..c1727d6890 100644 --- a/aries/aries_vcx/tests/test_did_exchange.rs +++ b/aries/aries_vcx/tests/test_did_exchange.rs @@ -7,7 +7,7 @@ use aries_vcx::{ protocols::did_exchange::{ resolve_enc_key_from_invitation, state_machine::{ - create_our_did_document, + helpers::create_peer_did_4, requester::{helpers::invitation_get_first_did_service, DidExchangeRequester}, responder::DidExchangeResponder, }, @@ -23,17 +23,14 @@ use did_doc::schema::{ types::uri::Uri, }; use did_parser_nom::Did; -use did_peer::{ - peer_did::{numalgos::numalgo2::Numalgo2, PeerDid}, - resolver::{options::PublicKeyEncoding, PeerDidResolutionOptions, PeerDidResolver}, -}; -use did_resolver::traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}; +use did_peer::resolver::PeerDidResolver; use did_resolver_registry::ResolverRegistry; use did_resolver_sov::resolution::DidSovResolver; use log::info; use messages::msg_fields::protocols::out_of_band::invitation::{ Invitation, InvitationContent, OobService, }; +use pretty_assertions::assert_eq; use test_utils::devsetup::{dev_build_profile_vdr_ledger, SetupPoolDirectory}; use url::Url; @@ -43,23 +40,8 @@ use crate::utils::test_agent::{ pub mod utils; -pub(crate) async fn resolve_didpeer2( - did_peer: &PeerDid, - encoding: PublicKeyEncoding, -) -> DidDocument { - let DidResolutionOutput { did_document, .. } = PeerDidResolver::new() - .resolve( - did_peer.did(), - &PeerDidResolutionOptions { - encoding: Some(encoding), - }, - ) - .await - .unwrap(); - did_document -} - fn assert_key_agreement(a: DidDocument, b: DidDocument) { + log::warn!("comparing did doc a: {}, b: {}", a, b); let a_key = resolve_base58_key_agreement(&a).unwrap(); let b_key = resolve_base58_key_agreement(&b).unwrap(); assert_eq!(a_key, b_key); @@ -126,11 +108,8 @@ async fn did_exchange_test() -> Result<(), Box> { invitation ); - let (requesters_did_document, _our_verkey) = - create_our_did_document(&agent_invitee.wallet, dummy_url.clone(), vec![]).await?; - info!("Requester prepares did document: {requesters_did_document}"); - let requesters_peer_did = PeerDid::::from_did_doc(requesters_did_document.clone())?; - info!("Requester prepares their peer:did: {requesters_peer_did}"); + let (requesters_peer_did, _our_verkey) = + create_peer_did_4(&agent_invitee.wallet, dummy_url.clone(), vec![]).await?; let did_inviter: Did = invitation_get_first_did_service(&invitation)?; info!( "Invitee resolves Inviter's DID from invitation {} (as a first DID service found in the \ @@ -154,13 +133,12 @@ async fn did_exchange_test() -> Result<(), Box> { &request ); - let (responders_did_document, _our_verkey) = - create_our_did_document(&agent_invitee.wallet, dummy_url.clone(), vec![]).await?; + let (responders_peer_did, _our_verkey) = + create_peer_did_4(&agent_invitee.wallet, dummy_url.clone(), vec![]).await?; + let responders_did_document = responders_peer_did.resolve_did_doc()?; info!("Responder prepares did document: {responders_did_document}"); - let responders_peer_did = PeerDid::::from_did_doc(responders_did_document.clone())?; - info!("Responder prepares their peer:did: {responders_peer_did}"); - let check_diddoc = resolve_didpeer2(&responders_peer_did, PublicKeyEncoding::Base58).await; + let check_diddoc = responders_peer_did.resolve_did_doc()?; info!("Responder decodes constructed peer:did as did document: {check_diddoc}"); let TransitionResult { @@ -168,7 +146,7 @@ async fn did_exchange_test() -> Result<(), Box> { state: responder, } = DidExchangeResponder::::receive_request( &agent_inviter.wallet, - resolver_registry, + resolver_registry.clone(), request, &responders_peer_did, Some(invitation_key), @@ -179,7 +157,10 @@ async fn did_exchange_test() -> Result<(), Box> { let TransitionResult { state: requester, output: complete, - } = requester.receive_response(response).await.unwrap(); + } = requester + .receive_response(response, resolver_registry) + .await + .unwrap(); let responder = responder.receive_complete(complete).unwrap(); @@ -218,7 +199,8 @@ async fn did_exchange_test() -> Result<(), Box> { info!("Encrypted message: {:?}", m); - let expected_sender_vk = resolve_base58_key_agreement(&requesters_did_document)?; + let requesters_peer_did = requesters_peer_did.resolve_did_doc()?; + let expected_sender_vk = resolve_base58_key_agreement(&requesters_peer_did)?; let unpacked = EncryptionEnvelope::auth_unpack(&agent_invitee.wallet, m.0, &expected_sender_vk).await?; diff --git a/aries/misc/legacy/libvdrtools/indy-api-types/src/errors.rs b/aries/misc/legacy/libvdrtools/indy-api-types/src/errors.rs index d792848571..cfa8677fe0 100644 --- a/aries/misc/legacy/libvdrtools/indy-api-types/src/errors.rs +++ b/aries/misc/legacy/libvdrtools/indy-api-types/src/errors.rs @@ -587,7 +587,7 @@ where } thread_local! { - pub static CURRENT_ERROR_C_JSON: RefCell> = RefCell::new(None); + pub static CURRENT_ERROR_C_JSON: RefCell> = const { RefCell::new(None) }; } pub fn set_current_error(err: &IndyError) { diff --git a/did_core/did_doc/src/schema/did_doc.rs b/did_core/did_doc/src/schema/did_doc.rs index fa131a68a3..e955316031 100644 --- a/did_core/did_doc/src/schema/did_doc.rs +++ b/did_core/did_doc/src/schema/did_doc.rs @@ -77,26 +77,108 @@ impl DidDocument { self.verification_method.as_ref() } + pub fn verification_method_by_id(&self, id: &str) -> Option<&VerificationMethod> { + self.verification_method + .iter() + .find(|vm| match vm.id().fragment() { + Some(fragment) => fragment == id, + None => false, + }) + } + pub fn authentication(&self) -> &[VerificationMethodKind] { self.authentication.as_ref() } + fn try_match_and_deref_verification_method<'a>( + &'a self, + vm: &'a VerificationMethodKind, + id: &str, + ) -> Option<&VerificationMethod> { + return match vm { + VerificationMethodKind::Resolved(vm) => { + if vm.id().fragment() == Some(id) { + Some(vm) + } else { + None + } + } + VerificationMethodKind::Resolvable(vm_ref) => { + if vm_ref.fragment() == Some(id) { + self.dereference_key(vm_ref) + } else { + None + } + } + }; + } + + pub fn authentication_by_id(&self, id: &str) -> Option<&VerificationMethod> { + for vm in self.authentication.iter() { + match self.try_match_and_deref_verification_method(vm, id) { + Some(vm) => return Some(vm), + None => continue, + } + } + None + } + pub fn assertion_method(&self) -> &[VerificationMethodKind] { self.assertion_method.as_ref() } + pub fn assertion_method_by_key(&self, id: &str) -> Option<&VerificationMethod> { + for vm in self.assertion_method.iter() { + match self.try_match_and_deref_verification_method(vm, id) { + Some(vm) => return Some(vm), + None => continue, + } + } + None + } + pub fn key_agreement(&self) -> &[VerificationMethodKind] { self.key_agreement.as_ref() } + pub fn key_agreement_by_id(&self, id: &str) -> Option<&VerificationMethod> { + for vm in self.key_agreement.iter() { + match self.try_match_and_deref_verification_method(vm, id) { + Some(vm) => return Some(vm), + None => continue, + } + } + None + } + pub fn capability_invocation(&self) -> &[VerificationMethodKind] { self.capability_invocation.as_ref() } + pub fn capability_invocation_by_id(&self, id: &str) -> Option<&VerificationMethod> { + for vm in self.capability_invocation.iter() { + match self.try_match_and_deref_verification_method(vm, id) { + Some(vm) => return Some(vm), + None => continue, + } + } + None + } + pub fn capability_delegation(&self) -> &[VerificationMethodKind] { self.capability_delegation.as_ref() } + pub fn capability_delegation_by_id(&self, id: &str) -> Option<&VerificationMethod> { + for vm in self.capability_delegation.iter() { + match self.try_match_and_deref_verification_method(vm, id) { + Some(vm) => return Some(vm), + None => continue, + } + } + None + } + pub fn service(&self) -> &[Service] { self.service.as_ref() } @@ -131,7 +213,12 @@ impl DidDocument { self.verification_method.push(method); } - pub fn add_authentication(&mut self, method: VerificationMethod) { + // authentication + pub fn add_authentication(&mut self, method: VerificationMethodKind) { + self.authentication.push(method); + } + + pub fn add_authentication_object(&mut self, method: VerificationMethod) { self.authentication .push(VerificationMethodKind::Resolved(method)); } @@ -141,7 +228,12 @@ impl DidDocument { .push(VerificationMethodKind::Resolvable(reference)); } - pub fn add_assertion_method(&mut self, method: VerificationMethod) { + // assertion + pub fn add_assertion_method(&mut self, method: VerificationMethodKind) { + self.assertion_method.push(method); + } + + pub fn add_assertion_method_object(&mut self, method: VerificationMethod) { self.assertion_method .push(VerificationMethodKind::Resolved(method)); } @@ -151,17 +243,27 @@ impl DidDocument { .push(VerificationMethodKind::Resolvable(reference)); } - pub fn add_key_agreement(&mut self, method: VerificationMethod) { + // key agreement + pub fn add_key_agreement(&mut self, method: VerificationMethodKind) { + self.key_agreement.push(method); + } + + pub fn add_key_agreement_object(&mut self, method: VerificationMethod) { self.key_agreement .push(VerificationMethodKind::Resolved(method)); } - pub fn add_key_agreement_ref(&mut self, refernece: DidUrl) { + pub fn add_key_agreement_ref(&mut self, reference: DidUrl) { self.key_agreement - .push(VerificationMethodKind::Resolvable(refernece)); + .push(VerificationMethodKind::Resolvable(reference)); } - pub fn add_capability_invocation(&mut self, method: VerificationMethod) { + // capability invocation + pub fn add_capability_invocation(&mut self, method: VerificationMethodKind) { + self.capability_invocation.push(method); + } + + pub fn add_capability_invocation_object(&mut self, method: VerificationMethod) { self.capability_invocation .push(VerificationMethodKind::Resolved(method)); } @@ -171,7 +273,12 @@ impl DidDocument { .push(VerificationMethodKind::Resolvable(reference)); } - pub fn add_capability_delegation(&mut self, method: VerificationMethod) { + // capability delegation + pub fn add_capability_delegation(&mut self, method: VerificationMethodKind) { + self.capability_delegation.push(method); + } + + pub fn add_capability_delegation_object(&mut self, method: VerificationMethod) { self.capability_delegation .push(VerificationMethodKind::Resolved(method)); } @@ -243,19 +350,19 @@ mod tests { did_doc.set_controller(OneOrList::One(controller.clone())); did_doc.add_verification_method(verification_method.clone()); - did_doc.add_authentication(verification_method.clone()); + did_doc.add_authentication_object(verification_method.clone()); did_doc.add_authentication_ref(authentication_reference.clone()); - did_doc.add_assertion_method(assertion_method.clone()); + did_doc.add_assertion_method_object(assertion_method.clone()); did_doc.add_assertion_method_ref(authentication_reference.clone()); - did_doc.add_key_agreement(verification_method.clone()); + did_doc.add_key_agreement_object(verification_method.clone()); did_doc.add_key_agreement_ref(authentication_reference.clone()); - did_doc.add_capability_invocation(verification_method.clone()); + did_doc.add_capability_invocation_object(verification_method.clone()); did_doc.add_capability_invocation_ref(authentication_reference.clone()); - did_doc.add_capability_delegation(verification_method.clone()); + did_doc.add_capability_delegation_object(verification_method.clone()); did_doc.add_capability_delegation_ref(authentication_reference.clone()); did_doc.set_service(vec![service.clone()]) diff --git a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/encoding.rs b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/encoding.rs index 73c65a3187..f973619e0d 100644 --- a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/encoding.rs +++ b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/encoding.rs @@ -181,7 +181,7 @@ mod tests { ); let mut did_document = DidDocument::new(Did::parse(did_full.clone()).unwrap()); - did_document.add_key_agreement(vm_0); + did_document.add_key_agreement_object(vm_0); did_document.add_verification_method(vm_1); let did = append_encoded_key_segments(did.to_string(), &did_document).unwrap(); @@ -241,7 +241,7 @@ mod tests { ); let mut did_document = DidDocument::new(did_full.parse().unwrap()); - did_document.add_key_agreement(vm); + did_document.add_key_agreement_object(vm); let result = append_encoded_key_segments(did.to_string(), &did_document); assert!(result.is_err()); @@ -275,8 +275,8 @@ mod tests { ); let mut did_document = DidDocument::new(did_full.parse().unwrap()); - did_document.add_assertion_method(vm_0); - did_document.add_key_agreement(vm_1); + did_document.add_assertion_method_object(vm_0); + did_document.add_key_agreement_object(vm_1); did_document.add_verification_method(vm_2); let did = append_encoded_key_segments(did.to_string(), &did_document).unwrap(); diff --git a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/helpers.rs b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/helpers.rs index dae0c2158e..29ea1fbcf7 100644 --- a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/helpers.rs +++ b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/helpers.rs @@ -93,16 +93,16 @@ fn add_key_from_element( for vm in vms.into_iter() { match purpose { ElementPurpose::Assertion => { - did_doc.add_assertion_method(vm); + did_doc.add_assertion_method_object(vm); } ElementPurpose::Encryption => { - did_doc.add_key_agreement(vm); + did_doc.add_key_agreement_object(vm); } ElementPurpose::Verification => { did_doc.add_verification_method(vm); } - ElementPurpose::CapabilityInvocation => did_doc.add_capability_invocation(vm), - ElementPurpose::CapabilityDelegation => did_doc.add_capability_delegation(vm), + ElementPurpose::CapabilityInvocation => did_doc.add_capability_invocation_object(vm), + ElementPurpose::CapabilityDelegation => did_doc.add_capability_delegation_object(vm), _ => return Err(DidPeerError::UnsupportedPurpose(purpose.into())), } } diff --git a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo4/construction_did_doc.rs b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo4/construction_did_doc.rs index 5d6d204380..f2c4be1fa0 100644 --- a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo4/construction_did_doc.rs +++ b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo4/construction_did_doc.rs @@ -75,6 +75,33 @@ impl DidPeer4ConstructionDidDocument { for vm in &self.verification_method { did_doc.add_verification_method(vm.contextualize(did_peer_4)); } + for vm in &self.key_agreement { + did_doc.add_key_agreement(vm.contextualize(did_peer_4)) + } + for vm in &self.authentication { + did_doc.add_authentication(vm.contextualize(did_peer_4)) + } + for vm in &self.assertion_method { + did_doc.add_assertion_method(vm.contextualize(did_peer_4)) + } + for vm in &self.capability_delegation { + did_doc.add_capability_delegation(vm.contextualize(did_peer_4)) + } + for vm in &self.capability_invocation { + did_doc.add_capability_invocation(vm.contextualize(did_peer_4)) + } + // ** safety note (panic) ** + // Formally every DID is URI. Assuming the parsers for both DID and URI correctly + // implement respective specs, this will never panic. + let did_short_form = did_peer_4.short_form().to_string(); + let did_as_uri = Uri::new(&did_short_form).unwrap_or_else(|_| { + panic!( + "DID or URI implementation is buggy, because DID {} failed to be parsed as URI. \ + This counters W3C DID-CORE spec which states that \"DIDs are URIs\" [RFC3986].", + did_short_form + ) + }); + did_doc.add_also_known_as(did_as_uri); did_doc } @@ -211,7 +238,7 @@ impl DidPeer4VerificationMethod { pub(crate) fn contextualize(&self, did_peer_4: &PeerDid) -> VerificationMethod { VerificationMethod::builder() .id(self.id.clone()) - .controller(did_peer_4.did().clone()) + .controller(did_peer_4.short_form().clone()) .verification_method_type(self.verification_method_type) .public_key(self.public_key.clone()) .build() diff --git a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo4/mod.rs b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo4/mod.rs index 0547386b27..a7af761137 100644 --- a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo4/mod.rs +++ b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo4/mod.rs @@ -19,6 +19,8 @@ impl Numalgo for Numalgo4 { } impl PeerDid { + /// Implementation of did:peer:4 creation spec: + /// https://identity.foundation/peer-did-method-spec/#creating-a-did pub fn new(encoded_document: DidPeer4ConstructionDidDocument) -> Result { let serialized = serde_json::to_string(&encoded_document)?; let mut prefixed_bytes = Vec::new(); @@ -26,11 +28,6 @@ impl PeerDid { prefixed_bytes.push(0x00u8); prefixed_bytes.extend_from_slice(serialized.as_bytes()); let encoded_document = multibase::encode(multibase::Base::Base58Btc, prefixed_bytes); - // Take SHA2-256 digest of the encoded document (encode the bytes as utf-8) - // Prefix these bytes with the multihash prefix for SHA2-256 and the hash length (varint - // 0x12 for prefix, varint 0x20 for 32 bytes in length) Multibase encode the bytes - // as base58btc (base58 encode the value and prefix with a z) Consider this value - // the hash let hash_raw = sha256::digest(&encoded_document); let prefix = vec![0x12u8, 0x20u8]; let hash = multibase::encode( @@ -53,21 +50,30 @@ impl PeerDid { Ok(self.did().clone()) } - pub fn short_form(&self) -> Result { - let short_id = self - .did() - .id() - .to_string() - .split(':') - .collect::>()[0] - .to_string(); - Did::parse(format!("did:peer:{}", short_id)).map_err(|e| { + pub fn short_form(&self) -> Did { + let parts = self.did().id().split(':').collect::>(); + let short_form_id = match parts.first() { + None => { + return self.did().clone(); // the DID was short form already + } + Some(hash_part) => hash_part, + }; + let short_form_did = format!("did:peer:{}", short_form_id); + let parse_result = Did::parse(short_form_did).map_err(|e| { DidPeerError::GeneralError(format!("Failed to parse short form of PeerDid: {}", e)) - }) + }); + // ** safety note (panic) ** + // This should only panic if the parser is inherently buggy. We rely on following + // assumptions: + // - `did:peer:` is a valid DID prefix + // - `short_form_did` is substring/prefix of `self.id()`, without colons, and therefore + // valid DID ID + // - every peer-did includes hash component followed prefix "did:peer:" + parse_result.expect("Failed to parse short form of PeerDid") } pub fn hash(&self) -> Result { - let short_form_did = self.short_form()?; + let short_form_did = self.short_form(); let hash = short_form_did.id()[1..].to_string(); // the first character of id did:peer:4 ID is always "4", followed by hash Ok(hash) } @@ -126,6 +132,16 @@ mod tests { PeerDid, }; + fn prepare_verification_method(key_id: &str) -> DidPeer4VerificationMethod { + DidPeer4VerificationMethod::builder() + .id(DidUrl::parse(key_id.to_string()).unwrap()) + .verification_method_type(VerificationMethodType::Ed25519VerificationKey2020) + .public_key(PublicKeyField::Base58 { + public_key_base58: "z27uFkiq".to_string(), + }) + .build() + } + #[test] fn test_create_did_peer_4() { let service = Service::new( @@ -134,26 +150,45 @@ mod tests { OneOrList::One(ServiceType::DIDCommV2), HashMap::default(), ); - let vm = DidPeer4VerificationMethod::builder() - .id(DidUrl::parse("#key-1".to_string()).unwrap()) - .verification_method_type(VerificationMethodType::Ed25519VerificationKey2020) - .public_key(PublicKeyField::Base58 { - public_key_base58: "z27uFkiq".to_string(), - }) - .build(); + let vm = prepare_verification_method("#shared-key-1"); + let vm_ka = prepare_verification_method("#key_agreement-1"); + let vm_auth = prepare_verification_method("#key-authentication-1"); + let vm_deleg = prepare_verification_method("#key-delegation-1"); + let vm_invoc = prepare_verification_method("#key-invocation-1"); let mut construction_did_doc = DidPeer4ConstructionDidDocument::new(); construction_did_doc.add_service(service); construction_did_doc.add_verification_method(vm); - log::info!( - "original didpeer4 document: {}", - serde_json::to_string_pretty(&construction_did_doc).unwrap() - ); + construction_did_doc.add_key_agreement(vm_ka); + construction_did_doc.add_authentication(vm_auth); + construction_did_doc.add_capability_delegation(vm_deleg); + construction_did_doc.add_capability_invocation(vm_invoc); + let did = PeerDid::::new(construction_did_doc).unwrap(); - assert_eq!(did.to_string(), "did:peer:4z84Vmeih9kTUrnxVanw9DhiVX9JNuW5cEz1RJx9dwrKcqh4bq96Z6zuc9m6oPV4gc6tafguyzd8dYih4N153Gh3XmWK:z2FrKwFgfDgrV5fdpSvPvBThURtNvDa3RWfoueUsEVQQmzJpMxXhAiutkPRRbuvVVeJDMZd2wdjeeNsRPx1csnDyQsoyhQWviaBd2LRen8fp9vZSkzmFmP1sgoKDXztkREhiUnKbXCiArA6t2nKed2NoGALYXFw1D72NbSgEhcMVzLL2wwgovV4D1HhEcvzXJQDKXwqUDaW1B3YgCMBKeEvy4vsaYhxf7JFcZzS5Ga8mSSUk3nAC9nXMWG3GT8XxzviQWxdfB2fwyKoy3bC3ihxwwjkpxVNuB72mJ"); + let did_expected = "did:peer:4z84UnqbnKs1uK42FKCz3QCr6JFMFYBZk2cPzkhHXETruZZpcdu6PtPyxzRdTYEdq7jWTWtqKykYxbtgmx34DUqyYEnT:zKj4qM7Uj9TKfiRp9DfxJMy1X7vBJEG9p7GnBbLLhA226Yh1SoYrcK942ZmBpAQXuXLLkohiPdJAYjbaatt2fFmhBvSR39zWMsWNqGBqmKW8vuy7uHwXKmuChtngE1WyMCM8r5DvwjubumVYq8uZWaurrdvzkdX57aM5y32kH5oFYjpBFDmugQAvzYP1VkTL8zF3G6wVHKvdAAzp8KracRWF7M6KnPHz3psRJ41Lktdk4NyNTfPZc1ztFV1v95ECazdRKwpFwmyZ9Gs5JhSCx1zYd9Ki4Zongb1VBCgFNVCjiADoUDfkNKoVu4QfzFGd1wCQEJFaYTcZ9N55r5cY215bAHq9fudyUvn2EeGd8FCfPyHPZxHZE5yFsKXmtauTLGJyFuWt31Kk31JN35zRui4nu3HRcnQNmkxADjVYnC7o4cb1D1DYKk2i3xL7mSwsDXUg2NN4mXfnM2JN6WFmGrDe2wKiKW4qc6w4RtmzGPN68LJVDh49dpwsaZM4hdkWc8s1D8mztRBbMDxKtJkDeZE23kpHCMfcfzQQCcPdpoXnpsNMoFaWh1q96cp72J1yNN4bQnSNxzNvMLjfdatmZrrqCkYd8ND4qU5eaE4HibjNsfx87dR2FN6mor8ktrXDirp1JezwU3NepeeHfs5EnY8V4aeMw3LAAEv4qrVTnr4jYmQHdfYVRJnP3qGkWwuHB2x9QhhMy8M4j5xHkNtVdV8Z9CFFuUGrnrPKvBMn2P5W5G3b4MxnWydmDdhdwirQAmHpJwRFoMDW9R55ckGhA6ZVo88BMwwCtKkeWibTHxjcHYdahYjYKzC6ZJGzU3DfHdmcprrN2oLRDcEPDxe6EejPSUu12iTHsCCV9r3txtuC2hvkRtmsgLChVD4Fh6VH22SzetPf513mToJvjfdVSdqaiftxj6"; + assert_eq!(did.to_string(), did_expected); let resolved_did_doc = did.resolve_did_doc().unwrap(); + println!( + "resolved document: {}", + serde_json::to_string_pretty(&resolved_did_doc).unwrap() + ); assert_eq!(resolved_did_doc.id().to_string(), did.did().to_string()); + assert!(resolved_did_doc + .verification_method_by_id("shared-key-1") + .is_some()); + assert!(resolved_did_doc + .key_agreement_by_id("key_agreement-1") + .is_some()); + assert!(resolved_did_doc + .authentication_by_id("key-authentication-1") + .is_some()); + assert!(resolved_did_doc + .capability_delegation_by_id("key-delegation-1") + .is_some()); + assert!(resolved_did_doc + .capability_invocation_by_id("key-invocation-1") + .is_some()); log::info!( "resolved document: {}", serde_json::to_string_pretty(&resolved_did_doc).unwrap() @@ -164,14 +199,14 @@ mod tests { fn long_form_to_short_form() { let peer_did = "did:peer:4z84UjLJ6ugExV8TJ5gJUtZap5q67uD34LU26m1Ljo2u9PZ4xHa9XnknHLc3YMST5orPXh3LKi6qEYSHdNSgRMvassKP:z27uFkiqJVwvvn2ke5M19UCvByS79r5NppqwjiGAJzkj1EM4sf2JmiUySkANKy4YNu8M7yKjSmvPJTqbcyhPrJs9TASzDs2fWE1vFegmaRJxHRF5M9wGTPwGR1NbPkLGsvcnXum7aN2f8kX3BnhWWWp"; let peer_did = PeerDid::::parse(peer_did).unwrap(); - assert_eq!(peer_did.short_form().unwrap().to_string(), "did:peer:4z84UjLJ6ugExV8TJ5gJUtZap5q67uD34LU26m1Ljo2u9PZ4xHa9XnknHLc3YMST5orPXh3LKi6qEYSHdNSgRMvassKP".to_string()); + assert_eq!(peer_did.short_form().to_string(), "did:peer:4z84UjLJ6ugExV8TJ5gJUtZap5q67uD34LU26m1Ljo2u9PZ4xHa9XnknHLc3YMST5orPXh3LKi6qEYSHdNSgRMvassKP".to_string()); } #[test] fn short_form_to_short_form() { let peer_did = "did:peer:4z84UjLJ6ugExV8TJ5gJUtZap5q67uD34LU26m1Ljo2u9PZ4xHa9XnknHLc3YMST5orPXh3LKi6qEYSHdNSgRMvassKP"; let peer_did = PeerDid::::parse(peer_did).unwrap(); - assert_eq!(peer_did.short_form().unwrap().to_string(), "did:peer:4z84UjLJ6ugExV8TJ5gJUtZap5q67uD34LU26m1Ljo2u9PZ4xHa9XnknHLc3YMST5orPXh3LKi6qEYSHdNSgRMvassKP".to_string()); + assert_eq!(peer_did.short_form().to_string(), "did:peer:4z84UjLJ6ugExV8TJ5gJUtZap5q67uD34LU26m1Ljo2u9PZ4xHa9XnknHLc3YMST5orPXh3LKi6qEYSHdNSgRMvassKP".to_string()); } #[test]