Skip to content

Commit

Permalink
hack: Enable did-exchange invitee protocol tracking by both thid and …
Browse files Browse the repository at this point in the history
…pthid

Signed-off-by: Patrik Stas <[email protected]>
  • Loading branch information
Patrik-Stas committed Mar 12, 2024
1 parent af2e543 commit 366f30e
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 10 deletions.
74 changes: 65 additions & 9 deletions aries/agents/rust/aries-vcx-agent/src/services/did_exchange.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::sync::Arc;

use aries_vcx::{
Expand Down Expand Up @@ -40,6 +41,7 @@ pub struct ServiceDidExchange {
resolver_registry: Arc<ResolverRegistry>,
service_endpoint: ServiceEndpoint,
did_exchange: Arc<ObjectCache<GenericDidExchange>>,
pthid_to_thid: HashMap<String, String>,
public_did: String,
}

Expand All @@ -60,7 +62,7 @@ impl ServiceDidExchange {
}

pub async fn send_request(
&self,
&mut self,
their_did: String,
invitation_id: String,
) -> AgentResult<String> {
Expand All @@ -77,6 +79,32 @@ impl ServiceDidExchange {
&our_peer_did,
)
.await?;

// TODO: decouple this from AATH. The reason why we identify the requester's did-exchange
// protocol with pthid is because that's what AATH expects when calling GET
// /agent/command/did-exchange/{id} where {id} is actually {pthid}.
// We should have internal strategy to manage threads ourselves, and build necessary
// extensions/mappings/accommodations in AATH backchannel
warn!("send_request >>> request: {}", request);
let pthid = request
.clone()
.decorators
.thread
.ok_or_else(|| {
AgentError::from_msg(
AgentErrorKind::InvalidState,
"Request did not contain a thread",
)
})?
.pthid
.ok_or_else(|| {
AgentError::from_msg(
AgentErrorKind::InvalidState,
"Request did not contain a pthread id",
)
})?;

// todo: messages must provide easier way to access this without all the shenanigans
let thid = request
.clone()
.decorators
Expand All @@ -88,6 +116,7 @@ impl ServiceDidExchange {
)
})?
.thid;

let ddo_their = requester.their_did_doc();
let ddo_our = requester.our_did_document();
let service = ddo_their.get_service_of_type(&ServiceType::DIDCommV1)?;
Expand All @@ -99,25 +128,30 @@ impl ServiceDidExchange {
service.id(),
)
.await?;
// todo: hack; There's issue on AATH level https://github.com/hyperledger/aries-agent-test-harness/issues/784
// but if AATH can not be changed and both thid and pthid are used to track instance
// of protocol then we need to update storage to enable identification by
// multiple IDs (both thid, pthid (or arbitrary other))
self.pthid_to_thid.insert(pthid.clone(), thid.clone())?;
self.did_exchange.insert(&thid, requester.clone())?;
VcxHttpClient
.send_message(encryption_envelope.0, service.service_endpoint())
.await?;
Ok(thid)
Ok(pthid)
}

// todo: one would expect this to be just IO utility - split this to process_request / process_response
// send_response
// todo: one would expect this to be just IO utility - split this to process_request /
// process_response send_response
pub async fn send_response(
&self,
request: Request,
invitation: OobInvitation,
) -> AgentResult<String> {
// 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.
// We don't want to be sending response if we don't know if there is any invitation
// associated with the request.
// Todo: messages should expose fallible API to get thid (for any aries msg). It's common
// pattern
// pattern
let thid = request
.clone()
.decorators
Expand Down Expand Up @@ -164,6 +198,7 @@ impl ServiceDidExchange {

pub async fn send_complete(&self, response: Response) -> AgentResult<String> {
let thid = response.decorators.thread.thid.clone();

let (requester, complete) = self
.did_exchange
.get(&thid)?
Expand Down Expand Up @@ -217,8 +252,29 @@ impl ServiceDidExchange {
self.public_did.as_ref()
}

pub fn get_state(&self, thread_id: &str) -> AgentResult<ThinState> {
Ok(self.did_exchange.get(thread_id)?.get_state())
// TODO: this 'thread_or_pthread' ugliness exists because in case of inviter, AATH identifies
// the instance of protocol by thid, but for invitee, it expects identification by pthid
// Created issue https://github.com/hyperledger/aries-agent-test-harness/issues/784
pub fn get_state(&self, thread_or_pthread: &str) -> AgentResult<ThinState> {
let thid = thread_or_pthread; // initially we assume we work with thid
let state = match self.did_exchange.get(thid) {
Ok(protocol) => {protocol.get_state()}
Err(_) => {
warn!("Failed to resolve did-exchange id {} as thid, trying to get state by pthid", thread_or_pthread);
let pthid = thread_or_pthread; // apparently we were dealing with pthid
let thid = self.pthid_to_thid.get(pthid)?;
match self.did_exchange.get(thid) {
Ok(protocol) => {protocol.get_state()}
Err(_) => {
return Err(AgentError::from_msg(
AgentErrorKind::InvalidState,
&format!("Failed to resolve did-exchange id {} as thid or pthid", thread_or_pthread),
))
}
}
}
};
Ok(state)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn construct_didexchange_complete(request_id: String, invitation_id: String)
.thread(
Thread::builder()
.thid(request_id)
.pthid(invitation_id)
.pthid(invitation_id) // did-exchange specified pthread must be present in the <complete> message type
.build(),
)
.timing(Timing::builder().out_time(Utc::now()).build())
Expand Down

0 comments on commit 366f30e

Please sign in to comment.