Skip to content

Commit

Permalink
Handle problem report, get invitation id
Browse files Browse the repository at this point in the history
Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
  • Loading branch information
mirgee authored and Patrik-Stas committed Nov 1, 2023
1 parent 5a63a13 commit a821d0e
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 38 deletions.
29 changes: 22 additions & 7 deletions agents/rust/aries-vcx-agent/src/services/did_exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;
use aries_vcx::{
core::profile::profile::Profile,
messages::msg_fields::protocols::{
did_exchange::{complete::Complete, request::Request, response::Response},
did_exchange::{complete::Complete, problem_report::ProblemReport, request::Request, response::Response},
out_of_band::invitation::Invitation as OobInvitation,
},
protocols::{
Expand Down Expand Up @@ -152,8 +152,9 @@ impl ServiceDidExchange {
self.did_exchange.insert(&request_id, responder.clone().into())
}

pub async fn send_complete(&self, thread_id: &str, response: Response) -> AgentResult<String> {
let (requester, complete) = self.did_exchange.get(thread_id)?.handle_response(response).await?;
pub async fn send_complete(&self, response: Response) -> AgentResult<String> {
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(),
Expand All @@ -168,18 +169,32 @@ impl ServiceDidExchange {
&HttpClient,
)
.await?;
self.did_exchange.insert(thread_id, requester.clone().into())
self.did_exchange.insert(&thread_id, requester.clone().into())
}

pub async fn receive_complete(&self, thread_id: &str, complete: Complete) -> AgentResult<String> {
let requester = self.did_exchange.get(thread_id)?.handle_complete(complete)?;
self.did_exchange.insert(thread_id, requester)
pub fn receive_complete(&self, complete: Complete) -> AgentResult<String> {
let thread_id = complete.decorators.thread.thid.clone();
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<String> {
let thread_id = problem_report.decorators.thread.thid.clone();
let requester = self
.did_exchange
.get(&thread_id)?
.handle_problem_report(problem_report)?;
self.did_exchange.insert(&thread_id, requester)
}

pub fn exists_by_id(&self, thread_id: &str) -> bool {
self.did_exchange.contains_key(thread_id)
}

pub fn invitation_id(&self, thread_id: &str) -> AgentResult<String> {
Ok(self.did_exchange.get(thread_id)?.invitation_id().to_string())
}

pub fn public_did(&self) -> &str {
self.public_did.as_ref()
}
Expand Down
81 changes: 79 additions & 2 deletions aries_vcx/src/protocols/did_exchange/state_machine/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ mod conversions;
mod thin_state;

use did_doc_sov::DidDocumentSov;
use messages::msg_fields::protocols::did_exchange::{complete::Complete, request::Request, response::Response};
use messages::msg_fields::protocols::did_exchange::{
complete::Complete, problem_report::ProblemReport, request::Request, response::Response,
};

use crate::{
errors::error::{AriesVcxError, AriesVcxErrorKind},
protocols::did_exchange::{
states::{completed::Completed, requester::request_sent::RequestSent, responder::response_sent::ResponseSent},
states::{
abandoned::Abandoned, completed::Completed, requester::request_sent::RequestSent,
responder::response_sent::ResponseSent,
},
transition::{transition_error::TransitionError, transition_result::TransitionResult},
},
};
Expand All @@ -29,12 +34,14 @@ pub enum GenericDidExchange {
pub enum RequesterState {
RequestSent(DidExchangeRequester<RequestSent>),
Completed(DidExchangeRequester<Completed>),
Abandoned(DidExchangeRequester<Abandoned>),
}

#[derive(Debug, Clone)]
pub enum ResponderState {
ResponseSent(DidExchangeResponder<ResponseSent>),
Completed(DidExchangeResponder<Completed>),
Abandoned(DidExchangeResponder<Abandoned>),
}

impl GenericDidExchange {
Expand All @@ -43,10 +50,12 @@ 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!(),
},
GenericDidExchange::Responder(responder_state) => match responder_state {
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!(),
},
}
}
Expand All @@ -56,10 +65,27 @@ impl GenericDidExchange {
GenericDidExchange::Requester(requester_state) => match requester_state {
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!(),
},
GenericDidExchange::Responder(responder_state) => match responder_state {
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!(),
},
}
}

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::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::Completed(completed_state) => completed_state.get_invitation_id(),
ResponderState::Abandoned(abandoned_state) => todo!(),
},
}
}
Expand Down Expand Up @@ -100,6 +126,13 @@ impl GenericDidExchange {
"Attempted to handle response in completed state",
),
)),
RequesterState::Abandoned(abandoned_state) => Err((
GenericDidExchange::Requester(RequesterState::Abandoned(abandoned_state)),
AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidState,
"Attempted to handle response in abandoned state",
),
)),
},
GenericDidExchange::Responder(responder) => Err((
GenericDidExchange::Responder(responder),
Expand Down Expand Up @@ -130,6 +163,13 @@ impl GenericDidExchange {
"Attempted to handle complete in completed state",
),
)),
ResponderState::Abandoned(_) => Err((
GenericDidExchange::Responder(responder_state),
AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidState,
"Attempted to handle complete in abandoned state",
),
)),
},
GenericDidExchange::Requester(requester_state) => Err((
GenericDidExchange::Requester(requester_state),
Expand All @@ -141,15 +181,52 @@ impl GenericDidExchange {
}
}

pub fn handle_problem_report(self, problem_report: ProblemReport) -> Result<Self, (Self, AriesVcxError)> {
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::Completed(completed_state) => Err((
GenericDidExchange::Requester(RequesterState::Completed(completed_state)),
AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidState,
"Attempted to handle problem report in completed state",
),
)),
RequesterState::Abandoned(abandoned_state) => Ok(GenericDidExchange::Requester(
RequesterState::Abandoned(abandoned_state),
)),
},
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::Completed(completed_state) => Err((
GenericDidExchange::Responder(ResponderState::Completed(completed_state)),
AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidState,
"Attempted to handle problem report in completed state",
),
)),
ResponderState::Abandoned(abandoned_state) => Ok(GenericDidExchange::Responder(
ResponderState::Abandoned(abandoned_state),
)),
},
}
}

