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

Handle trust pings in the AATH backchannel #1254

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading