Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Support DIDExchange 1.1 #1228 #1230

Merged
merged 26 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
edf4718
move existing into v1_0 section
gmulhearn-anonyome Jun 18, 2024
ab67558
duplicate types
gmulhearn-anonyome Jun 18, 2024
0354cb8
static generic types for messages created and piped thru all layers
gmulhearn-anonyome Jun 18, 2024
807e425
simplify generics
gmulhearn-anonyome Jun 19, 2024
e8b4e05
change approach to use runtime versioning rather than generics
gmulhearn-anonyome Jun 19, 2024
a020458
v1_1 branch processing, and some clippy
gmulhearn-anonyome Jun 19, 2024
f870743
remove old todos
gmulhearn-anonyome Jun 19, 2024
b1cbe84
fixes for aath with self for 4/7 performance on RFC0793 & 4/7 on 0023
gmulhearn-anonyome Jun 19, 2024
b913674
smalls patches from acapy testing
gmulhearn-anonyome Jun 19, 2024
5c1f6da
fix up mimetype handling as a result of testing acapy (text/string)
gmulhearn-anonyome Jun 19, 2024
494f8c8
handle multikey (acapy uses this)
gmulhearn-anonyome Jun 19, 2024
6ec33a4
make invite handshake 1.1
gmulhearn-anonyome Jun 19, 2024
a5ae36f
include invitation id
gmulhearn-anonyome Jun 19, 2024
83a2510
pthid in response (for acapy)
gmulhearn-anonyome Jun 19, 2024
98cfd54
Merge branch 'main' into gm/1228-did-exch-1_1
gmulhearn-anonyome Jun 19, 2024
5a5e327
merge fix and add hack for local aath testing
gmulhearn-anonyome Jun 19, 2024
c173cda
fixes for didpeer2
gmulhearn-anonyome Jun 20, 2024
55a7991
improve VM handling to understand more DIDDoc styles (acapy AATH test…
gmulhearn-anonyome Jun 20, 2024
3121644
fmt
gmulhearn-anonyome Jun 21, 2024
ba3570a
clean switcher
gmulhearn-anonyome Jun 21, 2024
9866a2a
label pass, and some fixes
gmulhearn-anonyome Jun 21, 2024
7ad8670
test fixes
gmulhearn-anonyome Jun 21, 2024
ed46a35
fix did rotate content
gmulhearn-anonyome Jun 24, 2024
5f5133d
pass in handshake ver
gmulhearn-anonyome Jun 24, 2024
6a054c6
any-wrapper approach
gmulhearn-anonyome Jun 26, 2024
8265ec1
lint
gmulhearn-anonyome Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 81 additions & 46 deletions aries/agents/aath-backchannel/src/controllers/did_exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ use actix_web::{get, post, web, Responder};
use aries_vcx_agent::aries_vcx::{
did_parser_nom::Did,
messages::{
msg_fields::protocols::did_exchange::{request::Request, DidExchange},
msg_fields::protocols::did_exchange::{
v1_0::DidExchangeV1_0, v1_1::DidExchangeV1_1, v1_x::request::Request, DidExchange,
},
AriesMessage,
},
protocols::did_exchange::state_machine::requester::helpers::invitation_get_first_did_service,
protocols::did_exchange::state_machine::requester::helpers::{
invitation_get_acceptable_did_exchange_version, invitation_get_first_did_service,
},
};
use serde_json::Value;

use crate::{
controllers::AathRequest,
Expand All @@ -32,11 +37,13 @@ impl HarnessAgent {
.aries_agent
.out_of_band()
.get_invitation(&invitation_id)?;

let version = invitation_get_acceptable_did_exchange_version(&invitation)?;
let did_inviter: Did = invitation_get_first_did_service(&invitation)?;
let (thid, pthid) = self
let (thid, pthid, my_did) = self
.aries_agent
.did_exchange()
.handle_msg_invitation(did_inviter.to_string(), Some(invitation_id))
.handle_msg_invitation(did_inviter.to_string(), Some(invitation_id), version)
.await?;
if let Some(ref pthid) = pthid {
self.store_mapping_pthid_thid(pthid.clone(), thid.clone());
Expand All @@ -46,18 +53,23 @@ impl HarnessAgent {
);
}
let connection_id = pthid.unwrap_or(thid);
Ok(json!({ "connection_id" : connection_id }).to_string())
Ok(json!({
"connection_id" : connection_id,
"my_did": my_did
})
.to_string())
}

pub fn queue_didexchange_request(&self, request: Request) -> HarnessResult<()> {
info!("queue_didexchange_request >> request: {}", request);
info!("queue_didexchange_request >> request: {:?}", request);
let mut msg_buffer = self.didx_msg_buffer.write().map_err(|_| {
HarnessError::from_msg(
HarnessErrorType::InvalidState,
"Failed to lock message buffer",
)
})?;
msg_buffer.push(request.into());
let m = AriesMessage::from(request);
msg_buffer.push(m);
Ok(())
}

Expand All @@ -66,13 +78,17 @@ impl HarnessAgent {
&self,
req: &CreateResolvableDidRequest,
) -> HarnessResult<String> {
let (thid, pthid) = self
let (thid, pthid, my_did) = self
.aries_agent
.did_exchange()
.handle_msg_invitation(req.their_public_did.clone(), None) // todo: separate the case with/without invitation on did_exchange handler
.handle_msg_invitation(req.their_public_did.clone(), None, Default::default()) // todo: separate the case with/without invitation on did_exchange handler
.await?;
let connection_id = pthid.unwrap_or(thid);
Ok(json!({ "connection_id": connection_id }).to_string())
Ok(json!({
"connection_id": connection_id,
"my_did": my_did
})
.to_string())
}

// Looks up an oldest unprocessed did-exchange request message
Expand All @@ -98,15 +114,21 @@ impl HarnessAgent {
})?
.clone()
};
if let AriesMessage::DidExchange(DidExchange::Request(ref request)) = request {
let thid = request.decorators.thread.clone().unwrap().thid;
Ok(json!({ "connection_id": thid }).to_string())
} else {
Err(HarnessError::from_msg(
HarnessErrorType::InvalidState,
"Message is not a request",
))
}
let request = match request {
AriesMessage::DidExchange(DidExchange::V1_0(DidExchangeV1_0::Request(request)))
| AriesMessage::DidExchange(DidExchange::V1_1(DidExchangeV1_1::Request(request))) => {
request
}
_ => {
return Err(HarnessError::from_msg(
HarnessErrorType::InvalidState,
"Message is not a request",
))
}
};