pub fn get_state(&self) -> ThinState {
match self {
GenericDidExchange::Requester(requester_state) => match requester_state {
RequesterState::RequestSent(_) => ThinState::RequestSent,
RequesterState::Completed(_) => ThinState::Completed,
RequesterState::Abandoned(_) => ThinState::Abandoned,
},
GenericDidExchange::Responder(responder_state) => match responder_state {
ResponderState::ResponseSent(_) => ThinState::RequestSent,
ResponderState::Completed(_) => ThinState::Completed,
ResponderState::Abandoned(_) => ThinState::Abandoned,
},
}
}
Expand Down
14 changes: 13 additions & 1 deletion aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ use url::Url;

use crate::{
errors::error::{AriesVcxError, AriesVcxErrorKind},
protocols::mediated_connection::pairwise_info::PairwiseInfo,
protocols::{
did_exchange::transition::transition_error::TransitionError, mediated_connection::pairwise_info::PairwiseInfo,
},
utils::from_legacy_did_doc_to_sov,
};

Expand Down Expand Up @@ -162,3 +164,13 @@ pub fn attach_to_ddo_sov(attachment: Attachment) -> Result<DidDocumentSov, Aries
)),
}
}

pub fn to_transition_error<S, T>(state: S) -> impl FnOnce(T) -> TransitionError<S>
where
T: Into<AriesVcxError>,
{
move |error| TransitionError {
error: error.into(),
state,
}
}
28 changes: 23 additions & 5 deletions aries_vcx/src/protocols/did_exchange/state_machine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use std::marker::PhantomData;
use did_doc_sov::DidDocumentSov;

use super::{
states::{abandoned::Abandoned, traits::ThreadId},
states::{
abandoned::Abandoned,
traits::{InvitationId, ThreadId},
},
transition::transition_result::TransitionResult,
};

