Skip to content

Commit

Permalink
Extract auto-update logic from aries (#155)
Browse files Browse the repository at this point in the history
* Extract verifier update state

Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com>

* Extract update state for prover

Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com>

* Extract update state for holder

Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com>

* Extract update state for issuer

Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com>

* WIP: Extract update for connection

Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com>
  • Loading branch information
mirgee authored Oct 22, 2020
1 parent 8f2c25e commit e2413d7
Show file tree
Hide file tree
Showing 18 changed files with 251 additions and 193 deletions.
2 changes: 1 addition & 1 deletion libvcx/src/api/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ pub extern fn vcx_credential_update_state_with_message(command_handle: CommandHa
command_handle, credential_handle, source_id);

spawn(move || {
match credential::update_state(credential_handle, Some(message), None) {
match credential::update_state(credential_handle, Some(&message), None) {
Ok(_) => (),
Err(e) => {
error!("vcx_credential_update_state_with_message_cb(command_handle: {}, rc: {}, state: {}), source_id: {:?}",
Expand Down
2 changes: 1 addition & 1 deletion libvcx/src/api/disclosed_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ pub extern fn vcx_disclosed_proof_update_state_with_message(command_handle: Comm
command_handle, proof_handle, source_id);

spawn(move || {
match disclosed_proof::update_state(proof_handle, Some(message), None) {
match disclosed_proof::update_state(proof_handle, Some(&message), None) {
Ok(s) => {
trace!("vcx_disclosed_proof_update_state__with_message_cb(command_handle: {}, rc: {}, state: {}) source_id: {}",
command_handle, error::SUCCESS.message, s, source_id);
Expand Down
2 changes: 1 addition & 1 deletion libvcx/src/api/issuer_credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ pub extern fn vcx_issuer_credential_update_state_with_message(command_handle: Co
}

spawn(move || {
match issuer_credential::update_state(credential_handle, Some(message), None) {
match issuer_credential::update_state(credential_handle, Some(&message), None) {
Ok(x) => {
trace!("vcx_issuer_credential_update_state_with_message_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}",
command_handle, credential_handle, error::SUCCESS.message, x, source_id);
Expand Down
2 changes: 1 addition & 1 deletion libvcx/src/api/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ pub extern fn vcx_proof_update_state_with_message(command_handle: CommandHandle,
}

spawn(move|| {
match proof::update_state(proof_handle, Some(message), None) {
match proof::update_state(proof_handle, Some(&message), None) {
Ok(x) => {
trace!("vcx_proof_update_state_with_message_cb(command_handle: {}, rc: {}, proof_handle: {}, state: {}) source_id: {}",
command_handle, error::SUCCESS.message, proof_handle, x, source_id);
Expand Down
48 changes: 10 additions & 38 deletions libvcx/src/aries/handlers/connection/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ impl Connection {
}
}

pub fn bootstrap_agent_info(&self) -> Option<&AgentInfo> {
match &self.connection_sm {
SmConnection::Inviter(sm_inviter) => {
sm_inviter.prev_agent_info()
}
SmConnection::Invitee(sm_invitee) => None
}
}

pub fn remote_did(&self) -> VcxResult<String> {
match &self.connection_sm {
SmConnection::Inviter(sm_inviter) => {
Expand Down Expand Up @@ -237,7 +246,7 @@ impl Connection {
}
}

fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
pub fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
match &self.connection_sm {
SmConnection::Inviter(sm_inviter) => {
sm_inviter.find_message_to_handle(messages)
Expand All @@ -257,43 +266,6 @@ impl Connection {
self.step(DidExchangeMessages::Connect())
}

/**
Tries to update state of connection state machine in 3 steps:
1. find relevant message in agency,
2. use it to update connection state and possibly send response over network,
3. update state of used message in agency to "Reviewed".
*/
pub fn update_state(&mut self) -> VcxResult<()> {
trace!("Connection::update_state >>>");

if self.is_in_null_state() {
warn!("Connection::update_state :: update state on connection in null state is ignored");
return Ok(());
}

// connection protocol itself handles message authentication where it makes sense
let messages = self.get_messages_noauth()?;
trace!("Connection::update_state >>> retrieved messages {:?}", messages);

if let Some((uid, message)) = self.find_message_to_handle(messages) {
trace!("Connection::update_state >>> handling message uid: {:?}", uid);
self.update_state_with_message(&message)?;
self.agent_info().clone().update_message_status(uid)?;
} else if let SmConnection::Inviter(sm_inviter) = &self.connection_sm {
trace!("Connection::update_state >>> Inviter found no message to handle on main connection agent. Will check bootstrap agent.");
if let Some((messages, bootstrap_agent_info)) = sm_inviter.get_bootstrap_agent_messages()? {
if let Some((uid, message)) = self.find_message_to_handle(messages) {
trace!("Connection::update_state >>> handling message found on bootstrap agent uid: {:?}", uid);
self.update_state_with_message(&message)?;
bootstrap_agent_info.update_message_status(uid)?;
}
}
}

trace!("Connection::update_state >>> done");
Ok(())
}

/**
Perform state machine transition using supplied message.
*/
Expand Down
12 changes: 0 additions & 12 deletions libvcx/src/aries/handlers/connection/inviter/state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,6 @@ impl SmConnectionInviter {
None
}

pub fn get_bootstrap_agent_messages(&self) -> VcxResult<Option<(HashMap<String, A2AMessage>, AgentInfo)>> {
let expected_sender_vk = match self.remote_vk() {
Ok(vk) => vk,
Err(_) => return Ok(None)
};
if let Some(prev_agent_info) = self.prev_agent_info() {
let messages = prev_agent_info.get_messages(&expected_sender_vk)?;
return Ok(Some((messages, prev_agent_info.clone())));
}
Ok(None)
}

pub fn get_protocols(&self) -> Vec<ProtocolDescriptor> {
ProtocolRegistry::init().protocols()
}
Expand Down
25 changes: 11 additions & 14 deletions libvcx/src/aries/handlers/issuance/holder/holder.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use std::collections::HashMap;
use std::convert::TryFrom;

use connection;
use error::prelude::*;
use aries::handlers::issuance::holder::state_machine::HolderSM;
use aries::handlers::issuance::messages::CredentialIssuanceMessage;
use aries::messages::a2a::A2AMessage;
use aries::messages::issuance::credential::{Credential, CredentialData};
use aries::messages::issuance::credential_offer::CredentialOffer;

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand All @@ -27,19 +25,18 @@ impl Holder {
self.step(CredentialIssuanceMessage::CredentialRequestSend(connection_handle))
}

pub fn update_state(&mut self, msg: Option<String>, connection_handle: Option<u32>) -> VcxResult<()> {
match msg {
Some(msg) => {
let message: A2AMessage = ::serde_json::from_str(&msg)
.map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidOption, format!("Cannot update state: Message deserialization failed: {:?}", err)))?;
pub fn maybe_update_connection_handle(&mut self, connection_handle: Option<u32>) -> u32 {
let conn_handle = connection_handle.unwrap_or(self.holder_sm.get_connection_handle());
self.holder_sm.set_connection_handle(conn_handle);
conn_handle
}

self.step(message.into())
}
None => {
self.holder_sm = self.holder_sm.clone().update_state(connection_handle)?;
Ok(())
}
}
pub fn is_terminal_state(&self) -> bool {
self.holder_sm.is_terminal_state()
}

pub fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
self.holder_sm.find_message_to_handle(messages)
}

pub fn get_status(&self) -> u32 {
Expand Down
30 changes: 9 additions & 21 deletions libvcx/src/aries/handlers/issuance/holder/state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,27 +75,7 @@ impl HolderSM {
}
}

pub fn update_state(mut self, connection_handle: Option<u32>) -> VcxResult<Self> {
trace!("Holder::update_state >>> ");

if self.is_terminal_state() { return Ok(self); }

let conn_handle = connection_handle.unwrap_or(self.state.get_connection_handle());
self.state.set_connection_handle(conn_handle);

let messages = connection::get_messages(conn_handle)?;

match self.find_message_to_handle(messages) {
Some((uid, msg)) => {
let state = self.handle_message(msg.into())?;
connection::update_message_status(conn_handle, uid)?;
Ok(state)
}
None => Ok(self)
}
}

fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
pub fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
trace!("Holder::find_message_to_handle >>> messages: {:?}", messages);

for (uid, message) in messages {
Expand Down Expand Up @@ -212,6 +192,14 @@ impl HolderSM {
}
}

pub fn get_connection_handle(&self) -> u32 {
self.state.get_connection_handle()
}

pub fn set_connection_handle(&mut self, conn_handle: u32) {
self.state.set_connection_handle(conn_handle)
}

pub fn get_credential(&self) -> VcxResult<(String, A2AMessage)> {
match self.state {
HolderState::Finished(ref state) => {
Expand Down
27 changes: 14 additions & 13 deletions libvcx/src/aries/handlers/issuance/issuer/issuer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use error::prelude::*;
use aries::handlers::issuance::issuer::state_machine::IssuerSM;
use aries::handlers::issuance::messages::CredentialIssuanceMessage;
Expand Down Expand Up @@ -35,23 +37,22 @@ impl Issuer {
Ok(self.issuer_sm.get_source_id())
}

pub fn is_terminal_state(&self) -> bool {
self.issuer_sm.is_terminal_state()
}

pub fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
self.issuer_sm.find_message_to_handle(messages)
}

pub fn revoke_credential(&self, publish: bool) -> VcxResult<()> {
self.issuer_sm.revoke(publish)
}

pub fn update_status(&mut self, msg: Option<String>, connection_handle: Option<u32>) -> VcxResult<()> {
match msg {
Some(msg) => {
let message: A2AMessage = ::serde_json::from_str(&msg)
.map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidOption, format!("Cannot deserialize Message: {:?}", err)))?;

self.step(message.into())
}
None => {
self.issuer_sm = self.issuer_sm.clone().update_state(connection_handle)?;
Ok(())
}
}
pub fn maybe_update_connection_handle(&mut self, connection_handle: Option<u32>) -> u32 {
let conn_handle = connection_handle.unwrap_or(self.issuer_sm.get_connection_handle());
self.issuer_sm.set_connection_handle(conn_handle);
conn_handle
}

pub fn get_credential_status(&self) -> VcxResult<u32> {
Expand Down
24 changes: 6 additions & 18 deletions libvcx/src/aries/handlers/issuance/issuer/state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,27 +123,15 @@ impl IssuerSM {
}
}

pub fn update_state(mut self, connection_handle: Option<u32>) -> VcxResult<Self> {
trace!("Issuer::update_state >>> ", );

if self.is_terminal_state() { return Ok(self); }

let conn_handle = connection_handle.unwrap_or(self.state.get_connection_handle());
self.state.set_connection_handle(conn_handle);

let messages = get_messages(conn_handle)?;
pub fn get_connection_handle(&self) -> u32 {
self.state.get_connection_handle()
}

match self.find_message_to_handle(messages) {
Some((uid, msg)) => {
let state = self.handle_message(msg.into())?;
connection::update_message_status(conn_handle, uid)?;
Ok(state)
}
None => Ok(self)
}
pub fn set_connection_handle(&mut self, conn_handle: u32) {
self.state.set_connection_handle(conn_handle)
}

fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
pub fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
trace!("Issuer::find_message_to_handle >>> messages: {:?}", messages);

for (uid, message) in messages {
Expand Down
33 changes: 11 additions & 22 deletions libvcx/src/aries/handlers/proof_presentation/prover/prover.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::convert::TryInto;
use std::collections::HashMap;

use ::{connection, settings};
use error::prelude::*;
Expand Down Expand Up @@ -59,41 +60,29 @@ impl Prover {
self.step(ProverMessages::SendPresentation(connection_handle))
}

pub fn update_state(&mut self, message: Option<&str>, connection_handle: Option<u32>) -> VcxResult<()> {
trace!("Prover::update_state >>> connection_handle: {:?}, message: {:?}", connection_handle, message);
pub fn has_transitions(&self) -> bool {
self.prover_sm.has_transitions()
}

if !self.prover_sm.has_transitions() {
trace!("Prover::update_state >> found no available transition");
return Ok(());
}
pub fn find_message_to_handle(&self, messages: HashMap<String, A2AMessage>) -> Option<(String, A2AMessage)> {
self.prover_sm.find_message_to_handle(messages)
}

pub fn maybe_update_connection_handle(&mut self, connection_handle: Option<u32>) -> VcxResult<u32> {
let connection_handle = connection_handle.unwrap_or(self.prover_sm.connection_handle()?);
self.prover_sm.set_connection_handle(connection_handle);

if let Some(message_) = message {
return self.update_state_with_message(message_);
}

let messages = connection::get_messages(connection_handle)?;
trace!("Prover::update_state >>> found messages: {:?}", messages);

if let Some((uid, message)) = self.prover_sm.find_message_to_handle(messages) {
self.handle_message(message.into())?;
connection::update_message_status(connection_handle, uid)?;
};

Ok(())
Ok(connection_handle)
}

pub fn update_state_with_message(&mut self, message: &str) -> VcxResult<()> {
pub fn update_state_with_message(&mut self, message: &str) -> VcxResult<u32> {
trace!("Prover::update_state_with_message >>> message: {:?}", message);

let a2a_message: A2AMessage = ::serde_json::from_str(&message)
.map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidOption, format!("Cannot updated state with message: Message deserialization failed: {:?}", err)))?;

self.handle_message(a2a_message.into())?;

Ok(())
Ok(self.state())
}

pub fn handle_message(&mut self, message: ProverMessages) -> VcxResult<()> {
Expand Down
Loading

0 comments on commit e2413d7

Please sign in to comment.