Skip to content

Commit

Permalink
Handle trust pings in the AATH backchannel (#1254)
Browse files Browse the repository at this point in the history
* handle trust ping

Signed-off-by: George Mulhearn <[email protected]>

* clipppy

Signed-off-by: George Mulhearn <[email protected]>

---------

Signed-off-by: George Mulhearn <[email protected]>
Co-authored-by: George Mulhearn <[email protected]>
  • Loading branch information
gmulhearn and gmulhearn-anonyome authored Jul 15, 2024
1 parent 398af5b commit 08bea95
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 68 deletions.
82 changes: 28 additions & 54 deletions aries/agents/aath-backchannel/src/controllers/didcomm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use aries_vcx_agent::aries_vcx::{
},
notification::Notification,
present_proof::{v1::PresentProofV1, PresentProof},
trust_ping::TrustPing,
},
AriesMessage,
},
Expand Down Expand Up @@ -75,14 +76,10 @@ impl HarnessAgent {
async fn handle_issuance_msg(
&self,
msg: CredentialIssuance,
connection_ids: Vec<String>,
sender_vk: &str,
connection_id: &str,
) -> HarnessResult<()> {
match msg {
CredentialIssuance::V1(msg) => {
self.handle_issuance_msg_v1(msg, connection_ids, sender_vk)
.await
}
CredentialIssuance::V1(msg) => self.handle_issuance_msg_v1(msg, connection_id).await,
CredentialIssuance::V2(_) => {
unimplemented!("V2 issuance is not implemented for aries-vcx aath")
}
Expand All @@ -92,35 +89,19 @@ impl HarnessAgent {
async fn handle_issuance_msg_v1(
&self,
msg: CredentialIssuanceV1,
connection_ids: Vec<String>,
sender_vk: &str,
connection_id: &str,
) -> HarnessResult<()> {
let connection_id = connection_ids.last();
match msg {
CredentialIssuanceV1::OfferCredential(offer) => {
if connection_ids.len() == 1 {
self.aries_agent
.holder()
.create_from_offer(connection_id.unwrap(), offer.clone())?;
} else {
return Err(HarnessError::from_msg(
HarnessErrorType::InvalidState,
&format!("Found multiple or no connections by verkey {}", sender_vk),
));
}
self.aries_agent
.holder()
.create_from_offer(connection_id, offer.clone())?;
}
CredentialIssuanceV1::ProposeCredential(proposal) => {
if connection_ids.len() == 1 {
self.aries_agent
.issuer()
.accept_proposal(connection_id.unwrap(), &proposal)
.await?;
} else {
return Err(HarnessError::from_msg(
HarnessErrorType::InvalidState,
&format!("Found multiple or no connections by verkey {}", sender_vk),
));
}
self.aries_agent
.issuer()
.accept_proposal(connection_id, &proposal)
.await?;
}
CredentialIssuanceV1::RequestCredential(request) => {
let thread_id = request
Expand Down Expand Up @@ -149,14 +130,10 @@ impl HarnessAgent {
async fn handle_presentation_msg(
&self,
msg: PresentProof,
connection_ids: Vec<String>,
sender_vk: &str,
connection_id: &str,
) -> HarnessResult<()> {
match msg {
PresentProof::V1(msg) => {
self.handle_presentation_msg_v1(msg, connection_ids, sender_vk)
.await
}
PresentProof::V1(msg) => self.handle_presentation_msg_v1(msg, connection_id).await,
PresentProof::V2(_) => {
unimplemented!("V2 issuance is not implemented for aries-vcx aath")
}
Expand All @@ -166,22 +143,13 @@ impl HarnessAgent {
async fn handle_presentation_msg_v1(
&self,
msg: PresentProofV1,
connection_ids: Vec<String>,
sender_vk: &str,
connection_id: &str,
) -> HarnessResult<()> {
let connection_id = connection_ids.last();
match msg {
PresentProofV1::RequestPresentation(request) => {
if connection_ids.len() == 1 {
self.aries_agent
.prover()
.create_from_request(connection_id.unwrap(), request)?;
} else {
return Err(HarnessError::from_msg(
HarnessErrorType::InvalidState,
&format!("Found multiple or no connections by verkey {}", sender_vk),
));
}
self.aries_agent
.prover()
.create_from_request(connection_id, request)?;
}
PresentProofV1::Presentation(presentation) => {
let thread_id = presentation.decorators.thread.thid.clone();
Expand Down Expand Up @@ -255,7 +223,6 @@ impl HarnessAgent {
)
})?;
info!("Received message: {}", message);
let connection_ids = self.aries_agent.connections().get_by_their_vk(&sender_vk)?;
match message {
AriesMessage::Notification(msg) => {
match msg {
Expand All @@ -272,15 +239,22 @@ impl HarnessAgent {
}
}
}
AriesMessage::TrustPing(TrustPing::Ping(msg)) => {
let connection_id = self.aries_agent.connections().get_by_sender_vk(sender_vk)?;
self.aries_agent
.connections()
.process_trust_ping(msg, &connection_id)
.await?
}
AriesMessage::Connection(msg) => self.handle_connection_msg(msg).await?,
AriesMessage::CredentialIssuance(msg) => {
self.handle_issuance_msg(msg, connection_ids, &sender_vk)
.await?
let connection_id = self.aries_agent.connections().get_by_sender_vk(sender_vk)?;
self.handle_issuance_msg(msg, &connection_id).await?
}
AriesMessage::DidExchange(msg) => self.handle_did_exchange_msg(msg).await?,
AriesMessage::PresentProof(msg) => {
self.handle_presentation_msg(msg, connection_ids, &sender_vk)
.await?
let connection_id = self.aries_agent.connections().get_by_sender_vk(sender_vk)?;
self.handle_presentation_msg(msg, &connection_id).await?
}
m => {
warn!("Received message of unexpected type: {}", m);
Expand Down
66 changes: 60 additions & 6 deletions aries/agents/aries-vcx-agent/src/handlers/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ use aries_vcx::{
msg_fields::protocols::{
connection::{request::Request, response::Response},
notification::ack::Ack,
trust_ping::ping::Ping,
},
AriesMessage,
},
protocols::connection::{
pairwise_info::PairwiseInfo, Connection, GenericConnection, State, ThinState,
protocols::{
connection::{
inviter::states::completed::Completed, pairwise_info::PairwiseInfo, Connection,
GenericConnection, State, ThinState,
},
trustping::build_ping_response,
},
};
use aries_vcx_ledger::ledger::indy_vdr_ledger::DefaultIndyLedgerRead;
Expand Down Expand Up @@ -179,6 +184,42 @@ impl<T: BaseWallet> ServiceConnections<T> {
Ok(())
}

/// Process a trust ping and send a pong. Also bump the connection state (ack) if needed.
pub async fn process_trust_ping(&self, ping: Ping, connection_id: &str) -> AgentResult<()> {
let generic_inviter = self.connections.get(connection_id)?;

let inviter: Connection<_, Completed> = match generic_inviter.state() {
ThinState::Inviter(State::Requested) => {
// bump state. requested -> complete
let inviter: Connection<_, _> = generic_inviter.try_into()?;
inviter.acknowledge_connection(&ping.clone().into())?
}
ThinState::Inviter(State::Completed) => generic_inviter.try_into()?,
s => {
return Err(AgentError::from_msg(
AgentErrorKind::GenericAriesVcxError,
&format!(
"Connection with handle {} cannot process a trust ping; State: {:?}",
connection_id, s
),
))
}
};

// send pong if desired
if ping.content.response_requested {
let response = build_ping_response(&ping);
inviter
.send_message(self.wallet.as_ref(), &response.into(), &VcxHttpClient)
.await?;
}

// update state
self.connections.insert(connection_id, inviter.into())?;

Ok(())
}

pub fn get_state(&self, thread_id: &str) -> AgentResult<ThinState> {
Ok(self.connections.get(thread_id)?.state())
}
Expand All @@ -187,16 +228,29 @@ impl<T: BaseWallet> ServiceConnections<T> {
self.connections.get(thread_id)
}

pub fn get_by_their_vk(&self, their_vk: &str) -> AgentResult<Vec<String>> {
let their_vk = their_vk.to_string();
pub fn get_by_sender_vk(&self, sender_vk: String) -> AgentResult<String> {
let f = |(id, m): (&String, &Mutex<GenericConnection>)| -> Option<String> {
let connection = m.lock().unwrap();
match connection.remote_vk() {
Ok(remote_vk) if remote_vk == their_vk => Some(id.to_string()),
Ok(remote_vk) if remote_vk == sender_vk => Some(id.to_string()),
_ => None,
}
};
self.connections.find_by(f)
let conns = self.connections.find_by(f)?;

if conns.len() > 1 {
return Err(AgentError::from_msg(
AgentErrorKind::InvalidState,
&format!(
"Found multiple connections by sender's verkey {}",
sender_vk
),
));
}
conns.into_iter().next().ok_or(AgentError::from_msg(
AgentErrorKind::InvalidState,
&format!("Found no connections by sender's verkey {}", sender_vk),
))
}

pub fn exists_by_id(&self, thread_id: &str) -> bool {
Expand Down
9 changes: 1 addition & 8 deletions aries/aries_vcx/src/protocols/connection/inviter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use crate::{
common::signing::sign_connection_response,
errors::error::VcxResult,
handlers::util::{verify_thread_id, AnyInvitation},
protocols::connection::trait_bounds::ThreadId,
};

pub type InviterConnection<S> = Connection<Inviter, S>;
Expand Down Expand Up @@ -235,16 +234,10 @@ impl InviterConnection<Requested> {

/// Acknowledges an invitee's connection by processing their first message
/// and transitions to [`InviterConnection<Completed>`].
///
/// # Errors
///
/// Will error out if the message's thread ID does not match
/// the ID of the thread context used in this connection.
pub fn acknowledge_connection(
self,
msg: &AriesMessage,
_msg: &AriesMessage,
) -> VcxResult<InviterConnection<Completed>> {
verify_thread_id(self.state.thread_id(), msg)?;
let state = Completed::new(
self.state.did_doc,
self.state.signed_response.decorators.thread.thid,
Expand Down

0 comments on commit 08bea95

Please sign in to comment.