let thid = request.decorators.thread.clone().unwrap().thid;
Ok(json!({ "connection_id": thid }).to_string())
}

// Note: AVF identifies protocols by thid, but AATH sometimes tracks identifies did-exchange
Expand Down Expand Up @@ -139,37 +161,50 @@ impl HarnessAgent {
)
})?
};
if let AriesMessage::DidExchange(DidExchange::Request(request)) = request {
let opt_invitation = match request.decorators.thread.clone().unwrap().pthid {
None => None,
Some(pthid) => {
let invitation = self.aries_agent.out_of_band().get_invitation(&pthid)?;
Some(invitation)
}
};
let (thid, pthid) = self
.aries_agent
.did_exchange()
.handle_msg_request(request.clone(), opt_invitation)
.await?;
let request = match request {
AriesMessage::DidExchange(DidExchange::V1_0(DidExchangeV1_0::Request(request)))
| AriesMessage::DidExchange(DidExchange::V1_1(DidExchangeV1_1::Request(request))) => {
request
}
_ => {
return Err(HarnessError::from_msg(
HarnessErrorType::InvalidState,
"Message is not a request",
))
}
};

if let Some(pthid) = pthid {
self.store_mapping_pthid_thid(pthid, thid.clone());
} else {
warn!("No storing pthid->this mapping; no pthid available");
let request_thread = &request.decorators.thread;

let opt_invitation = match request_thread.as_ref().and_then(|th| th.pthid.as_ref()) {
Some(pthid) => {
let invitation = self.aries_agent.out_of_band().get_invitation(pthid)?;
Some(invitation)
}
None => None,
};
let (thid, pthid, my_did, their_did) = self
.aries_agent
.did_exchange()
.handle_msg_request(request, opt_invitation)
.await?;

self.aries_agent
.did_exchange()
.send_response(thid.clone())
.await?;
Ok(json!({ "connection_id": thid }).to_string())
if let Some(pthid) = pthid {
self.store_mapping_pthid_thid(pthid, thid.clone());
} else {
Err(HarnessError::from_msg(
HarnessErrorType::InvalidState,
"Message is not a request",
))
warn!("No storing pthid->this mapping; no pthid available");
}

self.aries_agent
.did_exchange()
.send_response(thid.clone())
.await?;
Ok(json!({
"connection_id": thid,
"my_did": my_did,
"their_did": their_did
})
.to_string())
}

pub async fn didx_get_state(&self, connection_id: &str) -> HarnessResult<String> {
Expand Down Expand Up @@ -200,7 +235,7 @@ impl HarnessAgent {

#[post("/send-request")]
async fn send_did_exchange_request(
req: web::Json<AathRequest<()>>,
req: web::Json<AathRequest<Value>>,
agent: web::Data<RwLock<HarnessAgent>>,
) -> impl Responder {
agent
Expand Down
25 changes: 19 additions & 6 deletions aries/agents/aath-backchannel/src/controllers/didcomm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use aries_vcx_agent::aries_vcx::{
msg_fields::protocols::{
connection::Connection,
cred_issuance::{v1::CredentialIssuanceV1, CredentialIssuance},
did_exchange::DidExchange,
did_exchange::{v1_0::DidExchangeV1_0, v1_1::DidExchangeV1_1, DidExchange},
notification::Notification,
present_proof::{v1::PresentProofV1, PresentProof},
},
Expand Down Expand Up @@ -197,25 +197,38 @@ impl HarnessAgent {

async fn handle_did_exchange_msg(&self, msg: DidExchange) -> HarnessResult<()> {
match msg {
DidExchange::Request(request) => {
DidExchange::V1_0(DidExchangeV1_0::Request(request))
| DidExchange::V1_1(DidExchangeV1_1::Request(request)) => {
self.queue_didexchange_request(request)?;
}
DidExchange::Response(response) => {
DidExchange::V1_0(DidExchangeV1_0::Response(response)) => {
let res = self
.aries_agent
.did_exchange()
.handle_msg_response(response)
.handle_msg_response(response.into())
.await;
if let Err(err) = res {
error!("Error sending complete: {:?}", err);
};
}
DidExchange::Complete(complete) => {
DidExchange::V1_1(DidExchangeV1_1::Response(response)) => {
let res = self
.aries_agent
.did_exchange()
.handle_msg_response(response.into())
.await;
if let Err(err) = res {
error!("Error sending complete: {:?}", err);
};
}
DidExchange::V1_0(DidExchangeV1_0::Complete(complete))
| DidExchange::V1_1(DidExchangeV1_1::Complete(complete)) => {
self.aries_agent
.did_exchange()
.handle_msg_complete(complete)?;
}
DidExchange::ProblemReport(problem_report) => {
DidExchange::V1_0(DidExchangeV1_0::ProblemReport(problem_report))
| DidExchange::V1_1(DidExchangeV1_1::ProblemReport(problem_report)) => {
self.aries_agent
.did_exchange()
.receive_problem_report(problem_report)?;
Expand Down
51 changes: 30 additions & 21 deletions aries/agents/aries-vcx-agent/src/handlers/did_exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ use aries_vcx::{
did_parser_nom::Did,
messages::{
msg_fields::protocols::{
did_exchange::{
did_exchange::v1_x::{
complete::Complete, problem_report::ProblemReport, request::Request,
response::Response,
response::AnyResponse,
},
out_of_band::invitation::Invitation as OobInvitation,
},
msg_types::protocols::did_exchange::DidExchangeTypeV1,
AriesMessage,
},
protocols::did_exchange::{
Expand Down Expand Up @@ -63,17 +64,21 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {
&self,
their_did: String,
invitation_id: Option<String>,
) -> AgentResult<(String, Option<String>)> {
version: DidExchangeTypeV1,
) -> AgentResult<(String, Option<String>, String)> {
// todo: type the return type
let (our_peer_did, _our_verkey) =
create_peer_did_4(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]).await?;
let our_did = our_peer_did.did().to_string();

let their_did: Did = their_did.parse()?;
let (requester, request) = GenericDidExchange::construct_request(
self.resolver_registry.clone(),
invitation_id,
&their_did,
&our_peer_did,
"".to_owned(),
version,
)
.await?;

Expand Down Expand Up @@ -127,7 +132,7 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {
VcxHttpClient
.send_message(encryption_envelope.0, service.service_endpoint())
.await?;
Ok((thid, pthid))
Ok((thid, pthid, our_did))
}

// todo: whether invitation exists should handle the framework based on (p)thread matching
Expand All @@ -136,21 +141,21 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {
&self,
request: Request,
invitation: Option<OobInvitation>,
) -> AgentResult<(String, Option<String>)> {
) -> AgentResult<(String, Option<String>, String, String)> {
// todo: type the return type
// Todo: messages should expose fallible API to get thid (for any aries msg). It's common
// pattern
let thid = request
.clone()
.decorators
.thread
let thread = request.decorators.thread.as_ref();

let thid = thread
.ok_or_else(|| {
AgentError::from_msg(
AgentErrorKind::InvalidState,
"Request did not contain a thread id",
)
})?
.thid;
.thid
.clone();

// Todo: "invitation_key" should not be None; see the todo inside this scope
let invitation_key = match invitation {
Expand All @@ -165,34 +170,34 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {
}
};

let (peer_did_4_invitee, _our_verkey) =
let (our_peer_did, _our_verkey) =
create_peer_did_4(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]).await?;

let pthid = request
.clone()
.decorators
.thread
.clone()
let pthid = thread
.ok_or_else(|| {
AgentError::from_msg(
AgentErrorKind::InvalidState,
"Request did not contain a thread",
)
})?
.pthid;
.pthid
.clone();

let (responder, response) = GenericDidExchange::handle_request(
self.wallet.as_ref(),
self.resolver_registry.clone(),
request,
&peer_did_4_invitee,
&our_peer_did,
invitation_key,
)
.await?;
self.did_exchange
.insert(&thid, (responder.clone(), Some(response.into())))?;

Ok((thid, pthid))
let our_did = responder.our_did_document().id().to_string();
let their_did = responder.their_did_doc().id().to_string();

Ok((thid, pthid, our_did, their_did))
}

// todo: perhaps injectable transports? Or just return the message let the caller send it?
Expand Down Expand Up @@ -225,8 +230,12 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {
}

// todo: break down into "process_response" and "send_complete"
pub async fn handle_msg_response(&self, response: Response) -> AgentResult<String> {
let thid = response.decorators.thread.thid.clone();
pub async fn handle_msg_response(&self, response: AnyResponse) -> AgentResult<String> {
let thread = match response {
AnyResponse::V1_0(ref inner) => &inner.decorators.thread,
AnyResponse::V1_1(ref inner) => &inner.decorators.thread,
};
let thid = thread.thid.clone();

let (requester, _) = self.did_exchange.get(&thid)?;

Expand Down
2 changes: 1 addition & 1 deletion aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl<T: BaseWallet> ServiceOutOfBand<T> {
let sender = OutOfBandSender::create()
.append_service(&OobService::Did(peer_did.to_string()))
.append_handshake_protocol(Protocol::DidExchangeType(DidExchangeType::V1(
DidExchangeTypeV1::new_v1_0(),
DidExchangeTypeV1::new_v1_1(),
)))?;

self.out_of_band.insert(
Expand Down
Loading
Loading