Expand Down Expand Up @@ -49,10 +52,7 @@ impl<I, S: ThreadId> DidExchange<I, S> {
self,
reason: String,
problem_code: Option<ProblemCode>,
) -> TransitionResult<DidExchange<I, Abandoned>, ProblemReport>
where
S: ThreadId,
{
) -> TransitionResult<DidExchange<I, Abandoned>, ProblemReport> {
let problem_report = {
let id = Uuid::new_v4().to_string();
let content = ProblemReportContent {
Expand Down Expand Up @@ -80,6 +80,24 @@ impl<I, S: ThreadId> DidExchange<I, S> {
output: problem_report,
}
}

pub fn receive_problem_report(self, problem_report: ProblemReport) -> DidExchange<I, Abandoned> {
DidExchange {
state: Abandoned {
reason: problem_report.clone().content.explain.unwrap_or_default(),
request_id: self.state.thread_id().to_string(),
},
initiation_type: PhantomData,
our_did_document: self.our_did_document,
their_did_document: self.their_did_document,
}
}
}

impl<I, S: InvitationId> DidExchange<I, S> {
pub fn get_invitation_id(&self) -> &str {
self.state.invitation_id()
}
}

impl<I, S> DidExchange<I, S> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ 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},
state_machine::helpers::{
attach_to_ddo_sov, create_our_did_document, ddo_sov_to_attach, jws_sign_attach, to_transition_error,
},
states::{completed::Completed, requester::request_sent::RequestSent},
transition::{transition_error::TransitionError, transition_result::TransitionResult},
},
Expand All @@ -38,12 +40,6 @@ impl DidExchangeRequester<RequestSent> {
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 signed_attach = jws_sign_attach(
ddo_sov_to_attach(our_did_document.clone())?,
our_verkey.clone(),
&wallet,
)
.await?;
let request = construct_request(invitation.id.clone(), our_did_document.id().to_string())?;

Ok(TransitionResult {
Expand Down Expand Up @@ -79,7 +75,6 @@ impl DidExchangeRequester<RequestSent> {
"No verification method in requester's did document",
))?
.public_key()?;
let signed_attach = jws_sign_attach(ddo_sov_to_attach(our_did_document.clone())?, key, &wallet).await?;
let request = construct_request(invitation_id.clone(), our_did.to_string())?;

Ok(TransitionResult {
Expand Down Expand Up @@ -118,28 +113,19 @@ impl DidExchangeRequester<RequestSent> {
});
}
let did_document = if let Some(ddo) = response.content.did_doc {
attach_to_ddo_sov(ddo).map_err(|error| TransitionError {
error,
state: self.clone(),
})?
attach_to_ddo_sov(ddo).map_err(to_transition_error(self.clone()))?
} else {
PeerDidResolver::new()
.resolve(
&response
.content
.did
.parse()
.map_err(|error: ParseError| TransitionError {
error: error.into(),
state: self.clone(),
})?,
.map_err(to_transition_error(self.clone()))?,
&Default::default(),
)
.await
.map_err(|error: GenericError| TransitionError {
error: error.into(),
state: self.clone(),
})?
.map_err(to_transition_error(self.clone()))?
.did_document()
.to_owned()
.into()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ impl DidExchangeResponder<ResponseSent> {
));
}

// 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?;

Expand Down
8 changes: 7 additions & 1 deletion aries_vcx/src/protocols/did_exchange/states/completed.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::clone::Clone;

use super::traits::ThreadId;
use super::traits::{InvitationId, ThreadId};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Completed {
Expand All @@ -13,3 +13,9 @@ impl ThreadId for Completed {
self.request_id.as_str()
}
}

impl InvitationId for Completed {
fn invitation_id(&self) -> &str {
self.invitation_id.as_str()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::protocols::did_exchange::states::traits::ThreadId;
use crate::protocols::did_exchange::states::traits::{InvitationId, ThreadId};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RequestSent {
Expand All @@ -11,3 +11,9 @@ impl ThreadId for RequestSent {
self.request_id.as_str()
}
}

impl InvitationId for RequestSent {
fn invitation_id(&self) -> &str {
self.invitation_id.as_str()
}
}
Loading

0 comments on commit a821d0e

Please sign in to comment.