From 1df11a935447df4c94babb40f4f2745bcbfb91aa Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Fri, 15 Feb 2019 15:14:02 +0300 Subject: [PATCH 01/28] Added threading minimal support Signed-off-by: artem.ivanov --- .../src/actors/agent_connection.rs | 51 ++-- vcx/dummy-cloud-agent/src/domain/payload.rs | 73 ++++-- vcx/libvcx/Cargo.lock | 1 + vcx/libvcx/Cargo.toml | 1 + vcx/libvcx/src/connection.rs | 52 ++-- vcx/libvcx/src/credential.rs | 36 ++- vcx/libvcx/src/disclosed_proof.rs | 139 +++++----- vcx/libvcx/src/issuer_credential.rs | 248 ++++++++++-------- vcx/libvcx/src/lib.rs | 2 + vcx/libvcx/src/messages/get_message.rs | 15 +- vcx/libvcx/src/messages/invite.rs | 23 +- vcx/libvcx/src/messages/mod.rs | 175 +----------- vcx/libvcx/src/messages/payload.rs | 227 ++++++++++++++++ .../src/messages/proofs/proof_request.rs | 4 +- vcx/libvcx/src/messages/send_message.rs | 10 +- vcx/libvcx/src/proof.rs | 53 +++- vcx/libvcx/src/utils/mod.rs | 1 + vcx/libvcx/src/utils/uuid.rs | 3 + 18 files changed, 657 insertions(+), 457 deletions(-) create mode 100644 vcx/libvcx/src/messages/payload.rs create mode 100644 vcx/libvcx/src/utils/uuid.rs diff --git a/vcx/dummy-cloud-agent/src/actors/agent_connection.rs b/vcx/dummy-cloud-agent/src/actors/agent_connection.rs index e2f501f0df..069bea4a44 100644 --- a/vcx/dummy-cloud-agent/src/actors/agent_connection.rs +++ b/vcx/dummy-cloud-agent/src/actors/agent_connection.rs @@ -7,7 +7,7 @@ use domain::status::{ConnectionStatus, MessageStatusCode}; use domain::invite::{ForwardAgentDetail, InviteDetail, SenderDetail, AgentDetail}; use domain::internal_message::InternalMessage; use domain::key_deligation_proof::KeyDlgProof; -use domain::payload::{Payload, PayloadTypes, PayloadKinds}; +use domain::payload::{PayloadV1, PayloadV2, PayloadTypes, PayloadKinds, Thread}; use domain::protocol_type::{ProtocolType, ProtocolTypes}; use failure::{err_msg, Error, Fail}; use futures::*; @@ -803,15 +803,8 @@ impl AgentConnection { let msg_uid = msg_uid.to_string(); - let msg = ftry_act!(self, self.build_payload_message(RemoteMessageType::ConnReqAnswer, &json!({"senderDetail": msg_detail.sender_detail}))); - - future::ok(()) + self.build_payload_message(RemoteMessageType::ConnReqAnswer, &json!({"senderDetail": msg_detail.sender_detail})) .into_actor(self) - .and_then(move |_, slf, _| - crypto::auth_crypt(slf.wallet_handle, &slf.agent_pairwise_verkey, &slf.owner_verkey, &msg) - .map_err(|err| err.context("Can't encode Answer Payload.").into()) - .into_actor(slf) - ) .map(move |payload, slf, _| slf.state.messages.get_mut(&msg_uid) .map(|message| message.payload = Some(payload)) @@ -1136,19 +1129,43 @@ impl AgentConnection { Ok(message) } - fn build_payload_message(&self, type_: RemoteMessageType, msg: &T) -> Result, Error> where T: ::serde::Serialize + ::std::fmt::Debug { + fn build_payload_message(&self, type_: RemoteMessageType, msg: &T) -> ResponseFuture, Error> where T: ::serde::Serialize + ::std::fmt::Debug { trace!("AgentConnection::build_payload_message >> {:?}, {:?}", type_, msg); - let msg = rmp_serde::to_vec_named(&msg)?; + match ProtocolType::get() { + ProtocolTypes::V1 => { + let msg = ftry!(rmp_serde::to_vec_named(&msg));; - let payload_msg = Payload { - type_: PayloadTypes::build(PayloadKinds::from(type_)), - msg: to_i8(&msg) - }; + let payload_msg = PayloadV1 { + type_: PayloadTypes::build_v1(PayloadKinds::from(type_), "json"), + msg: to_i8(&msg) + }; + + let message = ftry!(rmp_serde::to_vec_named(&payload_msg)); + + crypto::auth_crypt(self.wallet_handle, &self.agent_pairwise_verkey, &self.owner_verkey, &message) + .map_err(|err| err.context("Can't encode Answer Payload.").into()) + .into_box() + }, + ProtocolTypes::V2 => { + let msg = ftry!(serde_json::to_string(&msg));; + + let payload_msg = PayloadV2 { + type_: PayloadTypes::build_v2(PayloadKinds::from(type_)), + id: String::new(), + msg, + thread: Thread::new(), + }; - rmp_serde::to_vec_named(&payload_msg) - .map_err(|err| err.into()) + let message = ftry!(serde_json::to_string(&payload_msg)); + let receiver_keys = ftry!(serde_json::to_string(&vec![&self.owner_verkey])); + + crypto::pack_message(self.wallet_handle, Some(&self.agent_pairwise_verkey), &receiver_keys, &message.as_bytes()) + .map_err(|err| err.context("Can't encode Answer Payload.").into()) + .into_box() + } + } } fn build_forward_message(&self, fwd: &str, message: Vec) -> Result, Error> { diff --git a/vcx/dummy-cloud-agent/src/domain/payload.rs b/vcx/dummy-cloud-agent/src/domain/payload.rs index 590478cf61..6d4e99bb2e 100644 --- a/vcx/dummy-cloud-agent/src/domain/payload.rs +++ b/vcx/dummy-cloud-agent/src/domain/payload.rs @@ -1,15 +1,34 @@ use domain::message_type::{MessageTypeV2, MessageFamilies, MESSAGE_VERSION_V1, MESSAGE_VERSION_V2, DID}; use domain::a2a::RemoteMessageType; use domain::protocol_type::{ProtocolType, ProtocolTypes}; +use std::collections::HashMap; #[derive(Deserialize, Serialize, Debug)] -pub struct Payload { +pub enum Payloads { + PayloadV1(PayloadV1), + PayloadV2(PayloadV2), +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct PayloadV1 { #[serde(rename = "@type")] - pub type_: PayloadTypes, + pub type_: PayloadTypeV1, #[serde(rename = "@msg")] pub msg: Vec, } +#[derive(Deserialize, Serialize, Debug)] +pub struct PayloadV2 { + #[serde(rename = "@type")] + pub type_: PayloadTypeV2, + #[serde(rename = "@id")] + pub id: String, + #[serde(rename = "@msg")] + pub msg: String, + #[serde(rename = "~thread")] + pub thread: Thread, +} + #[derive(Debug, Deserialize, Serialize)] #[serde(untagged)] pub enum PayloadTypes { @@ -76,23 +95,20 @@ impl PayloadKinds { } impl PayloadTypes { - pub fn build(kind: PayloadKinds) -> PayloadTypes { - match ProtocolType::get() { - ProtocolTypes::V1 => { - PayloadTypes::PayloadTypeV1(PayloadTypeV1 { - name: kind.name().to_string(), - ver: MESSAGE_VERSION_V1.to_string(), - fmt: "json".to_string(), - }) - } - ProtocolTypes::V2 => { - PayloadTypes::PayloadTypeV2(PayloadTypeV2 { - did: DID.to_string(), - family: kind.family(), - version: MESSAGE_VERSION_V2.to_string(), - type_: kind.name().to_string(), - }) - } + pub fn build_v1(kind: PayloadKinds, fmt: &str) -> PayloadTypeV1 { + PayloadTypeV1 { + name: kind.name().to_string(), + ver: MESSAGE_VERSION_V1.to_string(), + fmt: fmt.to_string(), + } + } + + pub fn build_v2(kind: PayloadKinds) -> PayloadTypeV2 { + PayloadTypeV2 { + did: DID.to_string(), + family: kind.family(), + version: MESSAGE_VERSION_V2.to_string(), + type_: kind.name().to_string(), } } } @@ -111,3 +127,22 @@ impl From for PayloadKinds { } } } + +#[derive(Debug, Deserialize, Serialize)] +pub struct Thread { + pub thid: Option, + pub pthid: Option, + pub sender_order: u32, + pub received_orders: HashMap, +} + +impl Thread { + pub fn new() -> Thread { + Thread { + thid: None, + pthid: None, + sender_order: 0, + received_orders: HashMap::new(), + } + } +} \ No newline at end of file diff --git a/vcx/libvcx/Cargo.lock b/vcx/libvcx/Cargo.lock index e62a84c391..15a369b6d9 100644 --- a/vcx/libvcx/Cargo.lock +++ b/vcx/libvcx/Cargo.lock @@ -589,6 +589,7 @@ dependencies = [ "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/vcx/libvcx/Cargo.toml b/vcx/libvcx/Cargo.toml index 0591a0edf0..c1ddfa4d98 100644 --- a/vcx/libvcx/Cargo.toml +++ b/vcx/libvcx/Cargo.toml @@ -52,6 +52,7 @@ log-panics = "2.0.0" tokio-threadpool = "0.1.6" futures = "0.1.23" libloading = "0.5.0" +uuid = {version = "0.7.1", default-features = false, features = ["v4"]} [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.5" diff --git a/vcx/libvcx/src/connection.rs b/vcx/libvcx/src/connection.rs index b0e22f866e..20443a3a8f 100644 --- a/vcx/libvcx/src/connection.rs +++ b/vcx/libvcx/src/connection.rs @@ -13,8 +13,9 @@ use settings; use messages::GeneralMessage; use messages; use messages::{MessageStatusCode, RemoteMessageType}; -use messages::invite::{InviteDetail, SenderDetail}; -use messages::get_message::{Message, Payload as MessagePayload}; +use messages::invite::{InviteDetail, SenderDetail, Payload as ConnectionPayload, AcceptanceDetails}; +use messages::payload::Payloads; +use messages::get_message::Message; use serde_json::Value; use utils::json::KeyMatch; use error::connection::ConnectionError; @@ -450,27 +451,34 @@ pub fn create_connection_with_invite(source_id: &str, details: &str) -> Result Result { debug!("connection {} parsing acceptance details for message {:?}", get_source_id(handle).unwrap_or_default(), message); let my_vk = settings::get_config_value(settings::CONFIG_SDK_TO_REMOTE_VERKEY)?; - let payload = messages::to_u8( - message.payload - .as_ref() - .ok_or(ConnectionError::CommonError(error::INVALID_MSGPACK.code_num))? - ); - // TODO: check returned verkey - let (_, payload) = crypto::parse_msg(&my_vk, &payload).map_err(|e| { ConnectionError::CommonError(e) })?; - - trace!("deserializing GetMsgResponse: {:?}", payload); - - let response: MessagePayload = rmp_serde::from_slice(&payload[..]) - .map_err(|err| { - error!("Could not parse outer msg: {}", err); - ConnectionError::CommonError(error::INVALID_MSGPACK.code_num) - })?; - - let payload = messages::to_u8(&response.msg); - // TODO: Refactor Error - let details = messages::invite::parse_invitation_acceptance_details(payload).map_err(|e| { ConnectionError::CommonError(e) })?; - Ok(details) + let payload = message.payload + .as_ref() + .ok_or(ConnectionError::CommonError(error::INVALID_MSGPACK.code_num))?; + + match settings::ProtocolTypes::from(settings::get_protocol_type()) { + settings::ProtocolTypes::V1 => { + let payload = messages::to_u8(&payload); + + // TODO: check returned verkey + let (_, payload) = crypto::parse_msg(&my_vk, &payload).map_err(|e| { ConnectionError::CommonError(e) })?; + + let response: ConnectionPayload = rmp_serde::from_slice(&payload[..]) + .map_err(|err| { + error!("Could not parse outer msg: {}", err); + ConnectionError::CommonError(error::INVALID_MSGPACK.code_num) + })?; + + let payload = messages::to_u8(&response.msg); + // TODO: Refactor Error + messages::invite::parse_invitation_acceptance_details(payload).map_err(|e| { ConnectionError::CommonError(e) }) + } + settings::ProtocolTypes::V2 => { + let (payload, _) = Payloads::decrypt_payload_v2(&my_vk, &payload)?; + let response: AcceptanceDetails = serde_json::from_str(&payload).or(Err(error::INVALID_JSON.code_num))?; + Ok(response.sender_detail) + } + } } pub fn update_state(handle: u32) -> Result { diff --git a/vcx/libvcx/src/credential.rs b/vcx/libvcx/src/credential.rs index 8cd596a28c..5cc55363f4 100644 --- a/vcx/libvcx/src/credential.rs +++ b/vcx/libvcx/src/credential.rs @@ -12,8 +12,8 @@ use issuer_credential::{CredentialOffer, CredentialMessage, PaymentInfo}; use credential_request::CredentialRequest; use messages; -use messages::GeneralMessage; -use messages::{RemoteMessageType, PayloadKinds}; +use messages::{GeneralMessage, RemoteMessageType}; +use messages::payload::{Payloads, PayloadKinds, Thread}; use utils::libindy::anoncreds::{libindy_prover_create_credential_req, libindy_prover_store_credential}; use utils::libindy::anoncreds; @@ -52,11 +52,11 @@ impl Default for Credential { credential: None, payment_info: None, payment_txn: None, + thread: Thread::new(), } } } - #[derive(Serialize, Deserialize, Debug, PartialEq)] pub struct Credential { source_id: String, @@ -76,6 +76,7 @@ pub struct Credential { cred_id: Option, payment_info: Option, payment_txn: Option, + thread: Thread } impl Credential { @@ -89,8 +90,7 @@ impl Credential { let prover_did = self.my_did.as_ref().ok_or(CredentialError::CommonError(error::INVALID_DID.code_num))?; let credential_offer = self.credential_offer.as_ref().ok_or(CredentialError::InvalidCredentialJson())?; - let (cred_def_id, cred_def_json) = anoncreds::get_cred_def_json(&credential_offer.cred_def_id) - .map_err(|err| CredentialError::CommonError(err))?; + let (cred_def_id, cred_def_json) = anoncreds::get_cred_def_json(&credential_offer.cred_def_id)?; /* debug!("storing credential offer: {}", credential_offer); @@ -99,8 +99,7 @@ impl Credential { let (req, req_meta) = libindy_prover_create_credential_req(&prover_did, &credential_offer.libindy_offer, - &cred_def_json) - .map_err(|ec| CredentialError::CommonError(ec))?; + &cred_def_json)?; Ok(CredentialRequest { libindy_cred_req: req, @@ -161,7 +160,7 @@ impl Credential { .msg_type(&RemoteMessageType::CredReq)? .agent_did(local_agent_did)? .agent_vk(local_agent_vk)? - .edge_agent_payload(&local_my_vk, &local_their_vk, &cred_req_json, PayloadKinds::CredReq)? + .edge_agent_payload(&local_my_vk, &local_their_vk, &cred_req_json, PayloadKinds::CredReq, Some(self.thread.clone()))? .ref_msg_id(&offer_msg_id)? .send_secure() .map_err(|err| { @@ -186,7 +185,11 @@ impl Credential { let (_, payload) = messages::get_message::get_ref_msg(msg_uid, my_did, my_vk, agent_did, agent_vk)?; - let credential = messages::Payload::decrypted(&my_vk, &payload)?; + let (credential, thread) = Payloads::decrypt(&my_vk, &payload)?; + + if let Some(_) = thread { + self.thread.increment_receiver(self.their_did.as_ref().map(String::as_str).unwrap_or("")); + } let credential_msg: CredentialMessage = serde_json::from_str(&credential) .or(Err(error::INVALID_CREDENTIAL_JSON.code_num))?; @@ -448,11 +451,16 @@ pub fn get_credential_offer_msg(connection_handle: u32, msg_id: &str) -> Result< if message[0].msg_type == RemoteMessageType::CredOffer { let payload = message.get(0).and_then(|msg| msg.payload.as_ref()) .ok_or(CredentialError::CommonError(error::INVALID_MESSAGES.code_num))?; - let offer = messages::Payload::decrypted(&my_vk, &payload).map_err(|ec| CredentialError::CommonError(ec))?; + + let (offer, thread) = Payloads::decrypt(&my_vk, &payload).map_err(|ec| CredentialError::CommonError(ec))?; let (mut offer, payment_info) = parse_json_offer(&offer)?; offer.msg_ref_id = Some(message[0].uid.to_owned()); + + if let Some(tr) = thread { + offer.thread_id = tr.thid.clone(); + } let mut payload = Vec::new(); payload.push(json!(offer)); if let Some(p) = payment_info { payload.push(json!(p)); } @@ -485,11 +493,15 @@ pub fn get_credential_offer_messages(connection_handle: u32) -> Result, agent_did: Option, agent_vk: Option, + thread: Thread } #[derive(Debug, Deserialize, Serialize)] @@ -84,7 +87,7 @@ pub struct CredInfo { } fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) - -> Result, ProofError> { + -> Result, ProofError> { let mut rtn = Vec::new(); @@ -123,7 +126,7 @@ fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) tails_file, } ); - } else { return Err(ProofError::InvalidCredData()) } + } else { return Err(ProofError::InvalidCredData()); } } } @@ -131,18 +134,15 @@ fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) } fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) - -> Result, ProofError> { - + -> Result, ProofError> { if let Some(ref attr) = proof_req.requested_attributes.get(attr_name) { - if let Some(ref interval) = attr.non_revoked { - return Ok(Some(NonRevokedInterval {from: interval.from, to: interval.to})) - } - else if let Some(ref interval) = proof_req.non_revoked { - return Ok(Some(NonRevokedInterval { from: interval.from, to: interval.to })) + return Ok(Some(NonRevokedInterval { from: interval.from, to: interval.to })); + } else if let Some(ref interval) = proof_req.non_revoked { + return Ok(Some(NonRevokedInterval { from: interval.from, to: interval.to })); } - return Ok(None) + return Ok(None); } // Todo: Handle case for predicates @@ -157,14 +157,12 @@ fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result< for cred_info in credentials_identifiers.iter_mut() { if let (Some(rev_reg_id), Some(cred_rev_id), Some(tails_file)) = (&cred_info.rev_reg_id, &cred_info.cred_rev_id, &cred_info.tails_file) { - if rtn.get(&rev_reg_id).is_none() { let (from, to) = if let Some(ref interval) = cred_info.revocation_interval - { (interval.from, interval.to) } - else { (None, None )}; + { (interval.from, interval.to) } else { (None, None) }; -// let from = from.unwrap_or(0); -// let to = to.unwrap_or(time::get_time().sec as u64); + // let from = from.unwrap_or(0); + // let to = to.unwrap_or(time::get_time().sec as u64); let cache = get_rev_reg_cache(&rev_reg_id); let (rev_state_json, timestamp) = if let Some(cached_rev_state) = cache.rev_state { @@ -175,7 +173,7 @@ fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result< let from = match from { Some(from) if from >= cached_rev_state.timestamp => { Some(cached_rev_state.timestamp) - }, + } _ => None }; @@ -256,12 +254,10 @@ fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result< } Ok(rtn.to_string()) - } impl DisclosedProof { - - fn set_proof_request(&mut self, req: ProofRequestMessage) {self.proof_request = Some(req)} + fn set_proof_request(&mut self, req: ProofRequestMessage) { self.proof_request = Some(req) } fn get_state(&self) -> u32 { trace!("DisclosedProof::get_state >>>"); @@ -274,7 +270,7 @@ impl DisclosedProof { fn retrieve_credentials(&self) -> Result { trace!("DisclosedProof::set_state >>>"); - if settings::test_indy_mode_enabled() {return Ok(CREDS_FROM_PROOF_REQ.to_string())} + if settings::test_indy_mode_enabled() { return Ok(CREDS_FROM_PROOF_REQ.to_string()); } let proof_req = self.proof_request .as_ref() @@ -293,7 +289,7 @@ impl DisclosedProof { for ref cred_info in credentials_identifiers { if rtn.get(&cred_info.schema_id).is_none() { let (_, schema_json) = anoncreds::get_schema_json(&cred_info.schema_id) - .or( Err(ProofError::InvalidSchema()))?; + .or(Err(ProofError::InvalidSchema()))?; let schema_json = serde_json::from_str(&schema_json) .or(Err(ProofError::InvalidSchema()))?; @@ -349,7 +345,7 @@ impl DisclosedProof { trace!("DisclosedProof::generate_proof >>> credentials: {}, self_attested_attrs: {}", credentials, self_attested_attrs); debug!("generating proof {}", self.source_id); - if settings::test_indy_mode_enabled() {return Ok(error::SUCCESS.code_num)} + if settings::test_indy_mode_enabled() { return Ok(error::SUCCESS.code_num); } let proof_req = self.proof_request.as_ref() .ok_or(ProofError::CreateProofError())?; @@ -369,10 +365,10 @@ impl DisclosedProof { let proof = anoncreds::libindy_prover_create_proof(&proof_req_data_json, &requested_credentials, - &self.link_secret_alias, + &self.link_secret_alias, &schemas_json, - &credential_defs_json, - Some(&revoc_states_json)).map_err(|ec| ProofError::CommonError(ec))?; + &credential_defs_json, + Some(&revoc_states_json)).map_err(|ec| ProofError::CommonError(ec))?; let mut proof_msg = ProofMessage::new(); proof_msg.libindy_proof = proof; self.proof = Some(proof_msg); @@ -414,26 +410,28 @@ impl DisclosedProof { false => { let proof: &ProofMessage = self.proof.as_ref().ok_or(ProofError::CreateProofError())?; serde_json::to_string(&proof).or(Err(ProofError::CommonError(error::INVALID_JSON.code_num)))? - }, + } true => DEFAULT_GENERATED_PROOF.to_string(), }; + self.thread.increment_receiver(self.their_did.as_ref().map(String::as_str).unwrap_or("")); + messages::send_message() .to(local_my_did)? .to_vk(local_my_vk)? .msg_type(&RemoteMessageType::Proof)? .agent_did(local_agent_did)? .agent_vk(local_agent_vk)? - .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof).or(Err(ProofError::ProofConnectionError()))? + .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof, Some(self.thread.clone())).or(Err(ProofError::ProofConnectionError()))? .ref_msg_id(ref_msg_uid)? .send_secure() - .map_err(|err|{ + .map_err(|err| { warn!("could not send proof: {}", err); err })?; self.state = VcxStateType::VcxStateAccepted; - return Ok(error::SUCCESS.code_num) + return Ok(error::SUCCESS.code_num); } fn set_source_id(&mut self, id: &str) { self.source_id = id.to_string(); } @@ -447,9 +445,9 @@ impl DisclosedProof { } fn from_str(s: &str) -> Result { trace!("DisclosedProof::from_str >>> data: {}", s); - let s:Value = serde_json::from_str(&s) + let s: Value = serde_json::from_str(&s) .or(Err(ProofError::InvalidJson()))?; - let proof: DisclosedProof= serde_json::from_value(s["data"].clone()) + let proof: DisclosedProof = serde_json::from_value(s["data"].clone()) .or(Err(ProofError::InvalidJson()))?; Ok(proof) } @@ -461,8 +459,7 @@ impl DisclosedProof { fn handle_err(code_num: u32) -> u32 { if code_num == error::INVALID_OBJ_HANDLE.code_num { error::INVALID_DISCLOSED_PROOF_HANDLE.code_num - } - else { + } else { code_num } } @@ -491,13 +488,13 @@ pub fn get_state(handle: u32) -> Result { // update_state is just the same as get_state for disclosed_proof pub fn update_state(handle: u32) -> Result { - HANDLE_MAP.get(handle, |obj|{ + HANDLE_MAP.get(handle, |obj| { Ok(obj.get_state()) }) } pub fn to_string(handle: u32) -> Result { - HANDLE_MAP.get(handle, |obj|{ + HANDLE_MAP.get(handle, |obj| { Ok(DisclosedProof::to_string(&obj)) }) } @@ -525,19 +522,19 @@ pub fn release_all() { } pub fn send_proof(handle: u32, connection_handle: u32) -> Result { - HANDLE_MAP.get_mut(handle, |obj|{ + HANDLE_MAP.get_mut(handle, |obj| { obj.send_proof(connection_handle).map_err(|e| e.to_error_code()) }).map_err(|ec| ProofError::CommonError(ec)) } pub fn generate_proof(handle: u32, credentials: String, self_attested_attrs: String) -> Result { - HANDLE_MAP.get_mut(handle, |obj|{ + HANDLE_MAP.get_mut(handle, |obj| { obj.generate_proof(&credentials, &self_attested_attrs).map_err(|e| e.to_error_code()) }).map_err(|ec| ProofError::CommonError(ec)) } pub fn retrieve_credentials(handle: u32) -> Result { - HANDLE_MAP.get_mut(handle, |obj|{ + HANDLE_MAP.get_mut(handle, |obj| { obj.retrieve_credentials().map_err(|e| e.to_error_code()) }).map_err(|ec| ProofError::CommonError(ec)) } @@ -566,10 +563,12 @@ pub fn get_proof_request(connection_handle: u32, msg_id: &str) -> Result = Default::default(); for msg in payload { - if msg.sender_did.eq(&my_did){ continue; } + if msg.sender_did.eq(&my_did) { continue; } if msg.msg_type == RemoteMessageType::ProofReq { let payload = msg.payload.ok_or(ProofError::CommonError(error::INVALID_HTTP_RESPONSE.code_num))?; - let req = messages::Payload::decrypted(&my_vk, &payload).map_err(|ec| ProofError::CommonError(ec))?; + let (req, thread) = Payloads::decrypt(&my_vk, &payload).map_err(|ec| ProofError::CommonError(ec))?; let mut req: ProofRequestMessage = serde_json::from_str(&req) .or(Err(ProofError::CommonError(error::INVALID_HTTP_RESPONSE.code_num)))?; req.msg_ref_id = Some(msg.uid.to_owned()); + req.thread_id = thread.and_then(|tr| tr.thid.clone()); messages.push(req); } } @@ -629,8 +629,8 @@ mod tests { use serde_json::Value; use utils::{ constants::{ ADDRESS_CRED_ID, LICENCE_CRED_ID, ADDRESS_SCHEMA_ID, - ADDRESS_CRED_DEF_ID, CRED_DEF_ID, SCHEMA_ID, ADDRESS_CRED_REV_ID, - ADDRESS_REV_REG_ID, REV_REG_ID, CRED_REV_ID, TEST_TAILS_FILE, REV_STATE_JSON }, + ADDRESS_CRED_DEF_ID, CRED_DEF_ID, SCHEMA_ID, ADDRESS_CRED_REV_ID, + ADDRESS_REV_REG_ID, REV_REG_ID, CRED_REV_ID, TEST_TAILS_FILE, REV_STATE_JSON }, get_temp_dir_path }; #[cfg(feature = "pool_tests")] @@ -661,7 +661,7 @@ mod tests { #[test] fn test_create_fails() { init!("true"); - assert_eq!(create_proof("1","{}").err(), + assert_eq!(create_proof("1", "{}").err(), Some(ProofError::CommonError(error::INVALID_JSON.code_num))); } @@ -672,7 +672,7 @@ mod tests { let connection_h = connection::tests::build_test_connection(); let requests = get_proof_request_messages(connection_h, None).unwrap(); - let requests:Value = serde_json::from_str(&requests).unwrap(); + let requests: Value = serde_json::from_str(&requests).unwrap(); let requests = serde_json::to_string(&requests[0]).unwrap(); let handle = create_proof("TEST_CREDENTIAL", &requests).unwrap(); @@ -682,20 +682,20 @@ mod tests { } #[test] - fn get_state_test(){ + fn get_state_test() { init!("true"); - let proof: DisclosedProof = Default::default(); + let proof: DisclosedProof = Default::default(); assert_eq!(VcxStateType::VcxStateNone as u32, proof.get_state()); - let handle = create_proof("id",::utils::constants::PROOF_REQUEST_JSON).unwrap(); + let handle = create_proof("id", ::utils::constants::PROOF_REQUEST_JSON).unwrap(); assert_eq!(VcxStateType::VcxStateRequestReceived as u32, get_state(handle).unwrap()) } #[test] fn to_string_test() { init!("true"); - let handle = create_proof("id",::utils::constants::PROOF_REQUEST_JSON).unwrap(); + let handle = create_proof("id", ::utils::constants::PROOF_REQUEST_JSON).unwrap(); let serialized = to_string(handle).unwrap(); - let j:Value = serde_json::from_str(&serialized).unwrap(); + let j: Value = serde_json::from_str(&serialized).unwrap(); assert_eq!(j["version"], "1.0"); DisclosedProof::from_str(&serialized).unwrap(); } @@ -703,7 +703,7 @@ mod tests { #[test] fn test_deserialize_fails() { assert_eq!(from_string("{}").err(), - Some(ProofError::CommonError(error::INVALID_JSON.code_num))); + Some(ProofError::CommonError(error::INVALID_JSON.code_num))); } #[test] @@ -943,7 +943,7 @@ mod tests { // All lower case let retrieved_creds = proof.retrieve_credentials().unwrap(); assert!(retrieved_creds.contains(r#""zip":"84000""#)); - let ret_creds_as_value:Value = serde_json::from_str(&retrieved_creds).unwrap(); + let ret_creds_as_value: Value = serde_json::from_str(&retrieved_creds).unwrap(); assert_eq!(ret_creds_as_value["attrs"]["zip_1"][0]["cred_info"]["attrs"]["zip"], "84000"); // First letter upper req["requested_attributes"]["zip_1"]["name"] = json!("Zip"); @@ -992,7 +992,7 @@ mod tests { tails_file: None, timestamp: None, }; - let selected_credentials : Value = json!({ + let selected_credentials: Value = json!({ "attrs":{ "height_1":{ "credential": { @@ -1062,7 +1062,7 @@ mod tests { assert_eq!(credential_def_identifiers(r#"{"attrs":{}}"#, &proof_req_no_interval()), Ok(Vec::new())); // missing cred info - let selected_credentials : Value = json!({ + let selected_credentials: Value = json!({ "attrs":{ "height_1":{ "interval":null } }, @@ -1073,7 +1073,7 @@ mod tests { assert_eq!(credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()), Err(ProofError::InvalidCredData())); // Optional Revocation - let mut selected_credentials : Value = json!({ + let mut selected_credentials: Value = json!({ "attrs":{ "height_1":{ "credential": { @@ -1114,7 +1114,7 @@ mod tests { assert_eq!(&credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()).unwrap(), &creds); // Missing schema ID - let mut selected_credentials : Value = json!({ + let mut selected_credentials: Value = json!({ "attrs":{ "height_1":{ "credential": { @@ -1177,7 +1177,7 @@ mod tests { proof.link_secret_alias = "main".to_string(); let all_creds: Value = serde_json::from_str(&proof.retrieve_credentials().unwrap()).unwrap(); - let selected_credentials : Value = json!({ + let selected_credentials: Value = json!({ "attrs":{ "address1_1": { "credential": all_creds["attrs"]["address1_1"][0], @@ -1222,7 +1222,7 @@ mod tests { }).to_string(); proof_req.proof_request_data = serde_json::from_str(&indy_proof_req).unwrap(); - let selected_credentials : Value = json!({}); + let selected_credentials: Value = json!({}); let self_attested: Value = json!({ "address1_1":"attested_address", @@ -1397,7 +1397,7 @@ mod tests { rev_reg_id: rev_reg_id.clone(), cred_rev_id: cred_rev_id, tails_file: Some(get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap().to_string()), - revocation_interval: Some(NonRevokedInterval{from: Some(cached_timestamp + 1), to: None}), + revocation_interval: Some(NonRevokedInterval { from: Some(cached_timestamp + 1), to: None }), timestamp: None, }; let rev_reg_id = rev_reg_id.unwrap(); @@ -1452,7 +1452,7 @@ mod tests { rev_reg_id: rev_reg_id.clone(), cred_rev_id: cred_rev_id, tails_file: Some(get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap().to_string()), - revocation_interval: Some(NonRevokedInterval{from: None, to: Some(cached_timestamp - 1)}), + revocation_interval: Some(NonRevokedInterval { from: None, to: Some(cached_timestamp - 1) }), timestamp: None, }; let rev_reg_id = rev_reg_id.unwrap(); @@ -1489,7 +1489,6 @@ mod tests { #[test] fn test_get_credential_intervals_from_proof_req() { - let proof_req = json!({ "nonce": "123432421212", "name": "proof_req_1", @@ -1510,11 +1509,11 @@ mod tests { assert_eq!(_get_revocation_interval("not here", &proof_req), Err(ProofError::InvalidCredData())); // attribute interval overrides proof request interval - let interval = Some(NonRevokedInterval {from: Some(123), to: Some(456)}); + let interval = Some(NonRevokedInterval { from: Some(123), to: Some(456) }); assert_eq!(_get_revocation_interval("address1_1", &proof_req), Ok(interval)); // when attribute interval is None, defaults to proof req interval - let interval = Some(NonRevokedInterval {from: Some(098), to: Some(123)}); + let interval = Some(NonRevokedInterval { from: Some(098), to: Some(123) }); assert_eq!(_get_revocation_interval("zip_2", &proof_req), Ok(interval)); // No interval provided for attribute or proof req diff --git a/vcx/libvcx/src/issuer_credential.rs b/vcx/libvcx/src/issuer_credential.rs index afa411cb40..c77d36f6d1 100644 --- a/vcx/libvcx/src/issuer_credential.rs +++ b/vcx/libvcx/src/issuer_credential.rs @@ -6,9 +6,8 @@ use std::collections::HashMap; use api::VcxStateType; use messages; use settings; -use messages::{RemoteMessageType, PayloadKinds}; -use messages::MessageStatusCode; -use messages::{GeneralMessage}; +use messages::{RemoteMessageType, MessageStatusCode, GeneralMessage}; +use messages::payload::{Payloads, PayloadKinds, Thread}; use connection; use credential_request::CredentialRequest; use utils::error; @@ -24,7 +23,7 @@ use serde_json::Value; use object_cache::ObjectCache; lazy_static! { - static ref ISSUER_CREDENTIAL_MAP: ObjectCache = Default::default(); +static ref ISSUER_CREDENTIAL_MAP: ObjectCache < IssuerCredential > = Default::default(); } static CREDENTIAL_OFFER_ID_KEY: &str = "claim_offer_id"; @@ -57,27 +56,36 @@ pub struct IssuerCredential { price: u64, payment_address: Option, // the following 6 are pulled from the connection object - agent_did: String, //agent_did for this relationship + agent_did: String, + //agent_did for this relationship agent_vk: String, - issued_did: String, //my_pw_did for this relationship + issued_did: String, + //my_pw_did for this relationship issued_vk: String, - remote_did: String, //their_pw_did for this relationship + remote_did: String, + //their_pw_did for this relationship remote_vk: String, + thread: Thread } #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub struct CredentialOffer { pub msg_type: String, - pub version: String, //vcx version of cred_offer - pub to_did: String, //their_pw_did for this relationship - pub from_did: String, //my_pw_did for this relationship + pub version: String, + //vcx version of cred_offer + pub to_did: String, + //their_pw_did for this relationship + pub from_did: String, + //my_pw_did for this relationship pub libindy_offer: String, pub cred_def_id: String, - pub credential_attrs: serde_json::Map, //promised attributes revealed in credential + pub credential_attrs: serde_json::Map, + //promised attributes revealed in credential pub schema_seq_no: u32, pub claim_name: String, pub claim_id: String, pub msg_ref_id: Option, + pub thread_id: Option, } #[derive(Serialize, Deserialize, Debug, PartialEq)] @@ -155,10 +163,8 @@ impl IssuerCredential { }; payload.push(cred_json); - let payload = match serde_json::to_string(&payload) { - Ok(p) => p, - Err(_) => return Err(IssuerCredError::CommonError(error::INVALID_JSON.code_num)) - }; + + let payload = serde_json::to_string(&payload).or(Err(IssuerCredError::CommonError(error::INVALID_JSON.code_num)))?; debug!("credential offer data: {}", payload); @@ -167,7 +173,7 @@ impl IssuerCredential { .to(&self.issued_did)? .to_vk(&self.issued_vk)? .msg_type(&RemoteMessageType::CredOffer)? - .edge_agent_payload(&self.issued_vk, &self.remote_vk, &payload, PayloadKinds::CredOffer)? + .edge_agent_payload(&self.issued_vk, &self.remote_vk, &payload, PayloadKinds::CredOffer, Some(self.thread.clone()))? .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? .set_title(&title)? @@ -182,6 +188,7 @@ impl IssuerCredential { self.msg_uid = response.get_msg_uid()?; self.state = VcxStateType::VcxStateOfferSent; self.credential_offer = Some(credential_offer); + debug!("sent credential offer for: {}", self.source_id); return Ok(error::SUCCESS.code_num); } @@ -214,12 +221,14 @@ impl IssuerCredential { let cred_req_msg_id = self.credential_request.as_ref().and_then(|cred_req| cred_req.msg_ref_id.as_ref()) .ok_or(IssuerCredError::InvalidCredRequest())?; + self.thread.sender_order += 1; + let response = messages::send_message() .to(&self.issued_did)? .to_vk(&self.issued_vk)? .msg_type(&RemoteMessageType::Cred)? .status_code(&MessageStatusCode::Accepted)? - .edge_agent_payload(&self.issued_vk, &self.remote_vk, &data, PayloadKinds::Cred)? + .edge_agent_payload(&self.issued_vk, &self.remote_vk, &data, PayloadKinds::Cred, Some(self.thread.clone()))? .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? .ref_msg_id(cred_req_msg_id)? @@ -231,6 +240,7 @@ impl IssuerCredential { self.msg_uid = response.get_msg_uid()?; self.state = VcxStateType::VcxStateAccepted; + debug!("issued credential: {}", self.source_id); return Ok(error::SUCCESS.code_num); } @@ -245,7 +255,8 @@ impl IssuerCredential { debug!("updating state for credential offer: {} msg_uid: {:?}", self.source_id, self.msg_uid); if self.state == VcxStateType::VcxStateRequestReceived { return Ok(self.get_state()); - } else if self.state != VcxStateType::VcxStateOfferSent || self.msg_uid.is_empty() || self.issued_did.is_empty() { + } + if self.state != VcxStateType::VcxStateOfferSent || self.msg_uid.is_empty() || self.issued_did.is_empty() { return Ok(self.get_state()); } let (offer_uid, payload) = messages::get_message::get_ref_msg(&self.msg_uid, @@ -255,10 +266,14 @@ impl IssuerCredential { &self.agent_vk) .map_err(|wc| IssuerCredError::CommonError(wc))?; - let payload = messages::Payload::decrypted(&self.issued_vk, &payload).map_err(|ec| IssuerCredError::CommonError(ec))?; + let (payload, thread) = Payloads::decrypt(&self.issued_vk, &payload).map_err(|ec| IssuerCredError::CommonError(ec))?; + let cred_req = parse_credential_req_payload(offer_uid, payload)?; - self.credential_request = Some(parse_credential_req_payload(offer_uid, payload)?); - + if let Some(tr) = thread { + self.thread.increment_receiver(self.remote_did.as_str()); + } + + self.credential_request = Some(cred_req); debug!("received credential request for credential offer: {}", self.source_id); self.state = VcxStateType::VcxStateRequestReceived; Ok(self.get_state()) @@ -306,12 +321,9 @@ impl IssuerCredential { claim_offer_id: self.msg_uid.clone(), from_did: String::from(did), version: String::from("0.1"), - msg_type: String::from("CRED"), + msg_type: PayloadKinds::Cred.name().to_string(), libindy_cred: cred, - rev_reg_def_json: match self.rev_reg_def_json { - Some(_) => self.rev_reg_def_json.clone().unwrap(), - None => String::new(), - }, + rev_reg_def_json: self.rev_reg_def_json.clone().unwrap_or(String::new()), cred_def_id: self.cred_def_id.clone(), cred_revoc_id, revoc_reg_delta_json, @@ -324,7 +336,7 @@ impl IssuerCredential { let libindy_offer = anoncreds::libindy_issuer_create_credential_offer(&self.cred_def_id) .map_err(|err| IssuerCredError::CommonError(err))?; Ok(CredentialOffer { - msg_type: String::from("CRED_OFFER"), + msg_type: PayloadKinds::CredOffer.name().to_string(), version: String::from("0.1"), to_did: to_did.to_string(), from_did: self.issued_did.clone(), @@ -335,6 +347,7 @@ impl IssuerCredential { msg_ref_id: None, cred_def_id: self.cred_def_id.clone(), libindy_offer, + thread_id: None, }) } @@ -403,7 +416,7 @@ impl IssuerCredential { pub fn to_string(&self) -> String { json!({ "version": DEFAULT_SERIALIZE_VERSION, - "data": json!(self), + "data": json ! ( self), }).to_string() } @@ -470,7 +483,6 @@ pub fn encode_attributes(attributes: &str) -> Result { // new style input such as {"address2":"101 Wilson Lane"} serde_json::Value::String(str_type) => str_type, - // anything else is an error _ => { warn!("Invalid Json for Attribute data"); @@ -480,9 +492,9 @@ pub fn encode_attributes(attributes: &str) -> Result { let encoded = encode(&first_attr).map_err(|x| IssuerCredError::CommonError(x))?; let attrib_values = json!({ - "raw" : first_attr, - "encoded": encoded - }); +"raw": first_attr, +"encoded": encoded +}); dictionary.insert(attr, attrib_values); } @@ -524,6 +536,7 @@ fn parse_credential_req_payload(offer_uid: String, payload: String) -> Result) -> Result, u32> { @@ -238,15 +236,6 @@ impl GeneralMessage for GetMessagesBuilder { } } -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -#[serde(rename_all = "camelCase")] -pub struct Payload { - #[serde(rename = "@type")] - msg_type: PayloadTypes, - #[serde(rename = "@msg")] - pub msg: Vec, -} - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] #[serde(rename_all = "camelCase")] pub struct DeliveryDetails { @@ -320,7 +309,7 @@ pub fn get_ref_msg(msg_id: &str, pw_did: &str, pw_vk: &str, agent_did: &str, age _ => return Err(error::NOT_READY.code_num), }; - let message = get_connection_messages(pw_did, pw_vk, agent_did, agent_vk, Some(vec![msg_id]))?; + let message: Vec = get_connection_messages(pw_did, pw_vk, agent_did, agent_vk, Some(vec![msg_id]))?; trace!("checking for pending message: {:?}", message); diff --git a/vcx/libvcx/src/messages/invite.rs b/vcx/libvcx/src/messages/invite.rs index c3f9da2739..677ad5cd47 100644 --- a/vcx/libvcx/src/messages/invite.rs +++ b/vcx/libvcx/src/messages/invite.rs @@ -476,15 +476,24 @@ impl GeneralMessage for AcceptInviteBuilder { } } -pub fn parse_invitation_acceptance_details(payload: Vec) -> Result { - #[serde(rename_all = "camelCase")] - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] - struct Details { - sender_detail: SenderDetail, - } +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +#[serde(rename_all = "camelCase")] +pub struct Payload { + #[serde(rename = "@type")] + msg_type: ::messages::payload::PayloadTypes, + #[serde(rename = "@msg")] + pub msg: Vec, +} +#[serde(rename_all = "camelCase")] +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AcceptanceDetails { + pub sender_detail: SenderDetail, +} + +pub fn parse_invitation_acceptance_details(payload: Vec) -> Result { debug!("parsing invitation acceptance details: {:?}", payload); - let response: Details = rmp_serde::from_slice(&payload[..]).or(Err(error::INVALID_MSGPACK.code_num))?; + let response: AcceptanceDetails = rmp_serde::from_slice(&payload[..]).or(Err(error::INVALID_MSGPACK.code_num))?; Ok(response.sender_detail) } diff --git a/vcx/libvcx/src/messages/mod.rs b/vcx/libvcx/src/messages/mod.rs index 0a7eb8c811..58c9cdef92 100644 --- a/vcx/libvcx/src/messages/mod.rs +++ b/vcx/libvcx/src/messages/mod.rs @@ -9,6 +9,7 @@ pub mod agent_utils; pub mod update_connection; pub mod update_message; pub mod message_type; +pub mod payload; use std::u8; use settings; @@ -30,7 +31,6 @@ use self::message_type::*; use serde::{de, Deserialize, Deserializer, ser, Serialize, Serializer}; use serde_json::Value; -use std::collections::HashMap; #[derive(Debug, Serialize)] #[serde(untagged)] @@ -563,90 +563,6 @@ impl<'de> Deserialize<'de> for RemoteMessageType { } } - -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] -#[serde(untagged)] -pub enum PayloadTypes { - PayloadTypeV1(PayloadTypeV1), - PayloadTypeV2(PayloadTypeV2), -} - -#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] -pub struct PayloadTypeV1 { - name: String, - ver: String, - fmt: String, -} - -type PayloadTypeV2 = MessageTypeV2; - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub enum PayloadKinds { - CredOffer, - CredReq, - Cred, - Proof, - ProofRequest, - Other(String) -} - -impl PayloadKinds { - fn family(&self) -> MessageFamilies { - match self { - PayloadKinds::CredOffer => MessageFamilies::CredentialExchange, - PayloadKinds::CredReq => MessageFamilies::CredentialExchange, - PayloadKinds::Cred => MessageFamilies::CredentialExchange, - PayloadKinds::Proof => MessageFamilies::CredentialExchange, - PayloadKinds::ProofRequest => MessageFamilies::CredentialExchange, - PayloadKinds::Other(family) => MessageFamilies::Unknown(family.to_string()), - } - } - - fn name<'a>(&'a self) -> &'a str { - match settings::get_protocol_type() { - settings::ProtocolTypes::V1 => { - match self { - PayloadKinds::CredOffer => "CRED_OFFER", - PayloadKinds::CredReq => "CRED_REQ", - PayloadKinds::Cred => "CRED", - PayloadKinds::ProofRequest => "PROOF_REQUEST", - PayloadKinds::Proof => "PROOF", - PayloadKinds::Other(kind) => kind, - } - } - settings::ProtocolTypes::V2 => { - match self { - PayloadKinds::CredOffer => "credential-offer", - PayloadKinds::CredReq => "credential-request", - PayloadKinds::Cred => "credential", - PayloadKinds::ProofRequest => "presentation-request", - PayloadKinds::Proof => "presentation", - PayloadKinds::Other(kind) => kind, - } - } - } - } -} - -impl PayloadTypes { - pub fn build_v1(kind: PayloadKinds, fmt: &str) -> PayloadTypes { - PayloadTypes::PayloadTypeV1(PayloadTypeV1 { - name: kind.name().to_string(), - ver: MESSAGE_VERSION_V1.to_string(), - fmt: fmt.to_string(), - }) - } - - pub fn build_v2(kind: PayloadKinds) -> PayloadTypes { - PayloadTypes::PayloadTypeV2(PayloadTypeV2 { - did: DID.to_string(), - family: kind.family(), - version: MESSAGE_VERSION_V2.to_string(), - type_: kind.name().to_string(), - }) - } -} - #[derive(Clone, Debug, PartialEq)] pub enum MessageStatusCode { Created, @@ -780,14 +696,6 @@ impl A2AMessageKinds { } } -#[derive(Debug, Deserialize, Serialize, PartialEq)] -pub struct Thread { - pub thid: String, - pub pthid: Option, - pub sender_order: u32, - pub received_orders: Option>, -} - pub fn prepare_message_for_agency(message: &A2AMessage, agency_did: &str) -> Result, u32> { match settings::get_protocol_type() { settings::ProtocolTypes::V1 => bundle_for_agency_v1(message, &agency_did), @@ -907,87 +815,6 @@ pub fn bundle_from_u8(data: Vec) -> Result>, u32> { }) } -#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] -pub struct Payload { - #[serde(rename = "@type")] - pub type_: PayloadTypes, - #[serde(rename = "@msg")] - pub msg: String, -} - -impl Payload { - // TODO: Refactor Error - // this will become a CommonError, because multiple types (Connection/Issuer Credential) use this function - // Possibly this function moves out of this file. - // On second thought, this should stick as a ConnectionError. - pub fn encrypted(my_vk: &str, their_vk: &str, data: &str, msg_type: PayloadKinds) -> Result, u32> { - match settings::ProtocolTypes::from(settings::get_protocol_type()) { - settings::ProtocolTypes::V1 => { - let payload = ::messages::Payload { - type_: PayloadTypes::build_v1(msg_type, "json"), - msg: data.to_string(), - }; - - let bytes = rmp_serde::to_vec_named(&payload) - .map_err(|err| { - error!("could not encode create_keys msg: {}", err); - error::INVALID_MSGPACK.code_num - })?; - - trace!("Sending payload: {:?}", bytes); - ::utils::libindy::crypto::prep_msg(&my_vk, &their_vk, &bytes) - } - settings::ProtocolTypes::V2 => { - let payload = ::messages::Payload { - type_: PayloadTypes::build_v2(msg_type), - msg: data.to_string(), - }; - - let message = serde_json::to_string(&payload) - .map_err(|err| { - error!("could not serialize create_keys msg: {}", err); - error::INVALID_MSGPACK.code_num - })?; - - let receiver_keys = serde_json::to_string(&vec![&their_vk]).or(Err(error::SERIALIZATION_ERROR.code_num))?; - - trace!("Sending payload: {:?}", message.as_bytes()); - ::utils::libindy::crypto::pack_message(Some(my_vk), &receiver_keys, message.as_bytes()) - } - } - } - - pub fn decrypted(my_vk: &str, payload: &Vec) -> Result { - match settings::ProtocolTypes::from(settings::get_protocol_type()) { - settings::ProtocolTypes::V1 => { - let (_, data) = crypto::parse_msg(&my_vk, &to_u8(payload))?; - - let my_payload: Payload = rmp_serde::from_slice(&data[..]) - .map_err(|err| { - error!("could not deserialize bundle with i8 or u8: {}", err); - error::INVALID_MSGPACK.code_num - })?; - Ok(my_payload.msg) - } - settings::ProtocolTypes::V2 => { - let unpacked_msg = crypto::unpack_message(&to_u8(payload))?; - - let message: Value = ::serde_json::from_slice(unpacked_msg.as_slice()) - .or(Err(error::INVALID_JSON.code_num))?; - - let message = message["message"].as_str().ok_or(error::INVALID_JSON.code_num)?.to_string(); - - let my_payload: Payload = serde_json::from_str(&message) - .map_err(|err| { - error!("could not deserialize bundle with i8 or u8: {}", err); - error::INVALID_MSGPACK.code_num - })?; - Ok(my_payload.msg) - } - } - } -} - fn prepare_forward_message(message: Vec, did: &str) -> Result, u32> { let agency_vk = settings::get_config_value(settings::CONFIG_AGENCY_VERKEY)?; diff --git a/vcx/libvcx/src/messages/payload.rs b/vcx/libvcx/src/messages/payload.rs new file mode 100644 index 0000000000..62c045ba78 --- /dev/null +++ b/vcx/libvcx/src/messages/payload.rs @@ -0,0 +1,227 @@ +use messages::message_type::*; +use messages::to_u8; +use settings::{ProtocolTypes, get_protocol_type}; +use utils::error; +use utils::libindy::crypto; + +use std::collections::HashMap; + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] +pub enum Payloads { + PayloadV1(PayloadV1), + PayloadV2(PayloadV2), +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] +pub struct PayloadV1 { + #[serde(rename = "@type")] + pub type_: PayloadTypeV1, + #[serde(rename = "@msg")] + pub msg: String, +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] +pub struct PayloadV2 { + #[serde(rename = "@type")] + pub type_: PayloadTypeV2, + #[serde(rename = "@id")] + pub id: String, + #[serde(rename = "@msg")] + pub msg: String, + #[serde(rename = "~thread")] + pub thread: Thread, +} + +impl Payloads { + // TODO: Refactor Error + // this will become a CommonError, because multiple types (Connection/Issuer Credential) use this function + // Possibly this function moves out of this file. + // On second thought, this should stick as a ConnectionError. + pub fn encrypt(my_vk: &str, their_vk: &str, data: &str, msg_type: PayloadKinds, thread: Option) -> Result, u32> { + match ProtocolTypes::from(get_protocol_type()) { + ProtocolTypes::V1 => { + let payload = PayloadV1 { + type_: PayloadTypes::build_v1(msg_type, "json"), + msg: data.to_string(), + }; + + let bytes = rmp_serde::to_vec_named(&payload) + .map_err(|err| { + error!("could not encode create_keys msg: {}", err); + error::INVALID_MSGPACK.code_num + })?; + + trace!("Sending payload: {:?}", bytes); + crypto::prep_msg(&my_vk, &their_vk, &bytes) + } + ProtocolTypes::V2 => { + let thread = thread.ok_or(error::INVALID_CONNECTION_HANDLE.code_num)?; + + let payload = PayloadV2 { + type_: PayloadTypes::build_v2(msg_type), + id: String::new(), + msg: data.to_string(), + thread, + }; + + let message = ::serde_json::to_string(&payload) + .map_err(|err| { + error!("could not serialize create_keys msg: {}", err); + error::INVALID_MSGPACK.code_num + })?; + + let receiver_keys = ::serde_json::to_string(&vec![&their_vk]).or(Err(error::SERIALIZATION_ERROR.code_num))?; + + trace!("Sending payload: {:?}", message.as_bytes()); + crypto::pack_message(Some(my_vk), &receiver_keys, message.as_bytes()) + } + } + } + + pub fn decrypt(my_vk: &str, payload: &Vec) -> Result<(String, Option), u32> { + match ProtocolTypes::from(get_protocol_type()) { + ProtocolTypes::V1 => { + let (_, data) = crypto::parse_msg(&my_vk, &to_u8(payload))?; + + let my_payload: PayloadV1 = rmp_serde::from_slice(&data[..]) + .map_err(|err| { + error!("could not deserialize bundle with i8 or u8: {}", err); + error::INVALID_MSGPACK.code_num + })?; + Ok((my_payload.msg, None)) + } + ProtocolTypes::V2 => { + Payloads::decrypt_payload_v2(my_vk, payload) + } + } + } + + pub fn decrypt_payload_v2(my_vk: &str, payload: &Vec) -> Result<(String, Option), u32> { + let unpacked_msg = crypto::unpack_message(&to_u8(payload))?; + + let message: ::serde_json::Value = ::serde_json::from_slice(unpacked_msg.as_slice()) + .or(Err(error::INVALID_JSON.code_num))?; + + let message = message["message"].as_str().ok_or(error::INVALID_JSON.code_num)?.to_string(); + + let mut my_payload: PayloadV2 = serde_json::from_str(&message) + .map_err(|err| { + error!("could not deserialize bundle with i8 or u8: {}", err); + error::INVALID_MSGPACK.code_num + })?; + + if my_payload.thread.thid.is_none() { + my_payload.thread.thid = Some(my_payload.id); + } + + Ok((my_payload.msg, Some(my_payload.thread))) + } +} + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[serde(untagged)] +pub enum PayloadTypes { + PayloadTypeV1(PayloadTypeV1), + PayloadTypeV2(PayloadTypeV2), +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] +pub struct PayloadTypeV1 { + name: String, + ver: String, + fmt: String, +} + +type PayloadTypeV2 = MessageTypeV2; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub enum PayloadKinds { + CredOffer, + CredReq, + Cred, + Proof, + ProofRequest, + Other(String) +} + +impl PayloadKinds { + fn family(&self) -> MessageFamilies { + match self { + PayloadKinds::CredOffer => MessageFamilies::CredentialExchange, + PayloadKinds::CredReq => MessageFamilies::CredentialExchange, + PayloadKinds::Cred => MessageFamilies::CredentialExchange, + PayloadKinds::Proof => MessageFamilies::CredentialExchange, + PayloadKinds::ProofRequest => MessageFamilies::CredentialExchange, + PayloadKinds::Other(family) => MessageFamilies::Unknown(family.to_string()), + } + } + + pub fn name<'a>(&'a self) -> &'a str { + match get_protocol_type() { + ProtocolTypes::V1 => { + match self { + PayloadKinds::CredOffer => "CRED_OFFER", + PayloadKinds::CredReq => "CRED_REQ", + PayloadKinds::Cred => "CRED", + PayloadKinds::ProofRequest => "PROOF_REQUEST", + PayloadKinds::Proof => "PROOF", + PayloadKinds::Other(kind) => kind, + } + } + ProtocolTypes::V2 => { + match self { + PayloadKinds::CredOffer => "credential-offer", + PayloadKinds::CredReq => "credential-request", + PayloadKinds::Cred => "credential", + PayloadKinds::ProofRequest => "presentation-request", + PayloadKinds::Proof => "presentation", + PayloadKinds::Other(kind) => kind, + } + } + } + } +} + +impl PayloadTypes { + pub fn build_v1(kind: PayloadKinds, fmt: &str) -> PayloadTypeV1 { + PayloadTypeV1 { + name: kind.name().to_string(), + ver: MESSAGE_VERSION_V1.to_string(), + fmt: fmt.to_string(), + } + } + + pub fn build_v2(kind: PayloadKinds) -> PayloadTypeV2 { + PayloadTypeV2 { + did: DID.to_string(), + family: kind.family(), + version: MESSAGE_VERSION_V2.to_string(), + type_: kind.name().to_string(), + } + } +} + +#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)] +pub struct Thread { + pub thid: Option, + pub pthid: Option, + pub sender_order: u32, + pub received_orders: HashMap, +} + +impl Thread { + pub fn new() -> Thread { + Thread { + thid: None, + pthid: None, + sender_order: 0, + received_orders: HashMap::new(), + } + } + + pub fn increment_receiver(&mut self, did: &str) { + self.received_orders.entry(did.to_string()) + .and_modify(|e| *e += 1) + .or_insert(0); + } +} \ No newline at end of file diff --git a/vcx/libvcx/src/messages/proofs/proof_request.rs b/vcx/libvcx/src/messages/proofs/proof_request.rs index 7c61467b52..526228d27e 100644 --- a/vcx/libvcx/src/messages/proofs/proof_request.rs +++ b/vcx/libvcx/src/messages/proofs/proof_request.rs @@ -88,7 +88,8 @@ pub struct ProofRequestMessage{ validate_rc: u32, pub msg_ref_id: Option, from_timestamp: Option, - to_timestamp: Option + to_timestamp: Option, + pub thread_id: Option } impl ProofPredicates { @@ -122,6 +123,7 @@ impl ProofRequestMessage { msg_ref_id: None, from_timestamp: None, to_timestamp: None, + thread_id: None, } } diff --git a/vcx/libvcx/src/messages/send_message.rs b/vcx/libvcx/src/messages/send_message.rs index 1af63bf9a2..f0ca9cb0c8 100644 --- a/vcx/libvcx/src/messages/send_message.rs +++ b/vcx/libvcx/src/messages/send_message.rs @@ -3,9 +3,9 @@ use connection; use api::VcxStateType; use messages::*; use messages::message_type::MessageTypes; +use messages::payload::{Payloads, PayloadKinds, Thread}; use utils::{httpclient, error}; - #[derive(Debug)] pub struct SendMessageBuilder { mtype: RemoteMessageType, @@ -58,9 +58,9 @@ impl SendMessageBuilder { Ok(self) } - pub fn edge_agent_payload(&mut self, my_vk: &str, their_vk: &str, data: &str, payload_type: PayloadKinds) -> Result<&mut Self, u32> { + pub fn edge_agent_payload(&mut self, my_vk: &str, their_vk: &str, data: &str, payload_type: PayloadKinds, thread: Option) -> Result<&mut Self, u32> { //todo: is this a json value, String?? - self.payload = Payload::encrypted(my_vk, their_vk, data, payload_type)?; + self.payload = Payloads::encrypt(my_vk, their_vk, data, payload_type, thread)?; Ok(self) } @@ -105,7 +105,7 @@ impl SendMessageBuilder { return Err(error::INVALID_HTTP_RESPONSE.code_num); } 1 - }, + } settings::ProtocolTypes::V2 => 0 }; @@ -198,7 +198,7 @@ pub fn send_generic_message(connection_handle: u32, msg: &str, msg_type: &str, m .to(&did)? .to_vk(&vk)? .msg_type(&RemoteMessageType::Other(msg_type.to_string()))? - .edge_agent_payload(&vk, &remote_vk, &msg, PayloadKinds::Other(msg_type.to_string()))? + .edge_agent_payload(&vk, &remote_vk, &msg, PayloadKinds::Other(msg_type.to_string()), None)? .agent_did(&agent_did)? .agent_vk(&agent_vk)? .set_title(&msg_title)? diff --git a/vcx/libvcx/src/proof.rs b/vcx/libvcx/src/proof.rs index cdab2931ea..9a0e90553f 100644 --- a/vcx/libvcx/src/proof.rs +++ b/vcx/libvcx/src/proof.rs @@ -9,7 +9,8 @@ use connection; use api::{VcxStateType, ProofStateType}; use messages::proofs::proof_message::{ProofMessage, CredInfo}; use messages; -use messages::{RemoteMessageType, PayloadKinds}; +use messages::RemoteMessageType; +use messages::payload::{Payloads, PayloadKinds, Thread}; use messages::proofs::proof_request::ProofRequestMessage; use messages::GeneralMessage; use utils::error; @@ -53,7 +54,8 @@ pub struct Proof { remote_vk: String, agent_did: String, agent_vk: String, - revocation_interval: RevocationInterval + revocation_interval: RevocationInterval, + thread: Thread } impl Proof { @@ -286,7 +288,7 @@ impl Proof { .set_title(&title)? .set_detail(&title)? .agent_vk(&self.agent_vk)? - .edge_agent_payload(&self.prover_vk, &self.remote_vk, &proof_request, PayloadKinds::ProofRequest).or(Err(ProofError::ProofConnectionError()))? + .edge_agent_payload(&self.prover_vk, &self.remote_vk, &proof_request, PayloadKinds::ProofRequest, Some(self.thread.clone())).or(Err(ProofError::ProofConnectionError()))? .send_secure() .map_err(|err| { warn!("{} could not send proofReq: {}", self.source_id, err); @@ -315,13 +317,17 @@ impl Proof { &self.agent_vk) .map_err(|ec| ProofError::ProofMessageError(ec))?; - let payload = messages::Payload::decrypted(&self.prover_vk, &payload).map_err(|ec| ProofError::CommonError(ec))?; + let (payload, thread) = Payloads::decrypt(&self.prover_vk, &payload).map_err(|ec| ProofError::CommonError(ec))?; self.proof = match parse_proof_payload(&payload) { Err(err) => return Ok(self.get_state()), Ok(x) => Some(x), }; + if let Some(tr) = thread { + self.thread.increment_receiver(self.remote_did.as_str()); + } + self.state = VcxStateType::VcxStateAccepted; match self.proof_validation() { @@ -416,7 +422,8 @@ pub fn create_proof(source_id: String, remote_vk: String::new(), agent_did: String::new(), agent_vk: String::new(), - revocation_interval: revocation_details + revocation_interval: revocation_details, + thread: Thread::new(), }; new_proof.validate_proof_request().map_err(|ec| ProofError::CommonError(ec))?; @@ -535,6 +542,7 @@ mod tests { use utils::httpclient; use connection::tests::build_test_connection; use utils::libindy::{pool, set_libindy_rc}; + use std::collections::HashMap; static PROOF_MSG: &str = r#"{"msg_type":"proof","version":"0.1","to_did":"BnRXf8yDMUwGyZVDkSENeq","from_did":"GxtnGN6ypZYgEqcftSQFnC","proof_request_id":"cCanHnpFAD","proofs":{"claim::e5fec91f-d03d-4513-813c-ab6db5715d55":{"proof":{"primary_proof":{"eq_proof":{"revealed_attrs":{"state":"96473275571522321025213415717206189191162"},"a_prime":"22605045280481376895214546474258256134055560453004805058368015338423404000586901936329279496160366852115900235316791489357953785379851822281248296428005020302405076144264617943389810572564188437603815231794326272302243703078443007359698858400857606408856314183672828086906560155576666631125808137726233827430076624897399072853872527464581329767287002222137559918765406079546649258389065217669558333867707240780369514832185660287640444094973804045885379406641474693993903268791773620198293469768106363470543892730424494655747935463337367735239405840517696064464669905860189004121807576749786474060694597244797343224031","e":"70192089123105616042684481760592174224585053817450673797400202710878562748001698340846985261463026529360990669802293480312441048965520897","v":"1148619141217957986496757711054111791862691178309410923416837802801708689012670430650138736456223586898110113348220116209094530854607083005898964558239710027534227973983322542548800291320747321452329327824406430787211689678096549398458892087551551587767498991043777397791000822007896620414888602588897806008609113730393639807814070738699614969916095861363383223421727858670289337712185089527052065958362840287749622133424503902085247641830693297082507827948006947829401008622239294382186995101394791468192083810475776455445579931271665980788474331866572497866962452476638881287668931141052552771328556458489781734943404258692308937784221642452132005267809852656378394530342203469943982066011466088478895643800295937901139711103301249691253510784029114718919483272055970725860849610885050165709968510696738864528287788491998027072378656038991754015693216663830793243584350961586874315757599094357535856429087122365865868729","m":{"address2":"11774234640096848605908744857306447015748098256395922562149769943967941106193320512788344020652220849708117081570187385467979956319507248530701654682748372348387275979419669108338","city":"4853213962270369118453000522408430296589146124488849630769837449684434138367659379663124155088827069418193027370932024893343033367076071757003149452226758383807126385017161888440","address1":"12970590675851114145396120869959510754345567924518524026685086869487243290925032320159287997675756075512889990901552679591155319959039145119122576164798225386578339739435869622811","zip":"8333721522340131864419931745588776943042067606218561135102011966361165456174036379901390244538991611895455576519950813910672825465382312504250936740379785802177629077591444977329"},"m1":"92853615502250003546205004470333326341901175168428906399291824325990659330595200000112546157141090642053863739870044907457400076448073272490169488870502566172795456430489790324815765612798273406119873266684053517977802902202155082987833343670942161987285661291655743810590661447300059024966135828466539810035","m2":"14442362430453309930284822850357071315613831915865367971974791350454381198894252834180803515368579729220423713315556807632571621646127926114010380486713602821529657583905131582938"},"ge_proofs":[]},"non_revoc_proof":null},"schema_seq_no":15,"issuer_did":"4fUDR9R7fjwELRvH9JT6HH"}},"aggregated_proof":{"c_hash":"68430476900085482958838239880418115228681348197588159723604944078288347793331","c_list":[[179,17,2,242,194,227,92,203,28,32,255,113,112,20,5,243,9,111,220,111,21,210,116,12,167,119,253,181,37,40,143,215,140,42,179,97,75,229,96,94,54,248,206,3,48,14,61,219,160,122,139,227,166,183,37,43,197,200,28,220,217,10,65,42,6,195,124,44,164,65,114,206,51,231,254,156,170,141,21,153,50,251,237,65,147,97,243,17,157,116,213,201,80,119,106,70,88,60,55,36,33,160,135,106,60,212,191,235,116,57,78,177,61,86,44,226,205,100,134,118,93,6,26,58,220,66,232,166,202,62,90,174,231,207,19,239,233,223,70,191,199,100,157,62,139,176,28,184,9,70,116,199,142,237,198,183,12,32,53,84,207,202,77,56,97,177,154,169,223,201,212,163,212,101,184,255,215,167,16,163,136,44,25,123,49,15,229,41,149,133,159,86,106,208,234,73,207,154,194,162,141,63,159,145,94,47,174,51,225,91,243,2,221,202,59,11,212,243,197,208,116,42,242,131,221,137,16,169,203,215,239,78,254,150,42,169,202,132,172,106,179,130,178,130,147,24,173,213,151,251,242,44,54,47,208,223]]},"requested_proof":{"revealed_attrs":{"sdf":["claim::e5fec91f-d03d-4513-813c-ab6db5715d55","UT","96473275571522321025213415717206189191162"]},"unrevealed_attrs":{},"self_attested_attrs":{},"predicates":{}}}"#; @@ -564,7 +572,14 @@ mod tests { remote_vk: VERKEY.to_string(), agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), - revocation_interval: RevocationInterval { from: None, to: None } + revocation_interval: RevocationInterval { from: None, to: None }, + + thread: Thread { + thid: None, + pthid: None, + sender_order: 0, + received_orders: HashMap::new(), + }, }) } @@ -726,7 +741,14 @@ mod tests { remote_vk: VERKEY.to_string(), agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), - revocation_interval: RevocationInterval { from: None, to: None } + revocation_interval: RevocationInterval { from: None, to: None }, + + thread: Thread { + thid: None, + pthid: None, + sender_order: 0, + received_orders: HashMap::new(), + }, }); httpclient::set_next_u8_response(PROOF_RESPONSE.to_vec()); @@ -761,7 +783,14 @@ mod tests { remote_vk: VERKEY.to_string(), agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), - revocation_interval: RevocationInterval { from: None, to: None } + revocation_interval: RevocationInterval { from: None, to: None }, + + thread: Thread { + thid: None, + pthid: None, + sender_order: 0, + received_orders: HashMap::new(), + }, }); httpclient::set_next_u8_response(PROOF_RESPONSE.to_vec()); @@ -935,7 +964,13 @@ mod tests { remote_vk: VERKEY.to_string(), agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), - revocation_interval: RevocationInterval { from: None, to: None } + revocation_interval: RevocationInterval { from: None, to: None }, + thread: Thread { + thid: None, + pthid: None, + sender_order: 0, + received_orders: HashMap::new(), + }, }; let rc = proof.proof_validation(); assert!(rc.is_ok()); diff --git a/vcx/libvcx/src/utils/mod.rs b/vcx/libvcx/src/utils/mod.rs index d1243e721d..b3b9e86a8e 100644 --- a/vcx/libvcx/src/utils/mod.rs +++ b/vcx/libvcx/src/utils/mod.rs @@ -18,6 +18,7 @@ pub mod openssl; pub mod json; pub mod libindy; pub mod threadpool; +pub mod uuid; use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use std::path::PathBuf; diff --git a/vcx/libvcx/src/utils/uuid.rs b/vcx/libvcx/src/utils/uuid.rs new file mode 100644 index 0000000000..6bdfc75e04 --- /dev/null +++ b/vcx/libvcx/src/utils/uuid.rs @@ -0,0 +1,3 @@ +pub fn uuid() -> String { + uuid::Uuid::new_v4().to_string() +} \ No newline at end of file From 0ef03b974a0339f7f0dac3da71a398a7bf3971ba Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 18 Feb 2019 09:40:39 +0300 Subject: [PATCH 02/28] Fixed code review comments Signed-off-by: artem.ivanov --- Jenkinsfile.cd | 3 +- Jenkinsfile.ci | 5 +- vcx/dummy-cloud-agent/sample-config.json | 3 +- .../src/actors/agent_connection.rs | 30 +++++----- vcx/dummy-cloud-agent/src/domain/a2a.rs | 28 +++++----- .../src/domain/message_type.rs | 26 +++++---- vcx/dummy-cloud-agent/src/domain/payload.rs | 4 +- .../src/domain/protocol_type.rs | 4 +- vcx/libvcx/src/lib.rs | 6 +- vcx/libvcx/src/messages/agent_utils.rs | 56 +++++++++---------- vcx/libvcx/src/messages/create_key.rs | 4 +- vcx/libvcx/src/messages/invite.rs | 21 ++++--- vcx/libvcx/src/messages/message_type.rs | 30 +++++----- vcx/libvcx/src/messages/mod.rs | 16 +++--- vcx/libvcx/src/messages/payload.rs | 6 +- vcx/libvcx/src/messages/send_message.rs | 5 +- 16 files changed, 129 insertions(+), 118 deletions(-) diff --git a/Jenkinsfile.cd b/Jenkinsfile.cd index f1d6457ded..2b57a4e158 100644 --- a/Jenkinsfile.cd +++ b/Jenkinsfile.cd @@ -387,7 +387,8 @@ def linuxVcxBuild(file, env_name, network_name, stashBuildResults) { testEnv.inside("--network=${network_name}") { sh ''' cd vcx/dummy-cloud-agent - LIBRARY_PATH=./ LD_LIBRARY_PATH=./:${LD_LIBRARY_PATH} RUST_BACKTRACE=1 RUST_LOG=indy=info PROTOCOL_TYPE=2.0 cargo run sample-config.json & + sed -i 's/\\("protocol_type": "\\)1.0/\\12.0/' sample-config.json + LIBRARY_PATH=./ LD_LIBRARY_PATH=./:${LD_LIBRARY_PATH} RUST_BACKTRACE=1 RUST_LOG=indy=info cargo run sample-config.json & ''' echo "${env_name} Libvcx Test: Run vcx demo test for protocol version 2.0" diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 5014a48978..269e9bb7db 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -13,7 +13,7 @@ def testing() { 'android-test': { androidTesting() }, 'macos-test' : { macosTesting() }, 'ios-test' : { iosTesting() }, -'redhat-test' : { rhelTesting() }, + 'redhat-test' : { rhelTesting() }, 'windows-test': { windowsTesting() } ]) } @@ -507,7 +507,8 @@ def linuxVcxBuild(file, env_name, network_name) { testEnv.inside("--network=${network_name}") { sh ''' cd vcx/dummy-cloud-agent - LIBRARY_PATH=./ LD_LIBRARY_PATH=./:${LD_LIBRARY_PATH} RUST_BACKTRACE=1 RUST_LOG=indy=info PROTOCOL_TYPE=2.0 cargo run sample-config.json & + sed -i 's/\\("protocol_type": "\\)1.0/\\12.0/' sample-config.json + LIBRARY_PATH=./ LD_LIBRARY_PATH=./:${LD_LIBRARY_PATH} RUST_BACKTRACE=1 RUST_LOG=indy=info cargo run sample-config.json & ''' echo "${env_name} Libvcx Test: Run tests" diff --git a/vcx/dummy-cloud-agent/sample-config.json b/vcx/dummy-cloud-agent/sample-config.json index de229e0b1d..8f5d5bb35b 100644 --- a/vcx/dummy-cloud-agent/sample-config.json +++ b/vcx/dummy-cloud-agent/sample-config.json @@ -20,5 +20,6 @@ "config": null, "credentials": null, "type": null - } + }, + "protocol_type": "1.0" } \ No newline at end of file diff --git a/vcx/dummy-cloud-agent/src/actors/agent_connection.rs b/vcx/dummy-cloud-agent/src/actors/agent_connection.rs index 069bea4a44..8836057116 100644 --- a/vcx/dummy-cloud-agent/src/actors/agent_connection.rs +++ b/vcx/dummy-cloud-agent/src/actors/agent_connection.rs @@ -241,7 +241,7 @@ impl AgentConnection { A2AMessageV2::UpdateMessageStatus(msg) => slf.handle_update_message_status(msg), _ => err_act!(slf, err_msg("Unsupported message")) } - }, + } _ => err_act!(slf, err_msg("Unsupported message")) }.map(|msgs, _, _| (msgs, sender_vk)) }) @@ -367,13 +367,13 @@ impl AgentConnection { let send_msg = msg.send_msg; let reply_to_msg_id = msg.reply_to_msg_id.clone(); - let msg_uid = msg.uid.clone(); + let msg_uid = msg.id.clone(); let sender_verkey = sender_verkey.to_string(); future::ok(()) .into_actor(self) .and_then(move |_, slf, _| { - slf.handle_create_connection_request_answer(msg.into(), reply_to_msg_id.clone(), msg_uid, sender_verkey) + slf.handle_create_connection_request_answer(msg.into(), reply_to_msg_id.clone(), Some(msg_uid), sender_verkey) .map(|(msg_uid, a2a_msgs), _, _| (msg_uid, a2a_msgs, reply_to_msg_id)) }) .and_then(move |(msg_uid, a2a_msgs, reply_to_msg_id), slf, _| { @@ -414,14 +414,14 @@ impl AgentConnection { let send_msg = msg.send_msg; let mtype = msg.mtype.clone(); - let uid = msg.uid.clone(); + let uid = msg.id.clone(); let reply_to_msg_id = msg.reply_to_msg_id.clone(); let sender_verkey = sender_verkey.to_string(); future::ok(()) .into_actor(self) .and_then(move |_, slf, _| { - slf.handle_create_general_message(mtype, msg.into(), reply_to_msg_id.clone(), uid, sender_verkey) + slf.handle_create_general_message(mtype, msg.into(), reply_to_msg_id.clone(), Some(uid), sender_verkey) .map(|(msg_uid, a2a_msgs), _, _| (msg_uid, a2a_msgs, reply_to_msg_id)) }) .and_then(move |(msg_uid, a2a_msgs, reply_to_msg_id), slf, _| { @@ -468,7 +468,7 @@ impl AgentConnection { let message = match ProtocolType::get() { ProtocolTypes::V1 => A2AMessage::Version1(A2AMessageV1::MessageCreated(MessageCreated { uid: msg.uid.clone() })), - ProtocolTypes::V2 => A2AMessage::Version2(A2AMessageV2::SendRemoteMessageResponse(SendRemoteMessageResponse { uid: msg.uid.clone(), sent: true })), + ProtocolTypes::V2 => A2AMessage::Version2(A2AMessageV2::SendRemoteMessageResponse(SendRemoteMessageResponse { id: msg.uid.clone(), sent: true })), }; ok_act!(self, (msg.uid, vec![message])) @@ -681,7 +681,7 @@ impl AgentConnection { .map(|uid, _, _| { let message = match ProtocolType::get() { ProtocolTypes::V1 => A2AMessage::Version1(A2AMessageV1::MessageCreated(MessageCreated { uid: uid.clone() })), - ProtocolTypes::V2 => A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswerResponse(ConnectionRequestAnswerResponse { uid: uid.clone(), sent: true })) + ProtocolTypes::V2 => A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswerResponse(ConnectionRequestAnswerResponse { id: uid.clone(), sent: true })) }; (uid, vec![message]) }) @@ -744,7 +744,7 @@ impl AgentConnection { .map(|uid, _, _| { let message = match ProtocolType::get() { ProtocolTypes::V1 => A2AMessage::Version1(A2AMessageV1::MessageCreated(MessageCreated { uid: uid.clone() })), - ProtocolTypes::V2 => A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswerResponse(ConnectionRequestAnswerResponse { uid: uid.clone(), sent: true })) + ProtocolTypes::V2 => A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswerResponse(ConnectionRequestAnswerResponse { id: uid.clone(), sent: true })) }; (uid, vec![message]) }) @@ -1135,7 +1135,8 @@ impl AgentConnection { match ProtocolType::get() { ProtocolTypes::V1 => { - let msg = ftry!(rmp_serde::to_vec_named(&msg));; + let msg = ftry!(rmp_serde::to_vec_named(&msg)); + ; let payload_msg = PayloadV1 { type_: PayloadTypes::build_v1(PayloadKinds::from(type_), "json"), @@ -1147,9 +1148,10 @@ impl AgentConnection { crypto::auth_crypt(self.wallet_handle, &self.agent_pairwise_verkey, &self.owner_verkey, &message) .map_err(|err| err.context("Can't encode Answer Payload.").into()) .into_box() - }, + } ProtocolTypes::V2 => { - let msg = ftry!(serde_json::to_string(&msg));; + let msg = ftry!(serde_json::to_string(&msg)); + ; let payload_msg = PayloadV2 { type_: PayloadTypes::build_v2(PayloadKinds::from(type_)), @@ -1213,7 +1215,7 @@ impl AgentConnection { } ProtocolTypes::V2 => { let message = ConnectionRequestResponse { - uid: msg.uid.clone(), + id: msg.uid.clone(), invite_detail, url_to_invite_detail: "".to_string(), // format!("{}/agency/invite/{}?msg_uid{}", AGENCY_DOMAIN_URL_PREFIX, self.agent_pairwise_did, msg_uid) @@ -1265,7 +1267,7 @@ impl AgentConnection { ProtocolTypes::V2 => { let msg = ConnectionRequestAnswer { send_msg: false, - uid: Some(message.uid.clone()), + id: message.uid.clone(), reply_to_msg_id: Some(reply_to.to_string()), key_dlg_proof: None, sender_detail, @@ -1307,8 +1309,8 @@ impl AgentConnection { ProtocolTypes::V2 => { let msg = SendRemoteMessage { mtype: message._type, + id: message.uid, send_msg: false, - uid: Some(message.uid), reply_to_msg_id: reply_to.map(String::from), msg, title, diff --git a/vcx/dummy-cloud-agent/src/domain/a2a.rs b/vcx/dummy-cloud-agent/src/domain/a2a.rs index e6bc2025c4..d70b70a7c7 100644 --- a/vcx/dummy-cloud-agent/src/domain/a2a.rs +++ b/vcx/dummy-cloud-agent/src/domain/a2a.rs @@ -467,8 +467,8 @@ pub struct ConfigsRemoved {} pub struct ConnectionRequest { #[serde(rename = "sendMsg")] pub send_msg: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub uid: Option, + #[serde(rename = "@id")] + id: String, #[serde(rename = "replyToMsgId")] pub reply_to_msg_id: Option, #[serde(rename = "keyDlgProof")] @@ -483,7 +483,8 @@ pub struct ConnectionRequest { #[derive(Debug, Deserialize, Serialize)] pub struct ConnectionRequestResponse { - pub uid: String, + #[serde(rename = "@id")] + pub id: String, #[serde(rename = "inviteDetail")] pub invite_detail: InviteDetail, #[serde(rename = "urlToInviteDetail")] @@ -495,8 +496,8 @@ pub struct ConnectionRequestResponse { pub struct ConnectionRequestAnswer { #[serde(rename = "sendMsg")] pub send_msg: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub uid: Option, + #[serde(rename = "@id")] + pub id: String, #[serde(rename = "replyToMsgId")] pub reply_to_msg_id: Option, #[serde(rename = "keyDlgProof")] @@ -511,7 +512,8 @@ pub struct ConnectionRequestAnswer { #[derive(Debug, Deserialize, Serialize)] pub struct ConnectionRequestAnswerResponse { - pub uid: String, + #[serde(rename = "@id")] + pub id: String, pub sent: bool, } @@ -519,13 +521,13 @@ pub struct ConnectionRequestAnswerResponse { #[serde(rename_all = "camelCase")] pub struct SendRemoteMessage { pub mtype: RemoteMessageType, + #[serde(rename = "@id")] + pub id: String, #[serde(rename = "replyToMsgId")] #[serde(skip_serializing_if = "Option::is_none")] pub reply_to_msg_id: Option, #[serde(rename = "sendMsg")] pub send_msg: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub uid: Option, #[serde(rename = "@msg")] pub msg: Vec, #[serde(skip_serializing_if = "Option::is_none")] @@ -537,7 +539,8 @@ pub struct SendRemoteMessage { #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct SendRemoteMessageResponse { - pub uid: String, + #[serde(rename = "@id")] + pub id: String, pub sent: bool, } @@ -1006,16 +1009,15 @@ impl<'de> Deserialize<'de> for A2AMessage { let value = Value::deserialize(deserializer).map_err(de::Error::custom)?; let message_type: MessageTypes = serde_json::from_value(value["@type"].clone()).map_err(de::Error::custom)?; - match message_type.version() { - "1.0" => + match message_type { + MessageTypes::MessageTypeV1(_) => A2AMessageV1::deserialize(value) .map(|msg| A2AMessage::Version1(msg)) .map_err(de::Error::custom), - "2.0" => + MessageTypes::MessageTypeV2(_) => A2AMessageV2::deserialize(value) .map(|msg| A2AMessage::Version2(msg)) .map_err(de::Error::custom), - _ => Err(de::Error::custom("Unexpected @type field structure.")) } } } diff --git a/vcx/dummy-cloud-agent/src/domain/message_type.rs b/vcx/dummy-cloud-agent/src/domain/message_type.rs index 0d27a83968..e0eac9893d 100644 --- a/vcx/dummy-cloud-agent/src/domain/message_type.rs +++ b/vcx/dummy-cloud-agent/src/domain/message_type.rs @@ -4,10 +4,8 @@ use regex::Regex; use failure::{err_msg, Error}; use domain::a2a::A2AMessageKinds; -pub const MESSAGE_VERSION_V1: &str = "1.0"; -pub const MESSAGE_VERSION_V2: &str = "2.0"; - pub const DID: &str = "did:sov:123456789abcdefghi1234"; +pub const MESSAGE_VERSION_V1: &str = "1.0"; #[derive(Debug, Deserialize, Serialize)] #[serde(untagged)] @@ -28,17 +26,10 @@ impl MessageTypes { MessageTypes::MessageTypeV2(MessageTypeV2 { did: DID.to_string(), family: kind.family(), - version: MESSAGE_VERSION_V2.to_string(), + version: kind.family().version().to_string(), type_: kind.name(), }) } - - pub fn version<'a>(&'a self) -> &'a str { - match self { - MessageTypes::MessageTypeV1(type_) => type_.ver.as_str(), - MessageTypes::MessageTypeV2(type_) => type_.version.as_str(), - } - } } #[derive(Deserialize, Serialize, Debug)] @@ -65,6 +56,19 @@ pub enum MessageFamilies { Other(String), } +impl MessageFamilies { + pub fn version(&self) -> &'static str { + match self { + MessageFamilies::Routing => "2.0", + MessageFamilies::Onboarding => "2.0", + MessageFamilies::Pairwise => "2.0", + MessageFamilies::Configs => "2.0", + MessageFamilies::CredentialExchange => "2.0", + _ => "2.0" + } + } +} + impl From for MessageFamilies { fn from(family: String) -> Self { match family.as_str() { diff --git a/vcx/dummy-cloud-agent/src/domain/payload.rs b/vcx/dummy-cloud-agent/src/domain/payload.rs index 6d4e99bb2e..6a7464ce7f 100644 --- a/vcx/dummy-cloud-agent/src/domain/payload.rs +++ b/vcx/dummy-cloud-agent/src/domain/payload.rs @@ -1,4 +1,4 @@ -use domain::message_type::{MessageTypeV2, MessageFamilies, MESSAGE_VERSION_V1, MESSAGE_VERSION_V2, DID}; +use domain::message_type::{MessageTypeV2, MessageFamilies, MESSAGE_VERSION_V1, DID}; use domain::a2a::RemoteMessageType; use domain::protocol_type::{ProtocolType, ProtocolTypes}; use std::collections::HashMap; @@ -107,7 +107,7 @@ impl PayloadTypes { PayloadTypeV2 { did: DID.to_string(), family: kind.family(), - version: MESSAGE_VERSION_V2.to_string(), + version: kind.family().version().to_string(), type_: kind.name().to_string(), } } diff --git a/vcx/dummy-cloud-agent/src/domain/protocol_type.rs b/vcx/dummy-cloud-agent/src/domain/protocol_type.rs index d1633e6e16..687a3da7d6 100644 --- a/vcx/dummy-cloud-agent/src/domain/protocol_type.rs +++ b/vcx/dummy-cloud-agent/src/domain/protocol_type.rs @@ -8,9 +8,7 @@ pub struct ProtocolType {} impl ProtocolType { pub fn set(protocol_type_config: Option) { - let protocol_type = protocol_type_config.or( - std::env::var("PROTOCOL_TYPE").ok().map(ProtocolTypes::from)) - .unwrap_or(ProtocolTypes::default()); + let protocol_type = protocol_type_config.map(ProtocolTypes::from).unwrap_or(ProtocolTypes::default()); let mut p_t = PROTOCOL_TYPE.lock().unwrap(); *p_t = protocol_type; } diff --git a/vcx/libvcx/src/lib.rs b/vcx/libvcx/src/lib.rs index a7ccaf18d9..baa39c90d5 100644 --- a/vcx/libvcx/src/lib.rs +++ b/vcx/libvcx/src/lib.rs @@ -252,7 +252,7 @@ mod tests { assert_ne!(delta, delta_after_revoke); } - fn real_proof_demo() { + fn _real_proof_demo() { let number_of_attributes = 10; let institution_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); @@ -316,7 +316,7 @@ mod tests { fn test_real_proof() { init!("agency"); - real_proof_demo(); + _real_proof_demo(); teardown!("agency"); } @@ -411,7 +411,7 @@ mod tests { fn test_real_proof_for_protocol_type_v2() { init!("agency_2_0"); - real_proof_demo(); + _real_proof_demo(); teardown!("agency"); } diff --git a/vcx/libvcx/src/messages/agent_utils.rs b/vcx/libvcx/src/messages/agent_utils.rs index a3c3d1f6f3..c0752a214d 100644 --- a/vcx/libvcx/src/messages/agent_utils.rs +++ b/vcx/libvcx/src/messages/agent_utils.rs @@ -9,11 +9,11 @@ use utils::libindy::signus::create_and_store_my_did; #[derive(Serialize, Deserialize, Debug)] pub struct Connect { #[serde(rename = "@type")] - pub msg_type: MessageTypes, + msg_type: MessageTypes, #[serde(rename = "fromDID")] - pub from_did: String, + from_did: String, #[serde(rename = "fromDIDVerKey")] - pub from_vk: String, + from_vk: String, } impl Connect { @@ -29,17 +29,17 @@ impl Connect { #[derive(Serialize, Deserialize, Debug)] pub struct ConnectResponse { #[serde(rename = "@type")] - pub msg_type: MessageTypes, + msg_type: MessageTypes, #[serde(rename = "withPairwiseDID")] - pub from_did: String, + from_did: String, #[serde(rename = "withPairwiseDIDVerKey")] - pub from_vk: String, + from_vk: String, } #[derive(Serialize, Deserialize, Debug)] pub struct SignUp { #[serde(rename = "@type")] - pub msg_type: MessageTypes, + msg_type: MessageTypes, } impl SignUp { @@ -53,13 +53,13 @@ impl SignUp { #[derive(Serialize, Deserialize, Debug)] pub struct SignUpResponse { #[serde(rename = "@type")] - pub msg_type: MessageTypes, + msg_type: MessageTypes, } #[derive(Serialize, Deserialize, Debug)] pub struct CreateAgent { #[serde(rename = "@type")] - pub msg_type: MessageTypes, + msg_type: MessageTypes, } impl CreateAgent { @@ -73,19 +73,19 @@ impl CreateAgent { #[derive(Serialize, Deserialize, Debug)] pub struct CreateAgentResponse { #[serde(rename = "@type")] - pub msg_type: MessageTypes, + msg_type: MessageTypes, #[serde(rename = "withPairwiseDID")] - pub from_did: String, + from_did: String, #[serde(rename = "withPairwiseDIDVerKey")] - pub from_vk: String, + from_vk: String, } #[derive(Serialize, Deserialize, Debug)] pub struct UpdateConnectionMethod { #[serde(rename = "@type")] - pub msg_type: MessageTypes, + msg_type: MessageTypes, #[serde(rename = "comMethod")] - pub com_method: ComMethod, + com_method: ComMethod, } impl UpdateConnectionMethod { @@ -155,7 +155,7 @@ pub fn connect_register_provision(config: &str) -> Result { settings::set_config_value(settings::CONFIG_WALLET_STORAGE_CREDS, _storage_credentials); } - wallet::init_wallet(&wallet_name, my_config.wallet_type.as_ref().map(String::as_str), + wallet::init_wallet(&wallet_name, my_config.wallet_type.as_ref().map(String::as_str), my_config.storage_config.as_ref().map(String::as_str), my_config.storage_credentials.as_ref().map(String::as_str))?; trace!("initialized wallet"); @@ -345,7 +345,7 @@ pub fn update_agent_info(id: &str, value: &str) -> Result<(), u32> { } } -pub fn update_agent_info_v1(to_did: &str, com_method: ComMethod) -> Result<(), u32> { +fn update_agent_info_v1(to_did: &str, com_method: ComMethod) -> Result<(), u32> { if settings::test_agency_mode_enabled() { httpclient::set_next_u8_response(REGISTER_RESPONSE.to_vec()); } @@ -357,7 +357,7 @@ pub fn update_agent_info_v1(to_did: &str, com_method: ComMethod) -> Result<(), u Ok(()) } -pub fn update_agent_info_v2(to_did: &str, com_method: ComMethod) -> Result<(), u32> { +fn update_agent_info_v2(to_did: &str, com_method: ComMethod) -> Result<(), u32> { let message = A2AMessage::Version2( A2AMessageV2::UpdateConnectionMethod(UpdateConnectionMethod::build(com_method)) ); @@ -365,7 +365,7 @@ pub fn update_agent_info_v2(to_did: &str, com_method: ComMethod) -> Result<(), u Ok(()) } -pub fn send_message_to_agency(message: &A2AMessage, did: &str) -> Result, u32> { +fn send_message_to_agency(message: &A2AMessage, did: &str) -> Result, u32> { let data = prepare_message_for_agency(message, &did)?; let response = httpclient::post_u8(&data).or(Err(error::INVALID_HTTP_RESPONSE.code_num))?; @@ -386,11 +386,11 @@ mod tests { let host = "http://www.whocares.org"; let wallet_key = "test_key"; let config = json!({ -"agency_url": host.to_string(), -"agency_did": agency_did.to_string(), -"agency_verkey": agency_vk.to_string(), -"wallet_key": wallet_key.to_string(), -}); + "agency_url": host.to_string(), + "agency_did": agency_did.to_string(), + "agency_verkey": agency_vk.to_string(), + "wallet_key": wallet_key.to_string(), + }); let result = connect_register_provision(&config.to_string()).unwrap(); assert!(result.len() > 0); @@ -406,11 +406,11 @@ mod tests { let host = "http://localhost:8080"; let wallet_key = "test_key"; let config = json!({ -"agency_url": host.to_string(), -"agency_did": agency_did.to_string(), -"agency_verkey": agency_vk.to_string(), -"wallet_key": wallet_key.to_string(), -}); + "agency_url": host.to_string(), + "agency_did": agency_did.to_string(), + "agency_verkey": agency_vk.to_string(), + "wallet_key": wallet_key.to_string(), + }); let result = connect_register_provision(&config.to_string()).unwrap(); assert!(result.len() > 0); diff --git a/vcx/libvcx/src/messages/create_key.rs b/vcx/libvcx/src/messages/create_key.rs index 93abdc5083..3ac99a9a09 100644 --- a/vcx/libvcx/src/messages/create_key.rs +++ b/vcx/libvcx/src/messages/create_key.rs @@ -30,9 +30,9 @@ pub struct CreateKeyResponse { #[serde(rename = "@type")] msg_type: MessageTypes, #[serde(rename = "withPairwiseDID")] - pub for_did: String, + for_did: String, #[serde(rename = "withPairwiseDIDVerKey")] - pub for_verkey: String, + for_verkey: String, } #[derive(Debug)] diff --git a/vcx/libvcx/src/messages/invite.rs b/vcx/libvcx/src/messages/invite.rs index 677ad5cd47..7edf02b5c4 100644 --- a/vcx/libvcx/src/messages/invite.rs +++ b/vcx/libvcx/src/messages/invite.rs @@ -3,6 +3,7 @@ use messages::*; use messages::message_type::{MessageTypes, MessageTypeV1, MessageTypeV2}; use utils::{httpclient, error}; use utils::constants::*; +use utils::uuid::uuid; #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct SendInviteMessageDetails { @@ -24,8 +25,8 @@ pub struct ConnectionRequest { msg_type: MessageTypeV2, #[serde(rename = "sendMsg")] send_msg: bool, - #[serde(skip_serializing_if = "Option::is_none")] - uid: Option, + #[serde(rename = "@id")] + id: String, #[serde(rename = "replyToMsgId")] reply_to_msg_id: Option, #[serde(rename = "keyDlgProof")] @@ -42,7 +43,8 @@ pub struct ConnectionRequest { pub struct ConnectionRequestResponse { #[serde(rename = "@type")] msg_type: MessageTypeV2, - uid: String, + #[serde(rename = "@id")] + id: String, #[serde(rename = "inviteDetail")] invite_detail: InviteDetail, #[serde(rename = "urlToInviteDetail")] @@ -70,8 +72,8 @@ pub struct ConnectionRequestAnswer { msg_type: MessageTypeV2, #[serde(rename = "sendMsg")] send_msg: bool, - #[serde(skip_serializing_if = "Option::is_none")] - uid: Option, + #[serde(rename = "@id")] + id: String, #[serde(rename = "replyToMsgId")] reply_to_msg_id: Option, #[serde(rename = "keyDlgProof")] @@ -156,7 +158,8 @@ pub struct SendInviteBuilder { pub struct ConnectionRequestAnswerResponse { #[serde(rename = "@type")] msg_type: MessageTypeV2, - uid: String, + #[serde(rename = "@id")] + id: String, sent: bool, } @@ -357,7 +360,7 @@ impl AcceptInviteBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::MessageCreated(res)) => Ok(res.uid), - A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswerResponse(res)) => Ok(res.uid), + A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswerResponse(res)) => Ok(res.id), _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) } } @@ -405,7 +408,7 @@ impl GeneralMessage for SendInviteBuilder { let msg = ConnectionRequest { msg_type: MessageTypes::build_v2(A2AMessageKinds::ConnectionRequest), send_msg: true, - uid: None, + id: uuid(), reply_to_msg_id: None, key_dlg_proof: self.payload.key_dlg_proof.clone(), target_name: self.payload.target_name.clone(), @@ -460,7 +463,7 @@ impl GeneralMessage for AcceptInviteBuilder { let msg = ConnectionRequestAnswer { msg_type: MessageTypes::build_v2(A2AMessageKinds::ConnectionRequestAnswer), send_msg: true, - uid: None, + id: uuid(), reply_to_msg_id: self.reply_to_msg_id.clone(), key_dlg_proof: self.payload.key_dlg_proof.clone(), sender_detail: self.payload.sender_detail.clone(), diff --git a/vcx/libvcx/src/messages/message_type.rs b/vcx/libvcx/src/messages/message_type.rs index fd9519e5f5..c69a8c8c38 100644 --- a/vcx/libvcx/src/messages/message_type.rs +++ b/vcx/libvcx/src/messages/message_type.rs @@ -7,7 +7,6 @@ use messages::A2AMessageKinds; use utils::error; pub const MESSAGE_VERSION_V1: &str = "1.0"; -pub const MESSAGE_VERSION_V2: &str = "2.0"; pub const DID: &str = "did:sov:123456789abcdefghi1234"; #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] @@ -29,7 +28,7 @@ impl MessageTypes { MessageTypeV2 { did: DID.to_string(), family: kind.family(), - version: MESSAGE_VERSION_V2.to_string(), + version: kind.family().version().to_string(), type_: kind.name(), } } @@ -40,20 +39,6 @@ impl MessageTypes { settings::ProtocolTypes::V2 => MessageTypes::MessageTypeV2(MessageTypes::build_v2(kind)) } } - - pub fn name<'a>(&'a self) -> &'a str { - match self { - MessageTypes::MessageTypeV1(type_) => type_.name.as_str(), - MessageTypes::MessageTypeV2(type_) => type_.type_.as_str(), - } - } - - pub fn version<'a>(&'a self) -> &'a str { - match self { - MessageTypes::MessageTypeV1(type_) => type_.ver.as_str(), - MessageTypes::MessageTypeV2(type_) => type_.version.as_str(), - } - } } #[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] @@ -80,6 +65,19 @@ pub enum MessageFamilies { Unknown(String), } +impl MessageFamilies { + pub fn version(&self) -> &'static str { + match self { + MessageFamilies::Routing => "2.0", + MessageFamilies::Onboarding => "2.0", + MessageFamilies::Pairwise => "2.0", + MessageFamilies::Configs => "2.0", + MessageFamilies::CredentialExchange => "2.0", + _ => "2.0" + } + } +} + impl From for MessageFamilies { fn from(family: String) -> Self { match family.as_str() { diff --git a/vcx/libvcx/src/messages/mod.rs b/vcx/libvcx/src/messages/mod.rs index 58c9cdef92..2710dd5f77 100644 --- a/vcx/libvcx/src/messages/mod.rs +++ b/vcx/libvcx/src/messages/mod.rs @@ -405,16 +405,15 @@ impl<'de> Deserialize<'de> for A2AMessage { let value = Value::deserialize(deserializer).map_err(de::Error::custom)?; let message_type: MessageTypes = serde_json::from_value(value["@type"].clone()).map_err(de::Error::custom)?; - match message_type.version() { - "1.0" => + match message_type { + MessageTypes::MessageTypeV1(_) => A2AMessageV1::deserialize(value) .map(|msg| A2AMessage::Version1(msg)) .map_err(de::Error::custom), - "2.0" => + MessageTypes::MessageTypeV2(_) => A2AMessageV2::deserialize(value) .map(|msg| A2AMessage::Version2(msg)) - .map_err(de::Error::custom), - _ => Err(de::Error::custom("Unexpected @type field structure.")) + .map_err(de::Error::custom) } } } @@ -493,14 +492,14 @@ pub enum MessageDetail { pub struct SendRemoteMessage { #[serde(rename = "@type")] pub msg_type: MessageTypeV2, + #[serde(rename = "@id")] + pub id: String, pub mtype: RemoteMessageType, #[serde(rename = "replyToMsgId")] #[serde(skip_serializing_if = "Option::is_none")] pub reply_to_msg_id: Option, #[serde(rename = "sendMsg")] pub send_msg: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub uid: Option, #[serde(rename = "@msg")] msg: Vec, #[serde(skip_serializing_if = "Option::is_none")] @@ -514,7 +513,8 @@ pub struct SendRemoteMessage { pub struct SendRemoteMessageResponse { #[serde(rename = "@type")] msg_type: MessageTypes, - pub uid: String, + #[serde(rename = "@id")] + pub id: String, pub sent: bool, } diff --git a/vcx/libvcx/src/messages/payload.rs b/vcx/libvcx/src/messages/payload.rs index 62c045ba78..d1e0cdedf3 100644 --- a/vcx/libvcx/src/messages/payload.rs +++ b/vcx/libvcx/src/messages/payload.rs @@ -15,7 +15,7 @@ pub enum Payloads { #[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] pub struct PayloadV1 { #[serde(rename = "@type")] - pub type_: PayloadTypeV1, + type_: PayloadTypeV1, #[serde(rename = "@msg")] pub msg: String, } @@ -23,7 +23,7 @@ pub struct PayloadV1 { #[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] pub struct PayloadV2 { #[serde(rename = "@type")] - pub type_: PayloadTypeV2, + type_: PayloadTypeV2, #[serde(rename = "@id")] pub id: String, #[serde(rename = "@msg")] @@ -195,7 +195,7 @@ impl PayloadTypes { PayloadTypeV2 { did: DID.to_string(), family: kind.family(), - version: MESSAGE_VERSION_V2.to_string(), + version: kind.family().version().to_string(), type_: kind.name().to_string(), } } diff --git a/vcx/libvcx/src/messages/send_message.rs b/vcx/libvcx/src/messages/send_message.rs index f0ca9cb0c8..b40f7fd843 100644 --- a/vcx/libvcx/src/messages/send_message.rs +++ b/vcx/libvcx/src/messages/send_message.rs @@ -5,6 +5,7 @@ use messages::*; use messages::message_type::MessageTypes; use messages::payload::{Payloads, PayloadKinds, Thread}; use utils::{httpclient, error}; +use utils::uuid::uuid; #[derive(Debug)] pub struct SendMessageBuilder { @@ -113,7 +114,7 @@ impl SendMessageBuilder { A2AMessage::Version1(A2AMessageV1::MessageSent(res)) => Ok(SendResponse { uid: res.uid, uids: res.uids }), A2AMessage::Version2(A2AMessageV2::SendRemoteMessageResponse(res)) => - Ok(SendResponse { uid: Some(res.uid.clone()), uids: if res.sent { vec![res.uid] } else { vec![] } }), + Ok(SendResponse { uid: Some(res.id.clone()), uids: if res.sent { vec![res.id] } else { vec![] } }), _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) } } @@ -151,10 +152,10 @@ impl GeneralMessage for SendMessageBuilder { settings::ProtocolTypes::V2 => { let message = SendRemoteMessage { msg_type: MessageTypes::build_v2(A2AMessageKinds::SendRemoteMessage), + id: uuid(), mtype: self.mtype.clone(), reply_to_msg_id: self.ref_msg_id.clone(), send_msg: true, - uid: self.uid.clone(), msg: self.payload.clone(), title: self.title.clone(), detail: self.detail.clone(), From 1fc989335238e0044110f85bdbd6cde91a4622f8 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 18 Feb 2019 13:19:48 +0300 Subject: [PATCH 03/28] Added threading to connection request messages Signed-off-by: artem.ivanov --- .../src/actors/agent_connection.rs | 22 ++++++++++---- vcx/dummy-cloud-agent/src/domain/a2a.rs | 10 +++++++ .../src/domain/internal_message.rs | 10 ++++--- vcx/dummy-cloud-agent/src/domain/invite.rs | 2 ++ vcx/dummy-cloud-agent/src/domain/payload.rs | 2 +- vcx/dummy-cloud-agent/src/utils/tests.rs | 4 ++- vcx/libvcx/src/connection.rs | 19 ++++++++++-- vcx/libvcx/src/messages/invite.rs | 29 ++++++++++++++++--- 8 files changed, 80 insertions(+), 18 deletions(-) diff --git a/vcx/dummy-cloud-agent/src/actors/agent_connection.rs b/vcx/dummy-cloud-agent/src/actors/agent_connection.rs index 8836057116..a48cc962e4 100644 --- a/vcx/dummy-cloud-agent/src/actors/agent_connection.rs +++ b/vcx/dummy-cloud-agent/src/actors/agent_connection.rs @@ -349,7 +349,8 @@ impl AgentConnection { &sender_did, None, None, - Some(map! { "phone_no".to_string() => msg_detail.phone_no.clone() })); + Some(map! { "phone_no".to_string() => msg_detail.phone_no.clone() }), + None); (msg, msg_detail) }) @@ -460,7 +461,8 @@ impl AgentConnection { &sender_did, None, Some(msg_detail.msg), - Some(map! {"detail".to_string() => msg_detail.detail, "title".to_string()=> msg_detail.title})); + Some(map! {"detail".to_string() => msg_detail.detail, "title".to_string()=> msg_detail.title}), + None); if let Some(msg_id) = reply_to_msg_id.as_ref() { self.answer_message(msg_id, &msg.uid, &MessageStatusCode::Accepted).unwrap(); @@ -639,6 +641,7 @@ impl AgentConnection { &msg_detail.sender_detail.did, None, None, + None, None); let sender_did = slf.user_pairwise_did.clone(); @@ -648,7 +651,8 @@ impl AgentConnection { &sender_did, Some(conn_req_msg.uid.as_str()), None, - None); + None, + msg_detail.thread.clone()); slf.state.agent_key_dlg_proof = Some(key_dlg_proof); slf.state.remote_connection_detail = Some(RemoteConnectionDetail { @@ -709,7 +713,8 @@ impl AgentConnection { &msg_detail.sender_detail.did, None, None, - None); + None, + msg_detail.thread.clone()); slf.state.remote_connection_detail = Some(RemoteConnectionDetail { forward_agent_detail: msg_detail.sender_agency_detail.clone(), @@ -758,7 +763,8 @@ impl AgentConnection { sender_did: &str, ref_msg_id: Option<&str>, payload: Option>, - sending_data: Option>>) -> InternalMessage { + sending_data: Option>>, + thread: Option) -> InternalMessage { trace!("AgentConnection::create_and_store_internal_message >> {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}", uid, mtype, status_code, sender_did, ref_msg_id, payload, sending_data); @@ -768,7 +774,8 @@ impl AgentConnection { sender_did, ref_msg_id, payload, - sending_data); + sending_data, + thread); self.state.messages.insert(msg.uid.to_string(), msg.clone()); msg } @@ -1200,6 +1207,7 @@ impl AgentConnection { }, status_code: msg.status_code.clone(), status_msg: msg.status_code.message().to_string(), + thread_id: msg_detail.thread_id.clone(), }; match ProtocolType::get() { @@ -1259,6 +1267,7 @@ impl AgentConnection { sender_detail, sender_agency_detail: self.forward_agent_detail.clone(), answer_status_code: MessageStatusCode::Accepted, + thread: None, }; vec![A2AMessage::Version1(A2AMessageV1::CreateMessage(msg_create)), @@ -1273,6 +1282,7 @@ impl AgentConnection { sender_detail, sender_agency_detail: self.forward_agent_detail.clone(), answer_status_code: MessageStatusCode::Accepted, + thread: message.thread.clone().unwrap_or(Thread::new()), }; vec![A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswer(msg))] } diff --git a/vcx/dummy-cloud-agent/src/domain/a2a.rs b/vcx/dummy-cloud-agent/src/domain/a2a.rs index d70b70a7c7..d98a5c052c 100644 --- a/vcx/dummy-cloud-agent/src/domain/a2a.rs +++ b/vcx/dummy-cloud-agent/src/domain/a2a.rs @@ -12,6 +12,7 @@ use domain::key_deligation_proof::KeyDlgProof; use domain::status::{MessageStatusCode, ConnectionStatus}; use domain::message_type::*; use domain::protocol_type::{ProtocolType, ProtocolTypes}; +use domain::payload::Thread; #[derive(Debug)] pub enum A2AMessageV1 { @@ -359,6 +360,7 @@ pub struct ConnectionRequestMessageDetail { pub phone_no: Option, #[serde(rename = "usePublicDID")] pub use_public_did: Option, + pub thread_id: Option, } impl From for ConnectionRequestMessageDetail { @@ -368,6 +370,7 @@ impl From for ConnectionRequestMessageDetail { target_name: con_req.target_name, phone_no: con_req.phone_no, use_public_did: Some(con_req.include_public_did), + thread_id: Some(con_req.id), } } } @@ -390,6 +393,8 @@ pub struct ConnectionRequestAnswerMessageDetail { pub sender_agency_detail: ForwardAgentDetail, #[serde(rename = "answerStatusCode")] pub answer_status_code: MessageStatusCode, + #[serde(skip_serializing_if = "Option::is_none")] + pub thread: Option } impl From for ConnectionRequestAnswerMessageDetail { @@ -399,6 +404,7 @@ impl From for ConnectionRequestAnswerMessageDetail { sender_detail: con_req_answer.sender_detail, sender_agency_detail: con_req_answer.sender_agency_detail, answer_status_code: con_req_answer.answer_status_code, + thread: Some(con_req_answer.thread), } } } @@ -479,6 +485,8 @@ pub struct ConnectionRequest { pub phone_no: Option, #[serde(rename = "usePublicDID")] pub include_public_did: bool, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Debug, Deserialize, Serialize)] @@ -508,6 +516,8 @@ pub struct ConnectionRequestAnswer { pub sender_agency_detail: ForwardAgentDetail, #[serde(rename = "answerStatusCode")] pub answer_status_code: MessageStatusCode, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Debug, Deserialize, Serialize)] diff --git a/vcx/dummy-cloud-agent/src/domain/internal_message.rs b/vcx/dummy-cloud-agent/src/domain/internal_message.rs index 1771c96e31..3b55e880ba 100644 --- a/vcx/dummy-cloud-agent/src/domain/internal_message.rs +++ b/vcx/dummy-cloud-agent/src/domain/internal_message.rs @@ -1,5 +1,6 @@ use domain::a2a::RemoteMessageType; use domain::status::MessageStatusCode; +use domain::payload::Thread; use utils::rand::rand_string; @@ -12,9 +13,9 @@ pub struct InternalMessage { pub sender_did: String, pub status_code: MessageStatusCode, pub ref_msg_id: Option, - pub seq_no: Option, // ? pub payload: Option>, - pub sending_data: HashMap> + pub sending_data: HashMap>, + pub thread: Option } impl InternalMessage { @@ -24,16 +25,17 @@ impl InternalMessage { sender_did: &str, ref_msg_id: Option<&str>, payload: Option>, - sending_data: Option>>) -> InternalMessage { + sending_data: Option>>, + thread: Option) -> InternalMessage { InternalMessage { uid: uid.map(String::from).unwrap_or(rand_string(10)), _type: mtype.clone(), sender_did: sender_did.to_string(), status_code, ref_msg_id: ref_msg_id.map(String::from), - seq_no: None, payload, sending_data: sending_data.unwrap_or(HashMap::new()), + thread, } } } diff --git a/vcx/dummy-cloud-agent/src/domain/invite.rs b/vcx/dummy-cloud-agent/src/domain/invite.rs index 99af4f011c..1d43ccd875 100644 --- a/vcx/dummy-cloud-agent/src/domain/invite.rs +++ b/vcx/dummy-cloud-agent/src/domain/invite.rs @@ -15,6 +15,8 @@ pub struct InviteDetail { pub status_code: MessageStatusCode, #[serde(rename = "statusMsg")] pub status_msg: String, + #[serde(rename = "threadId")] + pub thread_id: Option } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/vcx/dummy-cloud-agent/src/domain/payload.rs b/vcx/dummy-cloud-agent/src/domain/payload.rs index 6a7464ce7f..7e99c17fec 100644 --- a/vcx/dummy-cloud-agent/src/domain/payload.rs +++ b/vcx/dummy-cloud-agent/src/domain/payload.rs @@ -128,7 +128,7 @@ impl From for PayloadKinds { } } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct Thread { pub thid: Option, pub pthid: Option, diff --git a/vcx/dummy-cloud-agent/src/utils/tests.rs b/vcx/dummy-cloud-agent/src/utils/tests.rs index 5fc2bbc229..8e0caee951 100644 --- a/vcx/dummy-cloud-agent/src/utils/tests.rs +++ b/vcx/dummy-cloud-agent/src/utils/tests.rs @@ -341,6 +341,7 @@ pub fn compose_create_connection_request(wallet_handle: i32, target_name: None, phone_no: Some(PHONE_NO.to_string()), use_public_did: Some(true), + thread_id: None, }))); let msgs = [create_msg, msg_details]; @@ -390,7 +391,8 @@ pub fn compose_create_connection_request_answer(wallet_handle: i32, verkey: FORWARD_AGENT_DID_VERKEY.to_string(), endpoint: FORWARD_AGENT_ENDPOINT.to_string(), }, - answer_status_code: MessageStatusCode::Accepted + answer_status_code: MessageStatusCode::Accepted, + thread: None, } ))); diff --git a/vcx/libvcx/src/connection.rs b/vcx/libvcx/src/connection.rs index 20443a3a8f..591d53e8fc 100644 --- a/vcx/libvcx/src/connection.rs +++ b/vcx/libvcx/src/connection.rs @@ -14,7 +14,7 @@ use messages::GeneralMessage; use messages; use messages::{MessageStatusCode, RemoteMessageType}; use messages::invite::{InviteDetail, SenderDetail, Payload as ConnectionPayload, AcceptanceDetails}; -use messages::payload::Payloads; +use messages::payload::{Payloads, Thread}; use messages::get_message::Message; use serde_json::Value; use utils::json::KeyMatch; @@ -22,6 +22,7 @@ use error::connection::ConnectionError; use error::ToErrorCode; use object_cache::ObjectCache; use utils::constants::DEFAULT_SERIALIZE_VERSION; +use std::collections::HashMap; lazy_static! { static ref CONNECTION_MAP: ObjectCache = Default::default(); @@ -79,6 +80,7 @@ impl Connection { .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? .public_did(self.public_did.as_ref().map(String::as_str))? + .thread(&Thread::new())? .send_secure()?; self.state = VcxStateType::VcxStateOfferSent; @@ -106,7 +108,7 @@ impl Connection { fn _connect_accept_invite(&mut self) -> Result { debug!("accepting invite for connection {}", self.source_id); - let details = self.invite_detail.as_ref() + let details: &InviteDetail = self.invite_detail.as_ref() .ok_or_else(|| { warn!("{} can not connect without invite details", self.source_id); // TODO: Refactor Error @@ -123,12 +125,25 @@ impl Connection { .sender_agency_details(&details.sender_agency_detail)? .answer_status_code(&MessageStatusCode::Accepted)? .reply_to(&details.conn_req_id)? + .thread(&self._build_thread(&details))? .send_secure()?; self.state = VcxStateType::VcxStateAccepted; Ok(error::SUCCESS.code_num) } + fn _build_thread(&self, invite_detail: &InviteDetail) -> Thread { + let mut received_orders = HashMap::new(); + received_orders.insert(invite_detail.sender_detail.did.clone(), 0); + + Thread { + thid: invite_detail.thread_id.clone(), + pthid: None, + sender_order: 0, + received_orders, + } + } + fn connect(&mut self, options: &ConnectionOptions) -> Result { trace!("Connection::connect >>> options: {:?}", options); match self.state { diff --git a/vcx/libvcx/src/messages/invite.rs b/vcx/libvcx/src/messages/invite.rs index 7edf02b5c4..c93151fc67 100644 --- a/vcx/libvcx/src/messages/invite.rs +++ b/vcx/libvcx/src/messages/invite.rs @@ -1,6 +1,7 @@ use settings; use messages::*; use messages::message_type::{MessageTypes, MessageTypeV1, MessageTypeV2}; +use messages::payload::Thread; use utils::{httpclient, error}; use utils::constants::*; use utils::uuid::uuid; @@ -37,6 +38,8 @@ pub struct ConnectionRequest { phone_no: Option, #[serde(rename = "usePublicDID")] include_public_did: bool, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] @@ -84,6 +87,8 @@ pub struct ConnectionRequestAnswer { sender_agency_detail: Option, #[serde(rename = "answerStatusCode")] answer_status_code: Option, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] @@ -131,6 +136,7 @@ pub struct InviteDetail { pub sender_agency_detail: SenderAgencyDetail, pub target_name: String, pub status_msg: String, + pub thread_id: Option } #[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] @@ -152,6 +158,7 @@ pub struct SendInviteBuilder { agent_did: String, agent_vk: String, public_did: Option, + thread: Thread } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] @@ -187,6 +194,7 @@ impl InviteDetail { }, target_name: String::new(), status_msg: String::new(), + thread_id: None, } } } @@ -208,6 +216,7 @@ impl SendInviteBuilder { agent_did: String::new(), agent_vk: String::new(), public_did: None, + thread: Thread::new(), } } @@ -233,6 +242,11 @@ impl SendInviteBuilder { Ok(self) } + pub fn thread(&mut self, thread: &Thread) -> Result<&mut Self, u32> { + self.thread = thread.clone(); + Ok(self) + } + pub fn generate_signature(&mut self) -> Result<(), u32> { let signature = format!("{}{}", self.payload.key_dlg_proof.agent_did, self.payload.key_dlg_proof.agent_delegated_key); let signature = ::utils::libindy::crypto::sign(&self.to_vk, signature.as_bytes())?; @@ -283,7 +297,8 @@ pub struct AcceptInviteBuilder { payload: AcceptInviteMessageDetails, agent_did: String, agent_vk: String, - reply_to_msg_id: Option + reply_to_msg_id: Option, + thread: Thread } impl AcceptInviteBuilder { @@ -304,6 +319,7 @@ impl AcceptInviteBuilder { agent_did: String::new(), agent_vk: String::new(), reply_to_msg_id: None, + thread: Thread::new(), } } @@ -333,6 +349,11 @@ impl AcceptInviteBuilder { Ok(self) } + pub fn thread(&mut self, thread: &Thread) -> Result<&mut Self, u32> { + self.thread = thread.clone(); + Ok(self) + } + pub fn generate_signature(&mut self) -> Result<(), u32> { let signature = format!("{}{}", self.payload.key_dlg_proof.agent_did, self.payload.key_dlg_proof.agent_delegated_key); let signature = crypto::sign(&self.to_vk, signature.as_bytes())?; @@ -414,6 +435,7 @@ impl GeneralMessage for SendInviteBuilder { target_name: self.payload.target_name.clone(), phone_no: self.payload.phone_no.clone(), include_public_did: self.payload.include_public_did, + thread: self.thread.clone(), }; vec![A2AMessage::Version2(A2AMessageV2::ConnectionRequest(msg))] @@ -454,10 +476,8 @@ impl GeneralMessage for AcceptInviteBuilder { uid: None, }; - let details = self.payload.clone(); - vec![A2AMessage::Version1(A2AMessageV1::CreateMessage(msg_created)), - A2AMessage::Version1(A2AMessageV1::MessageDetail(MessageDetail::ConnectionRequestAnswer(details)))] + A2AMessage::Version1(A2AMessageV1::MessageDetail(MessageDetail::ConnectionRequestAnswer(self.payload.clone())))] } settings::ProtocolTypes::V2 => { let msg = ConnectionRequestAnswer { @@ -469,6 +489,7 @@ impl GeneralMessage for AcceptInviteBuilder { sender_detail: self.payload.sender_detail.clone(), sender_agency_detail: self.payload.sender_agency_detail.clone(), answer_status_code: self.payload.answer_status_code.clone(), + thread: self.thread.clone(), }; vec![A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswer(msg))] From 86523eb71b28235f38d6e50cc692062684f470db Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Thu, 21 Feb 2019 09:21:21 +0300 Subject: [PATCH 04/28] Migrated VCX on Failure crate for better error handling Signed-off-by: artem.ivanov --- vcx/libvcx/Cargo.lock | 1 + vcx/libvcx/Cargo.toml | 1 + vcx/libvcx/src/api/connection.rs | 55 ++- vcx/libvcx/src/api/credential.rs | 231 +++++------ vcx/libvcx/src/api/credential_def.rs | 30 +- vcx/libvcx/src/api/disclosed_proof.rs | 199 +++++---- vcx/libvcx/src/api/issuer_credential.rs | 262 ++++++------ vcx/libvcx/src/api/logger.rs | 4 +- vcx/libvcx/src/api/mod.rs | 7 - vcx/libvcx/src/api/proof.rs | 33 +- vcx/libvcx/src/api/schema.rs | 164 ++++---- vcx/libvcx/src/api/utils.rs | 20 +- vcx/libvcx/src/api/vcx.rs | 8 +- vcx/libvcx/src/api/wallet.rs | 41 +- vcx/libvcx/src/connection.rs | 277 ++++++------- vcx/libvcx/src/credential.rs | 244 ++++++----- vcx/libvcx/src/credential_def.rs | 236 +++++------ vcx/libvcx/src/disclosed_proof.rs | 240 ++++++----- vcx/libvcx/src/error/base.rs | 37 -- vcx/libvcx/src/error/common.rs | 3 - vcx/libvcx/src/error/connection.rs | 123 ------ vcx/libvcx/src/error/cred_def.rs | 60 --- vcx/libvcx/src/error/credential.rs | 62 --- vcx/libvcx/src/error/issuer_cred.rs | 67 --- vcx/libvcx/src/error/messages.rs | 23 -- vcx/libvcx/src/error/mod.rs | 384 +++++++++++++++++- vcx/libvcx/src/error/payment.rs | 58 --- vcx/libvcx/src/error/proof.rs | 78 ---- vcx/libvcx/src/error/schema.rs | 58 --- vcx/libvcx/src/error/wallet.rs | 81 ---- vcx/libvcx/src/issuer_credential.rs | 358 +++++++--------- vcx/libvcx/src/lib.rs | 2 + vcx/libvcx/src/messages/agent_utils.rs | 36 +- vcx/libvcx/src/messages/create_key.rs | 17 +- vcx/libvcx/src/messages/get_message.rs | 48 +-- vcx/libvcx/src/messages/invite.rs | 52 +-- vcx/libvcx/src/messages/message_type.rs | 6 +- vcx/libvcx/src/messages/mod.rs | 117 ++++-- vcx/libvcx/src/messages/payload.rs | 26 +- .../src/messages/proofs/proof_message.rs | 37 +- .../src/messages/proofs/proof_request.rs | 112 ++--- vcx/libvcx/src/messages/send_message.rs | 47 +-- vcx/libvcx/src/messages/update_connection.rs | 13 +- vcx/libvcx/src/messages/update_message.rs | 25 +- vcx/libvcx/src/messages/update_profile.rs | 21 +- vcx/libvcx/src/messages/validation.rs | 40 +- vcx/libvcx/src/object_cache/mod.rs | 31 +- vcx/libvcx/src/proof.rs | 230 +++++------ vcx/libvcx/src/schema.rs | 227 ++++------- vcx/libvcx/src/settings.rs | 81 ++-- vcx/libvcx/src/utils/error.rs | 26 -- vcx/libvcx/src/utils/httpclient.rs | 15 +- vcx/libvcx/src/utils/json.rs | 24 +- vcx/libvcx/src/utils/libindy/anoncreds.rs | 294 +++++++------- vcx/libvcx/src/utils/libindy/crypto.rs | 25 +- vcx/libvcx/src/utils/libindy/error_codes.rs | 48 +-- vcx/libvcx/src/utils/libindy/ledger.rs | 80 +++- vcx/libvcx/src/utils/libindy/logger.rs | 5 +- vcx/libvcx/src/utils/libindy/mod.rs | 3 +- vcx/libvcx/src/utils/libindy/payments.rs | 231 +++++------ vcx/libvcx/src/utils/libindy/pool.rs | 66 ++- vcx/libvcx/src/utils/libindy/signus.rs | 15 +- vcx/libvcx/src/utils/libindy/wallet.rs | 109 ++--- vcx/libvcx/src/utils/logger.rs | 16 +- vcx/libvcx/src/utils/openssl.rs | 8 +- 65 files changed, 2510 insertions(+), 3068 deletions(-) delete mode 100644 vcx/libvcx/src/error/base.rs delete mode 100644 vcx/libvcx/src/error/common.rs delete mode 100644 vcx/libvcx/src/error/connection.rs delete mode 100644 vcx/libvcx/src/error/cred_def.rs delete mode 100644 vcx/libvcx/src/error/credential.rs delete mode 100644 vcx/libvcx/src/error/issuer_cred.rs delete mode 100644 vcx/libvcx/src/error/messages.rs delete mode 100644 vcx/libvcx/src/error/payment.rs delete mode 100644 vcx/libvcx/src/error/proof.rs delete mode 100644 vcx/libvcx/src/error/schema.rs delete mode 100644 vcx/libvcx/src/error/wallet.rs diff --git a/vcx/libvcx/Cargo.lock b/vcx/libvcx/Cargo.lock index 15a369b6d9..63ec62b01c 100644 --- a/vcx/libvcx/Cargo.lock +++ b/vcx/libvcx/Cargo.lock @@ -562,6 +562,7 @@ dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "indy 1.8.1", "indy-sys 1.8.1", diff --git a/vcx/libvcx/Cargo.toml b/vcx/libvcx/Cargo.toml index c1ddfa4d98..ddba4ee673 100644 --- a/vcx/libvcx/Cargo.toml +++ b/vcx/libvcx/Cargo.toml @@ -53,6 +53,7 @@ tokio-threadpool = "0.1.6" futures = "0.1.23" libloading = "0.5.0" uuid = {version = "0.7.1", default-features = false, features = ["v4"]} +failure = "0.1.3" [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.5" diff --git a/vcx/libvcx/src/api/connection.rs b/vcx/libvcx/src/api/connection.rs index f01450ed84..e069adbc75 100644 --- a/vcx/libvcx/src/api/connection.rs +++ b/vcx/libvcx/src/api/connection.rs @@ -6,9 +6,8 @@ use utils::error; use utils::error::error_string; use utils::threadpool::spawn; use std::ptr; -use error::ToErrorCode; -use error::connection::ConnectionError; use connection::{get_source_id, create_connection, create_connection_with_invite, connect, to_string, get_state, release, is_valid_handle, update_state, from_string, get_invite_details, delete_connection}; +use error::prelude::*; /// Delete a Connection object and release its handle /// @@ -32,7 +31,7 @@ pub extern fn vcx_connection_delete_connection(command_handle: u32, check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); if !is_valid_handle(connection_handle) { - return ConnectionError::InvalidHandle().to_error_code() + return VcxErrorKind::InvalidConnectionHandle.into() } trace!("vcx_connection_delete_connection(command_handle: {}, connection_handle: {})", command_handle, connection_handle); spawn(move|| { @@ -43,7 +42,7 @@ pub extern fn vcx_connection_delete_connection(command_handle: u32, }, Err(e) => { trace!("vcx_connection_delete_connection_cb(command_handle: {}, rc: {})", command_handle, e); - cb(command_handle, e.to_error_code()); + cb(command_handle, e.into()); }, } @@ -83,8 +82,8 @@ pub extern fn vcx_connection_create(command_handle: u32, }, Err(x) => { warn!("vcx_connection_create_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, x.to_string(), 0, source_id); - cb(command_handle, x.to_error_code(), 0); + command_handle, x, 0, source_id); + cb(command_handle, x.into(), 0); }, }; @@ -127,8 +126,8 @@ pub extern fn vcx_connection_create_with_invite(command_handle: u32, }, Err(x) => { warn!("vcx_connection_create_with_invite_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, x.to_string(), 0, source_id); - cb(command_handle, x.to_error_code(), 0); + command_handle, x, 0, source_id); + cb(command_handle, x.into(), 0); }, }; @@ -198,8 +197,8 @@ pub extern fn vcx_connection_connect(command_handle:u32, }, Err(x) => { warn!("vcx_connection_connect_cb(command_handle: {}, connection_handle: {}, rc: {}, details: {}, source_id: {})", - command_handle, connection_handle, x.to_string(), "null", source_id); - cb(command_handle,x.to_error_code(), ptr::null_mut()); + command_handle, connection_handle, x, "null", source_id); + cb(command_handle,x.into(), ptr::null_mut()); }, }; @@ -247,8 +246,8 @@ pub extern fn vcx_connection_serialize(command_handle: u32, }, Err(x) => { warn!("vcx_connection_serialize_cb(command_handle: {}, connection_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, connection_handle, error_string(x), "null", source_id); - cb(command_handle, x, ptr::null_mut()); + command_handle, connection_handle, x, "null", source_id); + cb(command_handle, x.into(), ptr::null_mut()); }, }; @@ -290,8 +289,8 @@ pub extern fn vcx_connection_deserialize(command_handle: u32, }, Err(x) => { warn!("vcx_connection_deserialize_cb(command_handle: {}, rc: {}, handle: {} )", - command_handle, error_string(x.to_error_code()), 0); - (x.to_error_code(), 0) + command_handle, x, 0); + (x.into(), 0) }, }; @@ -342,8 +341,8 @@ pub extern fn vcx_connection_update_state(command_handle: u32, Err(x) => { warn!("vcx_connection_update_state_cb(command_handle: {}, rc: {}, connection_handle: {}, state: {}), source_id: {:?}", // TODO: Refactor Error - command_handle, error_string(x.to_error_code()), connection_handle, get_state(connection_handle), source_id); - x.to_error_code() + command_handle, x, connection_handle, get_state(connection_handle), source_id); + x.into() }, }; let state = get_state(connection_handle); @@ -434,8 +433,8 @@ pub extern fn vcx_connection_invite_details(command_handle: u32, }, Err(x) => { warn!("vcx_connection_invite_details_cb(command_handle: {}, connection_handle: {}, rc: {}, details: {}, source_id: {:?})", - command_handle, connection_handle, error_string(x.to_error_code()), "null", source_id); - cb(command_handle, x.to_error_code(), ptr::null_mut()); + command_handle, connection_handle, x, "null", source_id); + cb(command_handle, x.into(), ptr::null_mut()); } }; @@ -492,9 +491,9 @@ pub extern fn vcx_connection_send_message(command_handle: u32, }, Err(e) => { warn!("vcx_connection_send_message_cb(command_handle: {}, rc: {})", - command_handle, error_string(e)); + command_handle, e); - cb(command_handle, e, ptr::null_mut()); + cb(command_handle, e.into(), ptr::null_mut()); }, }; @@ -545,7 +544,7 @@ pub extern fn vcx_connection_sign_data(command_handle: u32, let vk = match ::connection::get_pw_verkey(connection_handle) { Ok(x) => x, - Err(e) => return e.to_error_code(), + Err(e) => return e.into(), }; spawn (move || { @@ -559,9 +558,9 @@ pub extern fn vcx_connection_sign_data(command_handle: u32, }, Err(e) => { warn!("vcx_messages_sign_data_cb(command_handle: {}, rc: {}, signature: null)", - command_handle, error_string(e)); + command_handle, e); - cb(command_handle, e, ptr::null_mut(), 0); + cb(command_handle, e.into(), ptr::null_mut(), 0); }, }; @@ -618,7 +617,7 @@ pub extern fn vcx_connection_verify_signature(command_handle: u32, let vk = match ::connection::get_their_pw_verkey(connection_handle) { Ok(x) => x, - Err(e) => return e.to_error_code(), + Err(e) => return e.into(), }; spawn (move || { @@ -631,9 +630,9 @@ pub extern fn vcx_connection_verify_signature(command_handle: u32, }, Err(e) => { warn!("vcx_connection_verify_signature_cb(command_handle: {}, rc: {}, valid: {})", - command_handle, error_string(e), false); + command_handle, e, false); - cb(command_handle, e, false); + cb(command_handle, e.into(), false); }, }; @@ -663,8 +662,8 @@ pub extern fn vcx_connection_release(connection_handle: u32) -> u32 { }, Err(e) => { warn!("vcx_connection_release(connection_handle: {}), rc: {}), source_id: {:?}", - connection_handle, error_string(e.to_error_code()), source_id); - e.to_error_code() + connection_handle, e, source_id); + e.into() }, } } diff --git a/vcx/libvcx/src/api/credential.rs b/vcx/libvcx/src/api/credential.rs index 7ec7e0efc0..89ffb04027 100644 --- a/vcx/libvcx/src/api/credential.rs +++ b/vcx/libvcx/src/api/credential.rs @@ -8,9 +8,8 @@ use utils::error::error_string; use connection; use credential; use std::ptr; -use error::credential::CredentialError; -use error::ToErrorCode; use utils::threadpool::spawn; +use error::prelude::*; /// Retrieves Payment Info from a Credential /// @@ -26,12 +25,12 @@ use utils::threadpool::spawn; #[no_mangle] #[allow(unused_variables, unused_mut)] pub extern fn vcx_credential_get_payment_info(command_handle: u32, - credential_handle: u32, - cb: Option) -> u32 { + credential_handle: u32, + cb: Option) -> u32 { info!("vcx_credential_get_payment_info >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - spawn(move|| { + spawn(move || { match credential::get_payment_information(credential_handle) { Ok(p) => { match p { @@ -40,20 +39,18 @@ pub extern fn vcx_credential_get_payment_info(command_handle: u32, trace!("vcx_credential_get_payment_info(command_handle: {}, rc: {}, msg: {})", command_handle, error::SUCCESS.code_num, info.clone()); let msg = CStringUtils::string_to_cstring(info); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, + } None => { let msg = CStringUtils::string_to_cstring(format!("{{}}")); trace!("vcx_credential_get_payment_info(command_handle: {}, rc: {}, msg: {})", command_handle, error::SUCCESS.code_num, "{}"); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); } } - }, + } Err(e) => { warn!("vcx_credential_get_payment_info(command_handle: {}, rc: {}, msg: {})", - command_handle, - e.to_error_code(), - "{}".to_string()); - cb(command_handle, e.to_error_code(), ptr::null_mut()); + command_handle, e, "{}"); + cb(command_handle, e.into(), ptr::null_mut()); } }; @@ -62,6 +59,7 @@ pub extern fn vcx_credential_get_payment_info(command_handle: u32, error::SUCCESS.code_num } + /// Create a Credential object that requests and receives a credential for an institution /// /// #Params @@ -77,7 +75,6 @@ pub extern fn vcx_credential_get_payment_info(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] #[allow(unused_variables, unused_mut)] pub extern fn vcx_credential_create_with_offer(command_handle: u32, @@ -91,20 +88,20 @@ pub extern fn vcx_credential_create_with_offer(command_handle: u32, check_useful_c_str!(offer, error::INVALID_OPTION.code_num); trace!("vcx_credential_create_with_offer(command_handle: {}, source_id: {}, offer: {})", - command_handle, source_id, offer); + command_handle, source_id, offer); - spawn(move|| { + spawn(move || { match credential::credential_create_with_offer(&source_id, &offer) { Ok(x) => { trace!("vcx_credential_create_with_offer_cb(command_handle: {}, source_id: {}, rc: {}, handle: {})", - command_handle, source_id, error_string(0), x); + command_handle, source_id, error_string(0), x); cb(command_handle, error::SUCCESS.code_num, x) - }, + } Err(x) => { warn!("vcx_credential_create_with_offer_cb(command_handle: {}, source_id: {}, rc: {}, handle: {})", - command_handle, source_id, x.to_error_code(), 0); - cb(command_handle, x.to_error_code(), 0); - }, + command_handle, source_id, x, 0); + cb(command_handle, x.into(), 0); + } }; Ok(()) @@ -129,31 +126,31 @@ pub extern fn vcx_credential_create_with_offer(command_handle: u32, #[allow(unused_variables, unused_mut)] pub extern fn vcx_get_credential(command_handle: u32, credential_handle: u32, - cb: Option) -> u32 { + cb: Option) -> u32 { info!("vcx_get_credential >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); if !credential::is_valid_handle(credential_handle) { - return CredentialError::InvalidHandle().to_error_code(); + return VcxErrorKind::InvalidCredentialHandle.into() } let source_id = credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_get_credential(command_handle: {}, credential_handle: {}) source_id: {})", - command_handle, credential_handle, source_id); + command_handle, credential_handle, source_id); - spawn(move|| { + spawn(move || { match credential::get_credential(credential_handle) { Ok(s) => { trace!("vcx_get_credential_cb(commmand_handle: {}, rc: {}, msg: {}) source_id: {}", - command_handle, error::SUCCESS.code_num, s, source_id); + command_handle, error::SUCCESS.code_num, s, source_id); let msg = CStringUtils::string_to_cstring(s); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, + } Err(e) => { error!("vcx_get_credential_cb(commmand_handle: {}, rc: {}, msg: {}) source_id: {}", - command_handle, e.to_error_code(), "".to_string(), source_id); - cb(command_handle, e.to_error_code(), ptr::null_mut()); - }, + command_handle, e, "".to_string(), source_id); + cb(command_handle, e.into(), ptr::null_mut()); + } }; Ok(()) @@ -177,7 +174,6 @@ pub extern fn vcx_get_credential(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] #[allow(unused_variables, unused_mut)] pub extern fn vcx_credential_create_with_msgid(command_handle: u32, @@ -192,9 +188,9 @@ pub extern fn vcx_credential_create_with_msgid(command_handle: u32, check_useful_c_str!(msg_id, error::INVALID_OPTION.code_num); trace!("vcx_credential_create_with_msgid(command_handle: {}, source_id: {}, connection_handle: {}, msg_id: {})", - command_handle, source_id, connection_handle, msg_id); + command_handle, source_id, connection_handle, msg_id); - spawn(move|| { + spawn(move || { match credential::get_credential_offer_msg(connection_handle, &msg_id) { Ok(offer) => { match credential::credential_create_with_offer(&source_id, &offer) { @@ -205,17 +201,17 @@ pub extern fn vcx_credential_create_with_msgid(command_handle: u32, }; let c_offer = CStringUtils::string_to_cstring(offer_string); trace!("vcx_credential_create_with_offer_cb(command_handle: {}, source_id: {}, rc: {}, handle: {}) source_id: {}", - command_handle, source_id, error_string(0), handle, source_id); + command_handle, source_id, error_string(0), handle, source_id); cb(command_handle, error::SUCCESS.code_num, handle, c_offer.as_ptr()) - }, + } Err(e) => { warn!("vcx_credential_create_with_offer_cb(command_handle: {}, source_id: {}, rc: {}, handle: {}) source_id: {}", - command_handle, source_id, e.to_error_code(), 0, source_id); - cb(command_handle, e.to_error_code(), 0, ptr::null_mut()); - }, + command_handle, source_id, e, 0, source_id); + cb(command_handle, e.into(), 0, ptr::null_mut()); + } }; - }, - Err(e) => cb(command_handle, e.to_error_code(), 0, ptr::null_mut()), + } + Err(e) => cb(command_handle, e.into(), 0, ptr::null_mut()), }; Ok(()) @@ -237,7 +233,6 @@ pub extern fn vcx_credential_create_with_msgid(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_credential_send_request(command_handle: u32, credential_handle: u32, @@ -258,20 +253,20 @@ pub extern fn vcx_credential_send_request(command_handle: u32, let source_id = credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_credential_send_request(command_handle: {}, credential_handle: {}, connection_handle: {}), source_id: {:?}", - command_handle, credential_handle, connection_handle, source_id); + command_handle, credential_handle, connection_handle, source_id); - spawn(move|| { + spawn(move || { match credential::send_credential_request(credential_handle, connection_handle) { Ok(x) => { trace!("vcx_credential_send_request_cb(command_handle: {}, rc: {}) source_id: {}", - command_handle, x.to_string(), source_id); - cb(command_handle,x); - }, + command_handle, x.to_string(), source_id); + cb(command_handle, x); + } Err(e) => { warn!("vcx_credential_send_request_cb(command_handle: {}, rc: {}) source_id: {}", - command_handle, e.to_string(), source_id); - cb(command_handle,e.to_error_code()); - }, + command_handle, e, source_id); + cb(command_handle, e.into()); + } }; Ok(()) @@ -291,11 +286,10 @@ pub extern fn vcx_credential_send_request(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_credential_get_offers(command_handle: u32, - connection_handle: u32, - cb: Option) -> u32 { + connection_handle: u32, + cb: Option) -> u32 { info!("vcx_credential_get_offers >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); @@ -305,21 +299,21 @@ pub extern fn vcx_credential_get_offers(command_handle: u32, } trace!("vcx_credential_get_offers(command_handle: {}, connection_handle: {})", - command_handle, connection_handle); + command_handle, connection_handle); - spawn(move|| { + spawn(move || { match credential::get_credential_offer_messages(connection_handle) { Ok(x) => { trace!("vcx_credential_get_offers_cb(command_handle: {}, rc: {}, msg: {})", - command_handle, x.to_string(), x); + command_handle, x.to_string(), x); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, + } Err(x) => { error!("vcx_credential_get_offers_cb(command_handle: {}, rc: {}, msg: null)", - command_handle, x.to_string()); - cb(command_handle, x.to_error_code(), ptr::null_mut()); - }, + command_handle, x); + cb(command_handle, x.into(), ptr::null_mut()); + } }; Ok(()) @@ -340,7 +334,6 @@ pub extern fn vcx_credential_get_offers(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_credential_update_state(command_handle: u32, credential_handle: u32, @@ -355,15 +348,15 @@ pub extern fn vcx_credential_update_state(command_handle: u32, let source_id = credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_credential_update_state(command_handle: {}, credential_handle: {}), source_id: {:?}", - command_handle, credential_handle, source_id); + command_handle, credential_handle, source_id); - spawn(move|| { + spawn(move || { match credential::update_state(credential_handle) { Ok(_) => (), Err(e) => { error!("vcx_credential_update_state_cb(command_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, error_string(e), 0, source_id); - cb(command_handle, e, 0) + command_handle, e, 0, source_id); + cb(command_handle, e.into(), 0) } } @@ -372,11 +365,11 @@ pub extern fn vcx_credential_update_state(command_handle: u32, trace!("vcx_credential_update_state_cb(command_handle: {}, rc: {}, state: {}), source_id: {:?}", command_handle, error_string(0), s, source_id); cb(command_handle, error::SUCCESS.code_num, s) - }, + } Err(e) => { error!("vcx_credential_update_state_cb(command_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, error_string(e.to_error_code()), 0, source_id); - cb(command_handle, e.to_error_code(), 0) + command_handle, e, 0, source_id); + cb(command_handle, e.into(), 0) } }; @@ -410,19 +403,19 @@ pub extern fn vcx_credential_get_state(command_handle: u32, let source_id = credential::get_source_id(handle).unwrap_or_default(); trace!("vcx_credential_get_state(command_handle: {}, credential_handle: {}), source_id: {:?}", - command_handle, handle, source_id); + command_handle, handle, source_id); - spawn(move|| { + spawn(move || { match credential::get_state(handle) { Ok(s) => { trace!("vcx_credential_get_state_cb(command_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, error_string(0), s, source_id); + command_handle, error_string(0), s, source_id); cb(command_handle, error::SUCCESS.code_num, s) - }, + } Err(e) => { error!("vcx_credential_get_state_cb(command_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, error_string(e.to_error_code()), 0, source_id); - cb(command_handle, e.to_error_code(), 0) + command_handle, e, 0, source_id); + cb(command_handle, e.into(), 0) } }; @@ -458,21 +451,21 @@ pub extern fn vcx_credential_serialize(command_handle: u32, let source_id = credential::get_source_id(handle).unwrap_or_default(); trace!("vcx_credential_serialize(command_handle: {}, credential_handle: {}), source_id: {:?}", - command_handle, handle, source_id); + command_handle, handle, source_id); - spawn(move|| { + spawn(move || { match credential::to_string(handle) { Ok(x) => { trace!("vcx_credential_serialize_cb(command_handle: {}, rc: {}, data: {}), source_id: {:?}", - command_handle, error_string(0), x, source_id); + command_handle, error_string(0), x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, + } Err(x) => { error!("vcx_credential_serialize_cb(command_handle: {}, rc: {}, data: {}), source_id: {:?}", - command_handle, error_string(x), 0, source_id); - cb(command_handle,x,ptr::null_mut()); - }, + command_handle, x, 0, source_id); + cb(command_handle, x.into(), ptr::null_mut()); + } }; Ok(()) @@ -503,21 +496,21 @@ pub extern fn vcx_credential_deserialize(command_handle: u32, check_useful_c_str!(credential_data, error::INVALID_OPTION.code_num); trace!("vcx_credential_deserialize(command_handle: {}, credential_data: {})", - command_handle, credential_data); + command_handle, credential_data); - spawn(move|| { + spawn(move || { match credential::from_string(&credential_data) { Ok(x) => { trace!("vcx_credential_deserialize_cb(command_handle: {}, rc: {}, credential_handle: {}) source_id: {}", - command_handle, error_string(0), x, credential::get_source_id(x).unwrap_or_default()); + command_handle, error_string(0), x, credential::get_source_id(x).unwrap_or_default()); cb(command_handle, 0, x); - }, + } Err(x) => { error!("vcx_credential_deserialize_cb(command_handle: {}, rc: {}, credential_handle: {}) source_id: {}", - command_handle, error_string(x), 0, ""); - cb(command_handle, x, 0); - }, + command_handle, x, 0, ""); + cb(command_handle, x.into(), 0); + } }; Ok(()) @@ -541,14 +534,14 @@ pub extern fn vcx_credential_release(handle: u32) -> u32 { match credential::release(handle) { Ok(_) => { trace!("vcx_credential_release(handle: {}, rc: {}), source_id: {:?}", - handle, error_string(0), source_id); + handle, error_string(0), source_id); error::SUCCESS.code_num - }, + } Err(e) => { error!("vcx_credential_release(handle: {}, rc: {}), source_id: {:?}", - handle, error_string(e.to_error_code()), source_id); - e.to_error_code() + handle, e, source_id); + e.into() } } } @@ -582,29 +575,29 @@ pub extern fn vcx_credential_get_payment_txn(command_handle: u32, let source_id = credential::get_source_id(handle).unwrap_or_default(); trace!("vcx_credential_get_payment_txn(command_handle: {}) source_id: {}", command_handle, source_id); - spawn(move|| { + spawn(move || { match credential::get_payment_txn(handle) { Ok(x) => { match serde_json::to_string(&x) { Ok(x) => { trace!("vcx_credential_get_payment_txn_cb(command_handle: {}, rc: {}, : {}), source_id: {}", - command_handle, error_string(0), x, credential::get_source_id(handle).unwrap_or_default()); + command_handle, error_string(0), x, credential::get_source_id(handle).unwrap_or_default()); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, 0, msg.as_ptr()); } Err(_) => { - error!("vcx_credential_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {}", - command_handle, error_string(error::INVALID_JSON.code_num), "null", credential::get_source_id(handle).unwrap_or_default()); + error!("vcx_credential_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {}", + command_handle, error_string(error::INVALID_JSON.code_num), "null", credential::get_source_id(handle).unwrap_or_default()); cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); } } - }, + } Err(x) => { error!("vcx_credential_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {}", - command_handle, x.to_string(), "null", credential::get_source_id(handle).unwrap_or_default()); - cb(command_handle, x.to_error_code(), ptr::null()); - }, + command_handle, x, "null", credential::get_source_id(handle).unwrap_or_default()); + cb(command_handle, x.into(), ptr::null()); + } }; Ok(()) @@ -616,6 +609,7 @@ pub extern fn vcx_credential_get_payment_txn(command_handle: u32, #[cfg(test)] mod tests { extern crate serde_json; + use super::*; use std::ffi::CString; use std::time::Duration; @@ -632,9 +626,9 @@ mod tests { init!("true"); let cb = return_types_u32::Return_U32_U32::new().unwrap(); assert_eq!(vcx_credential_create_with_offer(cb.command_handle, - CString::new("test_create").unwrap().into_raw(), - CString::new(::utils::constants::CREDENTIAL_OFFER_JSON).unwrap().into_raw(), - Some(cb.get_callback())), error::SUCCESS.code_num); + CString::new("test_create").unwrap().into_raw(), + CString::new(::utils::constants::CREDENTIAL_OFFER_JSON).unwrap().into_raw(), + Some(cb.get_callback())), error::SUCCESS.code_num); assert!(cb.receive(Some(Duration::from_secs(10))).unwrap() > 0); } @@ -653,10 +647,10 @@ mod tests { fn test_vcx_credential_serialize_and_deserialize() { init!("true"); let cb = return_types_u32::Return_U32_STR::new().unwrap(); - let handle = credential::credential_create_with_offer("test_vcx_credential_serialize",::utils::constants::CREDENTIAL_OFFER_JSON).unwrap(); + let handle = credential::credential_create_with_offer("test_vcx_credential_serialize", ::utils::constants::CREDENTIAL_OFFER_JSON).unwrap(); assert_eq!(vcx_credential_serialize(cb.command_handle, - handle, - Some(cb.get_callback())), error::SUCCESS.code_num); + handle, + Some(cb.get_callback())), error::SUCCESS.code_num); let s = cb.receive(Some(Duration::from_secs(2))).unwrap().unwrap(); let j: Value = serde_json::from_str(&s).unwrap(); assert_eq!(j["version"], DEFAULT_SERIALIZE_VERSION); @@ -671,17 +665,17 @@ mod tests { #[test] fn test_vcx_credential_send_request() { init!("true"); - let handle = credential::credential_create_with_offer("test_send_request",::utils::constants::CREDENTIAL_OFFER_JSON).unwrap(); - assert_eq!(credential::get_state(handle).unwrap(),VcxStateType::VcxStateRequestReceived as u32); + let handle = credential::credential_create_with_offer("test_send_request", ::utils::constants::CREDENTIAL_OFFER_JSON).unwrap(); + assert_eq!(credential::get_state(handle).unwrap(), VcxStateType::VcxStateRequestReceived as u32); let connection_handle = connection::tests::build_test_connection(); let cb = return_types_u32::Return_U32::new().unwrap(); - assert_eq!(vcx_credential_send_request(cb.command_handle,handle,connection_handle,0, Some(cb.get_callback())), error::SUCCESS.code_num); + assert_eq!(vcx_credential_send_request(cb.command_handle, handle, connection_handle, 0, Some(cb.get_callback())), error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); } #[test] - fn test_vcx_credential_get_new_offers(){ + fn test_vcx_credential_get_new_offers() { init!("true"); let cxn = ::connection::tests::build_test_connection(); let cb = return_types_u32::Return_U32_STR::new().unwrap(); @@ -698,10 +692,10 @@ mod tests { let cxn = ::connection::tests::build_test_connection(); let cb = return_types_u32::Return_U32_U32_STR::new().unwrap(); assert_eq!(vcx_credential_create_with_msgid(cb.command_handle, - CString::new("test_vcx_credential_create").unwrap().into_raw(), - cxn, - CString::new("123").unwrap().into_raw(), - Some(cb.get_callback())), error::SUCCESS.code_num); + CString::new("test_vcx_credential_create").unwrap().into_raw(), + cxn, + CString::new("123").unwrap().into_raw(), + Some(cb.get_callback())), error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); } @@ -711,7 +705,7 @@ mod tests { let handle = credential::from_string(DEFAULT_SERIALIZED_CREDENTIAL).unwrap(); assert!(handle > 0); let cb = return_types_u32::Return_U32_U32::new().unwrap(); - let rc = vcx_credential_get_state(cb.command_handle,handle,Some(cb.get_callback())); + let rc = vcx_credential_get_state(cb.command_handle, handle, Some(cb.get_callback())); assert_eq!(rc, error::SUCCESS.code_num); assert_eq!(cb.receive(Some(Duration::from_secs(10))).unwrap(), VcxStateType::VcxStateRequestReceived as u32); } @@ -720,20 +714,19 @@ mod tests { fn test_vcx_credential_update_state() { init!("true"); let cxn = ::connection::tests::build_test_connection(); - ::connection::connect(cxn,None).unwrap(); + ::connection::connect(cxn, None).unwrap(); let handle = credential::from_string(DEFAULT_SERIALIZED_CREDENTIAL).unwrap(); ::utils::httpclient::set_next_u8_response(::utils::constants::NEW_CREDENTIAL_OFFER_RESPONSE.to_vec()); let cb = return_types_u32::Return_U32_U32::new().unwrap(); assert_eq!(vcx_credential_update_state(cb.command_handle, handle, Some(cb.get_callback())), error::SUCCESS.code_num); - assert_eq!(cb.receive(Some(Duration::from_secs(10))).unwrap(),VcxStateType::VcxStateRequestReceived as u32); + assert_eq!(cb.receive(Some(Duration::from_secs(10))).unwrap(), VcxStateType::VcxStateRequestReceived as u32); let cb = return_types_u32::Return_U32::new().unwrap(); - assert_eq!(vcx_credential_send_request(cb.command_handle, handle, cxn,0, Some(cb.get_callback())), error::SUCCESS.code_num); + assert_eq!(vcx_credential_send_request(cb.command_handle, handle, cxn, 0, Some(cb.get_callback())), error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); - } #[test] - fn test_get_credential(){ + fn test_get_credential() { use utils::constants::FULL_CREDENTIAL_SERIALIZED; init!("true"); let handle = credential::from_string(FULL_CREDENTIAL_SERIALIZED).unwrap(); @@ -744,7 +737,7 @@ mod tests { cb.receive(Some(Duration::from_secs(10))).unwrap().unwrap(); let cb = return_types_u32::Return_U32_STR::new().unwrap(); - assert_eq!(vcx_get_credential(cb.command_handle, bad_handle, Some(cb.get_callback())), CredentialError::InvalidHandle().to_error_code()); + assert_eq!(vcx_get_credential(cb.command_handle, bad_handle, Some(cb.get_callback())), VcxErrorKind::InvalidCredentialHandle.into()); let handle = credential::from_string(DEFAULT_SERIALIZED_CREDENTIAL).unwrap(); let cb = return_types_u32::Return_U32_STR::new().unwrap(); @@ -762,7 +755,7 @@ mod tests { vcx_credential_get_payment_txn(cb.command_handle, handle, Some(cb.get_callback())); cb.receive(Some(Duration::from_secs(10))).unwrap(); } - + #[test] fn test_vcx_credential_release() { init!("true"); diff --git a/vcx/libvcx/src/api/credential_def.rs b/vcx/libvcx/src/api/credential_def.rs index 6f3b9eca8e..ac1dae5c1c 100644 --- a/vcx/libvcx/src/api/credential_def.rs +++ b/vcx/libvcx/src/api/credential_def.rs @@ -8,7 +8,6 @@ use utils::error::error_string; use std::ptr; use credential_def; use settings; -use error::ToErrorCode; use utils::threadpool::spawn; /// Create a new CredentialDef object that can create credential definitions on the ledger @@ -63,7 +62,7 @@ pub extern fn vcx_credentialdef_create(command_handle: u32, } else { match settings::get_config_value(settings::CONFIG_INSTITUTION_DID) { Ok(x) => x, - Err(x) => return x, + Err(x) => return x.into(), } }; @@ -90,8 +89,8 @@ pub extern fn vcx_credentialdef_create(command_handle: u32, }, Err(x) => { warn!("vcx_credential_def_create_cb(command_handle: {}, rc: {}, credentialdef_handle: {}), source_id: {:?}", - command_handle, error_string(x.to_error_code()), 0, ""); - (x.to_error_code(), 0) + command_handle, x, 0, ""); + (x.into(), 0) }, }; cb(command_handle, rc, handle); @@ -139,8 +138,8 @@ pub extern fn vcx_credentialdef_serialize(command_handle: u32, }, Err(x) => { warn!("vcx_credentialdef_serialize_cb(command_handle: {}, credentialdef_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, credentialdef_handle, error_string(x), "null", source_id); - cb(command_handle, x, ptr::null_mut()); + command_handle, credentialdef_handle, x, "null", source_id); + cb(command_handle, x.into(), ptr::null_mut()); }, }; @@ -180,10 +179,9 @@ pub extern fn vcx_credentialdef_deserialize(command_handle: u32, (error::SUCCESS.code_num, x) }, Err(e) => { - let error_code = e.to_error_code(); warn!("vcx_credentialdef_deserialize_cb(command_handle: {}, rc: {}, handle: {}), source_id: {}", - command_handle, error_code, 0, ""); - (error_code, 0) + command_handle, e, 0, ""); + (e.into(), 0) }, }; cb(command_handle, rc, handle); @@ -227,8 +225,8 @@ pub extern fn vcx_credentialdef_get_cred_def_id(command_handle: u32, }, Err(x) => { warn!("vcx_credentialdef_get_cred_def_id(command_handle: {}, cred_def_handle: {}, rc: {}, cred_def_id: {}) source_id: {}", - command_handle, cred_def_handle, x.to_string(), "", source_id); - cb(command_handle, x.to_error_code(), ptr::null_mut()); + command_handle, cred_def_handle, x, "", source_id); + cb(command_handle, x.into(), ptr::null_mut()); }, }; @@ -280,15 +278,15 @@ pub extern fn vcx_credentialdef_get_payment_txn(command_handle: u32, } Err(_) => { error!("vcx_credentialdef_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {}", - command_handle, error_string(error::INVALID_JSON.code_num), "null", credential_def::get_source_id(handle).unwrap_or_default()); + command_handle, error::INVALID_JSON.message, "null", credential_def::get_source_id(handle).unwrap_or_default()); cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); } } }, Err(x) => { error!("vcx_credentialdef_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {}", - command_handle, x.to_string(), "null", credential_def::get_source_id(handle).unwrap_or_default()); - cb(command_handle, x.to_error_code(), ptr::null()); + command_handle, x, "null", credential_def::get_source_id(handle).unwrap_or_default()); + cb(command_handle, x.into(), ptr::null()); }, }; @@ -319,8 +317,8 @@ pub extern fn vcx_credentialdef_release(credentialdef_handle: u32) -> u32 { Err(x) => { warn!("vcx_credentialdef_release(credentialdef_handle: {}, rc: {}), source_id: {}", - credentialdef_handle, x.to_string(), source_id); - x.to_error_code() + credentialdef_handle, x, source_id); + x.into() } } } diff --git a/vcx/libvcx/src/api/disclosed_proof.rs b/vcx/libvcx/src/api/disclosed_proof.rs index 753e0352fe..98cf066a54 100644 --- a/vcx/libvcx/src/api/disclosed_proof.rs +++ b/vcx/libvcx/src/api/disclosed_proof.rs @@ -7,7 +7,6 @@ use utils::error::error_string; use connection; use disclosed_proof; use std::ptr; -use error::ToErrorCode; use utils::threadpool::spawn; /// Create a proof for fulfilling a corresponding proof request @@ -23,7 +22,6 @@ use utils::threadpool::spawn; /// /// #Returns /// Error code as u32 - #[no_mangle] #[allow(unused_variables, unused_mut)] pub extern fn vcx_disclosed_proof_create_with_request(command_handle: u32, @@ -37,20 +35,20 @@ pub extern fn vcx_disclosed_proof_create_with_request(command_handle: u32, check_useful_c_str!(proof_req, error::INVALID_OPTION.code_num); trace!("vcx_disclosed_proof_create_with_request(command_handle: {}, source_id: {}, proof_req: {})", - command_handle, source_id, proof_req); + command_handle, source_id, proof_req); - spawn(move|| { - match disclosed_proof::create_proof(&source_id, &proof_req){ + spawn(move || { + match disclosed_proof::create_proof(&source_id, &proof_req) { Ok(x) => { trace!("vcx_disclosed_proof_create_with_request_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle, error_string(0), x, source_id); cb(command_handle, 0, x); - }, + } Err(x) => { error!("vcx_disclosed_proof_create_with_request_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), 0, source_id); - cb(command_handle, x.to_error_code(), 0); - }, + command_handle, x, 0, source_id); + cb(command_handle, x.into(), 0); + } }; Ok(()) @@ -75,7 +73,6 @@ pub extern fn vcx_disclosed_proof_create_with_request(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] #[allow(unused_variables, unused_mut)] pub extern fn vcx_disclosed_proof_create_with_msgid(command_handle: u32, @@ -90,27 +87,27 @@ pub extern fn vcx_disclosed_proof_create_with_msgid(command_handle: u32, check_useful_c_str!(msg_id, error::INVALID_OPTION.code_num); trace!("vcx_disclosed_proof_create_with_msgid(command_handle: {}, source_id: {}, connection_handle: {}, msg_id: {})", - command_handle, source_id, connection_handle, msg_id); + command_handle, source_id, connection_handle, msg_id); - spawn(move|| { + spawn(move || { match disclosed_proof::get_proof_request(connection_handle, &msg_id) { Ok(request) => { match disclosed_proof::create_proof(&source_id, &request) { Ok(handle) => { trace!("vcx_disclosed_proof_create_with_msgid_cb(command_handle: {}, rc: {}, handle: {}, proof_req: {}) source_id: {}", - command_handle, error_string(0), handle, request, source_id); + command_handle, error_string(0), handle, request, source_id); let msg = CStringUtils::string_to_cstring(request); cb(command_handle, error::SUCCESS.code_num, handle, msg.as_ptr()) - }, + } Err(e) => { warn!("vcx_disclosed_proof_create_with_msgid_cb(command_handle: {}, rc: {}, handle: {}, proof_req: {}) source_id: {}", - command_handle, e.to_string(), 0, request, source_id); + command_handle, e, 0, request, source_id); let msg = CStringUtils::string_to_cstring(request); - cb(command_handle, e.to_error_code(), 0, msg.as_ptr()); - }, + cb(command_handle, e.into(), 0, msg.as_ptr()); + } }; - }, - Err(e) => cb(command_handle, e.to_error_code(), 0, ptr::null()), + } + Err(e) => cb(command_handle, e.into(), 0, ptr::null()), }; Ok(()) @@ -132,7 +129,6 @@ pub extern fn vcx_disclosed_proof_create_with_msgid(command_handle: u32, /// /// #Returns /// Error code as u32 - #[no_mangle] pub extern fn vcx_disclosed_proof_send_proof(command_handle: u32, proof_handle: u32, @@ -152,20 +148,20 @@ pub extern fn vcx_disclosed_proof_send_proof(command_handle: u32, let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_disclosed_proof_send_proof(command_handle: {}, proof_handle: {}, connection_handle: {}) source_id: {}", - command_handle, proof_handle, connection_handle, source_id); + command_handle, proof_handle, connection_handle, source_id); - spawn(move|| { + spawn(move || { let err = match disclosed_proof::send_proof(proof_handle, connection_handle) { Ok(x) => { trace!("vcx_disclosed_proof_send_proof_cb(command_handle: {}, rc: {}) source_id: {}", - command_handle, error_string(0), source_id); - cb(command_handle,error::SUCCESS.code_num); - }, + command_handle, error_string(0), source_id); + cb(command_handle, error::SUCCESS.code_num); + } Err(x) => { error!("vcx_disclosed_proof_send_proof_cb(command_handle: {}, rc: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), source_id); - cb(command_handle,x.to_error_code()); - }, + command_handle, x, source_id); + cb(command_handle, x.into()); + } }; Ok(()) @@ -185,7 +181,6 @@ pub extern fn vcx_disclosed_proof_send_proof(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_disclosed_proof_get_requests(command_handle: u32, connection_handle: u32, @@ -199,21 +194,21 @@ pub extern fn vcx_disclosed_proof_get_requests(command_handle: u32, } trace!("vcx_disclosed_proof_get_requests(command_handle: {}, connection_handle: {})", - command_handle, connection_handle); + command_handle, connection_handle); - spawn(move|| { + spawn(move || { match disclosed_proof::get_proof_request_messages(connection_handle, None) { Ok(x) => { trace!("vcx_disclosed_proof_get_requests_cb(command_handle: {}, rc: {}, msg: {})", - command_handle, error_string(0), x); + command_handle, error_string(0), x); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, + } Err(x) => { error!("vcx_disclosed_proof_get_requests_cb(command_handle: {}, rc: {}, msg: {})", - command_handle, error_string(0), x); - cb(command_handle, x.to_error_code(), ptr::null_mut()); - }, + command_handle, error_string(0), x); + cb(command_handle, x.into(), ptr::null_mut()); + } }; Ok(()) @@ -247,19 +242,19 @@ pub extern fn vcx_disclosed_proof_get_state(command_handle: u32, let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_disclosed_proof_get_state(command_handle: {}, proof_handle: {}), source_id: {:?}", - command_handle, proof_handle, source_id); + command_handle, proof_handle, source_id); - spawn(move|| { + spawn(move || { match disclosed_proof::get_state(proof_handle) { Ok(s) => { trace!("vcx_disclosed_proof_get_state_cb(command_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, error_string(0), s, source_id); + command_handle, error_string(0), s, source_id); cb(command_handle, error::SUCCESS.code_num, s) - }, + } Err(e) => { error!("vcx_disclosed_proof_get_state_cb(command_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, error_string(e), 0, source_id); - cb(command_handle, e, 0) + command_handle, e, 0, source_id); + cb(command_handle, e.into(), 0) } }; @@ -294,19 +289,19 @@ pub extern fn vcx_disclosed_proof_update_state(command_handle: u32, let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_disclosed_proof_update_state(command_handle: {}, proof_handle: {}) source_id: {}", - command_handle, proof_handle, source_id); + command_handle, proof_handle, source_id); - spawn(move|| { + spawn(move || { match disclosed_proof::update_state(proof_handle) { Ok(s) => { trace!("vcx_disclosed_proof_update_state_cb(command_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, error_string(0), s, source_id); + command_handle, error_string(0), s, source_id); cb(command_handle, error::SUCCESS.code_num, s) - }, + } Err(e) => { error!("vcx_disclosed_proof_update_state_cb(command_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, error_string(e), 0, source_id); - cb(command_handle, e, 0) + command_handle, e, 0, source_id); + cb(command_handle, e.into(), 0) } }; @@ -341,21 +336,21 @@ pub extern fn vcx_disclosed_proof_serialize(command_handle: u32, let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_disclosed_proof_serialize(command_handle: {}, proof_handle: {}) source_id: {}", - command_handle, proof_handle, source_id); + command_handle, proof_handle, source_id); - spawn(move|| { + spawn(move || { match disclosed_proof::to_string(proof_handle) { Ok(x) => { trace!("vcx_disclosed_proof_serialize_cb(command_handle: {}, rc: {}, data: {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle, error_string(0), x, source_id); let msg = CStringUtils::string_to_cstring(x); - cb(command_handle, error::SUCCESS.code_num,msg.as_ptr()); - }, + cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); + } Err(x) => { error!("vcx_disclosed_proof_serialize_cb(command_handle: {}, rc: {}, data: {}) source_id: {}", - command_handle, error_string(x), 0, source_id); - cb(command_handle,x,ptr::null_mut()); - }, + command_handle, x, 0, source_id); + cb(command_handle, x.into(), ptr::null_mut()); + } }; Ok(()) @@ -386,21 +381,21 @@ pub extern fn vcx_disclosed_proof_deserialize(command_handle: u32, check_useful_c_str!(proof_data, error::INVALID_OPTION.code_num); trace!("vcx_disclosed_proof_deserialize(command_handle: {}, proof_data: {})", - command_handle, proof_data); + command_handle, proof_data); - spawn(move|| { + spawn(move || { match disclosed_proof::from_string(&proof_data) { Ok(x) => { trace!("vcx_disclosed_proof_deserialize_cb(command_handle: {}, rc: {}, proof_handle: {}) source_id: {}", - command_handle, error_string(0), x, disclosed_proof::get_source_id(x).unwrap_or_default()); + command_handle, error_string(0), x, disclosed_proof::get_source_id(x).unwrap_or_default()); cb(command_handle, 0, x); - }, + } Err(x) => { error!("vcx_disclosed_proof_deserialize_cb(command_handle: {}, rc: {}, proof_handle: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), 0, ""); - cb(command_handle, x.to_error_code(), 0); - }, + command_handle, x, 0, ""); + cb(command_handle, x.into(), 0); + } }; Ok(()) @@ -434,21 +429,21 @@ pub extern fn vcx_disclosed_proof_retrieve_credentials(command_handle: u32, let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_disclosed_proof_retrieve_credentials(command_handle: {}, proof_handle: {}) source_id: {}", - command_handle, proof_handle, source_id); + command_handle, proof_handle, source_id); - spawn(move|| { + spawn(move || { match disclosed_proof::retrieve_credentials(proof_handle) { Ok(x) => { trace!("vcx_disclosed_proof_retrieve_credentials(command_handle: {}, rc: {}, data: {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle, error_string(0), x, source_id); let msg = CStringUtils::string_to_cstring(x); - cb(command_handle, error::SUCCESS.code_num,msg.as_ptr()); - }, + cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); + } Err(x) => { error!("vcx_disclosed_proof_retrieve_credentials(command_handle: {}, rc: {}, data: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), 0, source_id); - cb(command_handle,x.to_error_code(),ptr::null_mut()); - }, + command_handle, x, 0, source_id); + cb(command_handle, x.into(), ptr::null_mut()); + } }; Ok(()) @@ -515,20 +510,20 @@ pub extern fn vcx_disclosed_proof_generate_proof(command_handle: u32, let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_disclosed_proof_generate_proof(command_handle: {}, proof_handle: {}, selected_credentials: {}, self_attested_attrs: {}) source_id: {}", - command_handle, proof_handle, selected_credentials, self_attested_attrs, source_id); + command_handle, proof_handle, selected_credentials, self_attested_attrs, source_id); - spawn(move|| { + spawn(move || { match disclosed_proof::generate_proof(proof_handle, selected_credentials, self_attested_attrs) { Ok(_) => { trace!("vcx_disclosed_proof_generate_proof(command_handle: {}, rc: {}) source_id: {}", - command_handle, error::SUCCESS.code_num, source_id); + command_handle, error::SUCCESS.code_num, source_id); cb(command_handle, error::SUCCESS.code_num); - }, + } Err(x) => { error!("vcx_disclosed_proof_generate_proof(command_handle: {}, rc: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), source_id); - cb(command_handle,x.to_error_code()); - }, + command_handle, x, source_id); + cb(command_handle, x.into()); + } }; Ok(()) @@ -551,23 +546,24 @@ pub extern fn vcx_disclosed_proof_release(handle: u32) -> u32 { let source_id = disclosed_proof::get_source_id(handle).unwrap_or_default(); match disclosed_proof::release(handle) { - Ok(_) => { + Ok(_) => { let success_err_code = error::SUCCESS.code_num; trace!("vcx_disclosed_proof_release(handle: {}, rc: {}), source_id: {:?}", - handle, error_string(success_err_code), source_id); + handle, error_string(success_err_code), source_id); success_err_code - }, + } Err(e) => { error!("vcx_disclosed_proof_release(handle: {}, rc: {}), source_id: {:?}", - handle, error_string(e), source_id); - e - }, + handle, e, source_id); + e.into() + } } } #[cfg(test)] mod tests { extern crate serde_json; + use super::*; use std::ffi::CString; use std::time::Duration; @@ -584,9 +580,9 @@ mod tests { init!("true"); let cb = return_types_u32::Return_U32_U32::new().unwrap(); assert_eq!(vcx_disclosed_proof_create_with_request(cb.command_handle, - CString::new("test_create").unwrap().into_raw(), - CString::new(::utils::constants::PROOF_REQUEST_JSON).unwrap().into_raw(), - Some(cb.get_callback())), error::SUCCESS.code_num); + CString::new("test_create").unwrap().into_raw(), + CString::new(::utils::constants::PROOF_REQUEST_JSON).unwrap().into_raw(), + Some(cb.get_callback())), error::SUCCESS.code_num); assert!(cb.receive(Some(Duration::from_secs(10))).unwrap() > 0); } @@ -598,7 +594,7 @@ mod tests { cb.command_handle, CString::new("test_create").unwrap().into_raw(), CString::new(BAD_PROOF_REQUEST).unwrap().into_raw(), - Some(cb.get_callback())),error::SUCCESS.code_num); + Some(cb.get_callback())), error::SUCCESS.code_num); assert_eq!(cb.receive(Some(Duration::from_secs(10))).err(), Some(error::INVALID_JSON.code_num)); } @@ -621,23 +617,22 @@ mod tests { fn test_vcx_disclosed_proof_release() { init!("true"); let cb = return_types_u32::Return_U32_STR::new().unwrap(); - let handle = disclosed_proof::create_proof("1",::utils::constants::PROOF_REQUEST_JSON).unwrap(); + let handle = disclosed_proof::create_proof("1", ::utils::constants::PROOF_REQUEST_JSON).unwrap(); let unknown_handle = handle + 1; let err = vcx_disclosed_proof_release(unknown_handle); assert_eq!(err, error::INVALID_DISCLOSED_PROOF_HANDLE.code_num); - } #[test] fn test_vcx_disclosed_proof_serialize_and_deserialize() { init!("true"); let cb = return_types_u32::Return_U32_STR::new().unwrap(); - let handle = disclosed_proof::create_proof("1",::utils::constants::PROOF_REQUEST_JSON).unwrap(); + let handle = disclosed_proof::create_proof("1", ::utils::constants::PROOF_REQUEST_JSON).unwrap(); assert_eq!(vcx_disclosed_proof_serialize(cb.command_handle, - handle, - Some(cb.get_callback())), error::SUCCESS.code_num); + handle, + Some(cb.get_callback())), error::SUCCESS.code_num); let s = cb.receive(Some(Duration::from_secs(2))).unwrap().unwrap(); - let j:Value = serde_json::from_str(&s).unwrap(); + let j: Value = serde_json::from_str(&s).unwrap(); assert_eq!(j["version"], DEFAULT_SERIALIZE_VERSION); let cb = return_types_u32::Return_U32_U32::new().unwrap(); @@ -654,33 +649,33 @@ mod tests { fn test_vcx_send_proof() { init!("true"); - let handle = disclosed_proof::create_proof("1",::utils::constants::PROOF_REQUEST_JSON).unwrap(); - assert_eq!(disclosed_proof::get_state(handle).unwrap(),VcxStateType::VcxStateRequestReceived as u32); + let handle = disclosed_proof::create_proof("1", ::utils::constants::PROOF_REQUEST_JSON).unwrap(); + assert_eq!(disclosed_proof::get_state(handle).unwrap(), VcxStateType::VcxStateRequestReceived as u32); let connection_handle = connection::tests::build_test_connection(); let cb = return_types_u32::Return_U32::new().unwrap(); - assert_eq!(vcx_disclosed_proof_send_proof(cb.command_handle,handle,connection_handle,Some(cb.get_callback())), error::SUCCESS.code_num); + assert_eq!(vcx_disclosed_proof_send_proof(cb.command_handle, handle, connection_handle, Some(cb.get_callback())), error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); } #[test] - fn test_vcx_proof_get_requests(){ + fn test_vcx_proof_get_requests() { init!("true"); let cxn = ::connection::tests::build_test_connection(); ::utils::httpclient::set_next_u8_response(::utils::constants::NEW_PROOF_REQUEST_RESPONSE.to_vec()); let cb = return_types_u32::Return_U32_STR::new().unwrap(); - assert_eq!(vcx_disclosed_proof_get_requests(cb.command_handle, cxn, Some(cb.get_callback())),error::SUCCESS.code_num as u32); + assert_eq!(vcx_disclosed_proof_get_requests(cb.command_handle, cxn, Some(cb.get_callback())), error::SUCCESS.code_num as u32); cb.receive(Some(Duration::from_secs(10))).unwrap(); } #[test] fn test_vcx_proof_get_state() { init!("true"); - let handle = disclosed_proof::create_proof("1",::utils::constants::PROOF_REQUEST_JSON).unwrap(); + let handle = disclosed_proof::create_proof("1", ::utils::constants::PROOF_REQUEST_JSON).unwrap(); assert!(handle > 0); let cb = return_types_u32::Return_U32_U32::new().unwrap(); - assert_eq!(vcx_disclosed_proof_get_state(cb.command_handle,handle,Some(cb.get_callback())),error::SUCCESS.code_num); + assert_eq!(vcx_disclosed_proof_get_state(cb.command_handle, handle, Some(cb.get_callback())), error::SUCCESS.code_num); let state = cb.receive(Some(Duration::from_secs(10))).unwrap(); assert_eq!(state, VcxStateType::VcxStateRequestReceived as u32); } diff --git a/vcx/libvcx/src/api/issuer_credential.rs b/vcx/libvcx/src/api/issuer_credential.rs index bc5d8e2644..dede6ae0a3 100644 --- a/vcx/libvcx/src/api/issuer_credential.rs +++ b/vcx/libvcx/src/api/issuer_credential.rs @@ -9,7 +9,6 @@ use connection; use settings; use issuer_credential; use std::ptr; -use error::ToErrorCode; use utils::threadpool::spawn; /// Create a Issuer Credential object that provides a credential for an enterprise's user @@ -40,13 +39,13 @@ use utils::threadpool::spawn; #[no_mangle] #[allow(unused_variables, unused_mut)] pub extern fn vcx_issuer_create_credential(command_handle: u32, - source_id: *const c_char, - cred_def_handle: u32, - issuer_did: *const c_char, - credential_data: *const c_char, - credential_name: *const c_char, - price: *const c_char, - cb: Option) -> u32 { + source_id: *const c_char, + cred_def_handle: u32, + issuer_did: *const c_char, + credential_data: *const c_char, + credential_name: *const c_char, + price: *const c_char, + cb: Option) -> u32 { info!("vcx_issuer_create_credential >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); @@ -61,7 +60,7 @@ pub extern fn vcx_issuer_create_credential(command_handle: u32, } else { match settings::get_config_value(settings::CONFIG_INSTITUTION_DID) { Ok(x) => x, - Err(x) => return x + Err(x) => return x.into() } }; @@ -75,25 +74,25 @@ pub extern fn vcx_issuer_create_credential(command_handle: u32, } trace!("vcx_issuer_create_credential(command_handle: {}, source_id: {}, cred_def_handle: {}, issuer_did: {}, credential_data: {}, credential_name: {})", - command_handle, - source_id, - cred_def_handle, - issuer_did, - credential_data, - credential_name); - - spawn(move|| { + command_handle, + source_id, + cred_def_handle, + issuer_did, + credential_data, + credential_name); + + spawn(move || { let (rc, handle) = match issuer_credential::issuer_credential_create(cred_def_handle, source_id, issuer_did, credential_name, credential_data, price) { Ok(x) => { trace!("vcx_issuer_create_credential_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), x, issuer_credential::get_source_id(x).unwrap_or_default()); + command_handle, error_string(0), x, issuer_credential::get_source_id(x).unwrap_or_default()); (error::SUCCESS.code_num, x) - }, + } Err(x) => { warn!("vcx_issuer_create_credential_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), 0, ""); - (x.to_error_code(), 0) - }, + command_handle, x, 0, ""); + (x.into(), 0) + } }; cb(command_handle, rc, handle); @@ -119,16 +118,16 @@ pub extern fn vcx_issuer_create_credential(command_handle: u32, /// Error code as a u32 #[no_mangle] pub extern fn vcx_issuer_send_credential_offer(command_handle: u32, - credential_handle: u32, - connection_handle: u32, - cb: Option) -> u32 { + credential_handle: u32, + connection_handle: u32, + cb: Option) -> u32 { info!("vcx_issuer_send_credential_offer >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_issuer_send_credential(command_handle: {}, credential_handle: {}, connection_handle: {}) source_id: {}", - command_handle, credential_handle, connection_handle, source_id); + command_handle, credential_handle, connection_handle, source_id); if !issuer_credential::is_valid_handle(credential_handle) { return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; @@ -138,21 +137,21 @@ pub extern fn vcx_issuer_send_credential_offer(command_handle: u32, return error::INVALID_CONNECTION_HANDLE.code_num; } - spawn(move|| { + spawn(move || { let err = match issuer_credential::send_credential_offer(credential_handle, connection_handle) { Ok(x) => { trace!("vcx_issuer_send_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {}", - command_handle, credential_handle, error_string(x), source_id); + command_handle, credential_handle, error_string(x), source_id); x - }, + } Err(x) => { warn!("vcx_issuer_send_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {})", - command_handle, credential_handle, error_string(x.to_error_code()), source_id); - x.to_error_code() - }, + command_handle, credential_handle, x, source_id); + x.into() + } }; - cb(command_handle,err); + cb(command_handle, err); Ok(()) }); @@ -173,31 +172,31 @@ pub extern fn vcx_issuer_send_credential_offer(command_handle: u32, /// Error code as a u32 #[no_mangle] pub extern fn vcx_issuer_credential_update_state(command_handle: u32, - credential_handle: u32, - cb: Option) -> u32 { + credential_handle: u32, + cb: Option) -> u32 { info!("vcx_issuer_credential_update_state >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_issuer_credential_update_state(command_handle: {}, credential_handle: {}) source_id: {}", - command_handle, credential_handle, source_id); + command_handle, credential_handle, source_id); if !issuer_credential::is_valid_handle(credential_handle) { return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; } - spawn(move|| { + spawn(move || { match issuer_credential::update_state(credential_handle) { Ok(x) => { trace!("vcx_issuer_credential_update_state_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, credential_handle, error_string(0), x, source_id); + command_handle, credential_handle, error_string(0), x, source_id); cb(command_handle, error::SUCCESS.code_num, x); - }, + } Err(x) => { warn!("vcx_issuer_credential_update_state_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, credential_handle, x.to_string(), 0, source_id); - cb(command_handle, x.to_error_code(), 0); + command_handle, credential_handle, x, 0, source_id); + cb(command_handle, x.into(), 0); } }; @@ -218,35 +217,34 @@ pub extern fn vcx_issuer_credential_update_state(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_issuer_credential_get_state(command_handle: u32, - credential_handle: u32, - cb: Option) -> u32 { + credential_handle: u32, + cb: Option) -> u32 { info!("vcx_issuer_credential_get_state >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_issuer_credential_get_state(command_handle: {}, credential_handle: {}) source_id: {}", - command_handle, credential_handle, source_id); + command_handle, credential_handle, source_id); if !issuer_credential::is_valid_handle(credential_handle) { return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; } - spawn(move|| { + spawn(move || { match issuer_credential::get_state(credential_handle) { Ok(x) => { trace!("vcx_issuer_credential_get_state_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, credential_handle, error_string(0), x, source_id); + command_handle, credential_handle, 0, x, source_id); cb(command_handle, error::SUCCESS.code_num, x); - }, + } Err(x) => { warn!("vcx_issuer_credential_get_state_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, credential_handle, error_string(x), 0, source_id); - cb(command_handle, x, 0); - }, + command_handle, credential_handle, x, 0, source_id); + cb(command_handle, x.into(), 0); + } }; Ok(()) @@ -260,6 +258,7 @@ pub extern fn vcx_issuer_get_credential_request(credential_handle: u32, credenti info!("vcx_issuer_get_credential_request >>>"); error::SUCCESS.code_num } + #[allow(unused_variables, unused_mut)] pub extern fn vcx_issuer_accept_credential(credential_handle: u32) -> u32 { info!("vcx_issuer_accept_credential >>>"); @@ -281,9 +280,9 @@ pub extern fn vcx_issuer_accept_credential(credential_handle: u32) -> u32 { /// Error code as a u32 #[no_mangle] pub extern fn vcx_issuer_send_credential(command_handle: u32, - credential_handle: u32, - connection_handle: u32, - cb: Option) -> u32 { + credential_handle: u32, + connection_handle: u32, + cb: Option) -> u32 { info!("vcx_issuer_send_credential >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); @@ -298,22 +297,22 @@ pub extern fn vcx_issuer_send_credential(command_handle: u32, let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_issuer_send_credential(command_handle: {}, credential_handle: {}, connection_handle: {}) source_id: {}", - command_handle, credential_handle, connection_handle, source_id); - spawn(move|| { + command_handle, credential_handle, connection_handle, source_id); + spawn(move || { let err = match issuer_credential::send_credential(credential_handle, connection_handle) { Ok(x) => { trace!("vcx_issuer_send_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {}", - command_handle, credential_handle, error_string(x), source_id); + command_handle, credential_handle, error_string(x), source_id); x - }, + } Err(x) => { warn!("vcx_issuer_send_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {}", - command_handle, credential_handle, error_string(x.to_error_code()), source_id); - x.to_error_code() - }, + command_handle, credential_handle, x, source_id); + x.into() + } }; - cb(command_handle,err); + cb(command_handle, err); Ok(()) }); @@ -340,8 +339,8 @@ pub extern fn vcx_issuer_terminate_credential(credential_handle: u32, terminatio /// Error code as a u32 #[no_mangle] pub extern fn vcx_issuer_credential_serialize(command_handle: u32, - credential_handle: u32, - cb: Option) -> u32 { + credential_handle: u32, + cb: Option) -> u32 { info!("vcx_issuer_credential_serialize >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); @@ -352,20 +351,20 @@ pub extern fn vcx_issuer_credential_serialize(command_handle: u32, let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_issuer_credential_serialize(credential_serialize(command_handle: {}, credential_handle: {}), source_id: {}", - command_handle, credential_handle, source_id); - spawn(move|| { + command_handle, credential_handle, source_id); + spawn(move || { match issuer_credential::to_string(credential_handle) { Ok(x) => { trace!("vcx_issuer_credential_serialize_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, credential_handle, error_string(0), x, source_id); + command_handle, credential_handle, error_string(0), x, source_id); let msg = CStringUtils::string_to_cstring(x); - cb(command_handle, error::SUCCESS.code_num,msg.as_ptr()); - }, + cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); + } Err(x) => { trace!("vcx_issuer_credential_serialize_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {})", - command_handle, credential_handle, error_string(x.to_error_code()), "null", source_id); - cb(command_handle,x.to_error_code(),ptr::null_mut()); - }, + command_handle, credential_handle, x, "null", source_id); + cb(command_handle, x.into(), ptr::null_mut()); + } }; Ok(()) @@ -387,8 +386,8 @@ pub extern fn vcx_issuer_credential_serialize(command_handle: u32, /// Error code as a u32 #[no_mangle] pub extern fn vcx_issuer_credential_deserialize(command_handle: u32, - credential_data: *const c_char, - cb: Option) -> u32 { + credential_data: *const c_char, + cb: Option) -> u32 { info!("vcx_issuer_credential_deserialize >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); @@ -396,18 +395,18 @@ pub extern fn vcx_issuer_credential_deserialize(command_handle: u32, trace!("vcx_issuer_credential_deserialize(command_handle: {}, credential_data: {})", command_handle, credential_data); - spawn(move|| { + spawn(move || { let (rc, handle) = match issuer_credential::from_string(&credential_data) { Ok(x) => { trace!("vcx_issuer_credential_deserialize_cb(command_handle: {}, rc: {}, handle: {}), source_id: {}", - command_handle, error_string(0), x, issuer_credential::get_source_id(x).unwrap_or_default()); + command_handle, error_string(0), x, issuer_credential::get_source_id(x).unwrap_or_default()); (error::SUCCESS.code_num, x) - }, + } Err(x) => { warn!("vcx_issuer_credential_deserialize_cb(command_handle: {}, rc: {}, handle: {})", - command_handle, x.to_string(), 0); - (x.to_error_code(), 0) - }, + command_handle, x, 0); + (x.into(), 0) + } }; cb(command_handle, rc, handle); @@ -432,14 +431,14 @@ pub extern fn vcx_issuer_credential_release(credential_handle: u32) -> u32 { match issuer_credential::release(credential_handle) { Ok(_) => { trace!("(vcx_issuer_credential_release credential_handle: {}, rc: {}), source_id: {}", - credential_handle, error_string(0), source_id); + credential_handle, error_string(0), source_id); error::SUCCESS.code_num - }, + } Err(e) => { warn!("(vcx_issuer_credential_release credential_handle: {}, rc: {}), source_id: {}", - credential_handle, error_string(e.to_error_code()), source_id); - e.to_error_code() - }, + credential_handle, e, source_id); + e.into() + } } } @@ -463,8 +462,8 @@ pub extern fn vcx_issuer_credential_release(credential_handle: u32) -> u32 { /// } #[no_mangle] pub extern fn vcx_issuer_credential_get_payment_txn(command_handle: u32, - handle: u32, - cb: Option) -> u32 { + handle: u32, + cb: Option) -> u32 { info!("vcx_issuer_credential_get_payment_txn >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); @@ -472,29 +471,29 @@ pub extern fn vcx_issuer_credential_get_payment_txn(command_handle: u32, let source_id = issuer_credential::get_source_id(handle).unwrap_or_default(); trace!("vcx_issuer_credential_get_payment_txn(command_handle: {}) source_id: {}", command_handle, source_id); - spawn(move|| { + spawn(move || { match issuer_credential::get_payment_txn(handle) { Ok(x) => { match serde_json::to_string(&x) { Ok(x) => { trace!("vcx_issuer_credential_get_payment_txn_cb(command_handle: {}, rc: {}, : {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle, error_string(0), x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, 0, msg.as_ptr()); } - Err(_) => { + Err(e) => { error!("vcx_issuer_credential_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}) source_id: {}", - command_handle, error_string(error::INVALID_JSON.code_num), "null", source_id); + command_handle, error::INVALID_JSON.message, "null", source_id); cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); } } - }, + } Err(x) => { error!("vcx_issuer_credential_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}) source_id: {}", - command_handle, x.to_string(), "null", source_id); - cb(command_handle, x.to_error_code(), ptr::null()); - }, + command_handle, x, "null", source_id); + cb(command_handle, x.into(), ptr::null()); + } }; Ok(()) @@ -518,7 +517,6 @@ pub extern fn vcx_issuer_credential_get_payment_txn(command_handle: u32, pub extern fn vcx_issuer_revoke_credential(command_handle: u32, credential_handle: u32, cb: Option) -> u32 { - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); if !issuer_credential::is_valid_handle(credential_handle) { @@ -529,21 +527,21 @@ pub extern fn vcx_issuer_revoke_credential(command_handle: u32, info!("vcx_issuer_revoke_credential(command_handle: {}, credential_handle: {}) source_id: {}", command_handle, credential_handle, source_id); - spawn(move|| { + spawn(move || { let err = match issuer_credential::revoke_credential(credential_handle) { Ok(_) => { info!("vcx_issuer_revoke_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {}", command_handle, credential_handle, error_string(error::SUCCESS.code_num), source_id); error::SUCCESS.code_num - }, + } Err(x) => { warn!("vcx_issuer_revoke_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {}", - command_handle, credential_handle, error_string(x), source_id); - x - }, + command_handle, credential_handle, x, source_id); + x.into() + } }; - cb(command_handle,err); + cb(command_handle, err); Ok(()) }); @@ -554,6 +552,7 @@ pub extern fn vcx_issuer_revoke_credential(command_handle: u32, #[cfg(test)] mod tests { extern crate serde_json; + use super::*; use std::ffi::CString; use std::ptr; @@ -635,13 +634,13 @@ mod tests { init!("true"); let cb = return_types_u32::Return_U32_U32::new().unwrap(); assert_eq!(vcx_issuer_create_credential(cb.command_handle, - CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), - ::credential_def::tests::create_cred_def_fake(), - ptr::null(), - CString::new(DEFAULT_ATTR).unwrap().into_raw(), - CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), - CString::new("1").unwrap().into_raw(), - Some(cb.get_callback())), error::SUCCESS.code_num); + CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), + ::credential_def::tests::create_cred_def_fake(), + ptr::null(), + CString::new(DEFAULT_ATTR).unwrap().into_raw(), + CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), + CString::new("1").unwrap().into_raw(), + Some(cb.get_callback())), error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); } @@ -665,27 +664,28 @@ mod tests { fn create_default_issuer_credential() -> u32 { let cb = return_types_u32::Return_U32_U32::new().unwrap(); assert_eq!(vcx_issuer_create_credential(cb.command_handle, - CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), - ::credential_def::tests::create_cred_def_fake(), - ptr::null(), - CString::new(DEFAULT_ATTR).unwrap().into_raw(), - CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), - CString::new("1").unwrap().into_raw(), - Some(cb.get_callback())), error::SUCCESS.code_num); - cb.receive(Some(Duration::from_secs(10))).unwrap() + CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), + ::credential_def::tests::create_cred_def_fake(), + ptr::null(), + CString::new(DEFAULT_ATTR).unwrap().into_raw(), + CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), + CString::new("1").unwrap().into_raw(), + Some(cb.get_callback())), error::SUCCESS.code_num); + cb.receive(Some(Duration::from_secs(10))).unwrap() } + #[test] fn test_vcx_issuer_credential_serialize_deserialize() { init!("true"); let cb = return_types_u32::Return_U32_U32::new().unwrap(); assert_eq!(vcx_issuer_create_credential(cb.command_handle, - CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), + CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), ::credential_def::tests::create_cred_def_fake(), - CString::new(DEFAULT_DID).unwrap().into_raw(), - CString::new(DEFAULT_ATTR).unwrap().into_raw(), - CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), - CString::new("1").unwrap().into_raw(), - Some(cb.get_callback())), error::SUCCESS.code_num); + CString::new(DEFAULT_DID).unwrap().into_raw(), + CString::new(DEFAULT_ATTR).unwrap().into_raw(), + CString::new(DEFAULT_CREDENTIAL_NAME).unwrap().into_raw(), + CString::new("1").unwrap().into_raw(), + Some(cb.get_callback())), error::SUCCESS.code_num); let handle = cb.receive(Some(Duration::from_secs(2))).unwrap(); let cb = return_types_u32::Return_U32_STR::new().unwrap(); assert_eq!(vcx_issuer_credential_serialize(cb.command_handle, @@ -697,7 +697,7 @@ mod tests { assert_eq!(vcx_issuer_credential_deserialize(cb.command_handle, CString::new(s).unwrap().into_raw(), Some(cb.get_callback())), - error::SUCCESS.code_num); + error::SUCCESS.code_num); let handle = cb.receive(Some(Duration::from_secs(2))).unwrap(); assert!(handle > 0); } @@ -706,10 +706,10 @@ mod tests { fn test_vcx_issuer_send_credential_offer() { init!("true"); let handle = issuer_credential::from_string(DEFAULT_SERIALIZED_ISSUER_CREDENTIAL).unwrap(); - assert_eq!(issuer_credential::get_state(handle).unwrap(),VcxStateType::VcxStateInitialized as u32); + assert_eq!(issuer_credential::get_state(handle).unwrap(), VcxStateType::VcxStateInitialized as u32); let connection_handle = ::connection::tests::build_test_connection(); - connection::connect(connection_handle,None).unwrap(); + connection::connect(connection_handle, None).unwrap(); let cb = return_types_u32::Return_U32::new().unwrap(); assert_eq!(vcx_issuer_send_credential_offer(cb.command_handle, @@ -729,7 +729,7 @@ mod tests { // create connection let connection_handle = ::connection::tests::build_test_connection(); - connection::connect(connection_handle,None).unwrap(); + connection::connect(connection_handle, None).unwrap(); // send the credential let cb = return_types_u32::Return_U32::new().unwrap(); @@ -742,7 +742,7 @@ mod tests { } #[test] - fn test_create_credential_arguments_correct(){ + fn test_create_credential_arguments_correct() { init!("true"); settings::set_config_value(settings::CONFIG_INSTITUTION_DID, DEFAULT_DID); let cb = return_types_u32::Return_U32_U32::new().unwrap(); @@ -766,7 +766,7 @@ mod tests { } #[test] - fn test_create_credential_invalid_price(){ + fn test_create_credential_invalid_price() { init!("true"); settings::set_config_value(settings::CONFIG_INSTITUTION_DID, DEFAULT_DID); let cb = return_types_u32::Return_U32_U32::new().unwrap(); @@ -816,8 +816,8 @@ mod tests { // send the credential let cb = return_types_u32::Return_U32::new().unwrap(); assert_eq!(vcx_issuer_revoke_credential(cb.command_handle, - handle, - Some(cb.get_callback())), + handle, + Some(cb.get_callback())), error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); } diff --git a/vcx/libvcx/src/api/logger.rs b/vcx/libvcx/src/api/logger.rs index 4d24322ef7..48a6bd4789 100644 --- a/vcx/libvcx/src/api/logger.rs +++ b/vcx/libvcx/src/api/logger.rs @@ -33,7 +33,7 @@ pub extern fn vcx_set_default_logger(pattern: *const c_char) -> u32 { }, Err(ec) => { error!("Logger Failed To Initialize: {}", ec); - ec + ec.into() }, } } @@ -68,7 +68,7 @@ pub extern fn vcx_set_logger(context: *const CVoid, }, Err(ec) => { error!("Logger Failed To Initialize: {}", ec); - ec + ec.into() }, } } diff --git a/vcx/libvcx/src/api/mod.rs b/vcx/libvcx/src/api/mod.rs index 47d34dc6bb..15904f8807 100644 --- a/vcx/libvcx/src/api/mod.rs +++ b/vcx/libvcx/src/api/mod.rs @@ -15,13 +15,6 @@ pub mod return_types_u32; use std::fmt; -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)] -pub enum Errorcode -{ - Success = 0, - Failure = 1, - Waiting = 2, -} /// This macro allows the VcxStateType to be /// serialized within serde as an integer (represented as /// a string, because its still JSON). diff --git a/vcx/libvcx/src/api/proof.rs b/vcx/libvcx/src/api/proof.rs index 984b1ba993..9b7c6a2907 100644 --- a/vcx/libvcx/src/api/proof.rs +++ b/vcx/libvcx/src/api/proof.rs @@ -7,7 +7,6 @@ use utils::error::error_string; use proof; use connection; use std::ptr; -use error::ToErrorCode; use utils::threadpool::spawn; /// Create a new Proof object that requests a proof for an enterprise @@ -96,8 +95,8 @@ pub extern fn vcx_proof_create(command_handle: u32, }, Err(x) => { warn!("vcx_proof_create_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), 0, proof::get_source_id(x.to_error_code()).unwrap_or_default()); - (x.to_error_code(), 0) + command_handle, x, 0,x); + (x.into(), 0) }, }; cb(command_handle, rc, handle); @@ -144,8 +143,8 @@ pub extern fn vcx_proof_update_state(command_handle: u32, }, Err(x) => { warn!("vcx_proof_update_state_cb(command_handle: {}, rc: {}, proof_handle: {}, state: {}) source_id: {}", - command_handle, x.to_string(), proof_handle, 0, source_id); - cb(command_handle, x.to_error_code(), 0); + command_handle, x, proof_handle, 0, source_id); + cb(command_handle, x.into(), 0); } } @@ -191,8 +190,8 @@ pub extern fn vcx_proof_get_state(command_handle: u32, }, Err(x) => { warn!("vcx_proof_get_state_cb(command_handle: {}, rc: {}, proof_handle: {}, state: {}) source_id: {}", - command_handle, x.to_string(), proof_handle, 0, source_id); - cb(command_handle, x.to_error_code(), 0); + command_handle, x, proof_handle, 0, source_id); + cb(command_handle, x.into(), 0); } } @@ -238,8 +237,8 @@ pub extern fn vcx_proof_serialize(command_handle: u32, }, Err(x) => { warn!("vcx_proof_serialize_cb(command_handle: {}, proof_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, proof_handle, error_string(x.to_error_code()), "null", source_id); - cb(command_handle, x.to_error_code(), ptr::null_mut()); + command_handle, proof_handle, x, "null", source_id); + cb(command_handle, x.into(), ptr::null_mut()); }, }; @@ -281,8 +280,8 @@ pub extern fn vcx_proof_deserialize(command_handle: u32, }, Err(x) => { warn!("vcx_proof_deserialize_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), 0, ""); - (x.to_error_code(), 0) + command_handle, x, 0, ""); + (x.into(), 0) }, }; cb(command_handle, rc, handle); @@ -313,8 +312,8 @@ pub extern fn vcx_proof_release(proof_handle: u32) -> u32 { }, Err(e) => { warn!("vcx_proof_release(proof_handle: {}, rc: {}), source_id: {}", - proof_handle, error_string(e.to_error_code()), source_id); - e.to_error_code() + proof_handle, e, source_id); + e.into() }, } } @@ -361,8 +360,8 @@ pub extern fn vcx_proof_send_request(command_handle: u32, }, Err(x) => { warn!("vcx_proof_send_request_cb(command_handle: {}, rc: {}, proof_handle: {}) source_id: {}", - command_handle, x.to_error_code(), proof_handle, source_id); - x.to_error_code() + command_handle, x, proof_handle, source_id); + x.into() }, }; @@ -421,8 +420,8 @@ pub extern fn vcx_get_proof(command_handle: u32, cb(command_handle, error::SUCCESS.code_num, proof::get_proof_state(proof_handle).unwrap_or(0), msg.as_ptr()); }, Err(x) => { - warn!("vcx_get_proof_cb(command_handle: {}, proof_handle: {}, rc: {}, proof: {}) source_id: {}", command_handle, proof_handle, x.to_error_code(), "null", source_id); - cb(command_handle, x.to_error_code(), proof::get_proof_state(proof_handle).unwrap_or(0), ptr::null_mut()); + warn!("vcx_get_proof_cb(command_handle: {}, proof_handle: {}, rc: {}, proof: {}) source_id: {}", command_handle, proof_handle, x, "null", source_id); + cb(command_handle, x.into(), proof::get_proof_state(proof_handle).unwrap_or(0), ptr::null_mut()); }, }; diff --git a/vcx/libvcx/src/api/schema.rs b/vcx/libvcx/src/api/schema.rs index 887084a3e0..b5742246cf 100644 --- a/vcx/libvcx/src/api/schema.rs +++ b/vcx/libvcx/src/api/schema.rs @@ -8,7 +8,6 @@ use utils::error::error_string; use std::ptr; use schema; use settings; -use error::ToErrorCode; use utils::threadpool::spawn; /// Create a new Schema object that can create or look up schemas on the ledger @@ -50,30 +49,29 @@ pub extern fn vcx_schema_create(command_handle: u32, let issuer_did = match settings::get_config_value(settings::CONFIG_INSTITUTION_DID) { Ok(x) => x, - Err(x) => return x + Err(x) => return x.into() }; - trace!(target:"vcx","vcx_schema_create(command_handle: {}, source_id: {}, schema_name: {}, schema_data: {})", - command_handle, source_id, schema_name, schema_data); - - spawn(move|| { - let ( rc, handle) = match schema::create_new_schema(&source_id, - issuer_did, - schema_name, - version, - schema_data) { + trace!(target: "vcx", "vcx_schema_create(command_handle: {}, source_id: {}, schema_name: {}, schema_data: {})", + command_handle, source_id, schema_name, schema_data); + + spawn(move || { + match schema::create_new_schema(&source_id, + issuer_did, + schema_name, + version, + schema_data) { Ok(x) => { - trace!(target:"vcx", "vcx_schema_create_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), x, source_id); - (error::SUCCESS.code_num, x) - }, + trace!(target: "vcx", "vcx_schema_create_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", + command_handle, error_string(0), x, source_id); + cb(command_handle, error::SUCCESS.code_num, x); + } Err(x) => { warn!("vcx_schema_create_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(x.to_error_code()), 0, source_id); - (x.to_error_code(), 0) }, + command_handle, x, 0, source_id); + cb(command_handle, x.into(), 0); + } }; - cb(command_handle, rc, handle); - Ok(()) }); @@ -102,25 +100,25 @@ pub extern fn vcx_schema_serialize(command_handle: u32, let source_id = schema::get_source_id(schema_handle).unwrap_or_default(); trace!("vcx_schema_serialize(command_handle: {}, schema_handle: {}) source_id: {}", - command_handle, schema_handle, source_id); + command_handle, schema_handle, source_id); if !schema::is_valid_handle(schema_handle) { return error::INVALID_SCHEMA_HANDLE.code_num; }; - spawn(move|| { + spawn(move || { match schema::to_string(schema_handle) { Ok(x) => { trace!("vcx_schema_serialize_cb(command_handle: {}, schema_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, schema_handle, error_string(0), x, source_id); + command_handle, schema_handle, error_string(0), x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, + } Err(x) => { warn!("vcx_schema_serialize_cb(command_handle: {}, schema_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, schema_handle, error_string(x.to_error_code()), "null", source_id); - cb(command_handle, x.to_error_code(), ptr::null_mut()); - }, + command_handle, schema_handle, x, "null", source_id); + cb(command_handle, x.into(), ptr::null_mut()); + } }; Ok(()) @@ -150,20 +148,19 @@ pub extern fn vcx_schema_deserialize(command_handle: u32, check_useful_c_str!(schema_data, error::INVALID_OPTION.code_num); trace!("vcx_schema_deserialize(command_handle: {}, schema_data: {})", command_handle, schema_data); - spawn(move|| { - let (rc, handle) = match schema::from_string(&schema_data) { + spawn(move || { + match schema::from_string(&schema_data) { Ok(x) => { trace!("vcx_schema_deserialize_cb(command_handle: {}, rc: {}, handle: {}), source_id: {}", - command_handle, error_string(0), x, schema::get_source_id(x).unwrap_or_default()); - (error::SUCCESS.code_num, x) - }, + command_handle, error_string(0), x, schema::get_source_id(x).unwrap_or_default()); + cb(command_handle, error::SUCCESS.code_num, x); + } Err(x) => { warn!("vcx_schema_deserialize_cb(command_handle: {}, rc: {}, handle: {}), source_id: {}", - command_handle, error_string(x.to_error_code()), 0, ""); - (x.to_error_code(), 0) - }, + command_handle, x, 0, ""); + cb(command_handle, x.into(), 0); + } }; - cb(command_handle, rc, handle); Ok(()) }); @@ -186,13 +183,13 @@ pub extern fn vcx_schema_release(schema_handle: u32) -> u32 { match schema::release(schema_handle) { Ok(_) => { trace!("vcx_schema_release(schema_handle: {}, rc: {}), source_id: {}", - schema_handle, error_string(0), source_id); + schema_handle, error_string(0), source_id); error::SUCCESS.code_num - }, + } Err(e) => { warn!("vcx_schema_release(schema_handle: {}, rc: {}), source_id: {}", - schema_handle, error_string(e.to_error_code()), source_id); - e.to_error_code() + schema_handle, e, source_id); + e.into() } } } @@ -219,19 +216,19 @@ pub extern fn vcx_schema_get_schema_id(command_handle: u32, return error::INVALID_SCHEMA_HANDLE.code_num; } - spawn(move|| { + spawn(move || { match schema::get_schema_id(schema_handle) { Ok(x) => { trace!("vcx_schema_get_schema_id(command_handle: {}, schema_handle: {}, rc: {}, schema_seq_no: {})", - command_handle, schema_handle, error_string(0), x); + command_handle, schema_handle, error_string(0), x); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, + } Err(x) => { warn!("vcx_schema_get_schema_id(command_handle: {}, schema_handle: {}, rc: {}, schema_seq_no: {})", - command_handle, schema_handle, x.to_string(), ""); - cb(command_handle, x.to_error_code(), ptr::null_mut()); - }, + command_handle, schema_handle, x, ""); + cb(command_handle, x.into(), ptr::null_mut()); + } }; Ok(()) @@ -264,23 +261,23 @@ pub extern fn vcx_schema_get_attributes(command_handle: u32, check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); check_useful_c_str!(schema_id, error::INVALID_OPTION.code_num); trace!("vcx_schema_get_attributes(command_handle: {}, source_id: {}, schema_id: {})", - command_handle, source_id, schema_id); + command_handle, source_id, schema_id); - spawn(move|| { + spawn(move || { match schema::get_schema_attrs(source_id, schema_id) { Ok((handle, data)) => { - let data:serde_json::Value = serde_json::from_str(&data).unwrap(); + let data: serde_json::Value = serde_json::from_str(&data).unwrap(); let data = data["data"].clone(); trace!("vcx_schema_get_attributes_cb(command_handle: {}, rc: {}, handle: {}, attrs: {})", - command_handle, error_string(0), handle, data); + command_handle, error_string(0), handle, data); let msg = CStringUtils::string_to_cstring(data.to_string()); cb(command_handle, error::SUCCESS.code_num, handle, msg.as_ptr()); - }, + } Err(x) => { warn!("vcx_schema_get_attributes_cb(command_handle: {}, rc: {}, handle: {}, attrs: {})", - command_handle, error_string(x.to_error_code()), 0, ""); - cb(command_handle, x.to_error_code(), 0, ptr::null_mut()); - }, + command_handle, x, 0, ""); + cb(command_handle, x.into(), 0, ptr::null_mut()); + } }; Ok(()) @@ -309,37 +306,37 @@ pub extern fn vcx_schema_get_attributes(command_handle: u32, /// } #[no_mangle] pub extern fn vcx_schema_get_payment_txn(command_handle: u32, - handle: u32, - cb: Option) -> u32 { + handle: u32, + cb: Option) -> u32 { info!("vcx_schema_get_payment_txn >>>"); check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); trace!("vcx_schema_get_payment_txn(command_handle: {})", command_handle); - spawn(move|| { + spawn(move || { match schema::get_payment_txn(handle) { Ok(x) => { match serde_json::to_string(&x) { Ok(x) => { trace!("vcx_schema_get_payment_txn_cb(command_handle: {}, rc: {}, : {}), source_id: {:?}", - command_handle, error_string(0), x, schema::get_source_id(handle).unwrap_or_default()); + command_handle, error_string(0), x, schema::get_source_id(handle).unwrap_or_default()); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, 0, msg.as_ptr()); } Err(_) => { error!("vcx_schema_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {:?}", - command_handle, error_string(error::INVALID_JSON.code_num), "null", schema::get_source_id(handle).unwrap_or_default()); + command_handle, error::INVALID_JSON.message, "null", schema::get_source_id(handle).unwrap_or_default()); cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); } } - }, + } Err(x) => { error!("vcx_schema_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {:?}", - command_handle, x.to_string(), "null", schema::get_source_id(handle).unwrap_or_default()); - cb(command_handle, x.to_error_code(), ptr::null()); - }, + command_handle, x, "null", schema::get_source_id(handle).unwrap_or_default()); + cb(command_handle, x.into(), ptr::null()); + } }; Ok(()) @@ -361,7 +358,7 @@ mod tests { use std::time::Duration; use settings; #[allow(unused_imports)] - use utils::constants::{ SCHEMA_ID, SCHEMA_WITH_VERSION, DEFAULT_SCHEMA_ATTRS, DEFAULT_SCHEMA_ID, DEFAULT_SCHEMA_NAME }; + use utils::constants::{SCHEMA_ID, SCHEMA_WITH_VERSION, DEFAULT_SCHEMA_ATTRS, DEFAULT_SCHEMA_ID, DEFAULT_SCHEMA_NAME}; use api::return_types_u32; #[test] @@ -369,24 +366,24 @@ mod tests { init!("true"); let cb = return_types_u32::Return_U32_U32::new().unwrap(); assert_eq!(vcx_schema_create(cb.command_handle, - CString::new("Test Source ID").unwrap().into_raw(), - CString::new("Test Schema").unwrap().into_raw(), - CString::new("0.0").unwrap().into_raw(), - CString::new("[att1, att2]").unwrap().into_raw(), - 0, - Some(cb.get_callback())), error::SUCCESS.code_num); + CString::new("Test Source ID").unwrap().into_raw(), + CString::new("Test Schema").unwrap().into_raw(), + CString::new("0.0").unwrap().into_raw(), + CString::new("[att1, att2]").unwrap().into_raw(), + 0, + Some(cb.get_callback())), error::SUCCESS.code_num); let handle = cb.receive(Some(Duration::from_secs(2))).unwrap(); - assert!(handle>0) + assert!(handle > 0) } - #[cfg(feature="pool_tests")] + #[cfg(feature = "pool_tests")] #[test] fn test_vcx_create_schema_with_pool() { init!("ledger"); let data = r#"["name","male"]"#; let schema_name: String = rand::thread_rng().gen_ascii_chars().take(25).collect::(); - let schema_version: String = format!("{}.{}",rand::thread_rng().gen::().to_string(), + let schema_version: String = format!("{}.{}", rand::thread_rng().gen::().to_string(), rand::thread_rng().gen::().to_string()); let cb = return_types_u32::Return_U32_U32::new().unwrap(); @@ -401,7 +398,7 @@ mod tests { let handle = cb.receive(Some(Duration::from_secs(5))).unwrap(); } - #[cfg(feature="pool_tests")] + #[cfg(feature = "pool_tests")] #[test] fn test_vcx_schema_get_attrs_with_pool() { init!("ledger"); @@ -409,9 +406,9 @@ mod tests { let cb = return_types_u32::Return_U32_U32_STR::new().unwrap(); assert_eq!(vcx_schema_get_attributes(cb.command_handle, - CString::new("Test Source ID").unwrap().into_raw(), - CString::new(schema_id).unwrap().into_raw(), - Some(cb.get_callback())), error::SUCCESS.code_num); + CString::new("Test Source ID").unwrap().into_raw(), + CString::new(schema_id).unwrap().into_raw(), + Some(cb.get_callback())), error::SUCCESS.code_num); let (err, attrs) = cb.receive(Some(Duration::from_secs(2))).unwrap(); let mut result_vec = vec!(attrs.clone().unwrap()); @@ -439,7 +436,7 @@ mod tests { fn test_vcx_schema_deserialize_succeeds() { init!("true"); let cb = return_types_u32::Return_U32_U32::new().unwrap(); - let err = vcx_schema_deserialize(cb.command_handle,CString::new(SCHEMA_WITH_VERSION).unwrap().into_raw(), Some(cb.get_callback())); + let err = vcx_schema_deserialize(cb.command_handle, CString::new(SCHEMA_WITH_VERSION).unwrap().into_raw(), Some(cb.get_callback())); assert_eq!(err, error::SUCCESS.code_num); let schema_handle = cb.receive(Some(Duration::from_secs(2))).unwrap(); assert!(schema_handle > 0); @@ -462,7 +459,6 @@ mod tests { assert_eq!(vcx_schema_get_schema_id(cb.command_handle, schema_handle, Some(cb.get_callback())), error::SUCCESS.code_num); let id = cb.receive(Some(Duration::from_secs(2))).unwrap().unwrap(); assert_eq!(DEFAULT_SCHEMA_ID, &id); - } #[test] @@ -477,7 +473,7 @@ mod tests { Some(cb.get_callback())), error::SUCCESS.code_num); let (handle, schema_data_as_string) = cb.receive(Some(Duration::from_secs(2))).unwrap(); let schema_data_as_string = schema_data_as_string.unwrap(); - let schema_as_json:serde_json::Value = serde_json::from_str(&schema_data_as_string).unwrap(); + let schema_as_json: serde_json::Value = serde_json::from_str(&schema_data_as_string).unwrap(); assert_eq!(schema_as_json["data"].to_string(), data); } @@ -486,7 +482,7 @@ mod tests { init!("true"); let cb = return_types_u32::Return_U32_STR::new().unwrap(); let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); - let handle = schema::create_new_schema("testid", did, "name".to_string(),"1.0".to_string(),"[\"name\":\"male\"]".to_string()).unwrap(); + let handle = schema::create_new_schema("testid", did, "name".to_string(), "1.0".to_string(), "[\"name\":\"male\"]".to_string()).unwrap(); let rc = vcx_schema_get_payment_txn(cb.command_handle, handle, Some(cb.get_callback())); let txn = cb.receive(Some(Duration::from_secs(2))).unwrap(); assert!(txn.is_some()); @@ -497,7 +493,7 @@ mod tests { fn test_vcx_schema_serialize_contains_version() { init!("ledger"); let cb = return_types_u32::Return_U32_U32::new().unwrap(); - let schema_name= format!("TestSchema-{}", rand::thread_rng().gen::()); + let schema_name = format!("TestSchema-{}", rand::thread_rng().gen::()); let source_id = "Test Source ID"; assert_eq!(vcx_schema_create(cb.command_handle, CString::new(source_id).unwrap().into_raw(), @@ -515,8 +511,8 @@ mod tests { assert_eq!(vcx_schema_serialize(cb.command_handle, handle, Some(cb.get_callback())), error::SUCCESS.code_num); let data = cb.receive(Some(Duration::from_secs(2))).unwrap().unwrap(); use schema::CreateSchema; - let j:serde_json::Value = serde_json::from_str(&data.clone()).unwrap(); - let schema:CreateSchema = serde_json::from_value(j["data"].clone()).unwrap(); + let j: serde_json::Value = serde_json::from_str(&data.clone()).unwrap(); + let schema: CreateSchema = serde_json::from_value(j["data"].clone()).unwrap(); assert_eq!(j["version"], "1.0"); assert_eq!(schema.get_source_id(), source_id); } @@ -525,7 +521,7 @@ mod tests { fn test_vcx_schema_release() { init!("true"); let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); - let handle = schema::create_new_schema("testid", did, "name".to_string(),"1.0".to_string(),"[\"name\":\"male\"]".to_string()).unwrap(); + let handle = schema::create_new_schema("testid", did, "name".to_string(), "1.0".to_string(), "[\"name\":\"male\"]".to_string()).unwrap(); let unknown_handle = handle + 1; assert_eq!(vcx_schema_release(unknown_handle), error::INVALID_SCHEMA_HANDLE.code_num); } diff --git a/vcx/libvcx/src/api/utils.rs b/vcx/libvcx/src/api/utils.rs index 83916d91c9..4806fe99c9 100644 --- a/vcx/libvcx/src/api/utils.rs +++ b/vcx/libvcx/src/api/utils.rs @@ -77,8 +77,8 @@ pub extern fn vcx_agent_provision_async(command_handle : u32, thread::spawn(move|| { match messages::agent_utils::connect_register_provision(&config) { Err(e) => { - error!("vcx_agent_provision_async_cb(command_handle: {}, rc: {}, config: NULL", command_handle, error_string(e)); - cb(command_handle, e, ptr::null_mut()); + error!("vcx_agent_provision_async_cb(command_handle: {}, rc: {}, config: NULL", command_handle, e); + cb(command_handle, e.into(), ptr::null_mut()); }, Ok(s) => { trace!("vcx_agent_provision_async_cb(command_handle: {}, rc: {}, config: {})", @@ -132,8 +132,8 @@ pub extern fn vcx_agent_update_info(command_handle: u32, }, Err(e) => { error!("vcx_agent_update_info_cb(command_handle: {}, rc: {})", - command_handle, error::error_string(e)); - cb(command_handle, e); + command_handle, e); + cb(command_handle, e.into()); }, }; @@ -173,9 +173,9 @@ pub extern fn vcx_ledger_get_fees(command_handle: u32, }, Err(e) => { warn!("vcx_ledget_get_fees_cb(command_handle: {}, rc: {}, fees: {})", - command_handle, error_string(e), "null"); + command_handle, e, "null"); - cb(command_handle, e, ptr::null_mut()); + cb(command_handle, e.into(), ptr::null_mut()); }, }; @@ -280,9 +280,9 @@ pub extern fn vcx_messages_download(command_handle: u32, }, Err(e) => { warn!("vcx_messages_download_cb(command_handle: {}, rc: {}, messages: {})", - command_handle, error_string(e), "null"); + command_handle, e, "null"); - cb(command_handle, e, ptr::null_mut()); + cb(command_handle, e.into(), ptr::null_mut()); }, }; @@ -331,9 +331,9 @@ pub extern fn vcx_messages_update_status(command_handle: u32, }, Err(e) => { warn!("vcx_messages_set_status_cb(command_handle: {}, rc: {})", - command_handle, error_string(e)); + command_handle, e); - cb(command_handle, e); + cb(command_handle, e.into()); }, }; diff --git a/vcx/libvcx/src/api/vcx.rs b/vcx/libvcx/src/api/vcx.rs index 4430abedba..3d2a64cc25 100644 --- a/vcx/libvcx/src/api/vcx.rs +++ b/vcx/libvcx/src/api/vcx.rs @@ -43,7 +43,7 @@ pub extern fn vcx_init_with_config(command_handle: u32, match settings::process_config_string(&config) { Err(e) => { error!("Invalid configuration specified: {}", e); - return e; + return e.into(); }, Ok(_) => (), } @@ -91,7 +91,7 @@ pub extern fn vcx_init (command_handle: u32, Ok(_) => { match settings::validate_payment_method() { Ok(_) => (), - Err(e) => return e + Err(e) => return e.into() } }, }; @@ -136,7 +136,7 @@ fn _finish_init(command_handle: u32, cb: extern fn(xcommand_handle: u32, err: u3 Ok(_) => (), Err(e) => { error!("Init Pool Error {}.", e); - return Ok(cb(command_handle, e)) + return Ok(cb(command_handle, e.into())) }, } } @@ -149,7 +149,7 @@ fn _finish_init(command_handle: u32, cb: extern fn(xcommand_handle: u32, err: u3 }, Err(e) => { error!("Init Wallet Error {}.", e); - cb(command_handle, e); + cb(command_handle, e.into()); } } Ok(()) diff --git a/vcx/libvcx/src/api/wallet.rs b/vcx/libvcx/src/api/wallet.rs index b1015a3cbe..dfed0ad29b 100644 --- a/vcx/libvcx/src/api/wallet.rs +++ b/vcx/libvcx/src/api/wallet.rs @@ -4,7 +4,6 @@ use self::libc::c_char; use utils::cstring::CStringUtils; use utils::error; use utils::error::error_string; -use error::ToErrorCode; use utils::libindy::payments::{pay_a_payee, get_wallet_token_info, create_address}; use utils::libindy::wallet::{export, import, get_wallet_handle}; use utils::libindy::wallet; @@ -40,17 +39,17 @@ pub extern fn vcx_wallet_get_token_info(command_handle: u32, match get_wallet_token_info() { Ok(x) => { trace!("vcx_wallet_get_token_info_cb(command_handle: {}, rc: {}, info: {})", - command_handle, error_string(0), x.to_string()); + command_handle, 0, x); let msg = CStringUtils::string_to_cstring(x.to_string()); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); }, Err(x) => { warn!("vcx_wallet_get_token_info_cb(command_handle: {}, rc: {}, info: {})", - command_handle, error_string(x), "null"); + command_handle, x, "null"); let msg = CStringUtils::string_to_cstring("".to_string()); - cb(command_handle, x, msg.as_ptr()); + cb(command_handle, x.into(), msg.as_ptr()); }, }; @@ -97,10 +96,10 @@ pub extern fn vcx_wallet_create_payment_address(command_handle: u32, }, Err(x) => { warn!("vcx_wallet_create_payment_address_cb(command_handle: {}, rc: {}, address: {})", - command_handle, error_string(x), "null"); + command_handle, x, "null"); let msg = CStringUtils::string_to_cstring("".to_string()); - cb(command_handle, x, msg.as_ptr()); + cb(command_handle, x.into(), msg.as_ptr()); }, }; @@ -167,9 +166,9 @@ pub extern fn vcx_wallet_add_record(command_handle: u32, }, Err(x) => { trace!("vcx_wallet_add_record(command_handle: {}, rc: {})", - command_handle, error_string(x)); + command_handle, x); - cb(command_handle, x); + cb(command_handle, x.into()); }, }; @@ -223,9 +222,9 @@ pub extern fn vcx_wallet_update_record_value(command_handle: u32, }, Err(x) => { trace!("vcx_wallet_update_record_value(command_handle: {}, rc: {})", - command_handle, error_string(x)); + command_handle, x); - cb(command_handle, x); + cb(command_handle, x.into()); }, }; @@ -407,10 +406,10 @@ pub extern fn vcx_wallet_get_record(command_handle: u32, }, Err(x) => { trace!("vcx_wallet_get_record(command_handle: {}, rc: {}, record_json: {})", - command_handle, error_string(x), "null"); + command_handle, x, "null"); let msg = CStringUtils::string_to_cstring("".to_string()); - cb(command_handle, x, msg.as_ptr()); + cb(command_handle, x.into(), msg.as_ptr()); }, }; @@ -461,9 +460,9 @@ pub extern fn vcx_wallet_delete_record(command_handle: u32, }, Err(x) => { trace!("vcx_wallet_delete_record(command_handle: {}, rc: {})", - command_handle, error_string(x)); + command_handle, x); - cb(command_handle, x); + cb(command_handle, x.into()); }, }; @@ -520,9 +519,9 @@ pub extern fn vcx_wallet_send_tokens(command_handle: u32, }, Err(e) => { let msg = "Failed to send tokens".to_string(); - trace!("vcx_wallet_send_tokens_cb(command_handle: {}, rc: {}, reciept: {})", command_handle, e.to_error_code(), msg); + trace!("vcx_wallet_send_tokens_cb(command_handle: {}, rc: {}, reciept: {})", command_handle, e, msg); let msg = CStringUtils::string_to_cstring("".to_string()); - cb(command_handle, e.to_error_code(), msg.as_ptr()); + cb(command_handle, e.into(), msg.as_ptr()); }, }; @@ -696,9 +695,8 @@ pub extern fn vcx_wallet_export(command_handle: u32, cb(command_handle, return_code); } Err(e) => { - let return_code = e.to_error_code(); - warn!("vcx_wallet_export(command_handle: {}, rc: {})", command_handle, return_code); - cb(command_handle, return_code); + warn!("vcx_wallet_export(command_handle: {}, rc: {})", command_handle, e); + cb(command_handle, e.into()); } }; @@ -745,9 +743,8 @@ pub extern fn vcx_wallet_import(command_handle: u32, cb(command_handle, return_code); } Err(e) => { - let return_code = e.to_error_code(); - warn!("vcx_wallet_import(command_handle: {}, rc: {})", command_handle, return_code); - cb(command_handle, return_code); + warn!("vcx_wallet_import(command_handle: {}, rc: {})", command_handle, e); + cb(command_handle, e.into()); } }; }); diff --git a/vcx/libvcx/src/connection.rs b/vcx/libvcx/src/connection.rs index 591d53e8fc..107e1bddf6 100644 --- a/vcx/libvcx/src/connection.rs +++ b/vcx/libvcx/src/connection.rs @@ -18,11 +18,11 @@ use messages::payload::{Payloads, Thread}; use messages::get_message::Message; use serde_json::Value; use utils::json::KeyMatch; -use error::connection::ConnectionError; -use error::ToErrorCode; use object_cache::ObjectCache; use utils::constants::DEFAULT_SERIALIZE_VERSION; use std::collections::HashMap; +use error::prelude::*; +use messages::ObjectWithVersion; lazy_static! { static ref CONNECTION_MAP: ObjectCache = Default::default(); @@ -47,7 +47,7 @@ impl Default for ConnectionOptions { } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] struct Connection { source_id: String, pw_did: String, @@ -69,7 +69,7 @@ struct Connection { impl Connection { - fn _connect_send_invite(&mut self, options: &ConnectionOptions) -> Result { + fn _connect_send_invite(&mut self, options: &ConnectionOptions) -> VcxResult { debug!("sending invite for connection {}", self.source_id); let (invite, url) = @@ -90,7 +90,7 @@ impl Connection { Ok(error::SUCCESS.code_num) } - pub fn delete_connection(&mut self) -> Result { + pub fn delete_connection(&mut self) -> VcxResult { trace!("Connection::delete_connection >>>"); messages::delete_connection() @@ -105,7 +105,7 @@ impl Connection { Ok(error::SUCCESS.code_num) } - fn _connect_accept_invite(&mut self) -> Result { + fn _connect_accept_invite(&mut self) -> VcxResult { debug!("accepting invite for connection {}", self.source_id); let details: &InviteDetail = self.invite_detail.as_ref() @@ -113,7 +113,7 @@ impl Connection { warn!("{} can not connect without invite details", self.source_id); // TODO: Refactor Error // TODO: Implement Correct Error - ConnectionError::GeneralConnectionError() + VcxError::from_msg(VcxErrorKind::GeneralConnectionError, "Invite details not found") })?; messages::accept_invite() @@ -125,14 +125,14 @@ impl Connection { .sender_agency_details(&details.sender_agency_detail)? .answer_status_code(&MessageStatusCode::Accepted)? .reply_to(&details.conn_req_id)? - .thread(&self._build_thread(&details))? + .thread(&self._build_thread_accept_invite(&details))? .send_secure()?; self.state = VcxStateType::VcxStateAccepted; Ok(error::SUCCESS.code_num) } - fn _build_thread(&self, invite_detail: &InviteDetail) -> Thread { + fn _build_thread_accept_invite(&self, invite_detail: &InviteDetail) -> Thread { let mut received_orders = HashMap::new(); received_orders.insert(invite_detail.sender_detail.did.clone(), 0); @@ -144,7 +144,7 @@ impl Connection { } } - fn connect(&mut self, options: &ConnectionOptions) -> Result { + fn connect(&mut self, options: &ConnectionOptions) -> VcxResult { trace!("Connection::connect >>> options: {:?}", options); match self.state { VcxStateType::VcxStateInitialized @@ -154,7 +154,7 @@ impl Connection { warn!("connection {} in state {} not ready to connect", self.source_id, self.state as u32); // TODO: Refactor Error // TODO: Implement Correct Error - Err(ConnectionError::GeneralConnectionError()) + Err(VcxError::from_msg(VcxErrorKind::GeneralConnectionError, "Connection is not ready to connect")) } } } @@ -201,29 +201,22 @@ impl Connection { fn get_source_id(&self) -> &String { &self.source_id } fn ready_to_connect(&self) -> bool { - if self.state == VcxStateType::VcxStateNone || self.state == VcxStateType::VcxStateAccepted { - false - } else { - true - } + self.state != VcxStateType::VcxStateNone && self.state != VcxStateType::VcxStateAccepted } - fn from_str(s: &str) -> Result { - let s: Value = serde_json::from_str(&s) - .or(Err(ConnectionError::InvalidJson()))?; - let connection: Connection = serde_json::from_value(s["data"].clone()) - .or(Err(ConnectionError::InvalidJson()))?; - Ok(connection) + fn from_str(data: &str) -> VcxResult { + ObjectWithVersion::deserialize(data) + .map(|obj: ObjectWithVersion| obj.data) + .map_err(|err| err.extend("Cannot deserialize Connection")) } - fn to_string(&self) -> String { - json!({ - "version": DEFAULT_SERIALIZE_VERSION, - "data": json!(self), - }).to_string() + fn to_string(&self) -> VcxResult { + ObjectWithVersion::new(DEFAULT_SERIALIZE_VERSION, self.to_owned()) + .serialize() + .map_err(|err| err.extend("Cannot serialize Connection")) } - fn create_agent_pairwise(&mut self) -> Result { + fn create_agent_pairwise(&mut self) -> VcxResult { debug!("creating pairwise keys on agent for connection {}", self.source_id); let (for_did, for_verkey) = messages::create_keys() @@ -238,18 +231,18 @@ impl Connection { Ok(error::SUCCESS.code_num) } - fn update_agent_profile(&mut self, options: &ConnectionOptions) -> Result { + fn update_agent_profile(&mut self, options: &ConnectionOptions) -> VcxResult { debug!("updating agent config for connection {}", self.source_id); if let Some(true) = options.use_public_did { - self.public_did = Some(settings::get_config_value(settings::CONFIG_INSTITUTION_DID).map_err(|e| ConnectionError::CommonError(e))?); + self.public_did = Some(settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?); }; if let Ok(name) = settings::get_config_value(settings::CONFIG_INSTITUTION_NAME) { messages::update_data() .to(&self.pw_did)? .name(&name)? - .logo_url(&settings::get_config_value(settings::CONFIG_INSTITUTION_LOGO_URL).map_err(|e| ConnectionError::CommonError(e))?)? + .logo_url(&settings::get_config_value(settings::CONFIG_INSTITUTION_LOGO_URL)?)? .use_public_did(&self.public_did)? .send_secure()?; } @@ -262,124 +255,113 @@ pub fn is_valid_handle(handle: u32) -> bool { CONNECTION_MAP.has_handle(handle) } -pub fn set_agent_did(handle: u32, did: &str) -> Result<(), ConnectionError> { +pub fn set_agent_did(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_agent_did(did); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_agent_did(did)) + }) } -pub fn get_agent_did(handle: u32) -> Result { +pub fn get_agent_did(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_agent_did().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + }) } -pub fn get_pw_did(handle: u32) -> Result { +pub fn get_pw_did(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_pw_did().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + }) } -pub fn set_pw_did(handle: u32, did: &str) -> Result<(), ConnectionError> { +pub fn set_pw_did(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_pw_did(did); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_pw_did(did)) + }) } -pub fn get_their_pw_did(handle: u32) -> Result { +pub fn get_their_pw_did(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { - Ok(cxn.get_their_pw_did().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.get_their_pw_did().to_string()) + }) } -pub fn set_their_pw_did(handle: u32, did: &str) -> Result<(), ConnectionError> { +pub fn set_their_pw_did(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_their_pw_did(did); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_their_pw_did(did)) + }) } -pub fn set_their_public_did(handle: u32, did: &str) -> Result<(), ConnectionError> { +pub fn set_their_public_did(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_their_public_did(did); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_their_public_did(did)) + }) } -pub fn get_their_public_did(handle: u32) -> Result, ConnectionError> { +pub fn get_their_public_did(handle: u32) -> VcxResult> { CONNECTION_MAP.get(handle, |cxn| { - Ok(cxn.get_their_public_did().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.get_their_public_did()) + }) } -pub fn get_their_pw_verkey(handle: u32) -> Result { +pub fn get_their_pw_verkey(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { - Ok(cxn.get_their_pw_verkey().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.get_their_pw_verkey().to_string()) + }) } -pub fn set_their_pw_verkey(handle: u32, did: &str) -> Result<(), ConnectionError> { +pub fn set_their_pw_verkey(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_their_pw_verkey(did); - Ok(()) - }).map_err(|e| { - ConnectionError::InvalidHandle() + Ok(cxn.set_their_pw_verkey(did)) }) } -pub fn get_uuid(handle: u32) -> Result { +pub fn get_uuid(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { - Ok(cxn.get_uuid().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.get_uuid().to_string()) + }) } -pub fn set_uuid(handle: u32, uuid: &str) -> Result<(), ConnectionError> { +pub fn set_uuid(handle: u32, uuid: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_uuid(uuid); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_uuid(uuid)) + }) } // TODO: Add NO_ENDPOINT error to connection error -pub fn get_endpoint(handle: u32) -> Result { +pub fn get_endpoint(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_endpoint().clone()) - }).or(Err(error::NO_ENDPOINT.code_num)) + }).or(Err(VcxError::from(VcxErrorKind::NoEndpoint))) } -pub fn set_endpoint(handle: u32, endpoint: &str) -> Result<(), ConnectionError> { +pub fn set_endpoint(handle: u32, endpoint: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_endpoint(endpoint); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_endpoint(endpoint)) + }) } -pub fn get_agent_verkey(handle: u32) -> Result { +pub fn get_agent_verkey(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_agent_verkey().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + }) } -pub fn set_agent_verkey(handle: u32, verkey: &str) -> Result<(), ConnectionError> { +pub fn set_agent_verkey(handle: u32, verkey: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_agent_verkey(verkey); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_agent_verkey(verkey)) + }) } -pub fn get_pw_verkey(handle: u32) -> Result { +pub fn get_pw_verkey(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_pw_verkey().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + }) } -pub fn set_pw_verkey(handle: u32, verkey: &str) -> Result<(), ConnectionError> { +pub fn set_pw_verkey(handle: u32, verkey: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_pw_verkey(verkey); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_pw_verkey(verkey)) + }) } pub fn get_state(handle: u32) -> u32 { @@ -393,22 +375,21 @@ pub fn get_state(handle: u32) -> u32 { } } -pub fn set_state(handle: u32, state: VcxStateType) -> Result<(), ConnectionError> { +pub fn set_state(handle: u32, state: VcxStateType) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { - cxn.set_state(state); - Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + Ok(cxn.set_state(state)) + }) } -pub fn get_source_id(handle: u32) -> Result { +pub fn get_source_id(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_source_id().clone()) - }).or(Err(ConnectionError::InvalidHandle())) + }) } -pub fn create_connection(source_id: &str) -> Result { +pub fn create_connection(source_id: &str) -> VcxResult { trace!("create_connection >>> source_id: {}", source_id); - let (pw_did, pw_verkey) = create_and_store_my_did(None).map_err(|ec| ConnectionError::CommonError(ec))?; + let (pw_did, pw_verkey) = create_and_store_my_did(None)?; debug!("did: {} verkey: {}, source id: {}", pw_did, pw_verkey, source_id); @@ -428,23 +409,24 @@ pub fn create_connection(source_id: &str) -> Result { public_did: None, their_public_did: None, }; - let new_handle = CONNECTION_MAP.add(c).map_err(|key| ConnectionError::CreateError(key))?; - Ok(new_handle) + CONNECTION_MAP.add(c) + .map_err(|_| VcxError::from_msg(VcxErrorKind::CreateConnection, "Cannot create connection")) } -pub fn create_connection_with_invite(source_id: &str, details: &str) -> Result { +pub fn create_connection_with_invite(source_id: &str, details: &str) -> VcxResult { debug!("create connection {} with invite {}", source_id, details); let details: Value = serde_json::from_str(&details) - .or(Err(ConnectionError::CommonError(error::INVALID_JSON.code_num)))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize invite")))?; let invite_details: InviteDetail = match serde_json::from_value(details.clone()) { Ok(x) => x, Err(x) => { // Try converting to abbreviated - let details = unabbrv_event_detail(details).or(Err(ConnectionError::CommonError(error::INVALID_JSON.code_num)))?; - let invite_details = serde_json::from_value(details).or(Err(ConnectionError::CommonError(error::INVALID_JSON.code_num)))?; + let details = unabbrv_event_detail(details)?; + let invite_details = serde_json::from_value(details) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize invite detail")))?; invite_details } }; @@ -463,40 +445,41 @@ pub fn create_connection_with_invite(source_id: &str, details: &str) -> Result Result { +pub fn parse_acceptance_details(handle: u32, message: &Message) -> VcxResult { debug!("connection {} parsing acceptance details for message {:?}", get_source_id(handle).unwrap_or_default(), message); let my_vk = settings::get_config_value(settings::CONFIG_SDK_TO_REMOTE_VERKEY)?; let payload = message.payload .as_ref() - .ok_or(ConnectionError::CommonError(error::INVALID_MSGPACK.code_num))?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidMessagePack, "Payload not found"))?; match settings::ProtocolTypes::from(settings::get_protocol_type()) { settings::ProtocolTypes::V1 => { let payload = messages::to_u8(&payload); // TODO: check returned verkey - let (_, payload) = crypto::parse_msg(&my_vk, &payload).map_err(|e| { ConnectionError::CommonError(e) })?; + let (_, payload) = crypto::parse_msg(&my_vk, &payload)?; let response: ConnectionPayload = rmp_serde::from_slice(&payload[..]) .map_err(|err| { error!("Could not parse outer msg: {}", err); - ConnectionError::CommonError(error::INVALID_MSGPACK.code_num) + VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot parse payload: {}", err)) })?; let payload = messages::to_u8(&response.msg); // TODO: Refactor Error - messages::invite::parse_invitation_acceptance_details(payload).map_err(|e| { ConnectionError::CommonError(e) }) + messages::invite::parse_invitation_acceptance_details(payload) } settings::ProtocolTypes::V2 => { let (payload, _) = Payloads::decrypt_payload_v2(&my_vk, &payload)?; - let response: AcceptanceDetails = serde_json::from_str(&payload).or(Err(error::INVALID_JSON.code_num))?; + let response: AcceptanceDetails = serde_json::from_str(&payload) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize AcceptanceDetails: {}", err)))?; Ok(response.sender_detail) } } } -pub fn update_state(handle: u32) -> Result { +pub fn update_state(handle: u32) -> VcxResult { debug!("updating state for connection {}", get_source_id(handle).unwrap_or_default()); let state = get_state(handle); @@ -520,7 +503,7 @@ pub fn update_state(handle: u32) -> Result { .map_err(|err| { error!("could not update state for handle {}: {}", handle, err); // TODO: Refactor Error - ConnectionError::CommonError(error::POST_MSG_FAILURE.code_num) + VcxError::from_msg(VcxErrorKind::PostMessageFailed, format!("Could not update state for handle {}", handle)) })?; debug!("connection {} update state response: {:?}", get_source_id(handle).unwrap_or_default(), response); @@ -539,95 +522,86 @@ pub fn update_state(handle: u32) -> Result { Ok(error::SUCCESS.code_num) } -pub fn delete_connection(handle: u32) -> Result { +pub fn delete_connection(handle: u32) -> VcxResult { CONNECTION_MAP.get_mut(handle, |t| { debug!("delete connection: {}", t.get_source_id()); - match t.delete_connection() { - Ok(x) => Ok(x), - Err(e) => { - return Err(e.to_error_code()); - } - } + t.delete_connection() }) - .or(Err(ConnectionError::CannotDeleteConnection())) + .or(Err(VcxError::from(VcxErrorKind::DeleteConnection))) .and(release(handle)) .and_then(|_| Ok(error::SUCCESS.code_num)) } -pub fn connect(handle: u32, options: Option) -> Result { +pub fn connect(handle: u32, options: Option) -> VcxResult { let options_obj: ConnectionOptions = match options.as_ref().map(|opt| opt.trim()) { None => ConnectionOptions::default(), Some(opt) if opt.is_empty() => ConnectionOptions::default(), Some(opt) => { serde_json::from_str(&opt) - .or(Err(ConnectionError::CommonError(error::INVALID_OPTION.code_num)))? + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidOption, format!("Cannot deserialize ConnectionOptions: {}", err)))? } }; CONNECTION_MAP.get_mut(handle, |t| { debug!("establish connection {}", t.get_source_id()); - t.create_agent_pairwise().map_err(|ec| ec.to_error_code())?; - t.update_agent_profile(&options_obj).map_err(|ec| ec.to_error_code())?; - t.connect(&options_obj).map_err(|ec| ec.to_error_code()) - }).map_err(|ec| ConnectionError::CommonError(ec)) + t.create_agent_pairwise()?; + t.update_agent_profile(&options_obj)?; + t.connect(&options_obj) + }) } -pub fn to_string(handle: u32) -> Result { +pub fn to_string(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |t| { // TODO: Make this an error.to_error_code and back again? - Ok(Connection::to_string(&t)) - }).or(Err(error::INVALID_CONNECTION_HANDLE.code_num)) + Connection::to_string(&t) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } -pub fn from_string(connection_data: &str) -> Result { +pub fn from_string(connection_data: &str) -> VcxResult { let derived_connection: Connection = Connection::from_str(connection_data)?; - let new_handle = CONNECTION_MAP.add(derived_connection).map_err(|ec| ConnectionError::CommonError(ec))?; + let new_handle = CONNECTION_MAP.add(derived_connection)?; debug!("inserting handle {} source_id {} into connection table", new_handle, get_source_id(new_handle).unwrap_or_default()); Ok(new_handle) } -pub fn release(handle: u32) -> Result<(), ConnectionError> { - match CONNECTION_MAP.release(handle) { - Ok(_) => Ok(()), - Err(_) => Err(ConnectionError::InvalidHandle()) - } +pub fn release(handle: u32) -> VcxResult<()> { + CONNECTION_MAP.release(handle) + .or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn release_all() { - match CONNECTION_MAP.drain() { - Ok(_) => (), - // TODO: This needs to be better - Err(_) => (), - }; + CONNECTION_MAP.drain().ok(); } -pub fn get_invite_details(handle: u32, abbreviated: bool) -> Result { +pub fn get_invite_details(handle: u32, abbreviated: bool) -> VcxResult { debug!("get invite details for connection {}", get_source_id(handle).unwrap_or_default()); CONNECTION_MAP.get(handle, |t| { match abbreviated { false => { - Ok(serde_json::to_string(&t.invite_detail) - .or(Err(ConnectionError::InviteDetailError()))) + serde_json::to_string(&t.invite_detail) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidInviteDetail, format!("Cannot serialize InviteDetail: {}", err))) } true => { - let details = serde_json::to_value(&t.invite_detail).or(Err(ConnectionError::InviteDetailError().to_error_code()))?; + let details = serde_json::to_value(&t.invite_detail) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidInviteDetail, format!("Cannot serialize InviteDetail: {}", err)))?; let abbr = abbrv_event_detail(details)?; - Ok(serde_json::to_string(&abbr).or(Err(ConnectionError::InviteDetailError()))) + serde_json::to_string(&abbr) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidInviteDetail, format!("Cannot serialize InviteDetail: {}", err))) } } - }).or(Err(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num)))? + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } -pub fn set_invite_details(handle: u32, invite_detail: &InviteDetail) -> Result<(), ConnectionError> { +pub fn set_invite_details(handle: u32, invite_detail: &InviteDetail) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { cxn.set_invite_detail(invite_detail.clone()); // TODO: Verify that this is ok to do...seems not rusty. Ok(()) - }).or(Err(ConnectionError::InvalidHandle())) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } //********** @@ -700,12 +674,13 @@ lazy_static! { }; } -fn abbrv_event_detail(val: Value) -> Result { +fn abbrv_event_detail(val: Value) -> VcxResult { mapped_key_rewrite(val, &ABBREVIATIONS) } -fn unabbrv_event_detail(val: Value) -> Result { +fn unabbrv_event_detail(val: Value) -> VcxResult { mapped_key_rewrite(val, &UNABBREVIATIONS) + .map_err(|err| VcxError::from_msg(VcxErrorKind::Common(err.into()), "Cannot unabbreviate event detail")) } diff --git a/vcx/libvcx/src/credential.rs b/vcx/libvcx/src/credential.rs index 5cc55363f4..6d7fcb2717 100644 --- a/vcx/libvcx/src/credential.rs +++ b/vcx/libvcx/src/credential.rs @@ -12,7 +12,7 @@ use issuer_credential::{CredentialOffer, CredentialMessage, PaymentInfo}; use credential_request::CredentialRequest; use messages; -use messages::{GeneralMessage, RemoteMessageType}; +use messages::{GeneralMessage, RemoteMessageType, ObjectWithVersion}; use messages::payload::{Payloads, PayloadKinds, Thread}; use utils::libindy::anoncreds::{libindy_prover_create_credential_req, libindy_prover_store_credential}; @@ -24,8 +24,8 @@ use connection; use settings; use utils::constants::DEFAULT_SERIALIZE_VERSION; -use error::{ToErrorCode, credential::CredentialError}; use serde_json::Value; +use error::prelude::*; lazy_static! { @@ -57,7 +57,7 @@ impl Default for Credential { } } -#[derive(Serialize, Deserialize, Debug, PartialEq)] +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Credential { source_id: String, state: VcxStateType, @@ -80,15 +80,15 @@ pub struct Credential { } impl Credential { - pub fn build_request(&self, my_did: &str, their_did: &str) -> Result { + pub fn build_request(&self, my_did: &str, their_did: &str) -> VcxResult { trace!("Credential::build_request >>> my_did: {}, their_did: {}", my_did, their_did); if self.state != VcxStateType::VcxStateRequestReceived { - return Err(CredentialError::NotReady()); + return Err(VcxError::from_msg(VcxErrorKind::NotReady, format!("credential {} has invalid state {} for sending credentialRequest", self.source_id, self.state as u32))); } - let prover_did = self.my_did.as_ref().ok_or(CredentialError::CommonError(error::INVALID_DID.code_num))?; - let credential_offer = self.credential_offer.as_ref().ok_or(CredentialError::InvalidCredentialJson())?; + let prover_did = self.my_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidDid))?; + let credential_offer = self.credential_offer.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredential))?; let (cred_def_id, cred_def_json) = anoncreds::get_cred_def_json(&credential_offer.cred_def_id)?; @@ -114,16 +114,16 @@ impl Credential { }) } - fn send_request(&mut self, connection_handle: u32) -> Result { + fn send_request(&mut self, connection_handle: u32) -> VcxResult { trace!("Credential::send_request >>> connection_handle: {}", connection_handle); debug!("sending credential request {} via connection: {}", self.source_id, connection::get_source_id(connection_handle).unwrap_or_default()); - self.my_did = Some(connection::get_pw_did(connection_handle).map_err(|ec| CredentialError::CommonError(ec.to_error_code()))?); - self.my_vk = Some(connection::get_pw_verkey(connection_handle).map_err(|ec| CredentialError::CommonError(ec.to_error_code()))?); - self.agent_did = Some(connection::get_agent_did(connection_handle).map_err(|ec| CredentialError::CommonError(ec.to_error_code()))?); - self.agent_vk = Some(connection::get_agent_verkey(connection_handle).map_err(|ec| CredentialError::CommonError(ec.to_error_code()))?); - self.their_did = Some(connection::get_their_pw_did(connection_handle).map_err(|ec| CredentialError::CommonError(ec.to_error_code()))?); - self.their_vk = Some(connection::get_their_pw_verkey(connection_handle).map_err(|ec| CredentialError::CommonError(ec.to_error_code()))?); + self.my_did = Some(connection::get_pw_did(connection_handle)?); + self.my_vk = Some(connection::get_pw_verkey(connection_handle)?); + self.agent_did = Some(connection::get_agent_did(connection_handle)?); + self.agent_vk = Some(connection::get_agent_verkey(connection_handle)?); + self.their_did = Some(connection::get_their_pw_did(connection_handle)?); + self.their_vk = Some(connection::get_their_pw_verkey(connection_handle)?); debug!("verifier_did: {:?} -- verifier_vk: {:?} -- agent_did: {:?} -- agent_vk: {:?} -- remote_vk: {:?}", self.my_did, @@ -132,21 +132,22 @@ impl Credential { self.their_vk, self.my_vk); - let local_their_did = self.their_did.as_ref().ok_or(CredentialError::InvalidHandle())?; - let local_their_vk = self.their_vk.as_ref().ok_or(CredentialError::InvalidHandle())?; - let local_agent_did = self.agent_did.as_ref().ok_or(CredentialError::InvalidHandle())?; - let local_agent_vk = self.agent_vk.as_ref().ok_or(CredentialError::InvalidHandle())?; - let local_my_did = self.my_did.as_ref().ok_or(CredentialError::InvalidHandle())?; - let local_my_vk = self.my_vk.as_ref().ok_or(CredentialError::InvalidHandle())?; + let local_their_did = self.their_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let local_their_vk = self.their_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let local_agent_did = self.agent_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let local_agent_vk = self.agent_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let local_my_did = self.my_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let local_my_vk = self.my_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; // if test mode, just get this. let cred_req: CredentialRequest = self.build_request(local_my_did, local_their_did)?; - let cred_req_json = serde_json::to_string(&cred_req).or(Err(CredentialError::InvalidCredentialJson()))?; + let cred_req_json = serde_json::to_string(&cred_req) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidCredential, format!("Cannot serialize CredentialRequest: {}", err)))?; self.credential_request = Some(cred_req); let offer_msg_id = self.credential_offer.as_ref().and_then(|offer| offer.msg_ref_id.clone()) - .ok_or(CredentialError::CommonError(error::CREATE_CREDENTIAL_REQUEST_ERROR.code_num))?; + .ok_or(VcxError::from(VcxErrorKind::CreateCredentialRequest))?; if self.payment_info.is_some() { let (payment_txn, _) = self.submit_payment()?; @@ -174,14 +175,12 @@ impl Credential { return Ok(error::SUCCESS.code_num); } - fn _check_msg(&mut self) -> Result<(), u32> { - let e_code: u32 = error::INVALID_CONNECTION_HANDLE.code_num; - - let agent_did = self.agent_did.as_ref().ok_or(e_code)?; - let agent_vk = self.agent_vk.as_ref().ok_or(e_code)?; - let my_did = self.my_did.as_ref().ok_or(e_code)?; - let my_vk = self.my_vk.as_ref().ok_or(e_code)?; - let msg_uid = self.msg_uid.as_ref().ok_or(e_code)?; + fn _check_msg(&mut self) -> VcxResult<()> { + let agent_did = self.agent_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let agent_vk = self.agent_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let my_did = self.my_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let my_vk = self.my_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; + let msg_uid = self.msg_uid.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; let (_, payload) = messages::get_message::get_ref_msg(msg_uid, my_did, my_vk, agent_did, agent_vk)?; @@ -192,10 +191,10 @@ impl Credential { } let credential_msg: CredentialMessage = serde_json::from_str(&credential) - .or(Err(error::INVALID_CREDENTIAL_JSON.code_num))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidCredential, format!("Cannot deserialize CredentialMessage: {}", err)))?; let cred_req: &CredentialRequest = self.credential_request.as_ref() - .ok_or(CredentialError::InvalidCredentialJson().to_error_code())?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidCredential, "Cannot find CredentialRequest"))?; let (_, cred_def_json) = anoncreds::get_cred_def_json(&cred_req.cred_def_id)?; @@ -206,7 +205,7 @@ impl Credential { &cred_def_json, match credential_msg.rev_reg_def_json.len() { 0 => None, - _ => Some(credential_msg.rev_reg_def_json), + _ => Some(&credential_msg.rev_reg_def_json), })?); self.state = VcxStateType::VcxStateAccepted; @@ -236,36 +235,34 @@ impl Credential { state } - fn get_credential(&self) -> Result { + fn get_credential(&self) -> VcxResult { trace!("Credential::get_credential >>>"); if self.state != VcxStateType::VcxStateAccepted { - return Err(CredentialError::InvalidState()); + return Err(VcxError::from(VcxErrorKind::InvalidState)); } - let credential = self.credential.as_ref().ok_or(CredentialError::InvalidState())?; + let credential = self.credential.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidState))?; Ok(self.to_cred_string(&credential)) } - fn get_credential_offer(&self) -> Result { + fn get_credential_offer(&self) -> VcxResult { trace!("Credential::get_credential_offer >>>"); if self.state != VcxStateType::VcxStateRequestReceived { - return Err(CredentialError::InvalidState()); + return Err(VcxError::from(VcxErrorKind::InvalidState)); } - let credential_offer = self.credential_offer.as_ref().ok_or(CredentialError::InvalidState())?; - let credential_offer_json = serde_json::to_string(credential_offer).or(Err(CredentialError::InvalidCredentialJson()))?; + let credential_offer = self.credential_offer.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidState))?; + let credential_offer_json = serde_json::to_string(credential_offer) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidCredential, format!("Cannot deserialize CredentilOffer: {}", err)))?; Ok(self.to_cred_offer_string(&credential_offer_json)) } fn get_credential_id(&self) -> String { - match self.cred_id.as_ref() { - Some(cid) => cid.to_string(), - None => "".to_string(), - } + self.cred_id.as_ref().map(String::as_str).unwrap_or("").to_string() } fn set_payment_info(&self, json: &mut serde_json::Map) { @@ -300,12 +297,12 @@ impl Credential { fn get_source_id(&self) -> &String { &self.source_id } - fn get_payment_txn(&self) -> Result { + fn get_payment_txn(&self) -> VcxResult { trace!("Credential::get_payment_txn >>>"); match (&self.payment_txn, &self.payment_info) { (Some(ref payment_txn), Some(_)) => Ok(payment_txn.clone()), - _ => Err(error::NO_PAYMENT_INFORMATION.code_num) + _ => Err(VcxError::from(VcxErrorKind::NoPaymentInformation)) } } @@ -317,52 +314,49 @@ impl Credential { self.payment_info.is_some() } - fn submit_payment(&self) -> Result<(PaymentTxn, String), CredentialError> { + fn submit_payment(&self) -> VcxResult<(PaymentTxn, String)> { debug!("{} submitting payment for premium credential", self.source_id); match &self.payment_info { &Some(ref pi) => { - let address = &pi.get_address()?; - let price = pi.get_price()?; + let address = &pi.get_address(); + let price = pi.get_price(); let (payment_txn, receipt) = pay_a_payee(price, address)?; Ok((payment_txn, receipt)) } - &None => Err(CredentialError::NoPaymentInformation()), + &None => Err(VcxError::from(VcxErrorKind::NoPaymentInformation)), } } - fn get_payment_info(&self) -> Result, CredentialError> { + fn get_payment_info(&self) -> VcxResult> { trace!("Credential::get_payment_info >>>"); Ok(self.payment_info.clone()) } - fn to_string(&self) -> String { - json!({ - "version": DEFAULT_SERIALIZE_VERSION, - "data": json!(self), - }).to_string() + fn to_string(&self) -> VcxResult { + ObjectWithVersion::new(DEFAULT_SERIALIZE_VERSION, self.to_owned()) + .serialize() + .map_err(|err| err.extend("Cannot serialize Credential")) } - fn from_str(s: &str) -> Result { - let s: Value = serde_json::from_str(&s) - .or(Err(CredentialError::InvalidCredentialJson()))?; - let obj: Credential = serde_json::from_value(s["data"].clone()) - .or(Err(CredentialError::InvalidCredentialJson()))?; - Ok(obj) + fn from_str(data: &str) -> VcxResult { + ObjectWithVersion::deserialize(data) + .map(|obj: ObjectWithVersion| obj.data) + .map_err(|err| err.extend("Cannot deserialize Schema")) } } //******************************************** // HANDLE FUNCTIONS //******************************************** -fn handle_err(code_num: u32) -> CredentialError { - if code_num == error::INVALID_OBJ_HANDLE.code_num { - CredentialError::InvalidHandle() +fn handle_err(err: VcxError) -> VcxError { + if err.kind() == VcxErrorKind::InvalidHandle { + VcxError::from(VcxErrorKind::InvalidCredentialHandle) } else { - CredentialError::CommonError(code_num) + err } } -pub fn credential_create_with_offer(source_id: &str, offer: &str) -> Result { +pub fn credential_create_with_offer(source_id: &str, offer: &str) -> VcxResult { trace!("credential_create_with_offer >>> source_id: {}, offer: {}", source_id, offer); let mut new_credential = _credential_create(source_id); @@ -374,7 +368,7 @@ pub fn credential_create_with_offer(source_id: &str, offer: &str) -> Result Credential { @@ -386,7 +380,7 @@ fn _credential_create(source_id: &str) -> Credential { new_credential } -pub fn update_state(handle: u32) -> Result { +pub fn update_state(handle: u32) -> VcxResult { HANDLE_MAP.get_mut(handle, |obj| { debug!("updating state for credential {} with msg_id {:?}", obj.source_id, obj.msg_uid); obj.update_state(); @@ -394,51 +388,51 @@ pub fn update_state(handle: u32) -> Result { }) } -pub fn get_credential(handle: u32) -> Result { +pub fn get_credential(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { debug!("getting credential {}", obj.get_source_id()); - obj.get_credential().map_err(|e| e.to_error_code()) - }).map_err(|ec| CredentialError::CommonError(ec)) + obj.get_credential() + }) } -pub fn get_payment_txn(handle: u32) -> Result { +pub fn get_payment_txn(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { obj.get_payment_txn() - }).or(Err(CredentialError::NoPaymentInformation())) + }).or(Err(VcxError::from(VcxErrorKind::NoPaymentInformation))) } -pub fn get_credential_offer(handle: u32) -> Result { +pub fn get_credential_offer(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { debug!("getting credential offer {}", obj.source_id); - obj.get_credential_offer().map_err(|e| e.to_error_code()) - }).map_err(|ec| CredentialError::CommonError(ec)) + obj.get_credential_offer() + }) } -pub fn get_credential_id(handle: u32) -> Result { +pub fn get_credential_id(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { Ok(obj.get_credential_id()) - }).map_err(|ec| CredentialError::CommonError(ec)) + }) } -pub fn get_state(handle: u32) -> Result { +pub fn get_state(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { Ok(obj.get_state()) }).map_err(handle_err) } -pub fn send_credential_request(handle: u32, connection_handle: u32) -> Result { +pub fn send_credential_request(handle: u32, connection_handle: u32) -> VcxResult { HANDLE_MAP.get_mut(handle, |obj| { - obj.send_request(connection_handle).map_err(|e| e.to_error_code()) + obj.send_request(connection_handle) }).map_err(handle_err) } -pub fn get_credential_offer_msg(connection_handle: u32, msg_id: &str) -> Result { +pub fn get_credential_offer_msg(connection_handle: u32, msg_id: &str) -> VcxResult { trace!("get_credential_offer_msg >>> connection_handle: {}, msg_id: {}", connection_handle, msg_id); - let my_did = connection::get_pw_did(connection_handle).map_err(|e| CredentialError::CommonError(e.to_error_code()))?; - let my_vk = connection::get_pw_verkey(connection_handle).map_err(|e| CredentialError::CommonError(e.to_error_code()))?; - let agent_did = connection::get_agent_did(connection_handle).map_err(|e| CredentialError::CommonError(e.to_error_code()))?; - let agent_vk = connection::get_agent_verkey(connection_handle).map_err(|e| CredentialError::CommonError(e.to_error_code()))?; + let my_did = connection::get_pw_did(connection_handle)?; + let my_vk = connection::get_pw_verkey(connection_handle)?; + let agent_did = connection::get_agent_did(connection_handle)?; + let agent_vk = connection::get_agent_verkey(connection_handle)?; if settings::test_agency_mode_enabled() { ::utils::httpclient::set_next_u8_response(::utils::constants::NEW_CREDENTIAL_OFFER_RESPONSE.to_vec()); } @@ -446,13 +440,13 @@ pub fn get_credential_offer_msg(connection_handle: u32, msg_id: &str) -> Result< &my_vk, &agent_did, &agent_vk, - Some(vec![msg_id.to_string()])).map_err(|ec| CredentialError::CommonError(ec))?; + Some(vec![msg_id.to_string()]))?; if message[0].msg_type == RemoteMessageType::CredOffer { let payload = message.get(0).and_then(|msg| msg.payload.as_ref()) - .ok_or(CredentialError::CommonError(error::INVALID_MESSAGES.code_num))?; + .ok_or(VcxError::from(VcxErrorKind::InvalidMessagePack))?; - let (offer, thread) = Payloads::decrypt(&my_vk, &payload).map_err(|ec| CredentialError::CommonError(ec))?; + let (offer, thread) = Payloads::decrypt(&my_vk, &payload)?; let (mut offer, payment_info) = parse_json_offer(&offer)?; @@ -465,20 +459,21 @@ pub fn get_credential_offer_msg(connection_handle: u32, msg_id: &str) -> Result< payload.push(json!(offer)); if let Some(p) = payment_info { payload.push(json!(p)); } - Ok(serde_json::to_string_pretty(&payload).or(Err(CredentialError::CommonError(error::INVALID_MESSAGES.code_num)))?) + serde_json::to_string_pretty(&payload) + .or(Err(VcxError::from(VcxErrorKind::InvalidMessages))) } else { - Err(CredentialError::CommonError(error::INVALID_MESSAGES.code_num)) + Err(VcxError::from(VcxErrorKind::InvalidMessages)) } } -pub fn get_credential_offer_messages(connection_handle: u32) -> Result { +pub fn get_credential_offer_messages(connection_handle: u32) -> VcxResult { trace!("Credential::get_credential_offer_messages >>> connection_handle: {}", connection_handle); debug!("checking agent for credential offers from connection {}", connection::get_source_id(connection_handle).unwrap_or_default()); - let my_did = connection::get_pw_did(connection_handle).map_err(|e| CredentialError::CommonError(e.to_error_code()))?; - let my_vk = connection::get_pw_verkey(connection_handle).map_err(|e| CredentialError::CommonError(e.to_error_code()))?; - let agent_did = connection::get_agent_did(connection_handle).map_err(|e| CredentialError::CommonError(e.to_error_code()))?; - let agent_vk = connection::get_agent_verkey(connection_handle).map_err(|e| CredentialError::CommonError(e.to_error_code()))?; + let my_did = connection::get_pw_did(connection_handle)?; + let my_vk = connection::get_pw_verkey(connection_handle)?; + let agent_did = connection::get_agent_did(connection_handle)?; + let agent_vk = connection::get_agent_verkey(connection_handle)?; if settings::test_agency_mode_enabled() { ::utils::httpclient::set_next_u8_response(::utils::constants::NEW_CREDENTIAL_OFFER_RESPONSE.to_vec()); } @@ -486,14 +481,16 @@ pub fn get_credential_offer_messages(connection_handle: u32) -> Result Result Result<(CredentialOffer, Option), CredentialError> { - let paid_offer: Value = serde_json::from_str(offer).or(Err(CredentialError::InvalidCredentialJson()))?; +pub fn parse_json_offer(offer: &str) -> VcxResult<(CredentialOffer, Option)> { + let paid_offer: Value = serde_json::from_str(offer) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidCredential, format!("Cannot deserialize offer: {}", err)))?; let mut payment: Option = None; let mut offer: Option = None; @@ -522,50 +521,45 @@ pub fn parse_json_offer(offer: &str) -> Result<(CredentialOffer, Option Result<(), CredentialError> { +pub fn release(handle: u32) -> VcxResult<()> { HANDLE_MAP.release(handle).map_err(handle_err) } pub fn release_all() { - match HANDLE_MAP.drain() { - Ok(_) => (), - Err(_) => (), - }; + HANDLE_MAP.drain().ok(); } pub fn is_valid_handle(handle: u32) -> bool { HANDLE_MAP.has_handle(handle) } -pub fn to_string(handle: u32) -> Result { +pub fn to_string(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { - Ok(Credential::to_string(&obj)) + Credential::to_string(&obj) }) } -pub fn get_source_id(handle: u32) -> Result { +pub fn get_source_id(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { Ok(obj.get_source_id().clone()) }).map_err(handle_err) } -pub fn from_string(credential_data: &str) -> Result { - let credential: Credential = match Credential::from_str(credential_data) { - Ok(x) => x, - Err(y) => return Err(error::INVALID_JSON.code_num), - }; - +pub fn from_string(credential_data: &str) -> VcxResult { + let credential: Credential = Credential::from_str(credential_data)?; let new_handle = HANDLE_MAP.add(credential)?; debug!("inserting handle {} into proof table", new_handle); @@ -573,21 +567,21 @@ pub fn from_string(credential_data: &str) -> Result { Ok(new_handle) } -pub fn is_payment_required(handle: u32) -> Result { +pub fn is_payment_required(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { Ok(obj.is_payment_required()) }).map_err(handle_err) } -pub fn submit_payment(handle: u32) -> Result<(PaymentTxn, String), CredentialError> { +pub fn submit_payment(handle: u32) -> VcxResult<(PaymentTxn, String)> { HANDLE_MAP.get_mut(handle, |obj| { - obj.submit_payment().map_err(|e| e.to_error_code()) + obj.submit_payment() }).map_err(handle_err) } -pub fn get_payment_information(handle: u32) -> Result, CredentialError> { +pub fn get_payment_information(handle: u32) -> VcxResult> { HANDLE_MAP.get(handle, |obj| { - obj.get_payment_info().map_err(|e| e.to_error_code()) + obj.get_payment_info() }).map_err(handle_err) } diff --git a/vcx/libvcx/src/credential_def.rs b/vcx/libvcx/src/credential_def.rs index a027430018..bdb33b7bb4 100644 --- a/vcx/libvcx/src/credential_def.rs +++ b/vcx/libvcx/src/credential_def.rs @@ -1,18 +1,15 @@ -extern crate serde_json; -extern crate rand; -extern crate libc; - -use utils::error; -use utils::libindy::payments::{PaymentTxn}; +use utils::libindy::payments::PaymentTxn; use utils::libindy::anoncreds; -use error::cred_def::CredDefError; use object_cache::ObjectCache; +use messages::ObjectWithVersion; +use error::prelude::*; +use utils::constants::DEFAULT_SERIALIZE_VERSION; lazy_static! { static ref CREDENTIALDEF_MAP: ObjectCache = Default::default(); } -#[derive(Deserialize, Debug, Serialize, PartialEq)] +#[derive(Clone, Deserialize, Debug, Serialize, PartialEq)] pub struct CredentialDef { id: String, tag: String, @@ -35,40 +32,26 @@ pub struct RevocationDetails { pub max_creds: Option, } -impl Default for CredentialDef { - fn default() -> CredentialDef { - CredentialDef { - id: String::new(), - tag: String::new(), - name: String::new(), - source_id: String::new(), - issuer_did: None, - cred_def_payment_txn: None, - rev_reg_def_payment_txn: None, - rev_reg_delta_payment_txn: None, - rev_reg_id: None, - rev_reg_def: None, - rev_reg_entry: None, - tails_file: None, - } - } -} - impl CredentialDef { - - pub fn from_str(input: &str) -> Result { - CredentialDef::from_string_with_version(&input).or(Err(CredDefError::CreateCredDefError())) + pub fn from_str(data: &str) -> VcxResult { + ObjectWithVersion::deserialize(data) + .map(|obj: ObjectWithVersion| obj.data) + .map_err(|err| err.extend("Cannot deserialize CredentialDefinition")) } - pub fn to_string(&self) -> String { self.to_string_with_version() } + pub fn to_string(&self) -> VcxResult { + ObjectWithVersion::new(DEFAULT_SERIALIZE_VERSION, self.to_owned()) + .serialize() + .map_err(|err| err.extend("Cannot serialize CredentialDefinition")) + } pub fn get_source_id(&self) -> &String { &self.source_id } - pub fn get_rev_reg_id(&self) -> Option { self.rev_reg_id.clone() } + pub fn get_rev_reg_id(&self) -> Option<&String> { self.rev_reg_id.as_ref() } - pub fn get_tails_file(&self) -> Option {self.tails_file.clone() } + pub fn get_tails_file(&self) -> Option<&String> { self.tails_file.as_ref() } - pub fn get_rev_reg_def(&self) -> Option { self.rev_reg_def.clone() } + pub fn get_rev_reg_def(&self) -> Option<&String> { self.rev_reg_def.as_ref() } pub fn get_cred_def_id(&self) -> &String { &self.id } @@ -76,25 +59,14 @@ impl CredentialDef { pub fn set_source_id(&mut self, source_id: String) { self.source_id = source_id.clone(); } - fn get_cred_def_payment_txn(&self) -> Result { Ok(self.cred_def_payment_txn.clone().ok_or(error::NOT_READY.code_num)?) } + fn get_cred_def_payment_txn(&self) -> VcxResult { + self.cred_def_payment_txn.clone() + .ok_or(err_msg(VcxErrorKind::NoPaymentInformation, "Payment information not found")) + } fn get_rev_reg_def_payment_txn(&self) -> Option { self.rev_reg_def_payment_txn.clone() } fn get_rev_reg_delta_payment_txn(&self) -> Option { self.rev_reg_delta_payment_txn.clone() } - - fn to_string_with_version(&self) -> String { - json!({ - "version": "1.0", - "data": json!(self), - }).to_string() - } - - fn from_string_with_version(data: &str) -> Result { - let values:serde_json::Value = serde_json::from_str(data).or(Err(CredDefError::CommonError(error::INVALID_JSON.code_num)))?; - let version = values["version"].to_string(); - let data = values["data"].to_string(); - serde_json::from_str(&data).or(Err(CredDefError::CreateCredDefError())) - } } pub fn create_new_credentialdef(source_id: String, @@ -102,31 +74,29 @@ pub fn create_new_credentialdef(source_id: String, issuer_did: String, schema_id: String, tag: String, - revocation_details: String) -> Result { + revocation_details: String) -> VcxResult { trace!("create_new_credentialdef >>> source_id: {}, name: {}, issuer_did: {}, schema_id: {}, revocation_details: {}", source_id, name, issuer_did, schema_id, revocation_details); let revocation_details: RevocationDetails = serde_json::from_str(&revocation_details) - .or(Err(CredDefError::InvalidRevocationDetails()))?; + .to_vcx(VcxErrorKind::InvalidRevocationDetails, "Cannot deserialize RevocationDeltas")?; - let (_, schema_json) = anoncreds::get_schema_json(&schema_id) - .map_err(|x| CredDefError::CommonError(x))?; + let (_, schema_json) = anoncreds::get_schema_json(&schema_id)?; // Creates Credential Definition in both wallet and on ledger let (id, cred_def_payment_txn) = anoncreds::create_cred_def(&issuer_did, - &schema_json, - &tag, - None, - revocation_details.support_revocation) - .map_err(|err| { - if err == error::CREDENTIAL_DEF_ALREADY_CREATED.code_num { - error!("Credential Definition for issuer_did {} already in wallet", issuer_did); - CredDefError::CredDefAlreadyCreatedError() - } else { - error!("{} with: {}", error::CREATE_CREDENTIAL_DEF_ERR.message, err); - CredDefError::CreateCredDefError() - } - })?; + &schema_json, + &tag, + None, + revocation_details.support_revocation) .map_err(|err| { + if err.kind() == VcxErrorKind::CredDefAlreadyCreated { + error!("Credential Definition for issuer_did {} already in wallet", issuer_did); + err + } else { + error!("{}", err); + VcxError::from(VcxErrorKind::CreateCredDef) + } + })?; // Creates Revocation Definition in wallet and on ledger // Posts Revocation Delta to Ledger @@ -136,25 +106,25 @@ pub fn create_new_credentialdef(source_id: String, let tails_file = revocation_details .tails_file .as_ref() - .ok_or(CredDefError::InvalidRevocationDetails())?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidRevocationDetails, "Invalid RevocationDetails: `tails_file` field not found"))?; let max_creds = revocation_details .max_creds - .ok_or(CredDefError::InvalidRevocationDetails())?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidRevocationDetails, "Invalid RevocationDetails: `max_creds` field not found"))?; let (rev_reg_id, rev_reg_def, rev_reg_entry, rev_def_payment) = anoncreds::create_rev_reg_def(&issuer_did, &id, &tails_file, max_creds) - .or(Err(CredDefError::CreateRevRegDefError()))?; + .map_err(|err| err.map(VcxErrorKind::CreateCredDef, "Cannot create CredentialDefinition"))?; let (delta_payment, _) = anoncreds::post_rev_reg_delta(&issuer_did, &rev_reg_id, &rev_reg_entry) - .or(Err(CredDefError::InvalidRevocationEntry()))?; + .map_err(|err| err.map(VcxErrorKind::InvalidRevocationEntry, "Cannot post RevocationEntry"))?; (Some(rev_reg_id), Some(rev_reg_def), Some(rev_reg_entry), rev_def_payment, delta_payment) } _ => (None, None, None, None, None), }; - let new_cred_def = CredentialDef { + let cred_def = CredentialDef { source_id, name, tag, @@ -169,104 +139,83 @@ pub fn create_new_credentialdef(source_id: String, tails_file: revocation_details.tails_file, }; - let new_handle = CREDENTIALDEF_MAP.add(new_cred_def).map_err(|key|CredDefError::CreateCredDefError())?; + let handle = CREDENTIALDEF_MAP.add(cred_def) + .map_err(|_| VcxError::from_msg(VcxErrorKind::CreateCredDef, "Cannot create credential definition"))?; - Ok(new_handle) + Ok(handle) } pub fn is_valid_handle(handle: u32) -> bool { CREDENTIALDEF_MAP.has_handle(handle) } -pub fn to_string(handle: u32) -> Result { +pub fn to_string(handle: u32) -> VcxResult { CREDENTIALDEF_MAP.get(handle, |cd| { - Ok(CredentialDef::to_string_with_version(&cd)) + cd.to_string() }) } -pub fn from_string(credentialdef_data: &str) -> Result { - let derived_credentialdef: CredentialDef = CredentialDef::from_str(credentialdef_data)?; - let source_id = derived_credentialdef.source_id.clone(); - let new_handle = CREDENTIALDEF_MAP.add(derived_credentialdef).map_err(|ec|CredDefError::CommonError(ec))?; - - Ok(new_handle) +pub fn from_string(data: &str) -> VcxResult { + let cred_def: CredentialDef = CredentialDef::from_str(data)?; + CREDENTIALDEF_MAP.add(cred_def) } -pub fn get_source_id(handle: u32) -> Result { - CREDENTIALDEF_MAP.get(handle,|c| { +pub fn get_source_id(handle: u32) -> VcxResult { + CREDENTIALDEF_MAP.get(handle, |c| { Ok(c.get_source_id().clone()) - }).map_err(|ec|CredDefError::CommonError(ec)) + }) } -pub fn get_cred_def_payment_txn(handle: u32) -> Result { - CREDENTIALDEF_MAP.get(handle,|c| { +pub fn get_cred_def_payment_txn(handle: u32) -> VcxResult { + CREDENTIALDEF_MAP.get(handle, |c| { c.get_cred_def_payment_txn() - }).or(Err(CredDefError::NoPaymentInformation())) + }) } -pub fn get_cred_def_id(handle: u32) -> Result { - CREDENTIALDEF_MAP.get(handle,|c| { +pub fn get_cred_def_id(handle: u32) -> VcxResult { + CREDENTIALDEF_MAP.get(handle, |c| { Ok(c.get_cred_def_id().clone()) - }).map_err(|ec|CredDefError::CommonError(ec)) + }) } -pub fn get_rev_reg_id(handle: u32) -> Result, CredDefError> { - CREDENTIALDEF_MAP.get(handle,|c| { - Ok(c.get_rev_reg_id().clone()) - }).map_err(|ec|CredDefError::CommonError(ec)) +pub fn get_rev_reg_id(handle: u32) -> VcxResult> { + CREDENTIALDEF_MAP.get(handle, |c| { + Ok(c.get_rev_reg_id().cloned()) + }) } -pub fn get_tails_file(handle: u32) -> Result, CredDefError> { - CREDENTIALDEF_MAP.get(handle,|c| { - Ok(c.get_tails_file().clone()) - }).map_err(|ec|CredDefError::CommonError(ec)) +pub fn get_tails_file(handle: u32) -> VcxResult> { + CREDENTIALDEF_MAP.get(handle, |c| { + Ok(c.get_tails_file().cloned()) + }) } -pub fn get_rev_reg_def(handle: u32) -> Result, CredDefError> { - CREDENTIALDEF_MAP.get(handle,|c| { - Ok(c.get_rev_reg_def().clone()) - }).map_err(|ec|CredDefError::CommonError(ec)) +pub fn get_rev_reg_def(handle: u32) -> VcxResult> { + CREDENTIALDEF_MAP.get(handle, |c| { + Ok(c.get_rev_reg_def().cloned()) + }) } -pub fn get_rev_reg_def_payment_txn(handle: u32) -> Result, CredDefError> { - CREDENTIALDEF_MAP.get(handle,|c| { +pub fn get_rev_reg_def_payment_txn(handle: u32) -> VcxResult> { + CREDENTIALDEF_MAP.get(handle, |c| { Ok(c.get_rev_reg_def_payment_txn()) - }).map_err(|ec|CredDefError::CommonError(ec)) + }) } -pub fn get_rev_reg_delta_payment_txn(handle: u32) -> Result, CredDefError> { - CREDENTIALDEF_MAP.get(handle,|c| { +pub fn get_rev_reg_delta_payment_txn(handle: u32) -> VcxResult> { + CREDENTIALDEF_MAP.get(handle, |c| { Ok(c.get_rev_reg_delta_payment_txn()) - }).map_err(|ec|CredDefError::CommonError(ec)) -} - -pub fn release(handle: u32) -> Result<(), CredDefError> { - match CREDENTIALDEF_MAP.release(handle) { - Ok(_) => Ok(()), - Err(_) => Err(CredDefError::InvalidHandle()), - } + }) } -pub fn find_handle(cred_def_id: &str) -> Result { - let mut handles = Vec::new(); - - for handle in CREDENTIALDEF_MAP.store.lock().unwrap().iter() { - handles.push(handle.0.clone()); - } - for handle in handles.iter() { - let id = get_cred_def_id(*handle).unwrap(); - println!("id: {}", id); - } - - Ok(error::SUCCESS.code_num) +pub fn release(handle: u32) -> VcxResult<()> { + CREDENTIALDEF_MAP.release(handle) + .or(Err(VcxError::from(VcxErrorKind::InvalidCredDefHandle))) } pub fn release_all() { - match CREDENTIALDEF_MAP.drain() { - Ok(_) => (), - Err(_) => (), - }; + CREDENTIALDEF_MAP.drain().ok(); } #[cfg(test)] @@ -334,8 +283,7 @@ pub mod tests { let payment = serde_json::to_string(&get_cred_def_payment_txn(handle).unwrap()).unwrap(); assert!(payment.len() > 0); - find_handle("123").unwrap(); -} + } #[test] fn test_get_credential_def_by_send_request_fails() { @@ -370,11 +318,11 @@ pub mod tests { let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); let rc = create_new_credentialdef("1".to_string(), - wallet_name.to_string(), - did, - schema_id, - "tag_1".to_string(), - r#"{"support_revocation":true}"#.to_string()); + wallet_name.to_string(), + did, + schema_id, + "tag_1".to_string(), + r#"{"support_revocation":true}"#.to_string()); assert_eq!(rc, Err(CredDefError::InvalidRevocationDetails())); } @@ -484,7 +432,7 @@ pub mod tests { let new_credentialdef_data = to_string(new_handle).unwrap(); let credentialdef1: CredentialDef = CredentialDef::from_str(&credentialdef_data).unwrap(); let credentialdef2: CredentialDef = CredentialDef::from_str(&new_credentialdef_data).unwrap(); - assert_eq!(credentialdef1,credentialdef2); + assert_eq!(credentialdef1, credentialdef2); assert_eq!(CredentialDef::from_str("{}").err(), Some(CredDefError::CreateCredDefError())); } @@ -497,11 +445,11 @@ pub mod tests { let h4 = create_new_credentialdef("SourceId".to_string(), CREDENTIAL_DEF_NAME.to_string(), ISSUER_DID.to_string(), SCHEMA_ID.to_string(), "tag".to_string(), "{}".to_string()).unwrap(); let h5 = create_new_credentialdef("SourceId".to_string(), CREDENTIAL_DEF_NAME.to_string(), ISSUER_DID.to_string(), SCHEMA_ID.to_string(), "tag".to_string(), "{}".to_string()).unwrap(); release_all(); - assert_eq!(release(h1),Err(CredDefError::InvalidHandle())); - assert_eq!(release(h2),Err(CredDefError::InvalidHandle())); - assert_eq!(release(h3),Err(CredDefError::InvalidHandle())); - assert_eq!(release(h4),Err(CredDefError::InvalidHandle())); - assert_eq!(release(h5),Err(CredDefError::InvalidHandle())); + assert_eq!(release(h1), Err(CredDefError::InvalidHandle())); + assert_eq!(release(h2), Err(CredDefError::InvalidHandle())); + assert_eq!(release(h3), Err(CredDefError::InvalidHandle())); + assert_eq!(release(h4), Err(CredDefError::InvalidHandle())); + assert_eq!(release(h5), Err(CredDefError::InvalidHandle())); } #[test] diff --git a/vcx/libvcx/src/disclosed_proof.rs b/vcx/libvcx/src/disclosed_proof.rs index 4e8e1903a8..ab20581b8c 100644 --- a/vcx/libvcx/src/disclosed_proof.rs +++ b/vcx/libvcx/src/disclosed_proof.rs @@ -8,10 +8,12 @@ use connection; use messages; use messages::GeneralMessage; use messages::RemoteMessageType; +use messages::ObjectWithVersion; use messages::payload::{Payloads, PayloadKinds, Thread}; use messages::proofs::proof_message::ProofMessage; use messages::proofs::proof_request::{ProofRequestMessage, ProofRequestData, NonRevokedInterval}; use time; +use error::prelude::*; use utils::libindy::anoncreds; use utils::libindy::anoncreds::{get_rev_reg_def_json, get_rev_reg_delta_json}; @@ -23,9 +25,6 @@ use utils::libindy::cache::{get_rev_reg_cache, set_rev_reg_cache, RevRegCache, R use serde_json::Value; -use error::ToErrorCode; -use error::proof::ProofError; - lazy_static! { static ref HANDLE_MAP: ObjectCache = Default::default(); } @@ -86,13 +85,11 @@ pub struct CredInfo { pub timestamp: Option } -fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) - -> Result, ProofError> { - +fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) -> VcxResult> { let mut rtn = Vec::new(); let credentials: Value = serde_json::from_str(credentials) - .or(Err(ProofError::InvalidJson()))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize credentials: {}", err)))?; if let Value::Object(ref attrs) = credentials["attrs"] { for (requested_attr, value) in attrs { @@ -100,7 +97,6 @@ fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) (value["credential"]["cred_info"]["referent"].as_str(), value["credential"]["cred_info"]["schema_id"].as_str(), value["credential"]["cred_info"]["cred_def_id"].as_str()) { - let rev_reg_id = value["credential"]["cred_info"]["rev_reg_id"] .as_str() .map(|x| x.to_string()); @@ -126,15 +122,14 @@ fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) tails_file, } ); - } else { return Err(ProofError::InvalidCredData()); } + } else { return Err(VcxError::from(VcxErrorKind::InvalidProofCredentialData)); } } } Ok(rtn) } -fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) - -> Result, ProofError> { +fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) -> VcxResult> { if let Some(ref attr) = proof_req.requested_attributes.get(attr_name) { if let Some(ref interval) = attr.non_revoked { return Ok(Some(NonRevokedInterval { from: interval.from, to: interval.to })); @@ -146,11 +141,11 @@ fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) } // Todo: Handle case for predicates - Err(ProofError::InvalidCredData()) + Err(VcxError::from(VcxErrorKind::InvalidProofCredentialData)) } // Also updates timestamp in credentials_identifiers -fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result { +fn build_rev_states_json(credentials_identifiers: &mut Vec) -> VcxResult { let mut rtn: Value = json!({}); let mut timestamps: HashMap = HashMap::new(); @@ -177,14 +172,13 @@ fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result< _ => None }; - let (_, rev_reg_def_json) = get_rev_reg_def_json(&rev_reg_id) - .map_err(|e| ProofError::CommonError(e))?; + let (_, rev_reg_def_json) = get_rev_reg_def_json(&rev_reg_id)?; let (rev_reg_id, rev_reg_delta_json, timestamp) = get_rev_reg_delta_json( &rev_reg_id, from, to - ).map_err(|e| ProofError::CommonError(e))?; + )?; let rev_state_json = anoncreds::libindy_prover_update_revocation_state( &rev_reg_def_json, @@ -192,7 +186,7 @@ fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result< &rev_reg_delta_json, &cred_rev_id, &tails_file - ).map_err(|e| ProofError::CommonError(e))?; + )?; if timestamp > cached_rev_state.timestamp { let new_cache = RevRegCache { @@ -207,21 +201,20 @@ fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result< (rev_state_json, timestamp) } } else { - let (_, rev_reg_def_json) = get_rev_reg_def_json(&rev_reg_id) - .map_err(|e| ProofError::CommonError(e))?; + let (_, rev_reg_def_json) = get_rev_reg_def_json(&rev_reg_id)?; let (rev_reg_id, rev_reg_delta_json, timestamp) = get_rev_reg_delta_json( &rev_reg_id, None, to - ).map_err(|e| ProofError::CommonError(e))?; + )?; let rev_state_json = anoncreds::libindy_prover_create_revocation_state( &rev_reg_def_json, &rev_reg_delta_json, &cred_rev_id, &tails_file - ).map_err(|e| ProofError::CommonError(e))?; + )?; let new_cache = RevRegCache { rev_state: Some(RevState { @@ -235,7 +228,7 @@ fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result< }; let rev_state_json: Value = serde_json::from_str(&rev_state_json) - .or(Err(ProofError::InvalidJson()))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize RevocationState: {}", err)))?; // TODO: proover should be able to create multiple states of same revocation policy for different timestamps // see ticket IS-1108 @@ -248,7 +241,7 @@ fn build_rev_states_json(credentials_identifiers: &mut Vec) -> Result< // If the rev_reg_id is already in the map, timestamp may not be updated on cred_info if cred_info.timestamp.is_none() { - cred_info.timestamp = timestamps.get(rev_reg_id).map(|x| x.clone()); + cred_info.timestamp = timestamps.get(rev_reg_id).cloned(); } } } @@ -268,31 +261,30 @@ impl DisclosedProof { self.state = state } - fn retrieve_credentials(&self) -> Result { + fn retrieve_credentials(&self) -> VcxResult { trace!("DisclosedProof::set_state >>>"); if settings::test_indy_mode_enabled() { return Ok(CREDS_FROM_PROOF_REQ.to_string()); } let proof_req = self.proof_request .as_ref() - .ok_or(ProofError::ProofNotReadyError())?; + .ok_or(VcxError::from(VcxErrorKind::NotReady))?; let indy_proof_req = serde_json::to_string(&proof_req.proof_request_data) - .or(Err(ProofError::InvalidJson()))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize proof request: {}", err)))?; anoncreds::libindy_prover_get_credentials_for_proof_req(&indy_proof_req) - .map_err(|err| ProofError::CommonError(err)) } - fn build_schemas_json(&self, credentials_identifiers: &Vec) -> Result { + fn build_schemas_json(&self, credentials_identifiers: &Vec) -> VcxResult { let mut rtn: Value = json!({}); for ref cred_info in credentials_identifiers { if rtn.get(&cred_info.schema_id).is_none() { let (_, schema_json) = anoncreds::get_schema_json(&cred_info.schema_id) - .or(Err(ProofError::InvalidSchema()))?; + .map_err(|err| err.map(VcxErrorKind::InvalidSchema, "Cannot get schema"))?; let schema_json = serde_json::from_str(&schema_json) - .or(Err(ProofError::InvalidSchema()))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidSchema, format!("Cannot deserialize schema: {}", err)))?; rtn[cred_info.schema_id.to_owned()] = schema_json; } @@ -300,16 +292,16 @@ impl DisclosedProof { Ok(rtn.to_string()) } - fn build_cred_def_json(&self, credentials_identifiers: &Vec) -> Result { + fn build_cred_def_json(&self, credentials_identifiers: &Vec) -> VcxResult { let mut rtn: Value = json!({}); for ref cred_info in credentials_identifiers { if rtn.get(&cred_info.cred_def_id).is_none() { let (_, credential_def) = anoncreds::get_cred_def_json(&cred_info.cred_def_id) - .or(Err(ProofError::InvalidCredData()))?; + .map_err(|err| err.map(VcxErrorKind::InvalidProofCredentialData, "Cannot get credential definition"))?; let credential_def = serde_json::from_str(&credential_def) - .or(Err(ProofError::InvalidCredData()))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidProofCredentialData, format!("Cannot deserialize credential definition: {}", err)))?; rtn[cred_info.cred_def_id.to_owned()] = credential_def; } @@ -317,9 +309,7 @@ impl DisclosedProof { Ok(rtn.to_string()) } - fn build_requested_credentials_json(&self, - credentials_identifiers: &Vec, - self_attested_attrs: &str) -> Result { + fn build_requested_credentials_json(&self, credentials_identifiers: &Vec, self_attested_attrs: &str) -> VcxResult { let mut rtn: Value = json!({ "self_attested_attributes":{}, "requested_attributes":{}, @@ -335,30 +325,27 @@ impl DisclosedProof { } let self_attested_attrs: Value = serde_json::from_str(self_attested_attrs) - .or(Err(ProofError::CommonError(error::INVALID_JSON.code_num)))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize self attested attributes: {}", err)))?; rtn["self_attested_attributes"] = self_attested_attrs; Ok(rtn.to_string()) } - fn generate_proof(&mut self, credentials: &str, self_attested_attrs: &str) -> Result { + fn generate_proof(&mut self, credentials: &str, self_attested_attrs: &str) -> VcxResult { trace!("DisclosedProof::generate_proof >>> credentials: {}, self_attested_attrs: {}", credentials, self_attested_attrs); debug!("generating proof {}", self.source_id); if settings::test_indy_mode_enabled() { return Ok(error::SUCCESS.code_num); } let proof_req = self.proof_request.as_ref() - .ok_or(ProofError::CreateProofError())?; + .ok_or(VcxError::from(VcxErrorKind::CreateProof))?; let proof_req_data_json = serde_json::to_string(&proof_req.proof_request_data) - .or(Err(ProofError::CommonError(error::INVALID_JSON.code_num)))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize proof request: {}", err)))?; - - let mut credentials_identifiers = credential_def_identifiers(credentials, - &proof_req.proof_request_data)?; + let mut credentials_identifiers = credential_def_identifiers(credentials, &proof_req.proof_request_data)?; let revoc_states_json = build_rev_states_json(&mut credentials_identifiers)?; - let requested_credentials = self.build_requested_credentials_json(&credentials_identifiers, - self_attested_attrs)?; + let requested_credentials = self.build_requested_credentials_json(&credentials_identifiers, self_attested_attrs)?; let schemas_json = self.build_schemas_json(&credentials_identifiers)?; let credential_defs_json = self.build_cred_def_json(&credentials_identifiers)?; @@ -368,7 +355,7 @@ impl DisclosedProof { &self.link_secret_alias, &schemas_json, &credential_defs_json, - Some(&revoc_states_json)).map_err(|ec| ProofError::CommonError(ec))?; + Some(&revoc_states_json))?; let mut proof_msg = ProofMessage::new(); proof_msg.libindy_proof = proof; self.proof = Some(proof_msg); @@ -376,17 +363,17 @@ impl DisclosedProof { Ok(error::SUCCESS.code_num) } - fn send_proof(&mut self, connection_handle: u32) -> Result { + fn send_proof(&mut self, connection_handle: u32) -> VcxResult { trace!("DisclosedProof::send_proof >>> connection_handle: {}", connection_handle); debug!("sending proof {} via connection: {}", self.source_id, connection::get_source_id(connection_handle).unwrap_or_default()); // There feels like there's a much more rusty way to do the below. - self.my_did = Some(connection::get_pw_did(connection_handle).or(Err(ProofError::ProofConnectionError()))?); - self.my_vk = Some(connection::get_pw_verkey(connection_handle).or(Err(ProofError::ProofConnectionError()))?); - self.agent_did = Some(connection::get_agent_did(connection_handle).or(Err(ProofError::ProofConnectionError()))?); - self.agent_vk = Some(connection::get_agent_verkey(connection_handle).or(Err(ProofError::ProofConnectionError()))?); - self.their_did = Some(connection::get_their_pw_did(connection_handle).or(Err(ProofError::ProofConnectionError()))?); - self.their_vk = Some(connection::get_their_pw_verkey(connection_handle).or(Err(ProofError::ProofConnectionError()))?); + self.my_did = Some(connection::get_pw_did(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); + self.my_vk = Some(connection::get_pw_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); + self.agent_did = Some(connection::get_agent_did(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); + self.agent_vk = Some(connection::get_agent_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); + self.their_did = Some(connection::get_their_pw_did(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); + self.their_vk = Some(connection::get_their_pw_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); debug!("verifier_did: {:?} -- verifier_vk: {:?} -- agent_did: {:?} -- agent_vk: {:?} -- remote_vk: {:?}", @@ -396,20 +383,21 @@ impl DisclosedProof { self.their_vk, self.my_vk); - self.their_did.as_ref().ok_or(ProofError::ProofConnectionError())?; - let local_their_vk = self.their_vk.as_ref().ok_or(ProofError::ProofConnectionError())?; - let local_agent_did = self.agent_did.as_ref().ok_or(ProofError::ProofConnectionError())?; - let local_agent_vk = self.agent_vk.as_ref().ok_or(ProofError::ProofConnectionError())?; - let local_my_did = self.my_did.as_ref().ok_or(ProofError::ProofConnectionError())?; - let local_my_vk = self.my_vk.as_ref().ok_or(ProofError::ProofConnectionError())?; + self.their_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidConnectionHandle))?; + let local_their_vk = self.their_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidConnectionHandle))?; + let local_agent_did = self.agent_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidConnectionHandle))?; + let local_agent_vk = self.agent_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidConnectionHandle))?; + let local_my_did = self.my_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidConnectionHandle))?; + let local_my_vk = self.my_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidConnectionHandle))?; - let proof_req = self.proof_request.as_ref().ok_or(ProofError::CreateProofError())?; - let ref_msg_uid = proof_req.msg_ref_id.as_ref().ok_or(ProofError::CreateProofError())?; + let proof_req = self.proof_request.as_ref().ok_or(VcxError::from(VcxErrorKind::CreateProof))?; + let ref_msg_uid = proof_req.msg_ref_id.as_ref().ok_or(VcxError::from(VcxErrorKind::CreateProof))?; let proof = match settings::test_indy_mode_enabled() { false => { - let proof: &ProofMessage = self.proof.as_ref().ok_or(ProofError::CreateProofError())?; - serde_json::to_string(&proof).or(Err(ProofError::CommonError(error::INVALID_JSON.code_num)))? + let proof: &ProofMessage = self.proof.as_ref().ok_or(VcxError::from(VcxErrorKind::CreateProof))?; + serde_json::to_string(&proof) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize proof: {}", err)))? } true => DEFAULT_GENERATED_PROOF.to_string(), }; @@ -422,7 +410,8 @@ impl DisclosedProof { .msg_type(&RemoteMessageType::Proof)? .agent_did(local_agent_did)? .agent_vk(local_agent_vk)? - .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof, Some(self.thread.clone())).or(Err(ProofError::ProofConnectionError()))? + .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof, Some(self.thread.clone())) + .or(Err(VcxError::from(VcxErrorKind::GeneralConnectionError)))? .ref_msg_id(ref_msg_uid)? .send_secure() .map_err(|err| { @@ -435,36 +424,35 @@ impl DisclosedProof { } fn set_source_id(&mut self, id: &str) { self.source_id = id.to_string(); } + fn get_source_id(&self) -> &String { &self.source_id } - fn to_string(&self) -> String { + + fn to_string(&self) -> VcxResult { trace!("DisclosedProof::to_string >>>"); - json!({ - "version": DEFAULT_SERIALIZE_VERSION, - "data": json!(self), - }).to_string() + ObjectWithVersion::new(DEFAULT_SERIALIZE_VERSION, self.to_owned()) + .serialize() + .map_err(|err| err.extend("Cannot serialize DisclosedProof")) } - fn from_str(s: &str) -> Result { - trace!("DisclosedProof::from_str >>> data: {}", s); - let s: Value = serde_json::from_str(&s) - .or(Err(ProofError::InvalidJson()))?; - let proof: DisclosedProof = serde_json::from_value(s["data"].clone()) - .or(Err(ProofError::InvalidJson()))?; - Ok(proof) + fn from_str(data: &str) -> VcxResult { + trace!("DisclosedProof::from_str >>> data: {}", data); + ObjectWithVersion::deserialize(data) + .map(|obj: ObjectWithVersion| obj.data) + .map_err(|err| err.extend("Cannot deserialize DisclosedProof")) } } //******************************************** // HANDLE FUNCTIONS //******************************************** -fn handle_err(code_num: u32) -> u32 { - if code_num == error::INVALID_OBJ_HANDLE.code_num { - error::INVALID_DISCLOSED_PROOF_HANDLE.code_num +fn handle_err(err: VcxError) -> VcxError { + if err.kind() == VcxErrorKind::InvalidHandle { + VcxError::from(VcxErrorKind::InvalidProofHandle) } else { - code_num + err } } -pub fn create_proof(source_id: &str, proof_req: &str) -> Result { +pub fn create_proof(source_id: &str, proof_req: &str) -> VcxResult { trace!("create_proof >>> source_id: {}, proof_req: {}", source_id, proof_req); debug!("creating disclosed proof with id: {}", source_id); @@ -473,70 +461,66 @@ pub fn create_proof(source_id: &str, proof_req: &str) -> Result new_proof.set_source_id(source_id); new_proof.set_proof_request(serde_json::from_str(proof_req) - .map_err(|_| ProofError::CommonError(error::INVALID_JSON.code_num))?); + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize proof request: {}", err)))?); new_proof.set_state(VcxStateType::VcxStateRequestReceived); - Ok(HANDLE_MAP.add(new_proof).map_err(|ec| ProofError::CommonError(ec))?) + HANDLE_MAP.add(new_proof) } -pub fn get_state(handle: u32) -> Result { +pub fn get_state(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { Ok(obj.get_state()) }).map_err(handle_err) } // update_state is just the same as get_state for disclosed_proof -pub fn update_state(handle: u32) -> Result { +pub fn update_state(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { Ok(obj.get_state()) }) } -pub fn to_string(handle: u32) -> Result { +pub fn to_string(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { - Ok(DisclosedProof::to_string(&obj)) + DisclosedProof::to_string(&obj) }) } -pub fn from_string(proof_data: &str) -> Result { - let derived_proof: DisclosedProof = DisclosedProof::from_str(proof_data) - .or(Err(ProofError::CommonError(error::INVALID_JSON.code_num)))?; +pub fn from_string(proof_data: &str) -> VcxResult { + let derived_proof: DisclosedProof = DisclosedProof::from_str(proof_data)?; - let new_handle = HANDLE_MAP.add(derived_proof).map_err(|ec| ProofError::CommonError(ec))?; + let new_handle = HANDLE_MAP.add(derived_proof)?; info!("inserting handle {} into proof table", new_handle); Ok(new_handle) } -pub fn release(handle: u32) -> Result<(), u32> { +pub fn release(handle: u32) -> VcxResult<()> { HANDLE_MAP.release(handle).map_err(handle_err) } pub fn release_all() { - match HANDLE_MAP.drain() { - Ok(_) => (), - Err(_) => (), - }; + HANDLE_MAP.drain().ok(); } -pub fn send_proof(handle: u32, connection_handle: u32) -> Result { +pub fn send_proof(handle: u32, connection_handle: u32) -> VcxResult { HANDLE_MAP.get_mut(handle, |obj| { - obj.send_proof(connection_handle).map_err(|e| e.to_error_code()) - }).map_err(|ec| ProofError::CommonError(ec)) + obj.send_proof(connection_handle) + }) } -pub fn generate_proof(handle: u32, credentials: String, self_attested_attrs: String) -> Result { +pub fn generate_proof(handle: u32, credentials: String, self_attested_attrs: String) -> VcxResult { HANDLE_MAP.get_mut(handle, |obj| { - obj.generate_proof(&credentials, &self_attested_attrs).map_err(|e| e.to_error_code()) - }).map_err(|ec| ProofError::CommonError(ec)) + obj.generate_proof(&credentials, &self_attested_attrs) + }) } -pub fn retrieve_credentials(handle: u32) -> Result { +pub fn retrieve_credentials(handle: u32) -> VcxResult { HANDLE_MAP.get_mut(handle, |obj| { - obj.retrieve_credentials().map_err(|e| e.to_error_code()) - }).map_err(|ec| ProofError::CommonError(ec)) + obj.retrieve_credentials() + }) } pub fn is_valid_handle(handle: u32) -> bool { @@ -544,13 +528,13 @@ pub fn is_valid_handle(handle: u32) -> bool { } //TODO one function with credential -pub fn get_proof_request(connection_handle: u32, msg_id: &str) -> Result { +pub fn get_proof_request(connection_handle: u32, msg_id: &str) -> VcxResult { trace!("get_proof_request >>> connection_handle: {}, msg_id: {}", connection_handle, msg_id); - let my_did = connection::get_pw_did(connection_handle).map_err(|e| ProofError::CommonError(e.to_error_code()))?; - let my_vk = connection::get_pw_verkey(connection_handle).map_err(|e| ProofError::CommonError(e.to_error_code()))?; - let agent_did = connection::get_agent_did(connection_handle).map_err(|e| ProofError::CommonError(e.to_error_code()))?; - let agent_vk = connection::get_agent_verkey(connection_handle).map_err(|e| ProofError::CommonError(e.to_error_code()))?; + let my_did = connection::get_pw_did(connection_handle)?; + let my_vk = connection::get_pw_verkey(connection_handle)?; + let agent_did = connection::get_agent_did(connection_handle)?; + let agent_vk = connection::get_agent_verkey(connection_handle)?; if settings::test_agency_mode_enabled() { httpclient::set_next_u8_response(::utils::constants::NEW_PROOF_REQUEST_RESPONSE.to_vec()); } @@ -558,33 +542,34 @@ pub fn get_proof_request(connection_handle: u32, msg_id: &str) -> Result) -> Result { +pub fn get_proof_request_messages(connection_handle: u32, match_name: Option<&str>) -> VcxResult { trace!("get_proof_request_messages >>> connection_handle: {}, match_name: {:?}", connection_handle, match_name); - let my_did = connection::get_pw_did(connection_handle).map_err(|e| ProofError::CommonError(e.to_error_code()))?; - let my_vk = connection::get_pw_verkey(connection_handle).map_err(|e| ProofError::CommonError(e.to_error_code()))?; - let agent_did = connection::get_agent_did(connection_handle).map_err(|e| ProofError::CommonError(e.to_error_code()))?; - let agent_vk = connection::get_agent_verkey(connection_handle).map_err(|e| ProofError::CommonError(e.to_error_code()))?; + let my_did = connection::get_pw_did(connection_handle)?; + let my_vk = connection::get_pw_verkey(connection_handle)?; + let agent_did = connection::get_agent_did(connection_handle)?; + let agent_vk = connection::get_agent_verkey(connection_handle)?; if settings::test_agency_mode_enabled() { httpclient::set_next_u8_response(::utils::constants::NEW_PROOF_REQUEST_RESPONSE.to_vec()); } @@ -592,7 +577,7 @@ pub fn get_proof_request_messages(connection_handle: u32, match_name: Option<&st &my_vk, &agent_did, &agent_vk, - None).map_err(|ec| ProofError::CommonError(ec))?; + None)?; let mut messages: Vec = Default::default(); @@ -600,11 +585,11 @@ pub fn get_proof_request_messages(connection_handle: u32, match_name: Option<&st if msg.sender_did.eq(&my_did) { continue; } if msg.msg_type == RemoteMessageType::ProofReq { - let payload = msg.payload.ok_or(ProofError::CommonError(error::INVALID_HTTP_RESPONSE.code_num))?; - let (req, thread) = Payloads::decrypt(&my_vk, &payload).map_err(|ec| ProofError::CommonError(ec))?; + let payload = msg.payload.ok_or(VcxError::from(VcxErrorKind::InvalidHttpResponse))?; + let (req, thread) = Payloads::decrypt(&my_vk, &payload)?; let mut req: ProofRequestMessage = serde_json::from_str(&req) - .or(Err(ProofError::CommonError(error::INVALID_HTTP_RESPONSE.code_num)))?; + .or(Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)))?; req.msg_ref_id = Some(msg.uid.to_owned()); req.thread_id = thread.and_then(|tr| tr.thid.clone()); @@ -612,10 +597,11 @@ pub fn get_proof_request_messages(connection_handle: u32, match_name: Option<&st } } - Ok(serde_json::to_string_pretty(&messages).or(Err(ProofError::InvalidJson()))?) + serde_json::to_string_pretty(&messages) + .or(Err(VcxError::from(VcxErrorKind::InvalidJson))) } -pub fn get_source_id(handle: u32) -> Result { +pub fn get_source_id(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { Ok(obj.get_source_id().clone()) }).map_err(handle_err) diff --git a/vcx/libvcx/src/error/base.rs b/vcx/libvcx/src/error/base.rs deleted file mode 100644 index efaae4fa52..0000000000 --- a/vcx/libvcx/src/error/base.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::fmt; -use std::error::Error; - -#[derive(Debug)] -pub enum BaseError { - WalletError(String), - ConnectionError(), - GeneralError(), -} - -impl fmt::Display for BaseError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - BaseError::GeneralError() => write!(f, "General Error"), - BaseError::WalletError(ref s) => write!(f, "Wallet Error: {}", s), - BaseError::ConnectionError() => write!(f, "Connection Error"), - } - } -} - -impl Error for BaseError { - fn cause(&self) -> Option<&Error> { - match *self { - BaseError::GeneralError() => None, - BaseError::WalletError(ref s) => None, - BaseError::ConnectionError() => None, - } - } - // TODO: Either implement this correctly or remove. - fn description(&self) -> &str { - match *self { - BaseError::WalletError(ref s) => "Wallet Error", - BaseError::GeneralError() => "General Base Error", - BaseError::ConnectionError() => "Connection Not Ready", - } - } -} diff --git a/vcx/libvcx/src/error/common.rs b/vcx/libvcx/src/error/common.rs deleted file mode 100644 index b28b04f643..0000000000 --- a/vcx/libvcx/src/error/common.rs +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/vcx/libvcx/src/error/connection.rs b/vcx/libvcx/src/error/connection.rs deleted file mode 100644 index 77ffee10fa..0000000000 --- a/vcx/libvcx/src/error/connection.rs +++ /dev/null @@ -1,123 +0,0 @@ - -use std::fmt; -use error::ToErrorCode; -use std::error::Error; -use utils::error::{INVALID_CONNECTION_HANDLE, - CONNECTION_ERROR, NOT_READY, - INVALID_INVITE_DETAILS, INVALID_MSGPACK, INVALID_JSON, - UNKNOWN_LIBINDY_ERROR, CANNOT_DELETE_CONNECTION, CREATE_CONNECTION_ERROR, - INVALID_WALLET_SETUP, COMMON_ERROR}; - -#[derive(Debug)] -pub enum ConnectionError { - CreateError(u32), - GeneralConnectionError(), - ConnectionNotReady(), - InviteDetailError(), - InvalidHandle(), - InvalidWalletSetup(), - InvalidMessagePack(), - InvalidJson(), - CannotDeleteConnection(), - CommonError(u32), -} - -impl From for ConnectionError { - fn from(err: u32) -> Self { - ConnectionError::CommonError(err) - } -} - -impl fmt::Display for ConnectionError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ConnectionError::InvalidHandle() => write!(f, "{}", INVALID_CONNECTION_HANDLE.message), - ConnectionError::GeneralConnectionError() => write!(f, "{}", CONNECTION_ERROR.message), - ConnectionError::InviteDetailError() => write!(f, "{}", INVALID_INVITE_DETAILS.message), - ConnectionError::CreateError(key) => write!(f, "{},{}", CREATE_CONNECTION_ERROR.message, key), - ConnectionError::ConnectionNotReady() => write!(f, "{}", NOT_READY.message), - ConnectionError::InvalidMessagePack() => write!(f, "{}", INVALID_MSGPACK.message), - ConnectionError::InvalidWalletSetup() => write!(f, "{}", INVALID_WALLET_SETUP.message), - ConnectionError::CannotDeleteConnection() => write!(f, "{}", CANNOT_DELETE_CONNECTION.message), - ConnectionError::InvalidJson() => write!(f, "{}", INVALID_JSON.message), - ConnectionError::CommonError(x) => connection_message(f, x), - } - } -} -fn connection_message(f: &mut fmt::Formatter, error_code: u32) -> fmt::Result { - if error_code == UNKNOWN_LIBINDY_ERROR.code_num { - // TODO: Make ths better, right now its just example code. - write!(f, "{}: Code: {} .. starting recovery steps.", UNKNOWN_LIBINDY_ERROR.message, UNKNOWN_LIBINDY_ERROR.code_num) - } else { - // TODO: Make ths better, right now its just example code. - write!(f, "Common Error had a value: {}.", error_code) - } -} -impl Error for ConnectionError { - fn cause(&self) -> Option<&Error> { - match *self { - ConnectionError::InvalidHandle() => None, - ConnectionError::CreateError(ref key) => None, - ConnectionError::GeneralConnectionError() => None, - ConnectionError::ConnectionNotReady() => None, - ConnectionError::InviteDetailError() => None, - ConnectionError::InvalidMessagePack() => None, - ConnectionError::InvalidWalletSetup() => None, - ConnectionError::InvalidJson() => None, - ConnectionError::CannotDeleteConnection() => None, - ConnectionError::CommonError(x) => None, - } - } - - // TODO: Either implement this correctly or remove. - fn description(&self) -> &str { - match *self { - ConnectionError::CreateError(ref key) => CREATE_CONNECTION_ERROR.message, - ConnectionError::InvalidMessagePack() => INVALID_MSGPACK.message, - ConnectionError::InvalidHandle() => INVALID_CONNECTION_HANDLE.message, - ConnectionError::GeneralConnectionError() => CONNECTION_ERROR.message, - ConnectionError::ConnectionNotReady() => NOT_READY.message, - ConnectionError::InviteDetailError() => INVALID_INVITE_DETAILS.message, - ConnectionError::InvalidWalletSetup() => INVALID_WALLET_SETUP.message, - ConnectionError::CannotDeleteConnection() => CANNOT_DELETE_CONNECTION.message, - ConnectionError::InvalidJson() => INVALID_JSON.message, - ConnectionError::CommonError(x) => COMMON_ERROR.message, - } - } -} - -impl ToErrorCode for ConnectionError { - fn to_error_code(&self) -> u32 { - match *self { - ConnectionError::InvalidHandle() => INVALID_CONNECTION_HANDLE.code_num, - ConnectionError::GeneralConnectionError() => CONNECTION_ERROR.code_num, - ConnectionError::ConnectionNotReady() => NOT_READY.code_num, - ConnectionError::InviteDetailError() => INVALID_INVITE_DETAILS.code_num, - ConnectionError::InvalidMessagePack() => INVALID_MSGPACK.code_num, - ConnectionError::CannotDeleteConnection() => CANNOT_DELETE_CONNECTION.code_num, - ConnectionError::CreateError(key) => CREATE_CONNECTION_ERROR.code_num, - ConnectionError::InvalidWalletSetup() => INVALID_WALLET_SETUP.code_num, - ConnectionError::InvalidJson() => INVALID_JSON.code_num, - ConnectionError::CommonError(x) => x, - } - } -} - -impl PartialEq for ConnectionError { - fn eq(&self, other: &ConnectionError) -> bool { - self.to_error_code() == other.to_error_code() - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn test_to_error_code() { - assert_eq!(ConnectionError::GeneralConnectionError().to_string(), "Error with Connection"); - assert_eq!(ConnectionError::GeneralConnectionError().to_error_code(), CONNECTION_ERROR.code_num); - assert_eq!(ConnectionError::ConnectionNotReady().to_string(), "Object not ready for specified action"); - assert_eq!(ConnectionError::ConnectionNotReady().to_error_code(), NOT_READY.code_num); - - } -} \ No newline at end of file diff --git a/vcx/libvcx/src/error/cred_def.rs b/vcx/libvcx/src/error/cred_def.rs deleted file mode 100644 index ca459d07f0..0000000000 --- a/vcx/libvcx/src/error/cred_def.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::fmt; -use error::ToErrorCode; -use utils::error::{NO_PAYMENT_INFORMATION, INVALID_CREDENTIAL_DEF_HANDLE, BUILD_CREDENTIAL_DEF_REQ_ERR, - CREDENTIAL_DEF_ALREADY_CREATED, CREATE_CREDENTIAL_DEF_ERR, INVALID_REVOCATION_DETAILS, - INVALID_REV_REG_DEF_CREATION, INVALID_REV_ENTRY}; - -#[derive(Debug)] -pub enum CredDefError { - BuildCredDefRequestError(), - RetrieveCredDefError(), - CreateCredDefError(), - CredDefAlreadyCreatedError(), - InvalidHandle(), - SchemaError(String), - NoPaymentInformation(), - CommonError(u32), - InvalidRevocationDetails(), - InvalidRevocationEntry(), - CreateRevRegDefError(), -} -impl fmt::Display for CredDefError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - CredDefError::SchemaError(ref s) => write!(f, "Schema Error: {}", s), - CredDefError::BuildCredDefRequestError() => write!(f, "Error Building Cred Def Request"), - CredDefError::RetrieveCredDefError() => write!(f, "Error Retrieving Cred Def Request"), - CredDefError::InvalidHandle() => write!(f, "Invalid credentialdef handle"), - CredDefError::CommonError(x) => write!(f, "This Cred Def common error had a value: {}", x), - CredDefError::CreateCredDefError() => write!(f, "{}", CREATE_CREDENTIAL_DEF_ERR.message ), - CredDefError::NoPaymentInformation() => write!(f, "{}", NO_PAYMENT_INFORMATION.message ), - CredDefError::CredDefAlreadyCreatedError() => write!(f, "{}", CREDENTIAL_DEF_ALREADY_CREATED.message ), - CredDefError::InvalidRevocationDetails() => write!(f, "{}", INVALID_REVOCATION_DETAILS.message ), - CredDefError::CreateRevRegDefError() => write!(f, "{}", INVALID_REV_REG_DEF_CREATION.message ), - CredDefError::InvalidRevocationEntry() => write!(f, "{}", INVALID_REV_ENTRY.message ), - } - } -} -impl ToErrorCode for CredDefError { - fn to_error_code(&self) -> u32 { - match *self { - CredDefError::SchemaError(ref s) => 7002, - CredDefError::BuildCredDefRequestError() => BUILD_CREDENTIAL_DEF_REQ_ERR.code_num, - CredDefError::RetrieveCredDefError() => 7001, - CredDefError::InvalidHandle() => INVALID_CREDENTIAL_DEF_HANDLE.code_num, - CredDefError::CreateCredDefError() => CREATE_CREDENTIAL_DEF_ERR.code_num, - CredDefError::NoPaymentInformation() => NO_PAYMENT_INFORMATION.code_num, - CredDefError::CredDefAlreadyCreatedError() => CREDENTIAL_DEF_ALREADY_CREATED.code_num, - CredDefError::InvalidRevocationDetails() => INVALID_REVOCATION_DETAILS.code_num, - CredDefError::CreateRevRegDefError() => INVALID_REV_REG_DEF_CREATION.code_num, - CredDefError::InvalidRevocationEntry() => INVALID_REV_ENTRY.code_num, - CredDefError::CommonError(x) => x, - } - } -} - -impl PartialEq for CredDefError { - fn eq(&self, other: &CredDefError) -> bool { - self.to_error_code() == other.to_error_code() - } -} \ No newline at end of file diff --git a/vcx/libvcx/src/error/credential.rs b/vcx/libvcx/src/error/credential.rs deleted file mode 100644 index 14b6fa86bd..0000000000 --- a/vcx/libvcx/src/error/credential.rs +++ /dev/null @@ -1,62 +0,0 @@ - -use std::fmt; -use error::ToErrorCode; -use utils::error::{NO_PAYMENT_INFORMATION, INVALID_CREDENTIAL_HANDLE, INVALID_STATE, NOT_READY, INVALID_JSON}; -use error::payment; - -#[derive(Debug)] -pub enum CredentialError { - NotReady(), - InvalidHandle(), - InvalidCredentialJson(), - InvalidState(), - PaymentError(payment::PaymentError), - NoPaymentInformation(), - CommonError(u32), -} - -impl fmt::Display for CredentialError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - CredentialError::InvalidState() => write!(f, "{}", INVALID_STATE.message), - CredentialError::NotReady() => write!(f, "{}", NOT_READY.message), - CredentialError::InvalidHandle() => write!(f, "{}", INVALID_CREDENTIAL_HANDLE.message), - CredentialError::InvalidCredentialJson() => write!(f, "{}", INVALID_JSON.message), - CredentialError::PaymentError(ref pe) => write!(f, "Payment Error: {}", pe.to_error_code()), - CredentialError::NoPaymentInformation() => write!(f, "{}", NO_PAYMENT_INFORMATION.message), - CredentialError::CommonError(x) => write!(f, "This Credential Error had a value: {}", x), - } - } -} - -impl PartialEq for CredentialError{ - fn eq(&self, other: &CredentialError) -> bool { - self.to_error_code() == other.to_error_code() - } -} - -impl ToErrorCode for CredentialError { - fn to_error_code(&self) -> u32 { - match *self { - CredentialError::InvalidState() => INVALID_STATE.code_num, - CredentialError::NotReady() => NOT_READY.code_num, - CredentialError::InvalidHandle() => INVALID_CREDENTIAL_HANDLE.code_num, - CredentialError::InvalidCredentialJson() => INVALID_JSON.code_num, - CredentialError::PaymentError(ref pe) => pe.to_error_code(), - CredentialError::NoPaymentInformation() => NO_PAYMENT_INFORMATION.code_num, - CredentialError::CommonError(x) => x, - } - } -} - -impl From for CredentialError { - fn from(error:payment::PaymentError) -> Self { - CredentialError::PaymentError(error) - } -} - -impl From for CredentialError{ - fn from(err: u32) -> Self { - CredentialError::CommonError(err) - } -} \ No newline at end of file diff --git a/vcx/libvcx/src/error/issuer_cred.rs b/vcx/libvcx/src/error/issuer_cred.rs deleted file mode 100644 index be06638c75..0000000000 --- a/vcx/libvcx/src/error/issuer_cred.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::fmt; -use utils::error::{INVALID_REVOCATION_DETAILS, NO_PAYMENT_INFORMATION, OBJECT_CACHE_ERROR, INVALID_CREDENTIAL_JSON, NOT_READY, INVALID_ISSUER_CREDENTIAL_HANDLE, INVALID_CREDENTIAL_REQUEST, INVALID_JSON}; -use error::ToErrorCode; -use serde_json; - -#[derive(Debug)] -pub enum IssuerCredError { - CommonError(u32), - CreateError(), - NotReadyError(), - InvalidHandle(), - InvalidCredRequest(), - InvalidCred(), - NoPaymentInformation(), - InvalidJson(), - InvalidRevocationInfo(), -} - -impl fmt::Display for IssuerCredError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - IssuerCredError::CommonError(x) => write!(f, "This Common Error had value: {}", x), - IssuerCredError::NotReadyError() => write!(f, "{}", NOT_READY.message), - IssuerCredError::InvalidHandle() => write!(f, "{}", INVALID_ISSUER_CREDENTIAL_HANDLE.message), - IssuerCredError::InvalidCredRequest() => write!(f, "{}", INVALID_CREDENTIAL_REQUEST.message), - IssuerCredError::InvalidCred() => write!(f, "{}", INVALID_CREDENTIAL_JSON.message), - IssuerCredError::InvalidJson() => write!(f, "{}", INVALID_JSON.message), - IssuerCredError::NoPaymentInformation() => write!(f, "{}", NO_PAYMENT_INFORMATION.message), - IssuerCredError::CreateError() => write!(f, "Could not create issuer credential"), - IssuerCredError::InvalidRevocationInfo() => write!(f, "{}",INVALID_REVOCATION_DETAILS.message), - } - } -} -impl ToErrorCode for IssuerCredError { - fn to_error_code(&self) -> u32 { - match *self { - IssuerCredError::NotReadyError() => NOT_READY.code_num, - IssuerCredError::InvalidHandle() => INVALID_ISSUER_CREDENTIAL_HANDLE.code_num, - IssuerCredError::InvalidCredRequest() => INVALID_CREDENTIAL_REQUEST.code_num, - IssuerCredError::InvalidJson() => INVALID_JSON.code_num, - IssuerCredError::InvalidCred() => INVALID_CREDENTIAL_JSON.code_num, - IssuerCredError::CreateError() => OBJECT_CACHE_ERROR.code_num, - IssuerCredError::NoPaymentInformation() => NO_PAYMENT_INFORMATION.code_num, - IssuerCredError::InvalidRevocationInfo() => INVALID_REVOCATION_DETAILS.code_num, - IssuerCredError::CommonError(x) => x, - } - } -} - -impl PartialEq for IssuerCredError { - fn eq(&self, other: &IssuerCredError) -> bool { - self.to_error_code() == other.to_error_code() - } -} - -impl From for IssuerCredError { - fn from(err:serde_json::Error) -> Self { - IssuerCredError::InvalidJson() - } -} - -impl From for IssuerCredError{ - fn from(err: u32) -> Self { - IssuerCredError::CommonError(err) - } -} - diff --git a/vcx/libvcx/src/error/messages.rs b/vcx/libvcx/src/error/messages.rs deleted file mode 100644 index 458d703599..0000000000 --- a/vcx/libvcx/src/error/messages.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::fmt; -use error::ToErrorCode; - -#[derive(Debug)] -pub enum MessageError { - MessagePackError(), -} - -impl fmt::Display for MessageError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - MessageError::MessagePackError() => write!(f, "Deserialize Error for Message Pack"), - } - } -} -impl ToErrorCode for MessageError { - fn to_error_code(&self) -> u32 { - match *self { - MessageError::MessagePackError() => 8001, - } - } - -} diff --git a/vcx/libvcx/src/error/mod.rs b/vcx/libvcx/src/error/mod.rs index 71d5c0c77e..bc68823c11 100644 --- a/vcx/libvcx/src/error/mod.rs +++ b/vcx/libvcx/src/error/mod.rs @@ -1,23 +1,375 @@ -pub mod base; -pub mod connection; -pub mod schema; -pub mod cred_def; -pub mod issuer_cred; -pub mod proof; -pub mod credential; -pub mod wallet; -pub mod messages; -pub mod payment; +use std::fmt; +use failure::{Context, Backtrace, Fail}; -pub trait ToErrorCode { - fn to_error_code(&self) -> u32; +use utils::error; + +pub mod prelude { + pub use super::{err_msg, VcxError, VcxErrorExt, VcxErrorKind, VcxResult, VcxResultExt}; +} + +#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)] +pub enum VcxErrorKind { + // Common + #[fail(display = "Object is in invalid state for requested operation")] + InvalidState, + #[fail(display = "Invalid Configuration")] + InvalidConfiguration, + #[fail(display = "Obj was not found with handle")] + InvalidHandle, + #[fail(display = "Invalid JSON string")] + InvalidJson, + #[fail(display = "Invalid Option")] + InvalidOption, + #[fail(display = "Invalid message pack")] + InvalidMessagePack, + #[fail(display = "Object cache error")] + ObjectCacheError, + #[fail(display = "Object not ready for specified action")] + NotReady, + #[fail(display = "IO Error, possibly creating a backup wallet")] + IOError, + + // Connection + #[fail(display = "Cannot create connection")] + CreateConnection, + #[fail(display = "Invalid connection handle")] + InvalidConnectionHandle, + #[fail(display = "Invalid invite detail")] + InvalidInviteDetail, + #[fail(display = "Cannot delete connection")] + DeleteConnection, + #[fail(display = "Error with Connection")] + GeneralConnectionError, + + // Payment + #[fail(display = "Payment information not found")] + NoPaymentInformation, + #[fail(display = "Insufficient amount of tokens to process request")] + InsufficientTokenAmount, + #[fail(display = "Invalid payment address")] + InvalidPaymentAddress, + + // Credential Definition error + #[fail(display = "Cannot create credential definition")] + CreateCredDef, + #[fail(display = "Credential definition already created")] + CredDefAlreadyCreated, + #[fail(display = "Invalid credential definition handle")] + InvalidCredDefHandle, + + // Revocation + #[fail(display = "Cannot create revocation registry definition")] + CreateRevRegDef, + #[fail(display = "Invalid revocation deltas")] + InvalidRevocationDetails, + #[fail(display = "Invalid revocation entry")] + InvalidRevocationEntry, + #[fail(display = "Invalid Credential Revocation timestamp")] + InvalidRevocationTimestamp, + + // Credential + #[fail(display = "Invalid credential handle")] + InvalidCredentialHandle, + #[fail(display = "could not create credential request")] + CreateCredentialRequest, + + // Issuer Credential + #[fail(display = "Invalid issuer credential handle")] + InvalidIssuerCredentialHandle, + #[fail(display = "Invalid Credential Request")] + InvalidCredentialRequest, + #[fail(display = "Invalid Credential")] + InvalidCredential, + #[fail(display = "Attributes provided to Credential Offer are not correct, possibly malformed")] + InvalidAttributesStructure, + + // Proof + #[fail(display = "Invalid proof handle")] + InvalidProofHandle, + #[fail(display = "Proof had invalid format")] + InvalidProof, + #[fail(display = "Schema was invalid or corrupt")] + InvalidSchema, + #[fail(display = "The Proof received does not have valid credentials listed.")] + InvalidProofCredentialData, + #[fail(display = "Could not create proof")] + CreateProof, + #[fail(display = "Proof Request Passed into Libindy Call Was Invalid")] + InvalidProofRequest, + + // Schema + #[fail(display = "Could not create schema")] + CreateSchema, + #[fail(display = "Invalid Schema Handle")] + InvalidSchemaHandle, + #[fail(display = "No Schema for that schema sequence number")] + InvalidSchemaSeqNo, + #[fail(display = "Duplicate Schema: Ledger Already Contains Schema For Given DID, Version, and Name Combination")] + DuplicationSchema, + #[fail(display = "Unknown Rejection of Schema Creation, refer to libindy documentation")] + UnknownSchemaRejection, + + // Pool + #[fail(display = "Formatting for Pool Config are incorrect.")] + CreatePoolConfig, + #[fail(display = "Invalid response from ledger for paid transaction")] + InvalidLedgerResponse, + #[fail(display = "No Pool open. Can't return handle.")] + NoPoolOpen, + #[fail(display = "Message failed in post.")] + PostMessageFailed, + + // Wallet + #[fail(display = "Error Creating a wallet")] + WalletCreate, + #[fail(display = "Missing wallet name in config")] + MissingWalletName, + #[fail(display = "Missing exported wallet path in config")] + MissingExportedWalletPath, + #[fail(display = "Missing exported backup key in config")] + MissingBackupKey, + #[fail(display = "Wallet Storage Parameter Either Malformed or Missing")] + InvalidWalletStorageParams, + #[fail(display = "Invalid Wallet or Search Handle")] + InvalidWalletHandle, + #[fail(display = "Indy wallet already exists")] + DuplicationWallet, + #[fail(display = "Wallet record not found")] + WalletRecordNotFound, + #[fail(display = "Record already exists in the wallet")] + DuplicationWalletRecord, + #[fail(display = "Wallet not found")] + WalletNotFound, + #[fail(display = "Indy wallet already open")] + WalletAlreadyOpen, + #[fail(display = "Configuration is missing wallet key")] + MissingWalletKey, + #[fail(display = "Attempted to add a Master Secret that already existed in wallet")] + DuplicationMasterSecret, + #[fail(display = "Attempted to add a DID to wallet when that DID already exists in wallet")] + DuplicationDid, + + // Logger + #[fail(display = "Logging Error")] + LoggingError, + + // Validation + #[fail(display = "Could not encode string to a big integer.")] + EncodeError, + #[fail(display = "Unknown Error")] + UnknownError, + #[fail(display = "Invalid DID")] + InvalidDid, + #[fail(display = "Invalid VERKEY")] + InvalidVerkey, + #[fail(display = "Invalid NONCE")] + InvalidNonce, + #[fail(display = "Invalid URL")] + InvalidUrl, + #[fail(display = "Configuration is missing the Payment Method parameter")] + MissingPaymentMethod, + #[fail(display = "Unable to serialize")] + SerializationError, + #[fail(display = "Value needs to be base58")] + NotBase58, + + // A2A + #[fail(display = "Invalid HTTP response.")] + InvalidHttpResponse, + #[fail(display = "No Endpoint set for Connection Object")] + NoEndpoint, + #[fail(display = "Error Retrieving messages from API")] + InvalidMessages, + + #[fail(display = "Common error {}", 0)] + Common(u32), + #[fail(display = "Liibndy error {}", 0)] + LiibndyError(u32), +} + +#[derive(Debug)] +pub struct VcxError { + inner: Context } -#[cfg(test)] -mod tests { - #[test] - fn test_to_error_code(){ +impl Fail for VcxError { + fn cause(&self) -> Option<&Fail> { + self.inner.cause() + } + fn backtrace(&self) -> Option<&Backtrace> { + self.inner.backtrace() } } + +impl fmt::Display for VcxError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut first = true; + + for cause in Fail::iter_chain(&self.inner) { + if first { + first = false; + writeln!(f, "Error: {}", cause)?; + } else { + writeln!(f, " Caused by: {}", cause)?; + } + } + + Ok(()) + } +} + +impl VcxError { + pub fn from_msg(kind: VcxErrorKind, msg: D) -> VcxError + where D: fmt::Display + fmt::Debug + Send + Sync + 'static { + VcxError { inner: Context::new(msg).context(kind) } + } + + pub fn kind(&self) -> VcxErrorKind { + *self.inner.get_context() + } + + pub fn extend(self, msg: D) -> VcxError + where D: fmt::Display + fmt::Debug + Send + Sync + 'static { + let kind = self.kind(); + VcxError { inner: self.inner.map(|_| msg).context(kind) } + } + + pub fn map(self, kind: VcxErrorKind, msg: D) -> VcxError + where D: fmt::Display + fmt::Debug + Send + Sync + 'static { + VcxError { inner: self.inner.map(|_| msg).context(kind) } + } +} + +pub fn err_msg(kind: VcxErrorKind, msg: D) -> VcxError + where D: fmt::Display + fmt::Debug + Send + Sync + 'static { + VcxError::from_msg(kind, msg) +} + +impl From for VcxError { + fn from(kind: VcxErrorKind) -> VcxError { + VcxError::from_msg(kind, ::utils::error::error_string(kind.clone().into())) + } +} + +impl From> for VcxError { + fn from(inner: Context) -> VcxError { + VcxError { inner } + } +} + +pub type ErrorCode = u32; + +impl From for ErrorCode { + fn from(code: VcxError) -> ErrorCode { + code.kind().into() + } +} + +impl From for ErrorCode { + fn from(code: VcxErrorKind) -> ErrorCode { + match code { + VcxErrorKind::InvalidState => error::INVALID_STATE.code_num, + VcxErrorKind::InvalidConfiguration => error::INVALID_CONFIGURATION.code_num, + VcxErrorKind::InvalidHandle => error::INVALID_OBJ_HANDLE.code_num, + VcxErrorKind::InvalidJson => error::INVALID_JSON.code_num, + VcxErrorKind::InvalidOption => error::INVALID_OPTION.code_num, + VcxErrorKind::InvalidMessagePack => error::INVALID_MSGPACK.code_num, + VcxErrorKind::ObjectCacheError => error::OBJECT_CACHE_ERROR.code_num, + VcxErrorKind::NoPaymentInformation => error::NO_PAYMENT_INFORMATION.code_num, + VcxErrorKind::NotReady => error::NOT_READY.code_num, + VcxErrorKind::InvalidRevocationDetails => error::INVALID_REVOCATION_DETAILS.code_num, + VcxErrorKind::GeneralConnectionError => error::CONNECTION_ERROR.code_num, + VcxErrorKind::IOError => error::IOERROR.code_num, + VcxErrorKind::CreateConnection => error::CREATE_CONNECTION_ERROR.code_num, + VcxErrorKind::InvalidConnectionHandle => error::INVALID_CONNECTION_HANDLE.code_num, + VcxErrorKind::InvalidInviteDetail => error::INVALID_INVITE_DETAILS.code_num, + VcxErrorKind::DeleteConnection => error::CANNOT_DELETE_CONNECTION.code_num, + VcxErrorKind::CreateCredDef => error::CREATE_CREDENTIAL_DEF_ERR.code_num, + VcxErrorKind::CredDefAlreadyCreated => error::CREDENTIAL_DEF_ALREADY_CREATED.code_num, + VcxErrorKind::InvalidCredDefHandle => error::INVALID_CREDENTIAL_DEF_HANDLE.code_num, + VcxErrorKind::InvalidRevocationEntry => error::INVALID_REV_ENTRY.code_num, + VcxErrorKind::CreateRevRegDef => error::INVALID_REV_REG_DEF_CREATION.code_num, + VcxErrorKind::InvalidCredentialHandle => error::INVALID_CREDENTIAL_HANDLE.code_num, + VcxErrorKind::CreateCredentialRequest => error::CREATE_CREDENTIAL_REQUEST_ERROR.code_num, + VcxErrorKind::InvalidIssuerCredentialHandle => error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num, + VcxErrorKind::InvalidCredentialRequest => error::INVALID_CREDENTIAL_REQUEST.code_num, + VcxErrorKind::InvalidCredential => error::INVALID_CREDENTIAL_JSON.code_num, + VcxErrorKind::InsufficientTokenAmount => error::INSUFFICIENT_TOKEN_AMOUNT.code_num, + VcxErrorKind::InvalidProofHandle => error::INVALID_PROOF_HANDLE.code_num, + VcxErrorKind::InvalidProof => error::INVALID_PROOF.code_num, + VcxErrorKind::InvalidSchema => error::INVALID_SCHEMA.code_num, + VcxErrorKind::InvalidProofCredentialData => error::INVALID_PROOF_CREDENTIAL_DATA.code_num, + VcxErrorKind::CreateProof => error::CREATE_PROOF_ERROR.code_num, + VcxErrorKind::InvalidRevocationTimestamp => error::INVALID_REVOCATION_TIMESTAMP.code_num, + VcxErrorKind::CreateSchema => error::INVALID_SCHEMA_CREATION.code_num, + VcxErrorKind::InvalidSchemaHandle => error::INVALID_SCHEMA_HANDLE.code_num, + VcxErrorKind::InvalidSchemaSeqNo => error::INVALID_SCHEMA_SEQ_NO.code_num, + VcxErrorKind::DuplicationSchema => error::DUPLICATE_SCHEMA.code_num, + VcxErrorKind::UnknownSchemaRejection => error::UNKNOWN_SCHEMA_REJECTION.code_num, + VcxErrorKind::WalletCreate => error::INVALID_WALLET_CREATION.code_num, + VcxErrorKind::MissingWalletName => error::MISSING_WALLET_NAME.code_num, + VcxErrorKind::InvalidWalletStorageParams => error::INVALID_WALLET_STORAGE_PARAMETER.code_num, + VcxErrorKind::InvalidWalletHandle => error::INVALID_WALLET_HANDLE.code_num, + VcxErrorKind::DuplicationWallet => error::WALLET_ALREADY_EXISTS.code_num, + VcxErrorKind::WalletNotFound => error::WALLET_NOT_FOUND.code_num, + VcxErrorKind::WalletRecordNotFound => error::WALLET_RECORD_NOT_FOUND.code_num, + VcxErrorKind::CreatePoolConfig => error::CREATE_POOL_CONFIG.code_num, + VcxErrorKind::DuplicationWalletRecord => error::DUPLICATE_WALLET_RECORD.code_num, + VcxErrorKind::WalletAlreadyOpen => error::WALLET_ALREADY_OPEN.code_num, + VcxErrorKind::DuplicationMasterSecret => error::DUPLICATE_MASTER_SECRET.code_num, + VcxErrorKind::DuplicationDid => error::DID_ALREADY_EXISTS_IN_WALLET.code_num, + VcxErrorKind::InvalidLedgerResponse => error::INVALID_LEDGER_RESPONSE.code_num, + VcxErrorKind::InvalidAttributesStructure => error::INVALID_ATTRIBUTES_STRUCTURE.code_num, + VcxErrorKind::InvalidPaymentAddress => error::INVALID_PAYMENT_ADDRESS.code_num, + VcxErrorKind::NoEndpoint => error::NO_ENDPOINT.code_num, + VcxErrorKind::InvalidProofRequest => error::INVALID_PROOF_REQUEST.code_num, + VcxErrorKind::NoPoolOpen => error::NO_POOL_OPEN.code_num, + VcxErrorKind::PostMessageFailed => error::POST_MSG_FAILURE.code_num, + VcxErrorKind::LoggingError => error::LOGGING_ERROR.code_num, + VcxErrorKind::EncodeError => error::BIG_NUMBER_ERROR.code_num, + VcxErrorKind::UnknownError => error::UNKNOWN_ERROR.code_num, + VcxErrorKind::InvalidDid => error::INVALID_DID.code_num, + VcxErrorKind::InvalidVerkey => error::INVALID_VERKEY.code_num, + VcxErrorKind::InvalidNonce => error::INVALID_NONCE.code_num, + VcxErrorKind::InvalidUrl => error::INVALID_URL.code_num, + VcxErrorKind::MissingWalletKey => error::MISSING_WALLET_KEY.code_num, + VcxErrorKind::MissingPaymentMethod => error::MISSING_PAYMENT_METHOD.code_num, + VcxErrorKind::SerializationError => error::SERIALIZATION_ERROR.code_num, + VcxErrorKind::NotBase58 => error::NOT_BASE58.code_num, + VcxErrorKind::InvalidHttpResponse => error::INVALID_HTTP_RESPONSE.code_num, + VcxErrorKind::InvalidMessages => error::INVALID_MESSAGES.code_num, + VcxErrorKind::MissingExportedWalletPath => error::MISSING_EXPORTED_WALLET_PATH.code_num, + VcxErrorKind::MissingBackupKey => error::MISSING_BACKUP_KEY.code_num, + VcxErrorKind::Common(num) => num, + VcxErrorKind::LiibndyError(num) => num, + } + } +} + +pub type VcxResult = Result; + +/// Extension methods for `Result`. +pub trait VcxResultExt { + fn to_vcx(self, kind: VcxErrorKind, msg: D) -> VcxResult where D: fmt::Display + Send + Sync + 'static; +} + +impl VcxResultExt for Result where E: Fail +{ + fn to_vcx(self, kind: VcxErrorKind, msg: D) -> VcxResult where D: fmt::Display + Send + Sync + 'static { + self.map_err(|err| err.context(msg).context(kind).into()) + } +} + +/// Extension methods for `Error`. +pub trait VcxErrorExt { + fn to_vcx(self, kind: VcxErrorKind, msg: D) -> VcxError where D: fmt::Display + Send + Sync + 'static; +} + +impl VcxErrorExt for E where E: Fail +{ + fn to_vcx(self, kind: VcxErrorKind, msg: D) -> VcxError where D: fmt::Display + Send + Sync + 'static { + self.context(msg).context(kind).into() + } +} \ No newline at end of file diff --git a/vcx/libvcx/src/error/payment.rs b/vcx/libvcx/src/error/payment.rs deleted file mode 100644 index 519e5f0677..0000000000 --- a/vcx/libvcx/src/error/payment.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::error::Error; -use error::ToErrorCode; -use utils::error:: { INVALID_OBJ_HANDLE, INSUFFICIENT_TOKEN_AMOUNT, INVALID_JSON }; -use std::fmt; - -#[derive(Debug)] -pub enum PaymentError { - InvalidHandle(), - InsufficientFunds(), - InvalidWalletJson(), - CommonError(u32), -} - -impl fmt::Display for PaymentError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt:: Result { - match *self { - PaymentError::InvalidHandle() => write!(f, "{}", INVALID_OBJ_HANDLE.message), - PaymentError::InsufficientFunds() => write!(f, "{}", INSUFFICIENT_TOKEN_AMOUNT.message), - PaymentError::InvalidWalletJson() => write!(f, "{}", INVALID_JSON.message), - PaymentError::CommonError(ec) => write!( f, "Libindy/Commmon Error: {}", ec), - } - } -} -impl Error for PaymentError { - fn cause(&self) -> Option<&Error> { - match *self { - PaymentError::InvalidHandle() => None, - PaymentError::InsufficientFunds() => None, - PaymentError::InvalidWalletJson() => None, - PaymentError::CommonError(ec) => None, - } - } - - fn description(&self) -> &str { - match *self { - PaymentError::InvalidHandle() => INVALID_OBJ_HANDLE.message, - PaymentError::InsufficientFunds() => INSUFFICIENT_TOKEN_AMOUNT.message, - PaymentError::InvalidWalletJson() => INVALID_JSON.message, - PaymentError::CommonError(ec) => "Libindy/Common Error", - } - } -} - -impl ToErrorCode for PaymentError { - fn to_error_code(&self) -> u32 { - match *self { - PaymentError::InvalidHandle() => INVALID_OBJ_HANDLE.code_num, - PaymentError::InsufficientFunds() => INSUFFICIENT_TOKEN_AMOUNT.code_num, - PaymentError::InvalidWalletJson() => INVALID_JSON.code_num, - PaymentError::CommonError(ec) => ec, - } - } -} - -impl PartialEq for PaymentError { - fn eq(&self, other: &PaymentError) -> bool {self.to_error_code() == other.to_error_code() } -} - diff --git a/vcx/libvcx/src/error/proof.rs b/vcx/libvcx/src/error/proof.rs deleted file mode 100644 index 9456253784..0000000000 --- a/vcx/libvcx/src/error/proof.rs +++ /dev/null @@ -1,78 +0,0 @@ -use std::fmt; -use error::ToErrorCode; -use utils::error::{INVALID_JSON, INVALID_PROOF_HANDLE, INVALID_PROOF, INVALID_PROOF_CREDENTIAL_DATA, INVALID_SCHEMA, -NOT_READY, INVALID_CONNECTION_HANDLE, CONNECTION_ERROR, FAILED_PROOF_COMPLIANCE, CREATE_PROOF_ERROR, INVALID_REVOCATION_TIMESTAMP, INVALID_REVOCATION_DETAILS}; - - -#[derive(Debug)] -pub enum ProofError{ - InvalidHandle(), - InvalidProof(), - InvalidCredData(), - InvalidSchema(), - InvalidRevocationInfo(), - ProofNotReadyError(), - ProofMessageError(u32), - ProofConnectionError(), - CreateProofError(), - InvalidConnection(), - FailedProofCompliance(), - InvalidJson(), - InvalidTimestamp(), - CommonError(u32), -} - -impl fmt::Display for ProofError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ProofError::InvalidHandle() => write!(f, "{}", INVALID_PROOF_HANDLE.message), - ProofError::InvalidProof() => write!(f, "{}", INVALID_PROOF.message), - ProofError::InvalidSchema() => write!(f, "{}", INVALID_SCHEMA.message), - ProofError::InvalidCredData() => write!(f, "{}", INVALID_PROOF_CREDENTIAL_DATA.message), - ProofError::InvalidConnection() => write!(f, "{}", CONNECTION_ERROR.message), - ProofError::ProofNotReadyError() => write!(f, "{}", NOT_READY.message), - ProofError::ProofConnectionError() => write!(f, "{}", INVALID_CONNECTION_HANDLE.message), - ProofError::FailedProofCompliance() => write!(f, "{}", FAILED_PROOF_COMPLIANCE.message), - ProofError::CreateProofError() => write!(f, "{}", CREATE_PROOF_ERROR.message), - ProofError::ProofMessageError(x) => write!(f, "Proof Error: Message Error value: , {}", x), - ProofError::InvalidJson() => write!(f, "{}", INVALID_JSON.message), - ProofError::InvalidTimestamp() => write!(f, "{}", INVALID_REVOCATION_TIMESTAMP.message), - ProofError::InvalidRevocationInfo() => write!(f, "{}",INVALID_REVOCATION_DETAILS.message), - ProofError::CommonError(x) => write!(f, "This Proof Error Common Error had value: {}", x), - } - } -} - -impl PartialEq for ProofError { - fn eq(&self, other: &ProofError) -> bool { - self.to_error_code() == other.to_error_code() - } -} - -impl ToErrorCode for ProofError { - fn to_error_code(&self) -> u32 { - match *self { - ProofError::InvalidHandle() => INVALID_PROOF_HANDLE.code_num, - ProofError::InvalidProof() => INVALID_PROOF.code_num, - ProofError::InvalidSchema() => INVALID_SCHEMA.code_num, - ProofError::InvalidCredData() => INVALID_PROOF_CREDENTIAL_DATA.code_num, - ProofError::InvalidRevocationInfo() => INVALID_REVOCATION_DETAILS.code_num, - ProofError::InvalidConnection() => CONNECTION_ERROR.code_num, - ProofError::CreateProofError() => CREATE_PROOF_ERROR.code_num, - ProofError::ProofNotReadyError() => NOT_READY.code_num, - ProofError::ProofConnectionError() => INVALID_CONNECTION_HANDLE.code_num, - ProofError::FailedProofCompliance() => FAILED_PROOF_COMPLIANCE.code_num, - ProofError::InvalidJson() => INVALID_JSON.code_num, - ProofError::InvalidTimestamp() => INVALID_REVOCATION_TIMESTAMP.code_num, - ProofError::ProofMessageError(x) => x, - ProofError::CommonError(x) => x, - } - } -} - -impl From for ProofError{ - fn from(err: u32) -> Self { - ProofError::CommonError(err) - } -} - diff --git a/vcx/libvcx/src/error/schema.rs b/vcx/libvcx/src/error/schema.rs deleted file mode 100644 index b9ff8b073a..0000000000 --- a/vcx/libvcx/src/error/schema.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::fmt; -use error::ToErrorCode; -use utils::error::{NO_PAYMENT_INFORMATION, INVALID_SCHEMA_CREATION, INVALID_SCHEMA_HANDLE, INVALID_SCHEMA_SEQ_NO, DUPLICATE_SCHEMA, UNKNOWN_SCHEMA_REJECTION}; -#[derive(Debug)] -pub enum SchemaError { - InvalidSchemaCreation(), - InvalidHandle(), - InvalidSchemaSeqNo(), - DuplicateSchema(), - UnknownRejection(), - NoPaymentInformation(), - CommonError(u32), -} - -impl ToErrorCode for SchemaError { - fn to_error_code(&self) -> u32 { - match *self { - SchemaError::InvalidSchemaCreation() => INVALID_SCHEMA_CREATION.code_num, - SchemaError::InvalidHandle() => INVALID_SCHEMA_HANDLE.code_num, - SchemaError::InvalidSchemaSeqNo() => INVALID_SCHEMA_SEQ_NO.code_num, - SchemaError::NoPaymentInformation() => NO_PAYMENT_INFORMATION.code_num, - SchemaError::UnknownRejection() => UNKNOWN_SCHEMA_REJECTION.code_num, - SchemaError::DuplicateSchema() => DUPLICATE_SCHEMA.code_num, - SchemaError::CommonError(x) => x, - } - } -} - -impl fmt::Display for SchemaError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - SchemaError::InvalidSchemaCreation() => write!(f, "{}", INVALID_SCHEMA_CREATION.message), - SchemaError::InvalidHandle() => write!(f, "{}", INVALID_SCHEMA_HANDLE.message), - SchemaError::InvalidSchemaSeqNo() => write!(f, "{}", INVALID_SCHEMA_SEQ_NO.message), - SchemaError::NoPaymentInformation() => write!(f, "{}", NO_PAYMENT_INFORMATION.message), - SchemaError::UnknownRejection() => write!(f, "{}", UNKNOWN_SCHEMA_REJECTION.code_num), - SchemaError::DuplicateSchema() => write!(f, "{}", DUPLICATE_SCHEMA.message), - SchemaError::CommonError(x) => write!(f, "This Schema Common Error had a value of {}", x), - } - } -} - -impl PartialEq for SchemaError { - fn eq(&self, other: &SchemaError) -> bool { - self.to_error_code() == other.to_error_code() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_schema_error () { - assert_eq!(SchemaError::InvalidSchemaCreation().to_error_code(), INVALID_SCHEMA_CREATION.code_num); - } - -} \ No newline at end of file diff --git a/vcx/libvcx/src/error/wallet.rs b/vcx/libvcx/src/error/wallet.rs deleted file mode 100644 index 307797d8ef..0000000000 --- a/vcx/libvcx/src/error/wallet.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::fmt; -use error::ToErrorCode; -use utils::error::{ - INVALID_WALLET_CREATION, - INVALID_WALLET_HANDLE, - WALLET_ALREADY_EXISTS, - INVALID_JSON, - IOERROR, - WALLET_RECORD_NOT_FOUND, - INVALID_WALLET_STORAGE_PARAMETER, -}; - -#[derive(Debug)] -pub enum WalletError { - InvalidWalletCreation(), - InvalidParamters(), - InvalidHandle(), - InvalidJson(), - IoError(), - DuplicateWallet(String), - RecordNotFound(), - CommonError(u32), -} - -impl ToErrorCode for WalletError { - fn to_error_code(&self) -> u32 { - match *self { - WalletError::InvalidWalletCreation() => INVALID_WALLET_CREATION.code_num, - WalletError::InvalidHandle() => INVALID_WALLET_HANDLE.code_num, - WalletError::DuplicateWallet(_) => WALLET_ALREADY_EXISTS.code_num, - WalletError::InvalidJson() => INVALID_JSON.code_num, - WalletError::IoError() => IOERROR.code_num, - WalletError::InvalidParamters() => INVALID_WALLET_STORAGE_PARAMETER.code_num, - WalletError::RecordNotFound() => WALLET_RECORD_NOT_FOUND.code_num, - WalletError::CommonError(x) => x, - } - } -} - -impl fmt::Display for WalletError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - WalletError::InvalidWalletCreation() => write!(f, "{}", INVALID_WALLET_CREATION.message), - WalletError::InvalidHandle() => write!(f, "{}", INVALID_WALLET_HANDLE.message), - WalletError::IoError() => write!(f, "{}", IOERROR.message), - WalletError::DuplicateWallet(ref s) => write!(f, "{}", s), - WalletError::InvalidJson() => write!(f, "{}", INVALID_JSON.message), - WalletError::InvalidParamters() => write!(f, "{}", INVALID_WALLET_STORAGE_PARAMETER.message), - WalletError::RecordNotFound() => write!(f, "{}", WALLET_RECORD_NOT_FOUND.message), - WalletError::CommonError(x) => write!(f, "This Wallet Common Error had a value of {}", x), - } - } -} - -impl PartialEq for WalletError { - fn eq(&self, other: &WalletError) -> bool { - self.to_error_code() == other.to_error_code() - } -} - -impl From for WalletError { - fn from(ec: u32) -> WalletError { - match ec { - 114 => WalletError::IoError(), - 200 => WalletError::InvalidWalletCreation(), - 1067 => WalletError::InvalidParamters(), - e => WalletError::CommonError(e), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_wallet_err () { - assert_eq!(WalletError::InvalidHandle().to_error_code(), INVALID_WALLET_HANDLE.code_num); - } - -} diff --git a/vcx/libvcx/src/issuer_credential.rs b/vcx/libvcx/src/issuer_credential.rs index c77d36f6d1..47710a5dc0 100644 --- a/vcx/libvcx/src/issuer_credential.rs +++ b/vcx/libvcx/src/issuer_credential.rs @@ -1,34 +1,28 @@ -extern crate rand; -extern crate serde_json; -extern crate libc; - use std::collections::HashMap; use api::VcxStateType; use messages; use settings; -use messages::{RemoteMessageType, MessageStatusCode, GeneralMessage}; +use messages::{RemoteMessageType, MessageStatusCode, GeneralMessage, ObjectWithVersion}; use messages::payload::{Payloads, PayloadKinds, Thread}; use connection; use credential_request::CredentialRequest; use utils::error; -use utils::error::INVALID_JSON; use utils::libindy::payments; use utils::libindy::anoncreds; use utils::constants::CRED_MSG; use utils::openssl::encode; use utils::libindy::payments::PaymentTxn; -use error::{issuer_cred::IssuerCredError, ToErrorCode, payment::PaymentError}; use utils::constants::DEFAULT_SERIALIZE_VERSION; -use serde_json::Value; use object_cache::ObjectCache; +use error::prelude::*; lazy_static! { -static ref ISSUER_CREDENTIAL_MAP: ObjectCache < IssuerCredential > = Default::default(); + static ref ISSUER_CREDENTIAL_MAP: ObjectCache < IssuerCredential > = Default::default(); } static CREDENTIAL_OFFER_ID_KEY: &str = "claim_offer_id"; -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct IssuerCredential { source_id: String, credential_attributes: String, @@ -111,50 +105,54 @@ pub struct PaymentInfo { } impl PaymentInfo { - pub fn get_address(&self) -> Result { - Ok(self.payment_addr.to_string()) + pub fn get_address(&self) -> String { + self.payment_addr.to_string() } - pub fn get_price(&self) -> Result { - Ok(self.price) + pub fn get_price(&self) -> u64 { + self.price } - pub fn to_string(&self) -> Result { serde_json::to_string(&self).or(Err(PaymentError::InvalidWalletJson())) } + pub fn to_string(&self) -> VcxResult { + ::serde_json::to_string(&self) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize payment info"))) + } } impl IssuerCredential { - fn validate_credential_offer(&self) -> Result { + fn validate_credential_offer(&self) -> VcxResult { //TODO: validate credential_attributes against credential_def debug!("successfully validated issuer_credential {}", self.source_id); Ok(error::SUCCESS.code_num) } - fn send_credential_offer(&mut self, connection_handle: u32) -> Result { + fn send_credential_offer(&mut self, connection_handle: u32) -> VcxResult { trace!("IssuerCredential::send_credential_offer >>> connection_handle: {}", connection_handle); debug!("sending credential offer for issuer_credential {} to connection {}", self.source_id, connection::get_source_id(connection_handle).unwrap_or_default()); if self.state != VcxStateType::VcxStateInitialized { warn!("credential {} has invalid state {} for sending credentialOffer", self.source_id, self.state as u32); - return Err(IssuerCredError::NotReadyError()); + return Err(VcxError::from_msg(VcxErrorKind::NotReady, format!("credential {} has invalid state {} for sending credentialOffer", self.source_id, self.state as u32))); } - if connection::is_valid_handle(connection_handle) == false { + if !connection::is_valid_handle(connection_handle) { warn!("invalid connection handle ({})", connection_handle); - return Err(IssuerCredError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num)); + return Err(VcxError::from_msg(VcxErrorKind::InvalidConnectionHandle, format!("invalid connection handle ({})", connection_handle))); } - self.agent_did = connection::get_agent_did(connection_handle).map_err(|e| IssuerCredError::CommonError(e.to_error_code()))?; - self.agent_vk = connection::get_agent_verkey(connection_handle).map_err(|e| IssuerCredError::CommonError(e.to_error_code()))?; - self.issued_did = connection::get_pw_did(connection_handle).map_err(|x| IssuerCredError::CommonError(x.to_error_code()))?; - self.issued_vk = connection::get_pw_verkey(connection_handle).map_err(|x| IssuerCredError::CommonError(x.to_error_code()))?; - self.remote_vk = connection::get_their_pw_verkey(connection_handle).map_err(|x| IssuerCredError::CommonError(x.to_error_code()))?; + self.agent_did = connection::get_agent_did(connection_handle)?; + self.agent_vk = connection::get_agent_verkey(connection_handle)?; + self.issued_did = connection::get_pw_did(connection_handle)?; + self.issued_vk = connection::get_pw_verkey(connection_handle)?; + self.remote_vk = connection::get_their_pw_verkey(connection_handle)?; let payment = self.generate_payment_info()?; let credential_offer = self.generate_credential_offer(&self.issued_did)?; let cred_json = json!(credential_offer); let mut payload = Vec::new(); - let connection_name = settings::get_config_value(settings::CONFIG_INSTITUTION_NAME).map_err(|e| IssuerCredError::CommonError(e))?; + let connection_name = settings::get_config_value(settings::CONFIG_INSTITUTION_NAME)?; + let title = if let Some(x) = payment { payload.push(json!(x)); format!("{} wants you to pay tokens for: {}", connection_name, self.credential_name) @@ -164,7 +162,8 @@ impl IssuerCredential { payload.push(cred_json); - let payload = serde_json::to_string(&payload).or(Err(IssuerCredError::CommonError(error::INVALID_JSON.code_num)))?; + let payload = ::serde_json::to_string(&payload) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize payload: {}", err)))?; debug!("credential offer data: {}", payload); @@ -193,33 +192,38 @@ impl IssuerCredential { return Ok(error::SUCCESS.code_num); } - fn send_credential(&mut self, connection_handle: u32) -> Result { + fn send_credential(&mut self, connection_handle: u32) -> VcxResult { trace!("IssuerCredential::send_credential >>> connection_handle: {}", connection_handle); debug!("sending credential for issuer_credential {} to connection {}", self.source_id, connection::get_source_id(connection_handle).unwrap_or_default()); if self.state != VcxStateType::VcxStateRequestReceived { warn!("credential {} has invalid state {} for sending credential", self.source_id, self.state as u32); - return Err(IssuerCredError::NotReadyError()); + return Err(VcxError::from_msg(VcxErrorKind::NotReady, format!("credential {} has invalid state {} for sending credential", self.source_id, self.state as u32))); } if connection::is_valid_handle(connection_handle) == false { warn!("invalid connection handle ({}) in send_credential_offer", connection_handle); - return Err(IssuerCredError::InvalidHandle()); + return Err(VcxError::from_msg(VcxErrorKind::InvalidCredentialHandle, format!("invalid connection handle ({}) in send_credential_offer", connection_handle))); } - self.verify_payment().map_err(|e| IssuerCredError::CommonError(e))?; + self.verify_payment()?; - let to = connection::get_pw_did(connection_handle).map_err(|e| IssuerCredError::CommonError(e.to_error_code()))?; + let to = connection::get_pw_did(connection_handle)?; let attrs_with_encodings = self.create_attributes_encodings()?; - let data = if settings::test_indy_mode_enabled() { CRED_MSG.to_string() } else { + + let data = if settings::test_indy_mode_enabled() { + CRED_MSG.to_string() + } else { let cred = self.generate_credential(&attrs_with_encodings, &to)?; - serde_json::to_string(&cred).or(Err(IssuerCredError::InvalidCred()))? + ::serde_json::to_string(&cred).or(Err(VcxError::from(VcxErrorKind::InvalidCredential)))? }; debug!("credential data: {}", data); - let cred_req_msg_id = self.credential_request.as_ref().and_then(|cred_req| cred_req.msg_ref_id.as_ref()) - .ok_or(IssuerCredError::InvalidCredRequest())?; + let cred_req_msg_id = self.credential_request + .as_ref() + .and_then(|cred_req| cred_req.msg_ref_id.as_ref()) + .ok_or(VcxError::from(VcxErrorKind::InvalidCredentialRequest))?; self.thread.sender_order += 1; @@ -245,13 +249,13 @@ impl IssuerCredential { return Ok(error::SUCCESS.code_num); } - pub fn create_attributes_encodings(&self) -> Result { + pub fn create_attributes_encodings(&self) -> VcxResult { encode_attributes(&self.credential_attributes) } // TODO: The error arm of this Result is never used in any calling functions. // So currently there is no way to test the error status. - fn get_credential_offer_status(&mut self) -> Result { + fn get_credential_offer_status(&mut self) -> VcxResult { debug!("updating state for credential offer: {} msg_uid: {:?}", self.source_id, self.msg_uid); if self.state == VcxStateType::VcxStateRequestReceived { return Ok(self.get_state()); @@ -263,11 +267,15 @@ impl IssuerCredential { &self.issued_did, &self.issued_vk, &self.agent_did, - &self.agent_vk) - .map_err(|wc| IssuerCredError::CommonError(wc))?; + &self.agent_vk)?; - let (payload, thread) = Payloads::decrypt(&self.issued_vk, &payload).map_err(|ec| IssuerCredError::CommonError(ec))?; - let cred_req = parse_credential_req_payload(offer_uid, payload)?; + let (payload, thread) = Payloads::decrypt(&self.issued_vk, &payload) + .map_err(|err| VcxError::from_msg(VcxErrorKind::Common(err.into()), "Cannot decrypt CredentialOffer payload"))?; + + let mut cred_req: CredentialRequest = ::serde_json::from_str(&payload) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize CredentialRequest: {}", err)))?; + + cred_req.msg_ref_id = Some(offer_uid); if let Some(tr) = thread { self.thread.increment_receiver(self.remote_did.as_str()); @@ -279,7 +287,7 @@ impl IssuerCredential { Ok(self.get_state()) } - fn update_state(&mut self) -> Result { + fn update_state(&mut self) -> VcxResult { trace!("IssuerCredential::update_state >>>"); self.get_credential_offer_status() //There will probably be more things here once we do other things with the credential @@ -292,28 +300,25 @@ impl IssuerCredential { } fn get_offer_uid(&self) -> &String { &self.msg_uid } fn set_offer_uid(&mut self, uid: &str) { self.msg_uid = uid.to_owned(); } - fn set_credential_request(&mut self, credential_request: CredentialRequest) -> Result { - self.credential_request = Some(credential_request); - Ok(error::SUCCESS.code_num) - } fn get_credential_attributes(&self) -> &String { &self.credential_attributes } fn get_source_id(&self) -> &String { &self.source_id } - fn generate_credential(&mut self, credential_data: &str, did: &str) -> Result { - let indy_cred_offer = &self.credential_offer.as_ref() - .ok_or(IssuerCredError::InvalidCred())?.libindy_offer; + fn generate_credential(&mut self, credential_data: &str, did: &str) -> VcxResult { + let indy_cred_offer = self.credential_offer + .as_ref() + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidCredential, "Invalid Credential: `credential_offer` field not found"))?; - let indy_cred_req = &self.credential_request.as_ref() - .ok_or(IssuerCredError::InvalidCredRequest())?.libindy_cred_req; + let indy_cred_req = self.credential_request + .as_ref() + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidCredentialRequest, "Invalid Credential: `credential_request` field not found"))?; - let (cred, cred_revoc_id, revoc_reg_delta_json) = anoncreds::libindy_issuer_create_credential( - &indy_cred_offer, - &indy_cred_req, - credential_data, - self.rev_reg_id.clone(), - self.tails_file.clone()) - .map_err(|x| IssuerCredError::CommonError(x))?; + let (cred, cred_revoc_id, revoc_reg_delta_json) = + anoncreds::libindy_issuer_create_credential(&indy_cred_offer.libindy_offer, + &indy_cred_req.libindy_cred_req, + &credential_data, + self.rev_reg_id.clone(), + self.tails_file.clone())?; self.cred_rev_id = cred_revoc_id.clone(); @@ -330,11 +335,11 @@ impl IssuerCredential { }) } - fn generate_credential_offer(&self, to_did: &str) -> Result { + fn generate_credential_offer(&self, to_did: &str) -> VcxResult { let attr_map = convert_to_map(&self.credential_attributes)?; //Todo: make a cred_def_offer error - let libindy_offer = anoncreds::libindy_issuer_create_credential_offer(&self.cred_def_id) - .map_err(|err| IssuerCredError::CommonError(err))?; + let libindy_offer = anoncreds::libindy_issuer_create_credential_offer(&self.cred_def_id)?; + Ok(CredentialOffer { msg_type: PayloadKinds::CredOffer.name().to_string(), version: String::from("0.1"), @@ -351,29 +356,28 @@ impl IssuerCredential { }) } - fn revoke_cred(&mut self) -> Result<(), IssuerCredError> { + fn revoke_cred(&mut self) -> VcxResult<()> { let tails_file = self.tails_file .as_ref() - .ok_or(IssuerCredError::InvalidRevocationInfo())?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidRevocationDetails, "Invalid RevocationInfo: `tails_file` field not found"))?; let rev_reg_id = self.rev_reg_id .as_ref() - .ok_or(IssuerCredError::InvalidRevocationInfo())?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidRevocationDetails, "Invalid RevocationInfo: `rev_reg_id` field not found"))?; let cred_rev_id = self.cred_rev_id .as_ref() - .ok_or(IssuerCredError::InvalidRevocationInfo())?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidRevocationDetails, "Invalid RevocationInfo: `cred_rev_id` field not found"))?; - let (payment, _) = anoncreds::revoke_credential(tails_file, rev_reg_id, cred_rev_id) - .map_err(|e| IssuerCredError::CommonError(e))?; + let (payment, _) = anoncreds::revoke_credential(tails_file, rev_reg_id, cred_rev_id)?; self.rev_cred_payment_txn = payment; Ok(()) } - fn generate_payment_info(&mut self) -> Result, IssuerCredError> { + fn generate_payment_info(&mut self) -> VcxResult> { if self.price > 0 { - let address: String = ::utils::libindy::payments::create_address(None).map_err(|x| IssuerCredError::CommonError(x))?; + let address: String = ::utils::libindy::payments::create_address(None)?; self.payment_address = Some(address.clone()); Ok(Some(PaymentInfo { payment_required: "one-time".to_string(), @@ -385,19 +389,19 @@ impl IssuerCredential { } } - fn verify_payment(&mut self) -> Result<(), u32> { + fn verify_payment(&mut self) -> VcxResult<()> { if self.price > 0 { let invoice_address = self.payment_address.as_ref() - .ok_or(error::INVALID_PAYMENT_ADDRESS.code_num)?; + .ok_or(VcxError::from(VcxErrorKind::InvalidPaymentAddress))?; let address = payments::get_address_info(&invoice_address)?; - if address.balance < self.price { return Err(error::INSUFFICIENT_TOKEN_AMOUNT.code_num); } + if address.balance < self.price { return Err(VcxError::from(VcxErrorKind::InsufficientTokenAmount)); } } Ok(()) } - fn get_payment_txn(&self) -> Result { + fn get_payment_txn(&self) -> VcxResult { trace!("IssuerCredential::get_payment_txn >>>"); match self.payment_address { @@ -409,21 +413,20 @@ impl IssuerCredential { outputs: Vec::new(), }) } - _ => Err(error::NO_PAYMENT_INFORMATION.code_num) + _ => Err(VcxError::from(VcxErrorKind::NoPaymentInformation)) } } - pub fn to_string(&self) -> String { - json!({ - "version": DEFAULT_SERIALIZE_VERSION, - "data": json ! ( self), - }).to_string() + pub fn to_string(&self) -> VcxResult { + ObjectWithVersion::new(DEFAULT_SERIALIZE_VERSION, self.to_owned()) + .serialize() + .map_err(|err| err.extend("Cannot serialize credential")) } - fn from_str(s: &str) -> Result { - let data: Value = serde_json::from_str(&s)?; - let cred = serde_json::from_value(data["data"].clone())?; - Ok(cred) + fn from_str(data: &str) -> VcxResult { + ObjectWithVersion::deserialize(data) + .map(|obj: ObjectWithVersion| obj.data) + .map_err(|err| err.extend("Cannot deserialize IssuerCredential")) } } @@ -446,34 +449,25 @@ impl IssuerCredential { } } */ -pub fn encode_attributes(attributes: &str) -> Result { - let mut attributes: serde_json::Value = match serde_json::from_str(attributes) { - Ok(x) => x, - Err(e) => { - warn!("Invalid Json for Attribute data"); - return Err(IssuerCredError::CommonError(INVALID_JSON.code_num)); - } - }; - let map = match attributes.as_object_mut() { - Some(x) => x, - None => { +pub fn encode_attributes(attributes: &str) -> VcxResult { + let mut attributes: HashMap = ::serde_json::from_str(attributes) + .map_err(|err| { warn!("Invalid Json for Attribute data"); - return Err(IssuerCredError::CommonError(INVALID_JSON.code_num)); - } - }; + VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize credential attributes: {}", err)) + })?; let mut dictionary = HashMap::new(); - for (attr, attr_data) in map.iter_mut() { + for (attr, attr_data) in attributes.iter_mut() { let first_attr: &str = match attr_data { // old style input such as {"address2":["101 Wilson Lane"]} serde_json::Value::Array(array_type) => { - let attrib_value: &str = match array_type.get(0).and_then(serde_json::Value::as_str) { + let attrib_value: &str = match array_type.get(0).and_then(::serde_json::Value::as_str) { Some(x) => x, None => { warn!("Cannot encode attribute: {}", error::INVALID_ATTRIBUTES_STRUCTURE.message); - return Err(IssuerCredError::CommonError(error::INVALID_ATTRIBUTES_STRUCTURE.code_num)); + return Err(VcxError::from_msg(VcxErrorKind::InvalidAttributesStructure, "Attribute value not found")); } }; @@ -482,62 +476,46 @@ pub fn encode_attributes(attributes: &str) -> Result { } // new style input such as {"address2":"101 Wilson Lane"} - serde_json::Value::String(str_type) => str_type, + ::serde_json::Value::String(str_type) => str_type, // anything else is an error _ => { warn!("Invalid Json for Attribute data"); - return Err(IssuerCredError::CommonError(INVALID_JSON.code_num)); + return Err(VcxError::from_msg(VcxErrorKind::InvalidJson, "Invalid Json for Attribute data")); } }; - let encoded = encode(&first_attr).map_err(|x| IssuerCredError::CommonError(x))?; + let encoded = encode(&first_attr)?; let attrib_values = json!({ -"raw": first_attr, -"encoded": encoded -}); + "raw": first_attr, + "encoded": encoded + }); dictionary.insert(attr, attrib_values); } - match serde_json::to_string_pretty(&dictionary) { - Ok(x) => Ok(x), - Err(x) => { + ::serde_json::to_string_pretty(&dictionary) + .map_err(|err| { warn!("Invalid Json for Attribute data"); - Err(IssuerCredError::CommonError(INVALID_JSON.code_num)) - } - } + VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Invalid Json for Attribute data: {}", err)) + }) } -pub fn get_encoded_attributes(handle: u32) -> Result { +pub fn get_encoded_attributes(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get(handle, |i| { - i.create_attributes_encodings().map_err(|ec| ec.to_error_code()) - }).map_err(|ec| IssuerCredError::CommonError(ec)) + i.create_attributes_encodings() + }) } -pub fn get_offer_uid(handle: u32) -> Result { +pub fn get_offer_uid(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get(handle, |i| { - Ok(i.get_offer_uid().clone()) + Ok(i.get_offer_uid().to_string()) }) } -pub fn get_payment_txn(handle: u32) -> Result { +pub fn get_payment_txn(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get(handle, |i| { i.get_payment_txn() - }).map_err(|ec| IssuerCredError::CommonError(ec)) -} - -fn parse_credential_req_payload(offer_uid: String, payload: String) -> Result { - debug!("parsing credentialReq payload: {:?}", payload); - - let mut my_credential_req: CredentialRequest = serde_json::from_str(&payload) - .map_err(|err| { - warn!("invalid json {}", err); - IssuerCredError::CommonError(error::INVALID_JSON.code_num) - })?; - - my_credential_req.msg_ref_id = Some(offer_uid); - - Ok(my_credential_req) + }) } pub fn issuer_credential_create(cred_def_handle: u32, @@ -545,14 +523,14 @@ pub fn issuer_credential_create(cred_def_handle: u32, issuer_did: String, credential_name: String, credential_data: String, - price: u64) -> Result { + price: u64) -> VcxResult { trace!("issuer_credential_create >>> cred_def_handle: {}, source_id: {}, issuer_did: {}, credential_name: {}, credential_data: {}, price: {}", cred_def_handle, source_id, issuer_did, credential_name, credential_data, price); - let cred_def_id = ::credential_def::get_cred_def_id(cred_def_handle).map_err(|ec| IssuerCredError::CommonError(ec.to_error_code()))?; - let rev_reg_id = ::credential_def::get_rev_reg_id(cred_def_handle).map_err(|ec| IssuerCredError::CommonError(ec.to_error_code()))?; - let tails_file = ::credential_def::get_tails_file(cred_def_handle).map_err(|ec| IssuerCredError::CommonError(ec.to_error_code()))?; - let rev_reg_def_json = ::credential_def::get_rev_reg_def(cred_def_handle).map_err(|ec| IssuerCredError::CommonError(ec.to_error_code()))?; + let cred_def_id = ::credential_def::get_cred_def_id(cred_def_handle)?; + let rev_reg_id = ::credential_def::get_rev_reg_id(cred_def_handle)?; + let tails_file = ::credential_def::get_tails_file(cred_def_handle)?; + let rev_reg_def_json = ::credential_def::get_rev_reg_def(cred_def_handle)?; let mut new_issuer_credential = IssuerCredential { credential_id: source_id.to_string(), @@ -589,122 +567,86 @@ pub fn issuer_credential_create(cred_def_handle: u32, new_issuer_credential.state = VcxStateType::VcxStateInitialized; - let new_handle = ISSUER_CREDENTIAL_MAP.add(new_issuer_credential).map_err(|key| IssuerCredError::CreateError())?; - debug!("creating issuer_credential {} with handle {}", get_source_id(new_handle).unwrap_or_default(), new_handle); + let handle = ISSUER_CREDENTIAL_MAP.add(new_issuer_credential)?; + debug!("creating issuer_credential {} with handle {}", get_source_id(handle).unwrap_or_default(), handle); - Ok(new_handle) + Ok(handle) } -pub fn update_state(handle: u32) -> Result { +pub fn update_state(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get_mut(handle, |i| { match i.update_state() { Ok(x) => Ok(x), Err(x) => Ok(i.get_state()), } - }).map_err(|ec| IssuerCredError::CommonError(ec)) + }) } -pub fn get_state(handle: u32) -> Result { +pub fn get_state(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get(handle, |i| { Ok(i.get_state()) }) } -pub fn release(handle: u32) -> Result<(), IssuerCredError> { - match ISSUER_CREDENTIAL_MAP.release(handle) { - Ok(_) => Ok(()), - Err(_) => Err(IssuerCredError::InvalidHandle()), - } +pub fn release(handle: u32) -> VcxResult<()> { + ISSUER_CREDENTIAL_MAP.release(handle) + .or(Err(VcxError::from(VcxErrorKind::InvalidIssuerCredentialHandle))) } pub fn release_all() { - match ISSUER_CREDENTIAL_MAP.drain() { - Ok(_) => (), - Err(_) => (), - }; + ISSUER_CREDENTIAL_MAP.drain().ok(); } pub fn is_valid_handle(handle: u32) -> bool { ISSUER_CREDENTIAL_MAP.has_handle(handle) } -pub fn to_string(handle: u32) -> Result { +pub fn to_string(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get(handle, |i| { - Ok(IssuerCredential::to_string(&i)) - }).map_err(|ec| IssuerCredError::CommonError(ec)) -} - -pub fn from_string(credential_data: &str) -> Result { - let derived_credential: IssuerCredential = IssuerCredential::from_str(credential_data)?; - let source_id = derived_credential.source_id.clone(); - let new_handle = ISSUER_CREDENTIAL_MAP.add(derived_credential).map_err(|ec| IssuerCredError::CommonError(ec))?; - Ok(new_handle) + i.to_string() + }) } -pub fn send_credential_offer(handle: u32, connection_handle: u32) -> Result { - ISSUER_CREDENTIAL_MAP.get_mut(handle, |i| { - i.send_credential_offer(connection_handle).map_err(|ec| ec.to_error_code()) - }).map_err(|ec| IssuerCredError::CommonError(ec)) +pub fn from_string(credential_data: &str) -> VcxResult { + let schema: IssuerCredential = IssuerCredential::from_str(credential_data)?; + ISSUER_CREDENTIAL_MAP.add(schema) } -pub fn send_credential(handle: u32, connection_handle: u32) -> Result { +pub fn send_credential_offer(handle: u32, connection_handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get_mut(handle, |i| { - i.send_credential(connection_handle).map_err(|ec| ec.to_error_code()) - }).map_err(|ec| IssuerCredError::CommonError(ec)) + i.send_credential_offer(connection_handle) + }) } -pub fn revoke_credential(handle: u32) -> Result<(), u32> { +pub fn send_credential(handle: u32, connection_handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get_mut(handle, |i| { - i.revoke_cred().map_err(|ec| ec.to_error_code()) + i.send_credential(connection_handle) }) } -fn get_offer_details(response: &str) -> Result { - match serde_json::from_str(response) { - Ok(json) => { - let json: serde_json::Value = json; - let detail = match json["uid"].as_str() { - Some(x) => x, - None => { - warn!("response had no uid"); - return Err(IssuerCredError::CommonError(error::INVALID_JSON.code_num)); - } - }; - Ok(String::from(detail)) - } - Err(_) => { - warn!("get_messages called without a valid response from server"); - Err(IssuerCredError::CommonError(error::INVALID_JSON.code_num)) - } - } -} - -pub fn set_credential_request(handle: u32, credential_request: CredentialRequest) -> Result { +pub fn revoke_credential(handle: u32) -> VcxResult<()> { ISSUER_CREDENTIAL_MAP.get_mut(handle, |i| { - i.set_credential_request(credential_request.clone()) - }).map_err(|ec| IssuerCredError::CommonError(ec)) + i.revoke_cred() + }) } -pub fn convert_to_map(s: &str) -> Result, IssuerCredError> { - let v: serde_json::Map = match serde_json::from_str(s) { - Ok(m) => m, - Err(_) => { +pub fn convert_to_map(s: &str) -> VcxResult> { + ::serde_json::from_str(s) + .map_err(|err| { warn!("{}", error::INVALID_ATTRIBUTES_STRUCTURE.message); - return Err(IssuerCredError::CommonError(error::INVALID_ATTRIBUTES_STRUCTURE.code_num)); - } - }; - Ok(v) + VcxError::from_msg(VcxErrorKind::InvalidAttributesStructure, error::INVALID_ATTRIBUTES_STRUCTURE.message) + }) } -pub fn get_credential_attributes(handle: u32) -> Result { +pub fn get_credential_attributes(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get(handle, |i| { - Ok(i.get_credential_attributes().clone()) + Ok(i.get_credential_attributes().to_string()) }) } -pub fn get_source_id(handle: u32) -> Result { +pub fn get_source_id(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get(handle, |i| { - Ok(i.get_source_id().clone()) + Ok(i.get_source_id().to_string()) }) } diff --git a/vcx/libvcx/src/lib.rs b/vcx/libvcx/src/lib.rs index baa39c90d5..491d842e84 100644 --- a/vcx/libvcx/src/lib.rs +++ b/vcx/libvcx/src/lib.rs @@ -31,6 +31,8 @@ extern crate regex; extern crate uuid; +extern crate failure; + #[macro_use] pub mod utils; pub mod settings; diff --git a/vcx/libvcx/src/messages/agent_utils.rs b/vcx/libvcx/src/messages/agent_utils.rs index c0752a214d..b0a86c1728 100644 --- a/vcx/libvcx/src/messages/agent_utils.rs +++ b/vcx/libvcx/src/messages/agent_utils.rs @@ -5,6 +5,7 @@ use messages::message_type::MessageTypes; use utils::{error, httpclient}; use utils::libindy::{wallet, anoncreds}; use utils::libindy::signus::create_and_store_my_did; +use error::prelude::*; #[derive(Serialize, Deserialize, Debug)] pub struct Connect { @@ -126,11 +127,12 @@ pub struct Config { } -pub fn connect_register_provision(config: &str) -> Result { +pub fn connect_register_provision(config: &str) -> VcxResult { trace!("connect_register_provision >>> config: {:?}", config); trace!("***Registering with agency"); - let my_config: Config = serde_json::from_str(&config).or(Err(error::INVALID_CONFIGURATION.code_num))?; + let my_config: Config = ::serde_json::from_str(&config) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidConfiguration, format!("Cannot parse config: {}", err)))?; let wallet_name = my_config.wallet_name.unwrap_or(settings::DEFAULT_WALLET_NAME.to_string()); @@ -156,7 +158,8 @@ pub fn connect_register_provision(config: &str) -> Result { } wallet::init_wallet(&wallet_name, my_config.wallet_type.as_ref().map(String::as_str), - my_config.storage_config.as_ref().map(String::as_str), my_config.storage_credentials.as_ref().map(String::as_str))?; + my_config.storage_config.as_ref().map(String::as_str), + my_config.storage_credentials.as_ref().map(String::as_str))?; trace!("initialized wallet"); anoncreds::libindy_prover_create_master_secret(::settings::DEFAULT_LINK_SECRET_ALIAS).ok(); // If MS is already in wallet then just continue @@ -221,7 +224,7 @@ pub fn connect_register_provision(config: &str) -> Result { Ok(final_config.to_string()) } -fn onboarding_v1(my_did: &str, my_vk: &str, agency_did: &str) -> Result<(String, String), u32> { +fn onboarding_v1(my_did: &str, my_vk: &str, agency_did: &str) -> VcxResult<(String, String)> { /* STEP 1 - CONNECT */ if settings::test_agency_mode_enabled() { httpclient::set_next_u8_response(CONNECTED_RESPONSE.to_vec()); @@ -236,7 +239,7 @@ fn onboarding_v1(my_did: &str, my_vk: &str, agency_did: &str) -> Result<(String, let ConnectResponse { from_vk: agency_pw_vk, from_did: agency_pw_did, .. } = match response.remove(0) { A2AMessage::Version1(A2AMessageV1::ConnectResponse(resp)) => resp, - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) }; settings::set_config_value(settings::CONFIG_REMOTE_TO_SDK_VERKEY, &agency_pw_vk); @@ -255,7 +258,7 @@ fn onboarding_v1(my_did: &str, my_vk: &str, agency_did: &str) -> Result<(String, let _response: SignUpResponse = match response.remove(0) { A2AMessage::Version1(A2AMessageV1::SignUpResponse(resp)) => resp, - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) }; /* STEP 3 - CREATE AGENT */ @@ -272,14 +275,14 @@ fn onboarding_v1(my_did: &str, my_vk: &str, agency_did: &str) -> Result<(String, let response: CreateAgentResponse = match response.remove(0) { A2AMessage::Version1(A2AMessageV1::CreateAgentResponse(resp)) => resp, - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) }; Ok((response.from_did, response.from_vk)) } // it will be changed next -fn onboarding_v2(my_did: &str, my_vk: &str, agency_did: &str) -> Result<(String, String), u32> { +fn onboarding_v2(my_did: &str, my_vk: &str, agency_did: &str) -> VcxResult<(String, String)> { /* STEP 1 - CONNECT */ let message = A2AMessage::Version2( A2AMessageV2::Connect(Connect::build(my_did, my_vk)) @@ -290,7 +293,7 @@ fn onboarding_v2(my_did: &str, my_vk: &str, agency_did: &str) -> Result<(String, let ConnectResponse { from_vk: agency_pw_vk, from_did: agency_pw_did, .. } = match response.remove(0) { A2AMessage::Version2(A2AMessageV2::ConnectResponse(resp)) => resp, - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) }; settings::set_config_value(settings::CONFIG_REMOTE_TO_SDK_VERKEY, &agency_pw_vk); @@ -305,7 +308,7 @@ fn onboarding_v2(my_did: &str, my_vk: &str, agency_did: &str) -> Result<(String, let _response: SignUpResponse = match response.remove(0) { A2AMessage::Version2(A2AMessageV2::SignUpResponse(resp)) => resp, - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) }; /* STEP 3 - CREATE AGENT */ @@ -318,13 +321,13 @@ fn onboarding_v2(my_did: &str, my_vk: &str, agency_did: &str) -> Result<(String, let response: CreateAgentResponse = match response.remove(0) { A2AMessage::Version2(A2AMessageV2::CreateAgentResponse(resp)) => resp, - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) }; Ok((response.from_did, response.from_vk)) } -pub fn update_agent_info(id: &str, value: &str) -> Result<(), u32> { +pub fn update_agent_info(id: &str, value: &str) -> VcxResult<()> { trace!("update_agent_info >>> id: {}, value: {}", id, value); let to_did = settings::get_config_value(settings::CONFIG_REMOTE_TO_SDK_DID)?; @@ -345,7 +348,7 @@ pub fn update_agent_info(id: &str, value: &str) -> Result<(), u32> { } } -fn update_agent_info_v1(to_did: &str, com_method: ComMethod) -> Result<(), u32> { +fn update_agent_info_v1(to_did: &str, com_method: ComMethod) -> VcxResult<()> { if settings::test_agency_mode_enabled() { httpclient::set_next_u8_response(REGISTER_RESPONSE.to_vec()); } @@ -357,7 +360,7 @@ fn update_agent_info_v1(to_did: &str, com_method: ComMethod) -> Result<(), u32> Ok(()) } -fn update_agent_info_v2(to_did: &str, com_method: ComMethod) -> Result<(), u32> { +fn update_agent_info_v2(to_did: &str, com_method: ComMethod) -> VcxResult<()> { let message = A2AMessage::Version2( A2AMessageV2::UpdateConnectionMethod(UpdateConnectionMethod::build(com_method)) ); @@ -365,10 +368,11 @@ fn update_agent_info_v2(to_did: &str, com_method: ComMethod) -> Result<(), u32> Ok(()) } -fn send_message_to_agency(message: &A2AMessage, did: &str) -> Result, u32> { +fn send_message_to_agency(message: &A2AMessage, did: &str) -> VcxResult> { let data = prepare_message_for_agency(message, &did)?; - let response = httpclient::post_u8(&data).or(Err(error::INVALID_HTTP_RESPONSE.code_num))?; + let response = httpclient::post_u8(&data) + .map_err(|err| err.map(VcxErrorKind::InvalidHttpResponse, error::INVALID_HTTP_RESPONSE.message))?; parse_response_from_agency(&response) } diff --git a/vcx/libvcx/src/messages/create_key.rs b/vcx/libvcx/src/messages/create_key.rs index 3ac99a9a09..cae42c0f99 100644 --- a/vcx/libvcx/src/messages/create_key.rs +++ b/vcx/libvcx/src/messages/create_key.rs @@ -1,8 +1,9 @@ use settings; use messages::*; use messages::message_type::MessageTypes; -use utils::{httpclient, error}; +use utils::httpclient; use utils::constants::CREATE_KEYS_RESPONSE; +use error::prelude::*; #[derive(Deserialize, Serialize, Debug, PartialEq)] #[serde(rename_all = "camelCase")] @@ -51,19 +52,19 @@ impl CreateKeyBuilder { } } - pub fn for_did(&mut self, did: &str) -> Result<&mut Self, u32> { + pub fn for_did(&mut self, did: &str) -> VcxResult<&mut Self> { validation::validate_did(did)?; self.for_did = did.to_string(); Ok(self) } - pub fn for_verkey(&mut self, verkey: &str) -> Result<&mut Self, u32> { + pub fn for_verkey(&mut self, verkey: &str) -> VcxResult<&mut Self> { validation::validate_verkey(verkey)?; self.for_verkey = verkey.to_string(); Ok(self) } - pub fn send_secure(&self) -> Result<(String, String), u32> { + pub fn send_secure(&self) -> VcxResult<(String, String)> { trace!("CreateKeyMsg::send >>>"); if settings::test_agency_mode_enabled() { @@ -72,12 +73,12 @@ impl CreateKeyBuilder { let data = self.prepare_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; self.parse_response(&response) } - fn prepare_request(&self) -> Result, u32> { + fn prepare_request(&self) -> VcxResult> { let message = match settings::get_protocol_type() { settings::ProtocolTypes::V1 => A2AMessage::Version1( @@ -94,7 +95,7 @@ impl CreateKeyBuilder { prepare_message_for_agency(&message, &agency_did) } - fn parse_response(&self, response: &Vec) -> Result<(String, String), u32> { + fn parse_response(&self, response: &Vec) -> VcxResult<(String, String)> { trace!("parse_response >>>"); let mut response = parse_response_from_agency(response)?; @@ -102,7 +103,7 @@ impl CreateKeyBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::CreateKeyResponse(res)) => Ok((res.for_did, res.for_verkey)), A2AMessage::Version2(A2AMessageV2::CreateKeyResponse(res)) => Ok((res.for_did, res.for_verkey)), - _ => Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) } } } diff --git a/vcx/libvcx/src/messages/get_message.rs b/vcx/libvcx/src/messages/get_message.rs index 7d0c8fb1ea..10c3db8d4c 100644 --- a/vcx/libvcx/src/messages/get_message.rs +++ b/vcx/libvcx/src/messages/get_message.rs @@ -1,7 +1,8 @@ use settings; use messages::*; use messages::message_type::MessageTypes; -use utils::{httpclient, error}; +use utils::httpclient; +use error::prelude::*; #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] #[serde(rename_all = "camelCase")] @@ -86,35 +87,35 @@ impl GetMessagesBuilder { } } - pub fn uid(&mut self, uids: Option>) -> Result<&mut Self, u32> { + pub fn uid(&mut self, uids: Option>) -> VcxResult<&mut Self> { //Todo: validate msg_uid?? self.uids = uids; Ok(self) } - pub fn status_codes(&mut self, status_codes: Option>) -> Result<&mut Self, u32> { + pub fn status_codes(&mut self, status_codes: Option>) -> VcxResult<&mut Self> { self.status_codes = status_codes; Ok(self) } - pub fn pairwise_dids(&mut self, pairwise_dids: Option>) -> Result<&mut Self, u32> { + pub fn pairwise_dids(&mut self, pairwise_dids: Option>) -> VcxResult<&mut Self> { //Todo: validate msg_uid?? self.pairwise_dids = pairwise_dids; Ok(self) } - pub fn include_edge_payload(&mut self, payload: &str) -> Result<&mut Self, u32> { + pub fn include_edge_payload(&mut self, payload: &str) -> VcxResult<&mut Self> { //todo: is this a json value, String?? self.exclude_payload = Some(payload.to_string()); Ok(self) } - pub fn send_secure(&mut self) -> Result, u32> { + pub fn send_secure(&mut self) -> VcxResult> { trace!("GetMessages::send >>>"); let data = self.prepare_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; if settings::test_agency_mode_enabled() && response.len() == 0 { return Ok(Vec::new()); @@ -123,7 +124,7 @@ impl GetMessagesBuilder { self.parse_response(response) } - fn parse_response(&self, response: Vec) -> Result, u32> { + fn parse_response(&self, response: Vec) -> VcxResult> { trace!("parse_get_messages_response >>>"); let mut response = parse_response_from_agency(&response)?; @@ -131,16 +132,16 @@ impl GetMessagesBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::GetMessagesResponse(res)) => Ok(res.msgs), A2AMessage::Version2(A2AMessageV2::GetMessagesResponse(res)) => Ok(res.msgs), - _ => Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) } } - pub fn download_messages(&mut self) -> Result, u32> { + pub fn download_messages(&mut self) -> VcxResult> { trace!("GetMessages::download >>>"); let data = self.prepare_download_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; if settings::test_agency_mode_enabled() && response.len() == 0 { return Ok(Vec::new()); @@ -151,7 +152,7 @@ impl GetMessagesBuilder { Ok(response) } - fn prepare_download_request(&self) -> Result, u32> { + fn prepare_download_request(&self) -> VcxResult> { let message = match settings::get_protocol_type() { settings::ProtocolTypes::V1 => A2AMessage::Version1( @@ -178,14 +179,14 @@ impl GetMessagesBuilder { prepare_message_for_agency(&message, &agency_did) } - fn parse_download_messages_response(response: Vec) -> Result, u32> { + fn parse_download_messages_response(response: Vec) -> VcxResult> { trace!("parse_get_connection_messages_response >>>"); let mut response = parse_response_from_agency(&response)?; let msgs = match response.remove(0) { A2AMessage::Version1(A2AMessageV1::GetMessagesByConnectionsResponse(res)) => res.msgs, A2AMessage::Version2(A2AMessageV2::GetMessagesByConnectionsResponse(res)) => res.msgs, - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) }; msgs @@ -210,7 +211,7 @@ impl GeneralMessage for GetMessagesBuilder { fn set_to_did(&mut self, to_did: String) { self.to_did = to_did; } fn set_to_vk(&mut self, to_vk: String) { self.to_vk = to_vk; } - fn prepare_request(&mut self) -> Result, u32> { + fn prepare_request(&mut self) -> VcxResult> { let message = match settings::get_protocol_type() { settings::ProtocolTypes::V1 => A2AMessage::Version1( @@ -277,7 +278,7 @@ impl Message { } } -pub fn get_connection_messages(pw_did: &str, pw_vk: &str, agent_did: &str, agent_vk: &str, msg_uid: Option>) -> Result, u32> { +pub fn get_connection_messages(pw_did: &str, pw_vk: &str, agent_did: &str, agent_vk: &str, msg_uid: Option>) -> VcxResult> { trace!("get_connection_messages >>> pw_did: {}, pw_vk: {}, agent_vk: {}, msg_uid: {:?}", pw_did, pw_vk, agent_vk, msg_uid); @@ -290,14 +291,14 @@ pub fn get_connection_messages(pw_did: &str, pw_vk: &str, agent_did: &str, agent .send_secure() .map_err(|err| { error!("could not post get_messages: {}", err); - error::POST_MSG_FAILURE.code_num + VcxError::from(VcxErrorKind::PostMessageFailed) })?; trace!("message returned: {:?}", response); Ok(response) } -pub fn get_ref_msg(msg_id: &str, pw_did: &str, pw_vk: &str, agent_did: &str, agent_vk: &str) -> Result<(String, Vec), u32> { +pub fn get_ref_msg(msg_id: &str, pw_did: &str, pw_vk: &str, agent_did: &str, agent_vk: &str) -> VcxResult<(String, Vec)> { trace!("get_ref_msg >>> msg_id: {}, pw_did: {}, pw_vk: {}, agent_did: {}, agent_vk: {}", msg_id, pw_did, pw_vk, agent_did, agent_vk); @@ -306,7 +307,7 @@ pub fn get_ref_msg(msg_id: &str, pw_did: &str, pw_vk: &str, agent_did: &str, age let msg_id = match message.get(0).as_ref().and_then(|message| message.ref_msg_id.as_ref()) { Some(ref ref_msg_id) if message[0].status_code == MessageStatusCode::Accepted => ref_msg_id.to_string(), - _ => return Err(error::NOT_READY.code_num), + _ => return Err(VcxError::from(VcxErrorKind::NotReady)), }; let message: Vec = get_connection_messages(pw_did, pw_vk, agent_did, agent_vk, Some(vec![msg_id]))?; @@ -319,11 +320,11 @@ pub fn get_ref_msg(msg_id: &str, pw_did: &str, pw_vk: &str, agent_did: &str, age // TODO: check returned verkey Ok((message[0].uid.clone(), payload.to_owned())) } - _ => Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)), } } -pub fn download_messages(pairwise_dids: Option>, status_codes: Option>, uids: Option>) -> Result, u32> { +pub fn download_messages(pairwise_dids: Option>, status_codes: Option>, uids: Option>) -> VcxResult> { trace!("download_messages >>> pairwise_dids: {:?}, status_codes: {:?}, uids: {:?}", pairwise_dids, status_codes, uids); @@ -337,8 +338,9 @@ pub fn download_messages(pairwise_dids: Option>, status_codes: Optio let codes = codes .iter() .map(|code| - serde_json::from_str::(&format!("\"{}\"", code)).or(Err(error::INVALID_JSON.code_num)) - ).collect::, u32>>()?; + ::serde_json::from_str::(&format!("\"{}\"", code)) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot parse message status code: {}", err))) + ).collect::>>()?; Some(codes) } None => None diff --git a/vcx/libvcx/src/messages/invite.rs b/vcx/libvcx/src/messages/invite.rs index c93151fc67..1e9722610d 100644 --- a/vcx/libvcx/src/messages/invite.rs +++ b/vcx/libvcx/src/messages/invite.rs @@ -2,9 +2,10 @@ use settings; use messages::*; use messages::message_type::{MessageTypes, MessageTypeV1, MessageTypeV2}; use messages::payload::Thread; -use utils::{httpclient, error}; +use utils::httpclient; use utils::constants::*; use utils::uuid::uuid; +use error::prelude::*; #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct SendInviteMessageDetails { @@ -220,13 +221,13 @@ impl SendInviteBuilder { } } - pub fn key_delegate(&mut self, key: &str) -> Result<&mut Self, u32> { + pub fn key_delegate(&mut self, key: &str) -> VcxResult<&mut Self> { validation::validate_key_delegate(key)?; self.payload.key_dlg_proof.agent_delegated_key = key.to_string(); Ok(self) } - pub fn public_did(&mut self, did: Option<&str>) -> Result<&mut Self, u32> { + pub fn public_did(&mut self, did: Option<&str>) -> VcxResult<&mut Self> { if did.is_some() { self.payload.include_public_did = true; } @@ -234,7 +235,7 @@ impl SendInviteBuilder { Ok(self) } - pub fn phone_number(&mut self, phone_number: Option<&str>) -> Result<&mut Self, u32> { + pub fn phone_number(&mut self, phone_number: Option<&str>) -> VcxResult<&mut Self> { if let Some(ref p_num) = phone_number { validation::validate_phone_number(p_num)?; self.payload.phone_no = phone_number.map(String::from); @@ -242,12 +243,12 @@ impl SendInviteBuilder { Ok(self) } - pub fn thread(&mut self, thread: &Thread) -> Result<&mut Self, u32> { + pub fn thread(&mut self, thread: &Thread) -> VcxResult<&mut Self> { self.thread = thread.clone(); Ok(self) } - pub fn generate_signature(&mut self) -> Result<(), u32> { + pub fn generate_signature(&mut self) -> VcxResult<()> { let signature = format!("{}{}", self.payload.key_dlg_proof.agent_did, self.payload.key_dlg_proof.agent_delegated_key); let signature = ::utils::libindy::crypto::sign(&self.to_vk, signature.as_bytes())?; let signature = base64::encode(&signature); @@ -255,7 +256,7 @@ impl SendInviteBuilder { Ok(()) } - pub fn send_secure(&mut self) -> Result<(InviteDetail, String), u32> { + pub fn send_secure(&mut self) -> VcxResult<(InviteDetail, String)> { trace!("SendInvite::send >>>"); if settings::test_agency_mode_enabled() { @@ -264,14 +265,14 @@ impl SendInviteBuilder { let data = self.prepare_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; let (invite, url) = self.parse_response(response)?; Ok((invite, url)) } - fn parse_response(&self, response: Vec) -> Result<(InviteDetail, String), u32> { + fn parse_response(&self, response: Vec) -> VcxResult<(InviteDetail, String)> { let mut response = parse_response_from_agency(&response)?; let index = match settings::get_protocol_type() { @@ -285,7 +286,7 @@ impl SendInviteBuilder { Ok((res.invite_detail, res.url_to_invite_detail)), A2AMessage::Version2(A2AMessageV2::ConnectionRequestResponse(res)) => Ok((res.invite_detail, res.url_to_invite_detail)), - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) } } } @@ -323,38 +324,38 @@ impl AcceptInviteBuilder { } } - pub fn key_delegate(&mut self, key: &str) -> Result<&mut Self, u32> { + pub fn key_delegate(&mut self, key: &str) -> VcxResult<&mut Self> { validation::validate_key_delegate(key)?; self.payload.key_dlg_proof.agent_delegated_key = key.to_string(); Ok(self) } - pub fn sender_details(&mut self, details: &SenderDetail) -> Result<&mut Self, u32> { + pub fn sender_details(&mut self, details: &SenderDetail) -> VcxResult<&mut Self> { self.payload.sender_detail = Some(details.clone()); Ok(self) } - pub fn sender_agency_details(&mut self, details: &SenderAgencyDetail) -> Result<&mut Self, u32> { + pub fn sender_agency_details(&mut self, details: &SenderAgencyDetail) -> VcxResult<&mut Self> { self.payload.sender_agency_detail = Some(details.clone()); Ok(self) } - pub fn answer_status_code(&mut self, code: &MessageStatusCode) -> Result<&mut Self, u32> { + pub fn answer_status_code(&mut self, code: &MessageStatusCode) -> VcxResult<&mut Self> { self.payload.answer_status_code = Some(code.clone()); Ok(self) } - pub fn reply_to(&mut self, id: &str) -> Result<&mut Self, u32> { + pub fn reply_to(&mut self, id: &str) -> VcxResult<&mut Self> { self.reply_to_msg_id = Some(id.to_string()); Ok(self) } - pub fn thread(&mut self, thread: &Thread) -> Result<&mut Self, u32> { + pub fn thread(&mut self, thread: &Thread) -> VcxResult<&mut Self> { self.thread = thread.clone(); Ok(self) } - pub fn generate_signature(&mut self) -> Result<(), u32> { + pub fn generate_signature(&mut self) -> VcxResult<()> { let signature = format!("{}{}", self.payload.key_dlg_proof.agent_did, self.payload.key_dlg_proof.agent_delegated_key); let signature = crypto::sign(&self.to_vk, signature.as_bytes())?; let signature = base64::encode(&signature); @@ -362,7 +363,7 @@ impl AcceptInviteBuilder { Ok(()) } - pub fn send_secure(&mut self) -> Result { + pub fn send_secure(&mut self) -> VcxResult { trace!("AcceptInvite::send >>>"); if settings::test_agency_mode_enabled() { @@ -371,18 +372,18 @@ impl AcceptInviteBuilder { let data = self.prepare_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; self.parse_response(response) } - fn parse_response(&self, response: Vec) -> Result { + fn parse_response(&self, response: Vec) -> VcxResult { let mut response = parse_response_from_agency(&response)?; match response.remove(0) { A2AMessage::Version1(A2AMessageV1::MessageCreated(res)) => Ok(res.uid), A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswerResponse(res)) => Ok(res.id), - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) } } } @@ -406,7 +407,7 @@ impl GeneralMessage for SendInviteBuilder { fn set_to_vk(&mut self, to_vk: String) { self.to_vk = to_vk; } - fn prepare_request(&mut self) -> Result, u32> { + fn prepare_request(&mut self) -> VcxResult> { self.generate_signature()?; let messages = @@ -462,7 +463,7 @@ impl GeneralMessage for AcceptInviteBuilder { fn set_to_did(&mut self, to_did: String) { self.to_did = to_did; } fn set_to_vk(&mut self, to_vk: String) { self.to_vk = to_vk; } - fn prepare_request(&mut self) -> Result, u32> { + fn prepare_request(&mut self) -> VcxResult> { self.generate_signature()?; let messages = @@ -515,9 +516,10 @@ pub struct AcceptanceDetails { pub sender_detail: SenderDetail, } -pub fn parse_invitation_acceptance_details(payload: Vec) -> Result { +pub fn parse_invitation_acceptance_details(payload: Vec) -> VcxResult { debug!("parsing invitation acceptance details: {:?}", payload); - let response: AcceptanceDetails = rmp_serde::from_slice(&payload[..]).or(Err(error::INVALID_MSGPACK.code_num))?; + let response: AcceptanceDetails = rmp_serde::from_slice(&payload[..]) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot deserialize AcceptanceDetails: {}", err)))?; Ok(response.sender_detail) } diff --git a/vcx/libvcx/src/messages/message_type.rs b/vcx/libvcx/src/messages/message_type.rs index c69a8c8c38..092af1952b 100644 --- a/vcx/libvcx/src/messages/message_type.rs +++ b/vcx/libvcx/src/messages/message_type.rs @@ -4,7 +4,7 @@ use serde::{de, Deserializer, Deserialize, Serializer, Serialize}; use serde_json::Value; use regex::Regex; use messages::A2AMessageKinds; -use utils::error; +use error::prelude::*; pub const MESSAGE_VERSION_V1: &str = "1.0"; pub const DID: &str = "did:sov:123456789abcdefghi1234"; @@ -105,7 +105,7 @@ impl ::std::string::ToString for MessageFamilies { } -fn parse_message_type(message_type: &str) -> Result<(String, String, String, String), u32> { +fn parse_message_type(message_type: &str) -> VcxResult<(String, String, String, String)> { lazy_static! { static ref RE: Regex = Regex::new(r"(?x) (?P[\d\w:]*); @@ -127,7 +127,7 @@ fn parse_message_type(message_type: &str) -> Result<(String, String, String, Str Some((did.to_string(), family.to_string(), version.to_string(), type_.to_string())), _ => None } - }).ok_or(error::INVALID_OPTION.code_num) // TODO: Check Error + }).ok_or(VcxError::from_msg(VcxErrorKind::InvalidOption, "Cannot parse @type")) } impl<'de> Deserialize<'de> for MessageTypeV2 { diff --git a/vcx/libvcx/src/messages/mod.rs b/vcx/libvcx/src/messages/mod.rs index 2710dd5f77..c24fb1c6bd 100644 --- a/vcx/libvcx/src/messages/mod.rs +++ b/vcx/libvcx/src/messages/mod.rs @@ -14,7 +14,6 @@ pub mod payload; use std::u8; use settings; use utils::libindy::crypto; -use utils::error; use self::create_key::{CreateKeyBuilder, CreateKey, CreateKeyResponse}; use self::update_connection::{DeleteConnectionBuilder, UpdateConnection, UpdateConnectionResponse}; use self::update_profile::{UpdateProfileDataBuilder, UpdateConfigs, UpdateConfigsResponse}; @@ -28,6 +27,7 @@ use self::update_message::{UpdateMessageStatusByConnections, UpdateMessageStatus use self::proofs::proof_request::ProofRequestMessage; use self::agent_utils::{Connect, ConnectResponse, SignUp, SignUpResponse, CreateAgent, CreateAgentResponse, UpdateConnectionMethod}; use self::message_type::*; +use error::prelude::*; use serde::{de, Deserialize, Deserializer, ser, Serialize, Serializer}; use serde_json::Value; @@ -696,18 +696,20 @@ impl A2AMessageKinds { } } -pub fn prepare_message_for_agency(message: &A2AMessage, agency_did: &str) -> Result, u32> { +pub fn prepare_message_for_agency(message: &A2AMessage, agency_did: &str) -> VcxResult> { match settings::get_protocol_type() { settings::ProtocolTypes::V1 => bundle_for_agency_v1(message, &agency_did), settings::ProtocolTypes::V2 => pack_for_agency_v2(message, agency_did) } } -fn bundle_for_agency_v1(message: &A2AMessage, agency_did: &str) -> Result, u32> { +fn bundle_for_agency_v1(message: &A2AMessage, agency_did: &str) -> VcxResult> { let agent_vk = settings::get_config_value(settings::CONFIG_REMOTE_TO_SDK_VERKEY)?; let my_vk = settings::get_config_value(settings::CONFIG_SDK_TO_REMOTE_VERKEY)?; - let message = rmp_serde::to_vec_named(&message).or(Err(error::UNKNOWN_ERROR.code_num))?; + let message = rmp_serde::to_vec_named(&message) + .map_err(|err| VcxError::from_msg(VcxErrorKind::UnknownError, format!("Cannot encode message: {}", err)))?; + let message = Bundled::create(message).encode()?; let message = crypto::prep_msg(&my_vk, &agent_vk, &message[..])?; @@ -715,46 +717,51 @@ fn bundle_for_agency_v1(message: &A2AMessage, agency_did: &str) -> Result Result, u32> { +fn pack_for_agency_v2(message: &A2AMessage, agency_did: &str) -> VcxResult> { let agent_vk = settings::get_config_value(settings::CONFIG_REMOTE_TO_SDK_VERKEY)?; let my_vk = settings::get_config_value(settings::CONFIG_SDK_TO_REMOTE_VERKEY)?; - let message = serde_json::to_string(&message).or(Err(error::SERIALIZATION_ERROR.code_num))?; - let receiver_keys = ::serde_json::to_string(&vec![&agent_vk]).or(Err(error::SERIALIZATION_ERROR.code_num))?; + let message = ::serde_json::to_string(&message) + .map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize A2A message: {}", err)))?; + + let receiver_keys = ::serde_json::to_string(&vec![&agent_vk]) + .map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize receiver keys: {}", err)))?; let message = crypto::pack_message(Some(&my_vk), &receiver_keys, message.as_bytes())?; prepare_forward_message(message, agency_did) } -fn parse_response_from_agency(response: &Vec) -> Result, u32> { +fn parse_response_from_agency(response: &Vec) -> VcxResult> { match settings::get_protocol_type() { settings::ProtocolTypes::V1 => parse_response_from_agency_v1(response), settings::ProtocolTypes::V2 => parse_response_from_agency_v2(response) } } -fn parse_response_from_agency_v1(response: &Vec) -> Result, u32> { +fn parse_response_from_agency_v1(response: &Vec) -> VcxResult> { let verkey = settings::get_config_value(settings::CONFIG_SDK_TO_REMOTE_VERKEY)?; let (_, data) = crypto::parse_msg(&verkey, &response)?; let bundle: Bundled> = bundle_from_u8(data)?; bundle.bundled .iter() .map(|msg| rmp_serde::from_slice(msg) - .map_err(|err| error::INVALID_JSON.code_num)) - .collect::, u32>>() + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize response: {}", err)))) + .collect::>>() } -fn parse_response_from_agency_v2(response: &Vec) -> Result, u32> { +fn parse_response_from_agency_v2(response: &Vec) -> VcxResult> { let unpacked_msg = crypto::unpack_message(&response[..])?; let message: Value = ::serde_json::from_slice(unpacked_msg.as_slice()) - .or(Err(error::INVALID_JSON.code_num))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize response: {}", err)))?; - let message = message["message"].as_str().ok_or(error::INVALID_JSON.code_num)?; + let message = message["message"].as_str() + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidJson, "Cannot find `message` field on response"))?; let message: A2AMessage = serde_json::from_str(message) - .map_err(|ec| { error::INVALID_JSON.code_num })?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize A2A message: {}", err)))?; + Ok(vec![message]) } @@ -772,21 +779,21 @@ impl Bundled { } } - pub fn encode(&self) -> Result, u32> where T: serde::Serialize { + pub fn encode(&self) -> VcxResult> where T: serde::Serialize { rmp_serde::to_vec_named(self) .map_err(|err| { error!("Could not convert bundle to messagepack: {}", err); - error::INVALID_MSGPACK.code_num + VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Could not encode bundle: {}", err)) }) } } -pub fn try_i8_bundle(data: Vec) -> Result>, u32> { +pub fn try_i8_bundle(data: Vec) -> VcxResult>> { let bundle: Bundled> = rmp_serde::from_slice(&data[..]) .map_err(|err| { warn!("could not deserialize bundle with i8, will try u8"); - error::INVALID_MSGPACK.code_num + VcxError::from_msg(VcxErrorKind::InvalidMessagePack, "Could not deserialize bundle with i8") })?; let mut new_bundle: Bundled> = Bundled { bundled: Vec::new() }; @@ -806,16 +813,16 @@ pub fn to_i8(bytes: &Vec) -> Vec { bytes.iter().map(|i| *i as i8).collect() } -pub fn bundle_from_u8(data: Vec) -> Result>, u32> { +pub fn bundle_from_u8(data: Vec) -> VcxResult>> { try_i8_bundle(data.clone()) .or_else(|_| rmp_serde::from_slice::>>(&data[..])) .map_err(|err| { error!("could not deserialize bundle with i8 or u8: {}", err); - error::INVALID_MSGPACK.code_num + VcxError::from_msg(VcxErrorKind::InvalidMessagePack, "Could not deserialize bundle with i8 or u8") }) } -fn prepare_forward_message(message: Vec, did: &str) -> Result, u32> { +fn prepare_forward_message(message: Vec, did: &str) -> VcxResult> { let agency_vk = settings::get_config_value(settings::CONFIG_AGENCY_VERKEY)?; let message = Forward::new(did.to_string(), message); @@ -826,33 +833,38 @@ fn prepare_forward_message(message: Vec, did: &str) -> Result, u32> } } -fn prepare_forward_message_for_agency_v1(message: &Forward, agency_vk: &str) -> Result, u32> { - let message = rmp_serde::to_vec_named(message).or(Err(error::UNKNOWN_ERROR.code_num))?; +fn prepare_forward_message_for_agency_v1(message: &Forward, agency_vk: &str) -> VcxResult> { + let message = rmp_serde::to_vec_named(message) + .map_err(|err| VcxError::from_msg(VcxErrorKind::UnknownError, format!("Cannot serialize Forward message: {}", err)))?; let message = Bundled::create(message).encode()?; crypto::prep_anonymous_msg(agency_vk, &message[..]) } -fn prepare_forward_message_for_agency_v2(message: &Forward, agency_vk: &str) -> Result, u32> { - let message = serde_json::to_string(message).or(Err(error::SERIALIZATION_ERROR.code_num))?; - let receiver_keys = serde_json::to_string(&vec![agency_vk]).or(Err(error::SERIALIZATION_ERROR.code_num))?; +fn prepare_forward_message_for_agency_v2(message: &Forward, agency_vk: &str) -> VcxResult> { + let message = serde_json::to_string(message) + .map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize Forward message: {}", err)))?; + + let receiver_keys = serde_json::to_string(&vec![agency_vk]) + .map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize receiver keys: {}", err)))?; + crypto::pack_message(None, &receiver_keys, message.as_bytes()) } -pub fn prepare_message_for_agent(messages: Vec, pw_vk: &str, agent_did: &str, agent_vk: &str) -> Result, u32> { +pub fn prepare_message_for_agent(messages: Vec, pw_vk: &str, agent_did: &str, agent_vk: &str) -> VcxResult> { match settings::get_protocol_type() { settings::ProtocolTypes::V1 => prepare_message_for_agent_v1(messages, pw_vk, agent_did, agent_vk), settings::ProtocolTypes::V2 => prepare_message_for_agent_v2(messages, pw_vk, agent_did, agent_vk) } } -fn prepare_message_for_agent_v1(messages: Vec, pw_vk: &str, agent_did: &str, agent_vk: &str) -> Result, u32> { +fn prepare_message_for_agent_v1(messages: Vec, pw_vk: &str, agent_did: &str, agent_vk: &str) -> VcxResult> { let message = messages .iter() .map(|msg| rmp_serde::to_vec_named(msg)) .collect::, _>>() .map(|msgs| Bundled { bundled: msgs }) .and_then(|bundle| rmp_serde::to_vec_named(&bundle)) - .or(Err(error::SERIALIZATION_ERROR.code_num))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize A2A message: {}", err)))?; let message = crypto::prep_msg(&pw_vk, agent_vk, &message[..])?; @@ -864,10 +876,15 @@ fn prepare_message_for_agent_v1(messages: Vec, pw_vk: &str, agent_di bundle_for_agency_v1(&A2AMessage::Version1(A2AMessageV1::Forward(message)), &to_did) } -fn prepare_message_for_agent_v2(messages: Vec, pw_vk: &str, agent_did: &str, agent_vk: &str) -> Result, u32> { - let message = messages.get(0).ok_or(error::SERIALIZATION_ERROR.code_num)?; - let message = serde_json::to_string(message).or(Err(error::SERIALIZATION_ERROR.code_num))?; - let receiver_keys = serde_json::to_string(&vec![&agent_vk]).or(Err(error::SERIALIZATION_ERROR.code_num))?; +fn prepare_message_for_agent_v2(messages: Vec, pw_vk: &str, agent_did: &str, agent_vk: &str) -> VcxResult> { + let message = messages.get(0) + .ok_or(VcxError::from_msg(VcxErrorKind::SerializationError, "Cannot get message"))?; + + let message = serde_json::to_string(message) + .map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize A2A message: {}", err)))?; + + let receiver_keys = serde_json::to_string(&vec![&agent_vk]) + .map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot receiver keys: {}", err)))?; let message = crypto::pack_message(Some(pw_vk), &receiver_keys, message.as_bytes())?; @@ -884,25 +901,25 @@ pub trait GeneralMessage { //todo: deserialize_message - fn to(&mut self, to_did: &str) -> Result<&mut Self, u32> { + fn to(&mut self, to_did: &str) -> VcxResult<&mut Self> { validation::validate_did(to_did)?; self.set_to_did(to_did.to_string()); Ok(self) } - fn to_vk(&mut self, to_vk: &str) -> Result<&mut Self, u32> { + fn to_vk(&mut self, to_vk: &str) -> VcxResult<&mut Self> { validation::validate_verkey(to_vk)?; self.set_to_vk(to_vk.to_string()); Ok(self) } - fn agent_did(&mut self, did: &str) -> Result<&mut Self, u32> { + fn agent_did(&mut self, did: &str) -> VcxResult<&mut Self> { validation::validate_did(did)?; self.set_agent_did(did.to_string()); Ok(self) } - fn agent_vk(&mut self, to_vk: &str) -> Result<&mut Self, u32> { + fn agent_vk(&mut self, to_vk: &str) -> VcxResult<&mut Self> { validation::validate_verkey(to_vk)?; self.set_agent_vk(to_vk.to_string()); Ok(self) @@ -913,7 +930,29 @@ pub trait GeneralMessage { fn set_agent_did(&mut self, did: String); fn set_agent_vk(&mut self, vk: String); - fn prepare_request(&mut self) -> Result, u32>; + fn prepare_request(&mut self) -> VcxResult>; +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ObjectWithVersion<'a, T> { + pub version: &'a str, + pub data: T +} + +impl<'a, 'de, T> ObjectWithVersion<'a, T> where T: ::serde::Serialize + ::serde::de::DeserializeOwned { + pub fn new(version: &'a str, data: T) -> ObjectWithVersion<'a, T> { + ObjectWithVersion { version, data } + } + + pub fn serialize(&self) -> VcxResult { + ::serde_json::to_string(self) + .to_vcx(VcxErrorKind::InvalidState, "Cannot serialize object") + } + + pub fn deserialize(data: &str) -> VcxResult> where T: ::serde::de::DeserializeOwned { + ::serde_json::from_str(data) + .to_vcx(VcxErrorKind::InvalidJson, "Cannot deserialize object") + } } pub fn create_keys() -> CreateKeyBuilder { CreateKeyBuilder::create() } diff --git a/vcx/libvcx/src/messages/payload.rs b/vcx/libvcx/src/messages/payload.rs index d1e0cdedf3..4555e9d2e6 100644 --- a/vcx/libvcx/src/messages/payload.rs +++ b/vcx/libvcx/src/messages/payload.rs @@ -1,8 +1,8 @@ use messages::message_type::*; use messages::to_u8; use settings::{ProtocolTypes, get_protocol_type}; -use utils::error; use utils::libindy::crypto; +use error::prelude::*; use std::collections::HashMap; @@ -37,7 +37,7 @@ impl Payloads { // this will become a CommonError, because multiple types (Connection/Issuer Credential) use this function // Possibly this function moves out of this file. // On second thought, this should stick as a ConnectionError. - pub fn encrypt(my_vk: &str, their_vk: &str, data: &str, msg_type: PayloadKinds, thread: Option) -> Result, u32> { + pub fn encrypt(my_vk: &str, their_vk: &str, data: &str, msg_type: PayloadKinds, thread: Option) -> VcxResult> { match ProtocolTypes::from(get_protocol_type()) { ProtocolTypes::V1 => { let payload = PayloadV1 { @@ -48,14 +48,14 @@ impl Payloads { let bytes = rmp_serde::to_vec_named(&payload) .map_err(|err| { error!("could not encode create_keys msg: {}", err); - error::INVALID_MSGPACK.code_num + VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot encrypt payload: {}", err)) })?; trace!("Sending payload: {:?}", bytes); crypto::prep_msg(&my_vk, &their_vk, &bytes) } ProtocolTypes::V2 => { - let thread = thread.ok_or(error::INVALID_CONNECTION_HANDLE.code_num)?; + let thread = thread.ok_or(VcxError::from(VcxErrorKind::InvalidState))?; let payload = PayloadV2 { type_: PayloadTypes::build_v2(msg_type), @@ -67,10 +67,11 @@ impl Payloads { let message = ::serde_json::to_string(&payload) .map_err(|err| { error!("could not serialize create_keys msg: {}", err); - error::INVALID_MSGPACK.code_num + VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize payload: {}", err)) })?; - let receiver_keys = ::serde_json::to_string(&vec![&their_vk]).or(Err(error::SERIALIZATION_ERROR.code_num))?; + let receiver_keys = ::serde_json::to_string(&vec![&their_vk]) + .map_err(|err| VcxError::from_msg(VcxErrorKind::SerializationError, format!("Cannot serialize receiver keys: {}", err)))?; trace!("Sending payload: {:?}", message.as_bytes()); crypto::pack_message(Some(my_vk), &receiver_keys, message.as_bytes()) @@ -78,7 +79,7 @@ impl Payloads { } } - pub fn decrypt(my_vk: &str, payload: &Vec) -> Result<(String, Option), u32> { + pub fn decrypt(my_vk: &str, payload: &Vec) -> VcxResult<(String, Option)> { match ProtocolTypes::from(get_protocol_type()) { ProtocolTypes::V1 => { let (_, data) = crypto::parse_msg(&my_vk, &to_u8(payload))?; @@ -86,7 +87,7 @@ impl Payloads { let my_payload: PayloadV1 = rmp_serde::from_slice(&data[..]) .map_err(|err| { error!("could not deserialize bundle with i8 or u8: {}", err); - error::INVALID_MSGPACK.code_num + VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot decrypt payload: {}", err)) })?; Ok((my_payload.msg, None)) } @@ -96,18 +97,19 @@ impl Payloads { } } - pub fn decrypt_payload_v2(my_vk: &str, payload: &Vec) -> Result<(String, Option), u32> { + pub fn decrypt_payload_v2(my_vk: &str, payload: &Vec) -> VcxResult<(String, Option)> { let unpacked_msg = crypto::unpack_message(&to_u8(payload))?; let message: ::serde_json::Value = ::serde_json::from_slice(unpacked_msg.as_slice()) - .or(Err(error::INVALID_JSON.code_num))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize payload: {}", err)))?; - let message = message["message"].as_str().ok_or(error::INVALID_JSON.code_num)?.to_string(); + let message = message["message"].as_str() + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidJson, "Cannot find `message` field"))?.to_string(); let mut my_payload: PayloadV2 = serde_json::from_str(&message) .map_err(|err| { error!("could not deserialize bundle with i8 or u8: {}", err); - error::INVALID_MSGPACK.code_num + VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize payload: {}", err)) })?; if my_payload.thread.thid.is_none() { diff --git a/vcx/libvcx/src/messages/proofs/proof_message.rs b/vcx/libvcx/src/messages/proofs/proof_message.rs index 58ffd1ab50..09bfa6a8c1 100644 --- a/vcx/libvcx/src/messages/proofs/proof_message.rs +++ b/vcx/libvcx/src/messages/proofs/proof_message.rs @@ -1,8 +1,7 @@ extern crate serde_json; -use utils::{ error }; use serde_json::Value; -use error::proof::ProofError; +use error::prelude::*; static ISSUER_DID: &'static str = "issuer_did"; static SEQUENCE_NUMBER: &'static str = "schema_seq_no"; @@ -11,7 +10,7 @@ static MSG_FROM_API: &str = r#"{"proofs":{"claim::71b6070f-14ba-45fa-876d-1fe849 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ProofMessage{ +pub struct ProofMessage { version: Option, to_did: Option, from_did: Option, @@ -38,26 +37,21 @@ impl ProofMessage { } } - pub fn to_string(&self) -> Result { - serde_json::to_string(&self).map_err(|err| { - error!("{} with: {}", error::INVALID_PROOF.message, err); - error::INVALID_PROOF.code_num - }) + pub fn to_string(&self) -> VcxResult { + serde_json::to_string(&self) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidProof, format!("Cannot serialize proof: {}", err))) } - pub fn from_str(payload:&str) -> Result { + pub fn from_str(payload: &str) -> VcxResult { serde_json::from_str(payload) - .map_err(|err| { - error!("{} with serde error: {}",error::INVALID_PROOF.message, err); - error::INVALID_PROOF.code_num - }) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidProof, format!("Cannot deserialize proof: {}", err))) } - pub fn get_credential_info(&self) -> Result, ProofError> { + pub fn get_credential_info(&self) -> VcxResult> { let mut rtn = Vec::new(); let credentials: Value = serde_json::from_str(&self.libindy_proof) - .or(Err(ProofError::InvalidJson()))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize liibndy proof: {}", err)))?; if let Value::Array(ref identifiers) = credentials["identifiers"] { for identifier in identifiers { @@ -76,23 +70,24 @@ impl ProofMessage { timestamp, } ); - } else { return Err(ProofError::InvalidCredData()) } + } else { return Err(VcxError::from(VcxErrorKind::InvalidProofCredentialData)); } } } Ok(rtn) } - } #[cfg(test)] pub mod tests { use super::*; use ::utils::constants::{SCHEMA_ID, CRED_DEF_ID, REV_REG_ID}; + static TEMP_REQUESTER_DID: &'static str = "GxtnGN6ypZYgEqcftSQFnC"; static MSG_FROM_API: &str = r#"{"proofs":{"claim::71b6070f-14ba-45fa-876d-1fe8491fe5d4":{"proof":{"primary_proof":{"eq_proof":{"revealed_attrs":{"sex":"5944657099558967239210949258394887428692050081607692519917050011144233115103","name":"1139481716457488690172217916278103335"},"a_prime":"55115757663642844902979276276581544287881791112969892277372135316353511833640150801244335663890109536491278379177551666081054765286807563008348637104046950934828407012194403360724040287698135607556244297972578864339500981366412262454282194811242239615009347165118318516694216754501345324782597475927199400880006212632553233049354866295429520527445980181939247828351677971991914388778860092824318440481574181300185829423762990910739241691289976584754979812272223819007422499654272590946235912914032826994670588466080422906806402660885408376207875827950805200378568062518210110828954480363081643567615791016011737856977","e":"34976147138641338975844073241645969211530343885520088294714132974884138611036204288689212378023649179372520412699253155486970203797562324","v":"961473607552945346906354315658276499450491951690969023699851664262072769313929148332129868528140265952852653009499943891795293148107502144091334703992581737220352761140064276811372868396353572957613845323343723271098601244774874235526135299483412285009916812621185291842845156342501611029106982811773616231232684804116984093651972537804480090649736612551759833591251845595059217608938213987633789344584340351801507541774726753840600143685051258161251666953243698589585559347435011414292427590918153421953579895479604685390401357681887618798200391305919594609949167659780330698000168295871428737686822637913218269005987492318466661186509308179489615192663542904993253626728197630057096161118638090776180812895097232529119979970798938360220605280817954648588493778338816318524451785027916181454650102696493927306340658666852294316562458212054696739343800993703515542777264448535624584845146378512183572107830260813929222999","m":{},"m1":"75548120024969192086664289521241751069844239013520403238642886571169851979005373784309432586593371476370934469326730539754613694936161784687213609047455188306625204249706249661640538349287762196100659095340756990269587317065862046598569445591945049204366911309949910119711238973099702616527117177036784698661","m2":"287944186286321709724396773443214682376883853676549188669693055373059354657799325692443906346632814001611911026063358134413175852024773765930829079850890920811398176944587192618"},"ge_proofs":[{"u":{"1":"1","0":"0","3":"3","2":"4"},"r":{"1":"1","0":"2","DELTA":"3","3":"4","2":"5"},"mj":"6","alpha":"7","t":{"1":"8","3":"3","0":"2","DELTA":"1","2":"2"},"predicate":{"attr_name":"age","p_type":"GE","value":18,"schema_seq_no":14,"issuer_did":"33UDR9R7fjwELRvH9JT6HH"}}]},"non_revoc_proof":null},"schema_seq_no":103,"issuer_did":"V4SGRU86Z58d6TV7PBUe6f"}},"aggregated_proof":{"c_hash":"63330487197040957750863022608534150304998351350639315143102570772502292901825","c_list":[[1,180,153,212,162,132,5,189,14,181,140,112,236,109,182,76,91,6,161,215,62,207,205,135,86,211,49,197,215,198,104,201,14,22,48,6,112,170,31,191,110,118,121,15,62,114,126,249,221,107,114,161,163,234,19,233,150,236,182,217,195,6,218,217,193,6,94,160,33,23,103,147,109,221,81,38,138,20,225,141,68,37,142,10,225,79,164,119,168,250,188,186,47,229,165,8,237,230,14,35,53,176,97,28,82,105,87,210,117,16,154,222,66,11,96,172,90,13,239,190,29,71,11,88,53,36,219,139,67,21,136,58,161,164,97,106,56,230,55,157,59,35,187,235,154,194,111,93,168,135,67,15,97,136,38,169,87,142,32,255,50,247,111,83,44,88,251,99,6,226,182,170,146,229,118,164,118,228,235,51,137,168,135,50,1,14,1,201,72,175,102,241,149,117,88,83,84,37,205,130,26,155,124,158,211,89,112,33,46,24,94,93,202,8,127,172,214,178,6,156,79,188,132,223,239,127,200,158,95,247,139,101,51,162,168,175,74,1,67,201,94,108,192,14,130,109,217,248,193,10,142,37,95,231,227,251,209]]},"requested_proof":{"revealed_attrs":{"attr2_uuid":["claim::71b6070f-14ba-45fa-876d-1fe8491fe5d4","male","5944657099558967239210949258394887428692050081607692519917050011144233115103"],"attr1_uuid":["claim::71b6070f-14ba-45fa-876d-1fe8491fe5d4","Alex","1139481716457488690172217916278103335"]},"unrevealed_attrs":{},"self_attested_attrs":{"self_attr":"self_value"},"predicates":{"predicate_id":"claim::71b6070f-14ba-45fa-876d-1fe8491fe5d4"}},"remoteDid":"KP8AaEBc368CMK1PqZaEzX","userPairwiseDid":"PofTCeegEXT7S2aAePhM6a"}"#; static TEST_ATTRS: &str = r#"[{"schema_seq_no":14,"issuer_did":"33UDR9R7fjwELRvH9JT6HH","credential_uuid":"claim::f33cc7c8-924f-4541-aeff-29a9aed9c46b","proof_attrs":[{"name":"state","value":"UT","revealed":true}]},{"schema_seq_no":15,"issuer_did":"4fUDR9R7fjwELRvH9JT6HH","credential_uuid":"claim::f22cc7c8-924f-4541-aeff-29a9aed9c46b","proof_attrs":[{"name":"state","value":"UT","revealed":true}]}]"#; - pub fn create_default_proof()-> ProofMessage { + + pub fn create_default_proof() -> ProofMessage { let mut proof = ProofMessage::new(); proof.libindy_proof = ::utils::constants::INDY_PROOF_JSON.to_string(); proof.from_did = Some(::settings::get_config_value(::settings::CONFIG_INSTITUTION_DID).unwrap()); @@ -100,18 +95,18 @@ pub mod tests { } #[test] - fn test_proof_struct(){ + fn test_proof_struct() { init!("true"); let offer = create_default_proof(); assert_eq!(offer.from_did, Some(::settings::get_config_value(::settings::CONFIG_INSTITUTION_DID).unwrap())); } #[test] - fn test_serialize_deserialize(){ + fn test_serialize_deserialize() { let proof = create_default_proof(); let serialized = proof.to_string().unwrap(); let proof2 = ProofMessage::from_str(&serialized).unwrap(); - assert_eq!(proof,proof2); + assert_eq!(proof, proof2); } #[test] diff --git a/vcx/libvcx/src/messages/proofs/proof_request.rs b/vcx/libvcx/src/messages/proofs/proof_request.rs index 526228d27e..df4deea51c 100644 --- a/vcx/libvcx/src/messages/proofs/proof_request.rs +++ b/vcx/libvcx/src/messages/proofs/proof_request.rs @@ -3,8 +3,8 @@ extern crate serde_json; use std::collections::HashMap; use std::vec::Vec; -use utils::error; use messages::validation; +use error::prelude::*; static PROOF_REQUEST: &str = "PROOF_REQUEST"; static PROOF_DATA: &str = "proof_request_data"; @@ -67,7 +67,7 @@ pub struct NonRevokedInterval { } #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ProofRequestData{ +pub struct ProofRequestData { nonce: String, name: String, #[serde(rename = "version")] @@ -78,14 +78,12 @@ pub struct ProofRequestData{ } #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ProofRequestMessage{ +pub struct ProofRequestMessage { #[serde(rename = "@type")] type_header: ProofType, #[serde(rename = "@topic")] topic: ProofTopic, pub proof_request_data: ProofRequestData, - #[serde(skip_serializing, default)] - validate_rc: u32, pub msg_ref_id: Option, from_timestamp: Option, to_timestamp: Option, @@ -115,11 +113,10 @@ impl ProofRequestMessage { nonce: String::new(), name: String::new(), data_version: String::new(), - requested_attributes:HashMap::new(), + requested_attributes: HashMap::new(), requested_predicates: HashMap::new(), non_revoked: None }, - validate_rc: 0, msg_ref_id: None, from_timestamp: None, to_timestamp: None, @@ -127,55 +124,45 @@ impl ProofRequestMessage { } } - pub fn type_version(&mut self, version: &str) -> &mut Self { + pub fn type_version(&mut self, version: &str) -> VcxResult<&mut Self> { self.type_header.type_version = String::from(version); - self + Ok(self) } - pub fn tid(&mut self, tid: u32) -> &mut Self { + pub fn tid(&mut self, tid: u32) -> VcxResult<&mut Self> { self.topic.tid = tid; - self + Ok(self) } - pub fn mid(&mut self, mid: u32) -> &mut Self { + pub fn mid(&mut self, mid: u32) -> VcxResult<&mut Self> { self.topic.mid = mid; - self + Ok(self) } - pub fn nonce(&mut self, nonce: &str) -> &mut Self { - match validation::validate_nonce(nonce) { - Ok(x) => { - self.proof_request_data.nonce = x; - self - }, - Err(x) => { - self.validate_rc = x; - self - }, - } + pub fn nonce(&mut self, nonce: &str) -> VcxResult<&mut Self> { + let nonce = validation::validate_nonce(nonce)?; + self.proof_request_data.nonce = nonce; + Ok(self) } - pub fn proof_name(&mut self, name: &str) -> &mut Self { + pub fn proof_name(&mut self, name: &str) -> VcxResult<&mut Self> { self.proof_request_data.name = String::from(name); - self + Ok(self) } - pub fn proof_data_version(&mut self, version: &str) -> &mut Self { + pub fn proof_data_version(&mut self, version: &str) -> VcxResult<&mut Self> { self.proof_request_data.data_version = String::from(version); - self + Ok(self) } - pub fn requested_attrs(&mut self, attrs: &str) -> &mut Self { + pub fn requested_attrs(&mut self, attrs: &str) -> VcxResult<&mut Self> { let mut check_req_attrs: HashMap = HashMap::new(); - let proof_attrs:Vec = match serde_json::from_str(attrs) { - Ok(a) => a, - Err(e) => { - debug!("Cannot parse attributes: {}", e); - self.validate_rc = error::INVALID_JSON.code_num; - return self - } - }; + let proof_attrs: Vec = serde_json::from_str(attrs) + .map_err(|err| { + debug!("Cannot parse attributes: {}", err); + VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot parse attributes: {}", err)) + })?; let mut index = 1; for attr in proof_attrs { @@ -184,22 +171,19 @@ impl ProofRequestMessage { } else { check_req_attrs.insert(attr.name.clone(), attr); } - index= index + 1; + index = index + 1; } self.proof_request_data.requested_attributes = check_req_attrs; - self + Ok(self) } - pub fn requested_predicates(&mut self, predicates: &str) -> &mut Self { + pub fn requested_predicates(&mut self, predicates: &str) -> VcxResult<&mut Self> { let mut check_predicates: HashMap = HashMap::new(); - let attr_values: Vec = match serde_json::from_str(predicates) { - Ok(a) => a, - Err(e) => { - debug!("Cannot parse predicates: {}", e); - self.validate_rc = error::INVALID_JSON.code_num; - return self - }, - }; + let attr_values: Vec = serde_json::from_str(predicates) + .map_err(|err| { + debug!("Cannot parse predicates: {}", err); + VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot parse predicates: {}", err)) + })?; let mut index = 1; for attr in attr_values { @@ -212,39 +196,31 @@ impl ProofRequestMessage { } self.proof_request_data.requested_predicates = check_predicates; - self + Ok(self) } - pub fn from_timestamp(&mut self, from: Option) -> &mut Self { + pub fn from_timestamp(&mut self, from: Option) -> VcxResult<&mut Self> { self.from_timestamp = from; - self + Ok(self) } - pub fn to_timestamp(&mut self, to: Option) -> &mut Self { + pub fn to_timestamp(&mut self, to: Option) -> VcxResult<&mut Self> { self.to_timestamp = to; - self + Ok(self) } - pub fn serialize_message(&mut self) -> Result { - if self.validate_rc != error::SUCCESS.code_num { - return Err(self.validate_rc) - } - - match serde_json::to_string(self) { - Ok(x) => Ok(x), - Err(_) => Err(error::INVALID_JSON.code_num) - } + pub fn serialize_message(&mut self) -> VcxResult { + serde_json::to_string(self) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize proof request: {}", err))) } pub fn get_proof_request_data(&self) -> String { json!(self)[PROOF_DATA].to_string() } - pub fn to_string(&self) -> Result { - match serde_json::to_string(&self){ - Ok(s) => Ok(s), - Err(_) => Err(error::INVALID_JSON.code_num), - } + pub fn to_string(&self) -> VcxResult { + serde_json::to_string(&self) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize proof request: {}", err))) } } @@ -252,7 +228,7 @@ impl ProofRequestMessage { #[cfg(test)] mod tests { use super::*; - use messages::{proof_request}; + use messages::proof_request; use utils::constants::{REQUESTED_ATTRS, REQUESTED_PREDICATES}; #[test] diff --git a/vcx/libvcx/src/messages/send_message.rs b/vcx/libvcx/src/messages/send_message.rs index b40f7fd843..d34f0c565a 100644 --- a/vcx/libvcx/src/messages/send_message.rs +++ b/vcx/libvcx/src/messages/send_message.rs @@ -4,8 +4,9 @@ use api::VcxStateType; use messages::*; use messages::message_type::MessageTypes; use messages::payload::{Payloads, PayloadKinds, Thread}; -use utils::{httpclient, error}; +use utils::httpclient; use utils::uuid::uuid; +use error::prelude::*; #[derive(Debug)] pub struct SendMessageBuilder { @@ -41,46 +42,46 @@ impl SendMessageBuilder { } } - pub fn msg_type(&mut self, msg: &RemoteMessageType) -> Result<&mut Self, u32> { + pub fn msg_type(&mut self, msg: &RemoteMessageType) -> VcxResult<&mut Self> { //Todo: validate msg?? self.mtype = msg.clone(); Ok(self) } - pub fn uid(&mut self, uid: Option<&str>) -> Result<&mut Self, u32> { + pub fn uid(&mut self, uid: Option<&str>) -> VcxResult<&mut Self> { //Todo: validate msg_uid?? self.uid = uid.map(String::from); Ok(self) } - pub fn status_code(&mut self, code: &MessageStatusCode) -> Result<&mut Self, u32> { + pub fn status_code(&mut self, code: &MessageStatusCode) -> VcxResult<&mut Self> { //Todo: validate that it can be parsed to number?? self.status_code = code.clone(); Ok(self) } - pub fn edge_agent_payload(&mut self, my_vk: &str, their_vk: &str, data: &str, payload_type: PayloadKinds, thread: Option) -> Result<&mut Self, u32> { + pub fn edge_agent_payload(&mut self, my_vk: &str, their_vk: &str, data: &str, payload_type: PayloadKinds, thread: Option) -> VcxResult<&mut Self> { //todo: is this a json value, String?? self.payload = Payloads::encrypt(my_vk, their_vk, data, payload_type, thread)?; Ok(self) } - pub fn ref_msg_id(&mut self, id: &str) -> Result<&mut Self, u32> { + pub fn ref_msg_id(&mut self, id: &str) -> VcxResult<&mut Self> { self.ref_msg_id = Some(String::from(id)); Ok(self) } - pub fn set_title(&mut self, title: &str) -> Result<&mut Self, u32> { + pub fn set_title(&mut self, title: &str) -> VcxResult<&mut Self> { self.title = Some(title.to_string()); Ok(self) } - pub fn set_detail(&mut self, detail: &str) -> Result<&mut Self, u32> { + pub fn set_detail(&mut self, detail: &str) -> VcxResult<&mut Self> { self.detail = Some(detail.to_string()); Ok(self) } - pub fn send_secure(&mut self) -> Result { + pub fn send_secure(&mut self) -> VcxResult { trace!("SendMessage::send >>>"); if settings::test_agency_mode_enabled() { @@ -89,21 +90,21 @@ impl SendMessageBuilder { let data = self.prepare_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; let result = self.parse_response(response)?; Ok(result) } - fn parse_response(&self, response: Vec) -> Result { + fn parse_response(&self, response: Vec) -> VcxResult { let mut response = parse_response_from_agency(&response)?; let index = match settings::get_protocol_type() { // TODO: THINK better settings::ProtocolTypes::V1 => { if response.len() <= 1 { - return Err(error::INVALID_HTTP_RESPONSE.code_num); + return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)); } 1 } @@ -115,7 +116,7 @@ impl SendMessageBuilder { Ok(SendResponse { uid: res.uid, uids: res.uids }), A2AMessage::Version2(A2AMessageV2::SendRemoteMessageResponse(res)) => Ok(SendResponse { uid: Some(res.id.clone()), uids: if res.sent { vec![res.id] } else { vec![] } }), - _ => return Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) } } } @@ -129,7 +130,7 @@ impl GeneralMessage for SendMessageBuilder { fn set_to_did(&mut self, to_did: String) { self.to_did = to_did; } fn set_to_vk(&mut self, to_vk: String) { self.to_vk = to_vk; } - fn prepare_request(&mut self) -> Result, u32> { + fn prepare_request(&mut self) -> VcxResult> { let messages = match settings::get_protocol_type() { settings::ProtocolTypes::V1 => { @@ -175,24 +176,24 @@ pub struct SendResponse { } impl SendResponse { - pub fn get_msg_uid(&self) -> Result { + pub fn get_msg_uid(&self) -> VcxResult { self.uids .get(0) .map(|uid| uid.to_string()) - .ok_or(error::INVALID_JSON.code_num) + .ok_or(VcxError::from(VcxErrorKind::InvalidJson)) } } -pub fn send_generic_message(connection_handle: u32, msg: &str, msg_type: &str, msg_title: &str) -> Result { +pub fn send_generic_message(connection_handle: u32, msg: &str, msg_type: &str, msg_title: &str) -> VcxResult { if connection::get_state(connection_handle) != VcxStateType::VcxStateAccepted as u32 { - return Err(error::NOT_READY.code_num); + return Err(VcxError::from(VcxErrorKind::NotReady)); } - let agent_did = connection::get_agent_did(connection_handle).or(Err(error::INVALID_CONNECTION_HANDLE.code_num))?; - let agent_vk = connection::get_agent_verkey(connection_handle).or(Err(error::INVALID_CONNECTION_HANDLE.code_num))?; - let did = connection::get_pw_did(connection_handle).or(Err(error::INVALID_CONNECTION_HANDLE.code_num))?; - let vk = connection::get_pw_verkey(connection_handle).or(Err(error::INVALID_CONNECTION_HANDLE.code_num))?; - let remote_vk = connection::get_their_pw_verkey(connection_handle).or(Err(error::INVALID_CONNECTION_HANDLE.code_num))?; + let agent_did = connection::get_agent_did(connection_handle)?; + let agent_vk = connection::get_agent_verkey(connection_handle)?; + let did = connection::get_pw_did(connection_handle)?; + let vk = connection::get_pw_verkey(connection_handle)?; + let remote_vk = connection::get_their_pw_verkey(connection_handle)?; let response = send_message() diff --git a/vcx/libvcx/src/messages/update_connection.rs b/vcx/libvcx/src/messages/update_connection.rs index ee4777d30c..831d0ee57d 100644 --- a/vcx/libvcx/src/messages/update_connection.rs +++ b/vcx/libvcx/src/messages/update_connection.rs @@ -1,7 +1,8 @@ use messages::*; use messages::message_type::MessageTypes; use settings; -use utils::{error, httpclient}; +use utils::httpclient; +use error::prelude::*; #[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] #[serde(rename_all = "camelCase")] @@ -72,7 +73,7 @@ impl DeleteConnectionBuilder { } } - pub fn send_secure(&mut self) -> Result<(), u32> { + pub fn send_secure(&mut self) -> VcxResult<()> { trace!("DeleteConnection::send >>>"); if settings::test_agency_mode_enabled() { @@ -81,14 +82,14 @@ impl DeleteConnectionBuilder { let data = self.prepare_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; let response = self.parse_response(&response)?; Ok(response) } - fn parse_response(&self, response: &Vec) -> Result<(), u32> { + fn parse_response(&self, response: &Vec) -> VcxResult<()> { trace!("parse_create_keys_response >>>"); let mut response = parse_response_from_agency(response)?; @@ -96,7 +97,7 @@ impl DeleteConnectionBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::UpdateConnectionResponse(res)) => Ok(()), A2AMessage::Version2(A2AMessageV2::UpdateConnectionResponse(res)) => Ok(()), - _ => Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) } } @@ -124,7 +125,7 @@ impl GeneralMessage for DeleteConnectionBuilder { fn set_to_did(&mut self, to_did: String) { self.to_did = to_did; } fn set_to_vk(&mut self, to_vk: String) { self.to_vk = to_vk; } - fn prepare_request(&mut self) -> Result, u32> { + fn prepare_request(&mut self) -> VcxResult> { let message = match settings::get_protocol_type() { settings::ProtocolTypes::V1 => A2AMessage::Version1( diff --git a/vcx/libvcx/src/messages/update_message.rs b/vcx/libvcx/src/messages/update_message.rs index 49b5e06a8e..c87952b925 100644 --- a/vcx/libvcx/src/messages/update_message.rs +++ b/vcx/libvcx/src/messages/update_message.rs @@ -1,7 +1,8 @@ use settings; use messages::*; use messages::message_type::MessageTypes; -use utils::{httpclient, error}; +use utils::httpclient; +use error::prelude::*; #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] #[serde(rename_all = "camelCase")] @@ -44,19 +45,19 @@ impl UpdateMessageStatusByConnectionsBuilder { } } - pub fn uids_by_conns(&mut self, uids_by_conns: Vec) -> Result<&mut Self, u32> { + pub fn uids_by_conns(&mut self, uids_by_conns: Vec) -> VcxResult<&mut Self> { //Todo: validate msg_uid?? self.uids_by_conns = uids_by_conns; Ok(self) } - pub fn status_code(&mut self, code: MessageStatusCode) -> Result<&mut Self, u32> { + pub fn status_code(&mut self, code: MessageStatusCode) -> VcxResult<&mut Self> { //Todo: validate that it can be parsed to number?? self.status_code = Some(code.clone()); Ok(self) } - pub fn send_secure(&mut self) -> Result<(), u32> { + pub fn send_secure(&mut self) -> VcxResult<()> { trace!("UpdateMessages::send >>>"); if settings::test_agency_mode_enabled() { @@ -65,12 +66,12 @@ impl UpdateMessageStatusByConnectionsBuilder { let data = self.prepare_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; self.parse_response(&response) } - fn prepare_request(&mut self) -> Result, u32> { + fn prepare_request(&mut self) -> VcxResult> { let message = match settings::get_protocol_type() { settings::ProtocolTypes::V1 => A2AMessage::Version1( @@ -98,7 +99,7 @@ impl UpdateMessageStatusByConnectionsBuilder { prepare_message_for_agency(&message, &agency_did) } - fn parse_response(&self, response: &Vec) -> Result<(), u32> { + fn parse_response(&self, response: &Vec) -> VcxResult<()> { trace!("parse_create_keys_response >>>"); let mut response = parse_response_from_agency(response)?; @@ -106,19 +107,21 @@ impl UpdateMessageStatusByConnectionsBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::UpdateMessageStatusByConnectionsResponse(res)) => Ok(()), A2AMessage::Version2(A2AMessageV2::UpdateMessageStatusByConnectionsResponse(res)) => Ok(()), - _ => Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) } } } -pub fn update_agency_messages(status_code: &str, msg_json: &str) -> Result<(), u32> { +pub fn update_agency_messages(status_code: &str, msg_json: &str) -> VcxResult<()> { trace!("update_agency_messages >>> status_code: {:?}, msg_json: {:?}", status_code, msg_json); - let status_code: MessageStatusCode = serde_json::from_str(&format!("\"{}\"", status_code)).or(Err(error::INVALID_JSON.code_num))?; + let status_code: MessageStatusCode = ::serde_json::from_str(&format!("\"{}\"", status_code)) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize MessageStatusCode: {}", err)))?; debug!("updating agency messages {} to status code: {:?}", msg_json, status_code); - let uids_by_conns: Vec = serde_json::from_str(msg_json).or(Err(error::INVALID_JSON.code_num))?; + let uids_by_conns: Vec = serde_json::from_str(msg_json) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize UIDsByConn: {}", err)))?; UpdateMessageStatusByConnectionsBuilder::create() .uids_by_conns(uids_by_conns)? diff --git a/vcx/libvcx/src/messages/update_profile.rs b/vcx/libvcx/src/messages/update_profile.rs index 0175b7bd71..6d2d6aea55 100644 --- a/vcx/libvcx/src/messages/update_profile.rs +++ b/vcx/libvcx/src/messages/update_profile.rs @@ -1,8 +1,9 @@ use settings; use messages::*; use messages::message_type::MessageTypes; -use utils::{httpclient, error}; +use utils::httpclient; use utils::constants::*; +use error::prelude::*; #[derive(Debug)] pub struct UpdateProfileDataBuilder { @@ -41,26 +42,26 @@ impl UpdateProfileDataBuilder { } } - pub fn to(&mut self, did: &str) -> Result<&mut Self, u32> { + pub fn to(&mut self, did: &str) -> VcxResult<&mut Self> { validation::validate_did(did)?; self.to_did = did.to_string(); Ok(self) } - pub fn name(&mut self, name: &str) -> Result<&mut Self, u32> { + pub fn name(&mut self, name: &str) -> VcxResult<&mut Self> { let config = ConfigOption { name: "name".to_string(), value: name.to_string() }; self.configs.push(config); Ok(self) } - pub fn logo_url(&mut self, url: &str) -> Result<&mut Self, u32> { + pub fn logo_url(&mut self, url: &str) -> VcxResult<&mut Self> { validation::validate_url(url)?; let config = ConfigOption { name: "logoUrl".to_string(), value: url.to_string() }; self.configs.push(config); Ok(self) } - pub fn use_public_did(&mut self, did: &Option) -> Result<&mut Self, u32> { + pub fn use_public_did(&mut self, did: &Option) -> VcxResult<&mut Self> { if let Some(x) = did { let config = ConfigOption { name: "publicDid".to_string(), value: x.to_string() }; self.configs.push(config); @@ -68,7 +69,7 @@ impl UpdateProfileDataBuilder { Ok(self) } - pub fn send_secure(&mut self) -> Result<(), u32> { + pub fn send_secure(&mut self) -> VcxResult<()> { trace!("UpdateProfileData::send_secure >>>"); if settings::test_agency_mode_enabled() { @@ -77,12 +78,12 @@ impl UpdateProfileDataBuilder { let data = self.prepare_request()?; - let response = httpclient::post_u8(&data).or(Err(error::POST_MSG_FAILURE.code_num))?; + let response = httpclient::post_u8(&data)?; self.parse_response(response) } - fn prepare_request(&self) -> Result, u32> { + fn prepare_request(&self) -> VcxResult> { let message = match settings::get_protocol_type() { settings::ProtocolTypes::V1 => A2AMessage::Version1( @@ -109,13 +110,13 @@ impl UpdateProfileDataBuilder { prepare_message_for_agency(&message, &agency_did) } - fn parse_response(&self, response: Vec) -> Result<(), u32> { + fn parse_response(&self, response: Vec) -> VcxResult<()> { let mut response = parse_response_from_agency(&response)?; match response.remove(0) { A2AMessage::Version1(A2AMessageV1::UpdateConfigsResponse(res)) => Ok(()), A2AMessage::Version2(A2AMessageV2::UpdateConfigsResponse(res)) => Ok(()), - _ => Err(error::INVALID_HTTP_RESPONSE.code_num) + _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) } } } diff --git a/vcx/libvcx/src/messages/validation.rs b/vcx/libvcx/src/messages/validation.rs index a78cd9f211..157535e0ad 100644 --- a/vcx/libvcx/src/messages/validation.rs +++ b/vcx/libvcx/src/messages/validation.rs @@ -1,51 +1,53 @@ extern crate rust_base58; extern crate openssl; -use self::openssl::bn::{ BigNum }; -use self::rust_base58::{FromBase58}; -use utils::error; +use self::openssl::bn::BigNum; +use self::rust_base58::FromBase58; use url::Url; +use error::prelude::*; -pub fn validate_did(did: &str) -> Result { +pub fn validate_did(did: &str) -> VcxResult { // assert len(base58.b58decode(did)) == 16 let check_did = String::from(did); match check_did.from_base58() { Ok(ref x) if x.len() == 16 => Ok(check_did), - Ok(_) => Err(error::INVALID_DID.code_num), - Err(x) => Err(error::NOT_BASE58.code_num) + Ok(_) => Err(VcxError::from_msg(VcxErrorKind::InvalidDid, "Invalid DID length")), + Err(x) => Err(VcxError::from_msg(VcxErrorKind::NotBase58, format!("Invalid DID: {}", x))), } } -pub fn validate_verkey(verkey: &str) -> Result { +pub fn validate_verkey(verkey: &str) -> VcxResult { // assert len(base58.b58decode(ver_key)) == 32 let check_verkey = String::from(verkey); match check_verkey.from_base58() { Ok(ref x) if x.len() == 32 => Ok(check_verkey), - Ok(_) => Err(error::INVALID_VERKEY.code_num), - Err(x) => Err(error::NOT_BASE58.code_num) + Ok(_) => Err(VcxError::from_msg(VcxErrorKind::InvalidVerkey, "Invalid Verkey length")), + Err(x) => Err(VcxError::from_msg(VcxErrorKind::NotBase58, format!("Invalid Verkey: {}", x))), } } -pub fn validate_nonce(nonce: &str) -> Result { - let nonce = BigNum::from_dec_str(nonce).or(Err(error::INVALID_NONCE.code_num))?; +pub fn validate_nonce(nonce: &str) -> VcxResult { + let nonce = BigNum::from_dec_str(nonce) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidNonce, err))?; if nonce.num_bits() > 80 { - return Err(error::INVALID_NONCE.code_num) + return Err(VcxError::from_msg(VcxErrorKind::InvalidNonce, "Invalid Nonce length")); } Ok(nonce.to_string()) } -pub fn validate_key_delegate(delegate: &str) -> Result { +pub fn validate_key_delegate(delegate: &str) -> VcxResult { //todo: find out what needs to be validated for key_delegate let check_delegate = String::from(delegate); Ok(check_delegate) } -pub fn validate_url(url: &str)->Result{ - Url::parse(url).or(Err(error::INVALID_URL.code_num))?; +pub fn validate_url(url: &str) -> VcxResult { + Url::parse(url) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidUrl, err))?; Ok(url.to_string()) } -pub fn validate_phone_number(p_num: &str)->Result{ +pub fn validate_phone_number(p_num: &str) -> VcxResult { Ok(String::from(p_num)) } @@ -59,7 +61,6 @@ mod tests { match validate_did(&to_did) { Err(x) => panic!("Should be valid did"), Ok(x) => assert_eq!(x, to_did.to_string()) - } } @@ -69,7 +70,6 @@ mod tests { match validate_did(&to_did) { Err(x) => assert_eq!(x, error::INVALID_DID.code_num), Ok(x) => panic!("Should be invalid did"), - } } @@ -88,7 +88,6 @@ mod tests { match validate_verkey(&verkey) { Err(x) => panic!("Should be valid verkey"), Ok(x) => assert_eq!(x, verkey) - } } @@ -98,7 +97,6 @@ mod tests { match validate_verkey(&verkey) { Err(x) => assert_eq!(x, error::INVALID_VERKEY.code_num), Ok(x) => panic!("Should be invalid verkey"), - } } @@ -110,6 +108,4 @@ mod tests { Ok(x) => panic!("Should be invalid verkey"), } } - - } \ No newline at end of file diff --git a/vcx/libvcx/src/object_cache/mod.rs b/vcx/libvcx/src/object_cache/mod.rs index c52723c7f8..5332b8059e 100644 --- a/vcx/libvcx/src/object_cache/mod.rs +++ b/vcx/libvcx/src/object_cache/mod.rs @@ -6,7 +6,8 @@ use std::sync::MutexGuard; use std::collections::HashMap; use std::ops::Deref; use std::ops::DerefMut; -use utils::error; + +use error::prelude::*; pub struct ObjectCache{ pub store: Mutex>>, @@ -23,12 +24,12 @@ impl Default for ObjectCache { impl ObjectCache { - fn _lock_store(&self) -> Result>>, u32> { + fn _lock_store(&self) -> VcxResult>>> { match self.store.lock() { Ok(g) => Ok(g), Err(e) => { error!("Unable to lock Object Store: {:?}", e); - Err(10) + Err(VcxError::from_msg(VcxErrorKind::Common(10), format!("Unable to lock Object Store: {:?}", e))) } } } @@ -41,33 +42,33 @@ impl ObjectCache { store.contains_key(&handle) } - pub fn get(&self, handle:u32, closure: F) -> Result - where F: Fn(&T) -> Result { + pub fn get(&self, handle:u32, closure: F) -> VcxResult + where F: Fn(&T) -> VcxResult { let store = self._lock_store()?; match store.get(&handle) { Some(m) => match m.lock() { Ok(obj) => closure(obj.deref()), - Err(err) => return Err(10) //TODO better error + Err(err) => return Err(VcxError::from_msg(VcxErrorKind::Common(10), "Unable to lock Object Store")) //TODO better error }, - None => return Err(error::INVALID_OBJ_HANDLE.code_num) + None => return Err(VcxError::from_msg(VcxErrorKind::InvalidHandle, format!("Object not found for handle: {}", handle))) } } - pub fn get_mut(&self, handle:u32, closure: F) -> Result - where F: Fn(&mut T) -> Result { + pub fn get_mut(&self, handle:u32, closure: F) -> VcxResult + where F: Fn(&mut T) -> VcxResult { let mut store = self._lock_store()?; match store.get_mut(&handle) { Some(m) => match m.lock() { Ok(mut obj) => closure(obj.deref_mut()), - Err(err) => return Err(10) //TODO better error + Err(err) => return Err(VcxError::from_msg(VcxErrorKind::Common(10), "Unable to lock Object Store")) //TODO better error }, - None => return Err(error::INVALID_OBJ_HANDLE.code_num) + None => return Err(VcxError::from_msg(VcxErrorKind::InvalidHandle, format!("Object not found for handle: {}", handle))) } } - pub fn add(&self, obj:T) -> Result { + pub fn add(&self, obj:T) -> VcxResult { let mut store = self._lock_store()?; let mut new_handle = rand::thread_rng().gen::(); @@ -84,15 +85,15 @@ impl ObjectCache { } } - pub fn release(&self, handle:u32) -> Result<(),u32> { + pub fn release(&self, handle:u32) -> VcxResult<()> { let mut store = self._lock_store()?; match store.remove(&handle) { Some(_) => Ok(()), - None => Err(error::INVALID_OBJ_HANDLE.code_num) + None => return Err(VcxError::from_msg(VcxErrorKind::InvalidHandle, format!("Object not found for handle: {}", handle))) } } - pub fn drain(&self) -> Result<(), u32> { + pub fn drain(&self) -> VcxResult<()> { let mut store = self._lock_store()?; Ok(store.clear()) } diff --git a/vcx/libvcx/src/proof.rs b/vcx/libvcx/src/proof.rs index 9a0e90553f..dc1f09ffe8 100644 --- a/vcx/libvcx/src/proof.rs +++ b/vcx/libvcx/src/proof.rs @@ -10,6 +10,7 @@ use api::{VcxStateType, ProofStateType}; use messages::proofs::proof_message::{ProofMessage, CredInfo}; use messages; use messages::RemoteMessageType; +use messages::ObjectWithVersion; use messages::payload::{Payloads, PayloadKinds, Thread}; use messages::proofs::proof_request::ProofRequestMessage; use messages::GeneralMessage; @@ -17,11 +18,10 @@ use utils::error; use utils::constants::*; use utils::libindy::anoncreds::libindy_verifier_verify_proof; use utils::libindy::anoncreds; -use error::proof::ProofError; -use error::ToErrorCode; use serde_json::Value; use utils::constants::DEFAULT_SERIALIZE_VERSION; use object_cache::ObjectCache; +use error::prelude::*; lazy_static! { static ref PROOF_MAP: ObjectCache = Default::default(); @@ -61,7 +61,7 @@ pub struct Proof { impl Proof { // leave this returning a u32 until we actually implement this method to do something // other than return success. - fn validate_proof_request(&self) -> Result { + fn validate_proof_request(&self) -> VcxResult { //TODO: validate proof request Ok(error::SUCCESS.code_num) } @@ -72,7 +72,7 @@ impl Proof { schemas_json: &str, credential_defs_json: &str, rev_reg_defs_json: &str, - rev_regs_json: &str) -> Result { + rev_regs_json: &str) -> VcxResult { if settings::test_indy_mode_enabled() { return Ok(error::SUCCESS.code_num); } debug!("starting libindy proof verification for {}", self.source_id); @@ -84,7 +84,7 @@ impl Proof { rev_regs_json).map_err(|err| { error!("Error: {}, Proof {} wasn't valid", err, self.source_id); self.proof_state = ProofStateType::ProofInvalid; - ProofError::InvalidProof() + VcxError::from(VcxErrorKind::InvalidProof) })?; if !valid { @@ -98,17 +98,16 @@ impl Proof { Ok(error::SUCCESS.code_num) } - fn build_credential_defs_json(&self, credential_data: &Vec) -> Result { + fn build_credential_defs_json(&self, credential_data: &Vec) -> VcxResult { debug!("{} building credential_def_json for proof validation", self.source_id); let mut credential_json = json!({}); for ref cred_info in credential_data.iter() { if credential_json.get(&cred_info.cred_def_id).is_none() { - let (id, credential_def) = anoncreds::get_cred_def_json(&cred_info.cred_def_id) - .map_err(|ec| ProofError::CommonError(ec))?; + let (id, credential_def) = anoncreds::get_cred_def_json(&cred_info.cred_def_id)?; let credential_def = serde_json::from_str(&credential_def) - .or(Err(ProofError::InvalidCredData()))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidProofCredentialData, format!("Cannot deserialize credential definition: {}", err)))?; credential_json[id] = credential_def; } @@ -117,7 +116,7 @@ impl Proof { Ok(credential_json.to_string()) } - fn build_schemas_json(&self, credential_data: &Vec) -> Result { + fn build_schemas_json(&self, credential_data: &Vec) -> VcxResult { debug!("{} building schemas json for proof validation", self.source_id); let mut schemas_json = json!({}); @@ -125,10 +124,10 @@ impl Proof { for ref cred_info in credential_data.iter() { if schemas_json.get(&cred_info.schema_id).is_none() { let (id, schema_json) = anoncreds::get_schema_json(&cred_info.schema_id) - .or(Err(ProofError::InvalidSchema()))?; + .map_err(|err| err.map(VcxErrorKind::InvalidSchema, "Cannot get schema"))?; let schema_val = serde_json::from_str(&schema_json) - .or(Err(ProofError::InvalidSchema()))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidSchema, format!("Cannot deserialize schema: {}", err)))?; schemas_json[id] = schema_val; } @@ -137,7 +136,7 @@ impl Proof { Ok(schemas_json.to_string()) } - fn build_rev_reg_defs_json(&self, credential_data: &Vec) -> Result { + fn build_rev_reg_defs_json(&self, credential_data: &Vec) -> VcxResult { debug!("{} building rev_reg_def_json for proof validation", self.source_id); let mut rev_reg_defs_json = json!({}); @@ -146,14 +145,14 @@ impl Proof { let rev_reg_id = cred_info .rev_reg_id .as_ref() - .ok_or(ProofError::InvalidRevocationInfo())?; + .ok_or(VcxError::from(VcxErrorKind::InvalidRevocationDetails))?; if rev_reg_defs_json.get(rev_reg_id).is_none() { let (id, json) = anoncreds::get_rev_reg_def_json(rev_reg_id) - .or(Err(ProofError::InvalidRevocationInfo()))?; + .or(Err(VcxError::from(VcxErrorKind::InvalidRevocationDetails)))?; let rev_reg_def_json = serde_json::from_str(&json) - .or(Err(ProofError::InvalidSchema()))?; + .or(Err(VcxError::from(VcxErrorKind::InvalidSchema)))?; rev_reg_defs_json[id] = rev_reg_def_json; } @@ -162,7 +161,7 @@ impl Proof { Ok(rev_reg_defs_json.to_string()) } - fn build_rev_reg_json(&self, credential_data: &Vec) -> Result { + fn build_rev_reg_json(&self, credential_data: &Vec) -> VcxResult { debug!("{} building rev_reg_json for proof validation", self.source_id); let mut rev_regs_json = json!({}); @@ -171,19 +170,19 @@ impl Proof { let rev_reg_id = cred_info .rev_reg_id .as_ref() - .ok_or(ProofError::InvalidRevocationInfo())?; + .ok_or(VcxError::from(VcxErrorKind::InvalidRevocationDetails))?; let timestamp = cred_info .timestamp .as_ref() - .ok_or(ProofError::InvalidTimestamp())?; + .ok_or(VcxError::from(VcxErrorKind::InvalidRevocationTimestamp))?; if rev_regs_json.get(rev_reg_id).is_none() { let (id, json, timestamp) = anoncreds::get_rev_reg(rev_reg_id, timestamp.to_owned()) - .or(Err(ProofError::InvalidRevocationInfo()))?; + .or(Err(VcxError::from(VcxErrorKind::InvalidRevocationDetails)))?; let rev_reg_json: Value = serde_json::from_str(&json) - .or(Err(ProofError::InvalidJson()))?; + .or(Err(VcxError::from(VcxErrorKind::InvalidJson)))?; let rev_reg_json = json!({timestamp.to_string(): rev_reg_json}); rev_regs_json[id] = rev_reg_json; @@ -193,27 +192,26 @@ impl Proof { Ok(rev_regs_json.to_string()) } - fn build_proof_json(&self) -> Result { + fn build_proof_json(&self) -> VcxResult { debug!("{} building proof json for proof validation", self.source_id); match self.proof { Some(ref x) => Ok(x.libindy_proof.clone()), - None => Err(ProofError::InvalidProof()), + None => Err(VcxError::from(VcxErrorKind::InvalidProof)), } } - fn build_proof_req_json(&self) -> Result { + fn build_proof_req_json(&self) -> VcxResult { debug!("{} building proof request json for proof validation", self.source_id); if let Some(ref x) = self.proof_request { return Ok(x.get_proof_request_data()); } - - Err(ProofError::InvalidProof()) + Err(VcxError::from(VcxErrorKind::InvalidProof)) } - fn proof_validation(&mut self) -> Result { + fn proof_validation(&mut self) -> VcxResult { let proof_msg = self.proof .clone() - .ok_or(ProofError::InvalidProof())?; + .ok_or(VcxError::from(VcxErrorKind::InvalidProof))?; let credential_data = proof_msg.get_credential_info()?; @@ -242,19 +240,19 @@ impl Proof { &rev_regs_json) } - fn send_proof_request(&mut self, connection_handle: u32) -> Result { + fn send_proof_request(&mut self, connection_handle: u32) -> VcxResult { trace!("Proof::send_proof_request >>> connection_handle: {}", connection_handle); if self.state != VcxStateType::VcxStateInitialized { warn!("proof {} has invalid state {} for sending proofRequest", self.source_id, self.state as u32); - return Err(ProofError::ProofNotReadyError()); + return Err(VcxError::from(VcxErrorKind::NotReady)); } debug!("sending proof request with proof: {}, and connection {}", self.source_id, connection_handle); - self.prover_did = connection::get_pw_did(connection_handle).map_err(|_| ProofError::InvalidConnection())?; - self.agent_did = connection::get_agent_did(connection_handle).map_err(|_| ProofError::InvalidConnection())?; - self.agent_vk = connection::get_agent_verkey(connection_handle).map_err(|_| ProofError::InvalidConnection())?; - self.remote_vk = connection::get_their_pw_verkey(connection_handle).map_err(|_| ProofError::InvalidConnection())?; - self.prover_vk = connection::get_pw_verkey(connection_handle).map_err(|_| ProofError::InvalidConnection())?; + self.prover_did = connection::get_pw_did(connection_handle).or(Err(VcxError::from(VcxErrorKind::GeneralConnectionError)))?; + self.agent_did = connection::get_agent_did(connection_handle).or(Err(VcxError::from(VcxErrorKind::GeneralConnectionError)))?; + self.agent_vk = connection::get_agent_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::GeneralConnectionError)))?; + self.remote_vk = connection::get_their_pw_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::GeneralConnectionError)))?; + self.prover_vk = connection::get_pw_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::GeneralConnectionError)))?; debug!("prover_did: {} -- agent_did: {} -- agent_vk: {} -- remote_vk: {} -- prover_vk: {}", self.prover_did, @@ -266,19 +264,18 @@ impl Proof { let data_version = "0.1"; let mut proof_obj = messages::proof_request(); let proof_request = proof_obj - .type_version(&self.version) - .nonce(&self.nonce) - .proof_name(&self.name) - .proof_data_version(data_version) - .requested_attrs(&self.requested_attrs) - .requested_predicates(&self.requested_predicates) - .from_timestamp(self.revocation_interval.from) - .to_timestamp(self.revocation_interval.to) - .serialize_message() - .map_err(|ec| ProofError::ProofMessageError(ec))?; + .type_version(&self.version)? + .nonce(&self.nonce)? + .proof_name(&self.name)? + .proof_data_version(data_version)? + .requested_attrs(&self.requested_attrs)? + .requested_predicates(&self.requested_predicates)? + .from_timestamp(self.revocation_interval.from)? + .to_timestamp(self.revocation_interval.to)? + .serialize_message()?; self.proof_request = Some(proof_obj); - let title = format!("{} wants you to share: {}", settings::get_config_value(settings::CONFIG_INSTITUTION_NAME).map_err(|e| ProofError::CommonError(e))?, self.name); + let title = format!("{} wants you to share: {}", settings::get_config_value(settings::CONFIG_INSTITUTION_NAME)?, self.name); let response = messages::send_message() .to(&self.prover_did)? @@ -288,23 +285,19 @@ impl Proof { .set_title(&title)? .set_detail(&title)? .agent_vk(&self.agent_vk)? - .edge_agent_payload(&self.prover_vk, &self.remote_vk, &proof_request, PayloadKinds::ProofRequest, Some(self.thread.clone())).or(Err(ProofError::ProofConnectionError()))? - .send_secure() - .map_err(|err| { - warn!("{} could not send proofReq: {}", self.source_id, err); - ProofError::ProofMessageError(err) - })?; + .edge_agent_payload(&self.prover_vk, &self.remote_vk, &proof_request, PayloadKinds::ProofRequest, Some(self.thread.clone())).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))? + .send_secure()?; self.msg_uid = response.get_msg_uid()?; self.state = VcxStateType::VcxStateOfferSent; return Ok(error::SUCCESS.code_num); } - fn get_proof(&self) -> Result { - Ok(self.proof.as_ref().ok_or(ProofError::InvalidHandle())?.libindy_proof.clone()) + fn get_proof(&self) -> VcxResult { + Ok(self.proof.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidProofHandle))?.libindy_proof.clone()) } - fn get_proof_request_status(&mut self) -> Result { + fn get_proof_request_status(&mut self) -> VcxResult { debug!("updating state for proof {} with msg_id {:?}", self.source_id, self.msg_uid); if self.state == VcxStateType::VcxStateAccepted { return Ok(self.get_state()); @@ -314,10 +307,9 @@ impl Proof { let (_, payload) = messages::get_message::get_ref_msg(&self.msg_uid, &self.prover_did, &self.prover_vk, &self.agent_did, - &self.agent_vk) - .map_err(|ec| ProofError::ProofMessageError(ec))?; + &self.agent_vk)?; - let (payload, thread) = Payloads::decrypt(&self.prover_vk, &payload).map_err(|ec| ProofError::CommonError(ec))?; + let (payload, thread) = Payloads::decrypt(&self.prover_vk, &payload)?; self.proof = match parse_proof_payload(&payload) { Err(err) => return Ok(self.get_state()), @@ -339,20 +331,15 @@ impl Proof { } Err(x) => { self.state = VcxStateType::VcxStateRequestReceived; - if x == ProofError::CommonError(error::TIMEOUT_LIBINDY_ERROR.code_num) { - warn!("Proof {} unable to be validated", self.source_id); - self.proof_state = ProofStateType::ProofUndefined; - } else { - warn!("Proof {} had invalid format with err {}", self.source_id, x); - self.proof_state = ProofStateType::ProofInvalid; - } + warn!("Proof {} had invalid format with err {}", self.source_id, x); + self.proof_state = ProofStateType::ProofInvalid; } }; Ok(self.get_state()) } - fn update_state(&mut self) -> Result { + fn update_state(&mut self) -> VcxResult { trace!("Proof::update_state >>>"); self.get_proof_request_status() } @@ -372,19 +359,16 @@ impl Proof { fn get_source_id(&self) -> &String { &self.source_id } - fn to_string(&self) -> String { - json!({ - "version": DEFAULT_SERIALIZE_VERSION, - "data": json!(self), - }).to_string() + fn to_string(&self) -> VcxResult { + ObjectWithVersion::new(DEFAULT_SERIALIZE_VERSION, self.to_owned()) + .serialize() + .map_err(|err| err.extend("Cannot serialize Proof")) } - fn from_str(s: &str) -> Result { - let s: Value = serde_json::from_str(&s) - .or(Err(ProofError::InvalidJson()))?; - let proof: Proof = serde_json::from_value(s["data"].clone()) - .or(Err(ProofError::InvalidJson()))?; - Ok(proof) + fn from_str(data: &str) -> VcxResult { + ObjectWithVersion::deserialize(data) + .map(|obj: ObjectWithVersion| obj.data) + .map_err(|err| err.extend("Cannot deserialize Proof")) } } @@ -392,14 +376,14 @@ pub fn create_proof(source_id: String, requested_attrs: String, requested_predicates: String, revocation_details: String, - name: String) -> Result { + name: String) -> VcxResult { trace!("create_proof >>> source_id: {}, requested_attrs: {}, requested_predicates: {}, name: {}", source_id, requested_attrs, requested_predicates, name); // TODO: Get this to actually validate as json, not just check length. - if requested_attrs.len() <= 0 { return Err(ProofError::CommonError(error::INVALID_JSON.code_num)); } + if requested_attrs.len() <= 0 { return Err(VcxError::from(VcxErrorKind::InvalidJson)); } let revocation_details: RevocationInterval = serde_json::from_str(&revocation_details) - .or(Err(ProofError::CommonError(error::INVALID_JSON.code_num)))?; + .or(Err(VcxError::from(VcxErrorKind::InvalidJson)))?; debug!("creating proof with source_id: {}, name: {}, requested_attrs: {}, requested_predicates: {}", source_id, name, requested_attrs, requested_predicates); @@ -415,7 +399,7 @@ pub fn create_proof(source_id: String, proof_state: ProofStateType::ProofUndefined, name, version: String::from("1.0"), - nonce: generate_nonce().map_err(|ec| ProofError::CommonError(ec))?, + nonce: generate_nonce()?, proof: None, proof_request: None, remote_did: String::new(), @@ -426,20 +410,19 @@ pub fn create_proof(source_id: String, thread: Thread::new(), }; - new_proof.validate_proof_request().map_err(|ec| ProofError::CommonError(ec))?; + new_proof.validate_proof_request()?; new_proof.state = VcxStateType::VcxStateInitialized; - let new_handle = PROOF_MAP.add(new_proof).map_err(|ec| ProofError::CreateProofError())?; - - Ok(new_handle) + PROOF_MAP.add(new_proof) + .or(Err(VcxError::from(VcxErrorKind::CreateProof))) } pub fn is_valid_handle(handle: u32) -> bool { PROOF_MAP.has_handle(handle) } -pub fn update_state(handle: u32) -> Result { +pub fn update_state(handle: u32) -> VcxResult { PROOF_MAP.get_mut(handle, |p| { match p.update_state() { Ok(x) => Ok(x), @@ -448,92 +431,81 @@ pub fn update_state(handle: u32) -> Result { Ok(p.get_state()) } } - }).map_err(|ec| ProofError::CommonError(ec)) + }) } -pub fn get_state(handle: u32) -> Result { +pub fn get_state(handle: u32) -> VcxResult { PROOF_MAP.get(handle, |p| { Ok(p.get_state()) - }).map_err(|ec| ProofError::CommonError(ec)) + }) } -pub fn get_proof_state(handle: u32) -> Result { +pub fn get_proof_state(handle: u32) -> VcxResult { PROOF_MAP.get(handle, |p| { Ok(p.get_proof_state()) - }).map_err(|ec| ProofError::CommonError(ec)) + }) } -pub fn release(handle: u32) -> Result<(), ProofError> { - match PROOF_MAP.release(handle) { - Ok(_) => Ok(()), - Err(_) => Err(ProofError::InvalidHandle()), - } +pub fn release(handle: u32) -> VcxResult<()> { + PROOF_MAP.release(handle).or(Err(VcxError::from(VcxErrorKind::InvalidProofHandle))) } pub fn release_all() { - match PROOF_MAP.drain() { - Ok(_) => (), - Err(_) => (), - }; + PROOF_MAP.drain().ok(); } -pub fn to_string(handle: u32) -> Result { +pub fn to_string(handle: u32) -> VcxResult { PROOF_MAP.get(handle, |p| { - Ok(Proof::to_string(&p)) - }).map_err(|ec| ProofError::CommonError(ec)) + Proof::to_string(&p) + }) } -pub fn get_source_id(handle: u32) -> Result { +pub fn get_source_id(handle: u32) -> VcxResult { PROOF_MAP.get(handle, |p| { Ok(p.get_source_id().clone()) - }).map_err(|ec| ProofError::CommonError(ec)) + }) } -pub fn from_string(proof_data: &str) -> Result { - let derived_proof: Proof = Proof::from_str(proof_data).map_err(|err| { - warn!("{} with serde error: {}", error::INVALID_JSON.message, err); - ProofError::CommonError(error::INVALID_JSON.code_num) - })?; +pub fn from_string(proof_data: &str) -> VcxResult { + let derived_proof: Proof = Proof::from_str(proof_data) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize Proof: {}", err)))?; let source_id = derived_proof.source_id.clone(); - let new_handle = PROOF_MAP.add(derived_proof).map_err(|ec| ProofError::CommonError(ec))?; - - Ok(new_handle) + PROOF_MAP.add(derived_proof) } -pub fn send_proof_request(handle: u32, connection_handle: u32) -> Result { +pub fn send_proof_request(handle: u32, connection_handle: u32) -> VcxResult { PROOF_MAP.get_mut(handle, |p| { - p.send_proof_request(connection_handle).map_err(|ec| ec.to_error_code()) - }).map_err(|ec| ProofError::CommonError(ec)) + p.send_proof_request(connection_handle) + }) } -pub fn get_proof_uuid(handle: u32) -> Result { +pub fn get_proof_uuid(handle: u32) -> VcxResult { PROOF_MAP.get(handle, |p| { Ok(p.get_proof_uuid().clone()) }) } -fn parse_proof_payload(payload: &str) -> Result { - let my_credential_req = ProofMessage::from_str(&payload).map_err(|err| { - warn!("invalid json {}", err); - error::INVALID_JSON.code_num - })?; +fn parse_proof_payload(payload: &str) -> VcxResult { + let my_credential_req = ProofMessage::from_str(&payload) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize ProofMessage: {}", err)))?; Ok(my_credential_req) } -pub fn get_proof(handle: u32) -> Result { +pub fn get_proof(handle: u32) -> VcxResult { PROOF_MAP.get(handle, |p| { - p.get_proof().map_err(|ec| ec.to_error_code()) - }).map_err(|ec| ProofError::CommonError(ec)) + p.get_proof() + }) } // TODO: This doesnt feel like it should be here (maybe utils?) -pub fn generate_nonce() -> Result { - let mut bn = BigNum::new().map_err(|err| error::BIG_NUMBER_ERROR.code_num)?; +pub fn generate_nonce() -> VcxResult { + let mut bn = BigNum::new().map_err(|err| VcxError::from_msg(VcxErrorKind::EncodeError, format!("Cannot generate nonce: {}", err)))?; BigNumRef::rand(&mut bn, LARGE_NONCE as i32, openssl::bn::MsbOption::MAYBE_ZERO, false) - .map_err(|_| error::BIG_NUMBER_ERROR.code_num)?; - Ok(bn.to_dec_str().map_err(|err| error::BIG_NUMBER_ERROR.code_num)?.to_string()) + .map_err(|err| VcxError::from_msg(VcxErrorKind::EncodeError, format!("Cannot generate nonce: {}", err)))?; + Ok(bn.to_dec_str() + .map_err(|err| VcxError::from_msg(VcxErrorKind::EncodeError, format!("Cannot generate nonce: {}", err)))?.to_string()) } #[cfg(test)] diff --git a/vcx/libvcx/src/schema.rs b/vcx/libvcx/src/schema.rs index 87f6869144..58318700fa 100644 --- a/vcx/libvcx/src/schema.rs +++ b/vcx/libvcx/src/schema.rs @@ -1,16 +1,13 @@ use serde_json; -use serde_json::Value; -extern crate rand; use settings; -use std::fmt; use std::string::ToString; -use utils::error; use utils::libindy::anoncreds; use utils::libindy::payments::PaymentTxn; -use error::schema::SchemaError; use utils::constants::DEFAULT_SERIALIZE_VERSION; use object_cache::ObjectCache; +use messages::ObjectWithVersion; +use error::prelude::*; lazy_static! { static ref SCHEMA_MAP: ObjectCache = Default::default(); @@ -24,7 +21,7 @@ pub struct SchemaData { attr_names: Vec, } -#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct CreateSchema { data: Vec, version: String, @@ -35,62 +32,29 @@ pub struct CreateSchema { payment_txn: Option, } -impl Default for CreateSchema { - fn default() -> CreateSchema { - CreateSchema { - data: Vec::new(), - version: String::new(), - schema_id: String::new(), - name: String::new(), - source_id: String::new(), - sequence_num: 0, - payment_txn: None, - } - } -} - -impl fmt::Display for CreateSchema { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match serde_json::to_string(&self){ - Ok(s) => { - write!(f, "{}", s) - }, - Err(e) => { - error!("{}: {:?}",error::INVALID_SCHEMA.message, e); - write!(f, "null") - } - } - } -} - impl CreateSchema { - - pub fn set_sequence_num(&mut self, sequence_num: u32) {self.sequence_num = sequence_num;} - - pub fn get_sequence_num(&self) -> u32 {let sequence_num = self.sequence_num as u32; sequence_num} + pub fn get_sequence_num(&self) -> u32 { self.sequence_num } pub fn get_source_id(&self) -> &String { &self.source_id } pub fn get_schema_id(&self) -> &String { &self.schema_id } - fn get_payment_txn(&self) -> Result { + fn get_payment_txn(&self) -> VcxResult { trace!("CreateSchema::get_payment_txn >>>"); - Ok(self.payment_txn.clone().ok_or(error::NOT_READY.code_num)?) + self.payment_txn.clone() + .ok_or(err_msg(VcxErrorKind::NoPaymentInformation, "Payment information not found")) } - fn to_string_with_version(&self) -> String { - json!({ - "version": DEFAULT_SERIALIZE_VERSION, - "data": json!(self), - }).to_string() + fn to_string(&self) -> VcxResult { + ObjectWithVersion::new(DEFAULT_SERIALIZE_VERSION, self.to_owned()) + .serialize() + .map_err(|err| err.extend("Cannot serialize Schema")) } - fn from_str(data: &str) -> Result { - let data:Value = serde_json::from_str(&data) - .or(Err(SchemaError::InvalidSchemaCreation()))?; - let schema: CreateSchema = serde_json::from_value(data["data"].clone()) - .or(Err(SchemaError::InvalidSchemaCreation()))?; - Ok(schema) + fn from_str(data: &str) -> VcxResult { + ObjectWithVersion::deserialize(data) + .map(|obj: ObjectWithVersion| obj.data) + .map_err(|err| err.extend("Cannot deserialize Schema")) } } @@ -98,18 +62,11 @@ pub fn create_new_schema(source_id: &str, issuer_did: String, name: String, version: String, - data: String) -> Result { - trace!("create_new_schema >>> source_id: {}, issuer_did: {}, name: {}, version: {}, data: {}", - source_id, issuer_did, name, version, data); - + data: String) -> VcxResult { + trace!("create_new_schema >>> source_id: {}, issuer_did: {}, name: {}, version: {}, data: {}", source_id, issuer_did, name, version, data); debug!("creating schema with source_id: {}, name: {}, issuer_did: {}", source_id, name, issuer_did); - let (schema_id, payment_txn) = anoncreds::create_schema(&name, &version, &data) - .map_err(|e| { - if e == error::UNKNOWN_SCHEMA_REJECTION.code_num {SchemaError::UnknownRejection()} - else if e == error::DUPLICATE_SCHEMA.code_num {SchemaError::DuplicateSchema()} - else {SchemaError::CommonError(e)} - })?; + let (schema_id, payment_txn) = anoncreds::create_schema(&name, &version, &data)?; debug!("created schema on ledger with id: {}", schema_id); @@ -124,25 +81,23 @@ pub fn create_new_schema(source_id: &str, payment_txn, }; - let new_handle = SCHEMA_MAP.add(new_schema).map_err(|key|SchemaError::InvalidSchemaCreation())?; - - Ok(new_handle) + SCHEMA_MAP.add(new_schema) + .map_err(|_| VcxError::from_msg(VcxErrorKind::CreateSchema, "Cannot create schema")) // TODO: looks useless } -pub fn get_schema_attrs(source_id: String, schema_id: String) -> Result<(u32, String), SchemaError> { +pub fn get_schema_attrs(source_id: String, schema_id: String) -> VcxResult<(u32, String)> { trace!("get_schema_attrs >>> source_id: {}, schema_id: {}", source_id, schema_id); - let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID) - .map_err(|e| SchemaError::CommonError(e))?; + let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; - let (schema_id, schema_json) = anoncreds::get_schema_json(&schema_id) - .or(Err(SchemaError::InvalidSchemaSeqNo()))?; + let (schema_id, schema_data_json) = anoncreds::get_schema_json(&schema_id) + .map_err(|err| err.map(VcxErrorKind::InvalidSchemaSeqNo, "No Schema for that schema sequence number"))?; - let schema_data: SchemaData = serde_json::from_str(&schema_json) - .or(Err(SchemaError::CommonError(error::INVALID_JSON.code_num)))?; + let schema_data: SchemaData = serde_json::from_str(&schema_data_json) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize schema: {}", err)))?; - let new_schema = CreateSchema { + let schema = CreateSchema { source_id, schema_id, sequence_num: 0, @@ -152,70 +107,60 @@ pub fn get_schema_attrs(source_id: String, schema_id: String) -> Result<(u32, St payment_txn: None, }; - let new_handle = SCHEMA_MAP.add(new_schema).map_err(|key|SchemaError::InvalidSchemaCreation())?; + let schema_json = schema.to_string()?; - Ok((new_handle, to_string(new_handle)?)) + let handle = SCHEMA_MAP.add(schema) + .map_err(|_| VcxError::from_msg(VcxErrorKind::CreateSchema, "Cannot create schema"))?; // TODO: looks useless + + Ok((handle, schema_json)) } pub fn is_valid_handle(handle: u32) -> bool { SCHEMA_MAP.has_handle(handle) } -pub fn get_sequence_num(handle: u32) -> Result { - SCHEMA_MAP.get(handle,|s|{ - Ok(s.get_sequence_num()) - }).map_err(|ec|SchemaError::CommonError(ec)) +pub fn to_string(handle: u32) -> VcxResult { + SCHEMA_MAP.get(handle, |s| { + s.to_string() + }) } -pub fn to_string(handle: u32) -> Result { - SCHEMA_MAP.get(handle,|s|{ - Ok(s.to_string_with_version().to_owned()) - }).map_err(|ec|SchemaError::CommonError(ec)) +pub fn get_sequence_num(handle: u32) -> VcxResult { + SCHEMA_MAP.get(handle, |s| { + Ok(s.get_sequence_num()) + }) } -pub fn get_source_id(handle: u32) -> Result { - SCHEMA_MAP.get(handle,|s|{ +pub fn get_source_id(handle: u32) -> VcxResult { + SCHEMA_MAP.get(handle, |s| { Ok(s.get_source_id().clone()) }) } -pub fn get_schema_id(handle: u32) -> Result { - SCHEMA_MAP.get(handle,|s|{ +pub fn get_schema_id(handle: u32) -> VcxResult { + SCHEMA_MAP.get(handle, |s| { Ok(s.get_schema_id().clone()) - }).map_err(|ec|SchemaError::CommonError(ec)) + }) } -pub fn get_payment_txn(handle: u32) -> Result { - SCHEMA_MAP.get(handle,|s|{ +pub fn get_payment_txn(handle: u32) -> VcxResult { + SCHEMA_MAP.get(handle, |s| { s.get_payment_txn() - }).or(Err(SchemaError::NoPaymentInformation())) + }) } -pub fn from_string(schema_data: &str) -> Result { - let derived_schema: CreateSchema = CreateSchema::from_str(schema_data) - .map_err(|_| { - error!("Invalid Json format for CreateSchema string"); - SchemaError::CommonError(error::INVALID_JSON.code_num) - })?; - - let source_id = derived_schema.source_id.clone(); - let new_handle = SCHEMA_MAP.add(derived_schema).map_err(|ec|SchemaError::CommonError(ec))?; - - Ok(new_handle) +pub fn from_string(schema_data: &str) -> VcxResult { + let schema: CreateSchema = CreateSchema::from_str(schema_data)?; + SCHEMA_MAP.add(schema) } -pub fn release(handle: u32) -> Result<(), SchemaError> { - match SCHEMA_MAP.release(handle) { - Ok(_) => Ok(()), - Err(_) => Err(SchemaError::InvalidHandle()), - } +pub fn release(handle: u32) -> VcxResult<()> { + SCHEMA_MAP.release(handle) + .or(Err(VcxError::from(VcxErrorKind::InvalidSchemaHandle))) } pub fn release_all() { - match SCHEMA_MAP.drain() { - Ok(_) => (), - Err(_) => (), - }; + SCHEMA_MAP.drain().ok(); } #[cfg(test)] @@ -225,20 +170,20 @@ pub mod tests { use super::*; #[allow(unused_imports)] use rand::Rng; - use utils::constants::{ SCHEMA_ID, SCHEMA_JSON }; + use utils::constants::{SCHEMA_ID, SCHEMA_JSON}; pub fn create_schema_real() -> u32 { let data = r#"["address1","address2","zip","city","state"]"#.to_string(); let schema_name: String = rand::thread_rng().gen_ascii_chars().take(25).collect::(); - let schema_version: String = format!("{}.{}",rand::thread_rng().gen::().to_string(), - rand::thread_rng().gen::().to_string()); + let schema_version: String = format!("{}.{}", rand::thread_rng().gen::().to_string(), + rand::thread_rng().gen::().to_string()); let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); create_new_schema("id", did, schema_name, schema_version, data).unwrap() } #[test] - fn test_create_schema_to_string(){ + fn test_create_schema_to_string() { let source_id = "testId"; let create_schema = CreateSchema { data: vec!["name".to_string(), "age".to_string(), "sex".to_string(), "height".to_string()], @@ -249,11 +194,9 @@ pub mod tests { sequence_num: 306, payment_txn: None, }; - let create_schema_str = r#"{"data":["name","age","sex","height"],"version":"1.0","schema_id":"2hoqvcwupRTUNkXn6ArYzs:2:test-licence:4.4.4","name":"schema_name","source_id":"testId","sequence_num":306,"payment_txn":null}"#; - assert_eq!(create_schema.to_string(), create_schema_str.to_string()); - let value: serde_json::Value = serde_json::from_str(&create_schema.to_string_with_version()).unwrap(); + let value: serde_json::Value = serde_json::from_str(&create_schema.to_string()).unwrap(); assert_eq!(value["version"], "1.0"); - let create_schema:CreateSchema = serde_json::from_str(&value["data"].to_string()).unwrap(); + let create_schema: CreateSchema = serde_json::from_str(&value["data"].to_string()).unwrap(); assert_eq!(create_schema.source_id, source_id); use utils::constants::SCHEMA_WITH_VERSION; let handle = from_string(SCHEMA_WITH_VERSION).unwrap(); @@ -261,11 +204,11 @@ pub mod tests { let value: serde_json::Value = serde_json::from_str(&schema_str).unwrap(); assert_eq!(value["version"], "1.0"); let data = value["data"].clone(); - let schema:CreateSchema = serde_json::from_str(&data.to_string()).unwrap(); + let schema: CreateSchema = serde_json::from_str(&data.to_string()).unwrap(); } #[test] - fn test_create_schema_success(){ + fn test_create_schema_success() { init!("true"); let data = r#"["name","male"]"#; assert!(create_new_schema("1", @@ -276,16 +219,16 @@ pub mod tests { } #[test] - fn test_get_schema_attrs_success(){ + fn test_get_schema_attrs_success() { init!("true"); - let (handle, schema_attrs ) = get_schema_attrs("Check For Success".to_string(), SCHEMA_ID.to_string()).unwrap(); + let (handle, schema_attrs) = get_schema_attrs("Check For Success".to_string(), SCHEMA_ID.to_string()).unwrap(); assert!(schema_attrs.contains(r#""schema_id":"2hoqvcwupRTUNkXn6ArYzs:2:test-licence:4.4.4""#)); assert!(schema_attrs.contains(r#""data":["height","name","sex","age"]"#)); assert!(handle > 0); } #[test] - fn test_create_schema_fails(){ + fn test_create_schema_fails() { init!("false"); let schema = create_new_schema("1", "VsKV7grR1BUE29mG2Fm2kX".to_string(), "name".to_string(), @@ -296,17 +239,17 @@ pub mod tests { #[cfg(feature = "pool_tests")] #[test] - fn test_get_schema_attrs_from_ledger(){ + fn test_get_schema_attrs_from_ledger() { init!("ledger"); let (schema_id, _) = ::utils::libindy::anoncreds::tests::create_and_write_test_schema(::utils::constants::DEFAULT_SCHEMA_ATTRS); - let (_, schema_attrs ) = get_schema_attrs("id".to_string(), schema_id.clone()).unwrap(); + let (_, schema_attrs) = get_schema_attrs("id".to_string(), schema_id.clone()).unwrap(); assert!(schema_attrs.contains(&schema_id)); } #[cfg(feature = "pool_tests")] #[test] - fn test_create_schema_with_pool(){ + fn test_create_schema_with_pool() { init!("ledger"); let handle = create_schema_real(); let payment = serde_json::to_string(&get_payment_txn(handle).unwrap()).unwrap(); @@ -318,9 +261,9 @@ pub mod tests { #[cfg(feature = "pool_tests")] #[test] - fn test_create_schema_no_fees_with_pool(){ + fn test_create_schema_no_fees_with_pool() { init!("ledger"); - ::utils::libindy::payments::mint_tokens_and_set_fees(Some(0),Some(0),Some(r#"{"101":0, "102":0}"#.to_string()), None).unwrap(); + ::utils::libindy::payments::mint_tokens_and_set_fees(Some(0), Some(0), Some(r#"{"101":0, "102":0}"#.to_string()), None).unwrap(); let handle = create_schema_real(); assert!(handle > 0); @@ -329,16 +272,16 @@ pub mod tests { #[cfg(feature = "pool_tests")] #[test] - fn test_create_duplicate_fails_no_fees(){ + fn test_create_duplicate_fails_no_fees() { use settings; init!("ledger"); - ::utils::libindy::payments::mint_tokens_and_set_fees(Some(0),Some(0),Some(r#"{"101":0, "102":0}"#.to_string()), None).unwrap(); + ::utils::libindy::payments::mint_tokens_and_set_fees(Some(0), Some(0), Some(r#"{"101":0, "102":0}"#.to_string()), None).unwrap(); let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); let data = r#"["address1","address2","zip","city","state"]"#.to_string(); let schema_name: String = rand::thread_rng().gen_ascii_chars().take(25).collect::(); - let schema_version: String = format!("{}.{}",rand::thread_rng().gen::().to_string(), + let schema_version: String = format!("{}.{}", rand::thread_rng().gen::().to_string(), rand::thread_rng().gen::().to_string()); let rc = create_new_schema("id", did.clone(), schema_name.clone(), schema_version.clone(), data.clone()); assert!(rc.is_ok()); @@ -353,21 +296,21 @@ pub mod tests { let data = r#"["address1","address2","zip","city","state"]"#; let version = r#"0.0.0"#; let did = r#"2hoqvcwupRTUNkXn6ArYzs"#; - let h1 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(),data.to_string()).unwrap(); - let h2 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(),data.to_string()).unwrap(); - let h3 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(),data.to_string()).unwrap(); - let h4 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(),data.to_string()).unwrap(); - let h5 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(),data.to_string()).unwrap(); + let h1 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(), data.to_string()).unwrap(); + let h2 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(), data.to_string()).unwrap(); + let h3 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(), data.to_string()).unwrap(); + let h4 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(), data.to_string()).unwrap(); + let h5 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(), data.to_string()).unwrap(); release_all(); - assert_eq!(release(h1).err(),Some(SchemaError::InvalidHandle())); - assert_eq!(release(h2).err(),Some(SchemaError::InvalidHandle())); - assert_eq!(release(h3).err(),Some(SchemaError::InvalidHandle())); - assert_eq!(release(h4).err(),Some(SchemaError::InvalidHandle())); - assert_eq!(release(h5).err(),Some(SchemaError::InvalidHandle())); + assert_eq!(release(h1).err(), Some(SchemaError::InvalidHandle())); + assert_eq!(release(h2).err(), Some(SchemaError::InvalidHandle())); + assert_eq!(release(h3).err(), Some(SchemaError::InvalidHandle())); + assert_eq!(release(h4).err(), Some(SchemaError::InvalidHandle())); + assert_eq!(release(h5).err(), Some(SchemaError::InvalidHandle())); } #[test] - fn test_errors(){ + fn test_errors() { init!("false"); assert_eq!(get_sequence_num(145661).err(), Some(SchemaError::CommonError(error::INVALID_OBJ_HANDLE.code_num))); assert_eq!(to_string(13435178).err(), Some(SchemaError::CommonError(error::INVALID_OBJ_HANDLE.code_num))); diff --git a/vcx/libvcx/src/settings.rs b/vcx/libvcx/src/settings.rs index 6b257609ed..5bb3c9acd7 100644 --- a/vcx/libvcx/src/settings.rs +++ b/vcx/libvcx/src/settings.rs @@ -11,6 +11,8 @@ use std::fs; use std::io::prelude::*; use serde_json::Value; +use error::prelude::*; + pub static CONFIG_POOL_NAME: &'static str = "pool_name"; pub static CONFIG_PROTOCOL_TYPE: &'static str = "protocol_type"; pub static CONFIG_AGENCY_ENDPOINT: &'static str = "agency_endpoint"; @@ -80,6 +82,7 @@ impl ToString for HashMap { v } } + pub fn set_defaults() -> u32 { trace!("set_defaults >>>"); @@ -112,44 +115,44 @@ pub fn set_defaults() -> u32 { error::SUCCESS.code_num } -pub fn validate_config(config: &HashMap) -> Result { +pub fn validate_config(config: &HashMap) -> VcxResult { trace!("validate_config >>> config: {:?}", config); //Mandatory parameters if config.get(CONFIG_WALLET_KEY).is_none() { - return Err(error::MISSING_WALLET_KEY.code_num); + return Err(VcxError::from(VcxErrorKind::MissingWalletKey)); } // If values are provided, validate they're in the correct format - validate_optional_config_val(config.get(CONFIG_INSTITUTION_DID), error::INVALID_DID.code_num, validation::validate_did)?; - validate_optional_config_val(config.get(CONFIG_INSTITUTION_VERKEY), error::INVALID_VERKEY.code_num, validation::validate_verkey)?; + validate_optional_config_val(config.get(CONFIG_INSTITUTION_DID), VcxErrorKind::InvalidDid, validation::validate_did)?; + validate_optional_config_val(config.get(CONFIG_INSTITUTION_VERKEY), VcxErrorKind::InvalidVerkey, validation::validate_verkey)?; - validate_optional_config_val(config.get(CONFIG_AGENCY_DID), error::INVALID_DID.code_num, validation::validate_did)?; - validate_optional_config_val(config.get(CONFIG_AGENCY_VERKEY), error::INVALID_VERKEY.code_num, validation::validate_verkey)?; + validate_optional_config_val(config.get(CONFIG_AGENCY_DID), VcxErrorKind::InvalidDid, validation::validate_did)?; + validate_optional_config_val(config.get(CONFIG_AGENCY_VERKEY), VcxErrorKind::InvalidVerkey, validation::validate_verkey)?; - validate_optional_config_val(config.get(CONFIG_SDK_TO_REMOTE_DID), error::INVALID_DID.code_num, validation::validate_did)?; - validate_optional_config_val(config.get(CONFIG_SDK_TO_REMOTE_VERKEY), error::INVALID_VERKEY.code_num, validation::validate_verkey)?; + validate_optional_config_val(config.get(CONFIG_SDK_TO_REMOTE_DID), VcxErrorKind::InvalidDid, validation::validate_did)?; + validate_optional_config_val(config.get(CONFIG_SDK_TO_REMOTE_VERKEY), VcxErrorKind::InvalidVerkey, validation::validate_verkey)?; - validate_optional_config_val(config.get(CONFIG_REMOTE_TO_SDK_DID), error::INVALID_DID.code_num, validation::validate_did)?; - validate_optional_config_val(config.get(CONFIG_REMOTE_TO_SDK_VERKEY), error::INVALID_VERKEY.code_num, validation::validate_verkey)?; + validate_optional_config_val(config.get(CONFIG_REMOTE_TO_SDK_DID), VcxErrorKind::InvalidDid, validation::validate_did)?; + validate_optional_config_val(config.get(CONFIG_REMOTE_TO_SDK_VERKEY), VcxErrorKind::InvalidVerkey, validation::validate_verkey)?; - validate_optional_config_val(config.get(CONFIG_AGENCY_ENDPOINT), error::INVALID_URL.code_num, Url::parse)?; - validate_optional_config_val(config.get(CONFIG_INSTITUTION_LOGO_URL), error::INVALID_URL.code_num, Url::parse)?; + validate_optional_config_val(config.get(CONFIG_AGENCY_ENDPOINT), VcxErrorKind::InvalidDid, Url::parse)?; + validate_optional_config_val(config.get(CONFIG_INSTITUTION_LOGO_URL), VcxErrorKind::InvalidVerkey, Url::parse)?; Ok(error::SUCCESS.code_num) } -fn validate_wallet_key(key: &str) -> Result { - if key == UNINITIALIZED_WALLET_KEY { return Err(error::MISSING_WALLET_KEY.code_num); } +fn validate_wallet_key(key: &str) -> VcxResult { + if key == UNINITIALIZED_WALLET_KEY { return Err(VcxError::from(VcxErrorKind::MissingWalletKey)); } Ok(error::SUCCESS.code_num) } -fn validate_optional_config_val(val: Option<&String>, err: u32, closure: F) -> Result +fn validate_optional_config_val(val: Option<&String>, err: VcxErrorKind, closure: F) -> VcxResult where F: Fn(&str) -> Result { if val.is_none() { return Ok(error::SUCCESS.code_num); } - closure(val.as_ref().ok_or(error::INVALID_CONFIGURATION.code_num)?) - .or(Err(err))?; + closure(val.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidConfiguration))?) + .or(Err(VcxError::from(err)))?; Ok(error::SUCCESS.code_num) } @@ -190,27 +193,29 @@ pub fn test_agency_mode_enabled() -> bool { } } -pub fn process_config_string(config: &str) -> Result { +pub fn process_config_string(config: &str) -> VcxResult { trace!("process_config_string >>> config {}", config); - let configuration: Value = serde_json::from_str(config).or(Err(error::INVALID_JSON.code_num))?; + let configuration: Value = serde_json::from_str(config) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize config: {}", err)))?; + if let Value::Object(ref map) = configuration { for (key, value) in map { - set_config_value(key, value.as_str().ok_or(error::INVALID_JSON.code_num)?); + set_config_value(key, value.as_str().ok_or(VcxError::from(VcxErrorKind::InvalidJson))?); } } validate_config( - &SETTINGS.read().or(Err(error::INVALID_CONFIGURATION.code_num))?.clone() + &SETTINGS.read().or(Err(VcxError::from(VcxErrorKind::InvalidConfiguration)))?.clone() ) } -pub fn process_config_file(path: &str) -> Result { +pub fn process_config_file(path: &str) -> VcxResult { trace!("process_config_file >>> path: {}", path); if !Path::new(path).is_file() { error!("Configuration path was invalid"); - Err(error::INVALID_CONFIGURATION.code_num) + Err(VcxError::from_msg(VcxErrorKind::InvalidConfiguration, "Cannot find config file")) } else { process_config_string(&read_config_file(path)?) } @@ -225,7 +230,7 @@ pub fn get_protocol_version() -> usize { Err(err) => { info!("Can't fetch protocol version from config ({}), use default one ({})", err, DEFAULT_PROTOCOL_VERSION); DEFAULT_PROTOCOL_VERSION - }, + } }; if protocol_version > MAX_SUPPORTED_PROTOCOL_VERSION { error!("Protocol version from config {}, greater then maximal supported {}, use maximum one", @@ -236,14 +241,15 @@ pub fn get_protocol_version() -> usize { } } -pub fn get_config_value(key: &str) -> Result { +pub fn get_config_value(key: &str) -> VcxResult { trace!("get_config_value >>> key: {}", key); SETTINGS .read() - .or(Err(error::INVALID_CONFIGURATION.code_num))? + .or(Err(VcxError::from_msg(VcxErrorKind::InvalidConfiguration, "Cannot read settings")))? .get(key) - .map_or(Err(error::INVALID_CONFIGURATION.code_num), |v| Ok(v.to_string())) + .map(|v| v.to_string()) + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidConfiguration, format!("Cannot read \"{}\" from settings", key))) } pub fn set_config_value(key: &str, value: &str) { @@ -256,7 +262,7 @@ pub fn get_wallet_config(wallet_name: &str, wallet_type: Option<&str>, storage_c "id": wallet_name, "storage_type": wallet_type }); - + let storage_config = get_config_value(CONFIG_WALLET_STORAGE_CONFIG).ok(); if let Some(_config) = storage_config { config["storage_config"] = serde_json::from_str(&_config).unwrap(); } @@ -276,14 +282,14 @@ pub fn get_wallet_credentials(storage_creds: Option<&str>) -> String { credentials.to_string() } -pub fn validate_payment_method() -> Result<(), u32> { +pub fn validate_payment_method() -> VcxResult<()> { let config = SETTINGS.read().unwrap(); if let Some(method) = config.get(CONFIG_PAYMENT_METHOD) { if !method.to_string().is_empty() { return Ok(()); } } - return Err(error::MISSING_PAYMENT_METHOD.code_num); + return Err(VcxError::from(VcxErrorKind::MissingPaymentMethod)); } pub fn get_payment_method() -> String { @@ -332,22 +338,25 @@ pub fn get_protocol_type() -> ProtocolTypes { ProtocolTypes::from(get_config_value(CONFIG_PROTOCOL_TYPE).unwrap_or(DEFAULT_PROTOCOL_TYPE.to_string())) } -pub fn write_config_to_file(config: &str, path_string: &str) -> Result<(), u32> { +pub fn write_config_to_file(config: &str, path_string: &str) -> VcxResult<()> { trace!("write_config_to_file >>> config: {}, path_string: {}", config, path_string); let mut file = fs::File::create(Path::new(path_string)) - .or(Err(error::UNKNOWN_ERROR.code_num))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::UnknownError, err))?; - file.write_all(config.as_bytes()).or(Err(error::UNKNOWN_ERROR.code_num))?; + file.write_all(config.as_bytes()) + .map_err(|err| VcxError::from_msg(VcxErrorKind::UnknownError, err))?; Ok(()) } -pub fn read_config_file(path: &str) -> Result { +pub fn read_config_file(path: &str) -> VcxResult { trace!("read_config_file >>> path: {}", path); - let mut file = fs::File::open(path).or(Err(error::UNKNOWN_ERROR.code_num))?; + let mut file = fs::File::open(path) + .map_err(|err| VcxError::from_msg(VcxErrorKind::UnknownError, err))?; let mut config = String::new(); - file.read_to_string(&mut config).or(Err(error::UNKNOWN_ERROR.code_num))?; + file.read_to_string(&mut config) + .map_err(|err| VcxError::from_msg(VcxErrorKind::UnknownError, err))?; Ok(config) } diff --git a/vcx/libvcx/src/utils/error.rs b/vcx/libvcx/src/utils/error.rs index 3f175f0ee4..f298e8af34 100644 --- a/vcx/libvcx/src/utils/error.rs +++ b/vcx/libvcx/src/utils/error.rs @@ -265,15 +265,6 @@ pub fn error_string(code_num:u32) -> String { } } -pub fn map_libindy_err(check_rtn: u32, default_rtn: u32) -> u32 { - match check_rtn { - x if x == TIMEOUT_LIBINDY_ERROR.code_num => { - x - }, - _ => default_rtn - } -} - #[cfg(test)] mod tests { use super::*; @@ -434,21 +425,4 @@ mod tests { fn test_invalid_master_secret() { assert_eq!(error_message(&INVALID_MASTER_SECRET.code_num), INVALID_MASTER_SECRET.message); } - - #[test] - fn test_map_libindy_err() { - let default = UNKNOWN_ERROR.code_num; - // Pass in arbitrary check val, rtn default err - assert_eq!(map_libindy_err(INVALID_SCHEMA_SEQ_NO.code_num, default), - default); - // Pass libindy timeout, rtn Err(libindy timeout) - assert_eq!(map_libindy_err(TIMEOUT_LIBINDY_ERROR.code_num, default), - TIMEOUT_LIBINDY_ERROR.code_num); - - let fn_map_err = |x: Result| x; - // map_libindy_err not called with Ok returned - assert_eq!(fn_map_err(Ok(0)).map_err(|x| map_libindy_err(x, default)), Ok(0)); - // map_libindy_err called with Err returned - assert_eq!(fn_map_err(Err(0)).map_err(|x| map_libindy_err(x, default)), Err(default)) - } } diff --git a/vcx/libvcx/src/utils/httpclient.rs b/vcx/libvcx/src/utils/httpclient.rs index 7273cf318f..71033f346d 100644 --- a/vcx/libvcx/src/utils/httpclient.rs +++ b/vcx/libvcx/src/utils/httpclient.rs @@ -4,14 +4,15 @@ use std::sync::Mutex; use reqwest; use reqwest::header::CONTENT_TYPE; use std::env; +use error::prelude::*; lazy_static! { static ref NEXT_U8_RESPONSE: Mutex>> = Mutex::new(vec![]); } //Todo: change this RC to a u32 -pub fn post_u8(body_content: &Vec) -> Result, &'static str> { - let endpoint = settings::get_config_value(settings::CONFIG_AGENCY_ENDPOINT).or(Err("Invalid Configuration"))?; +pub fn post_u8(body_content: &Vec) -> VcxResult> { + let endpoint = settings::get_config_value(settings::CONFIG_AGENCY_ENDPOINT)?; let url = format!("{}/agency/msg", endpoint); if settings::test_agency_mode_enabled() { @@ -23,7 +24,8 @@ pub fn post_u8(body_content: &Vec) -> Result, &'static str> { info!("::Android code"); set_ssl_cert_location(); } - let client = reqwest::ClientBuilder::new().build().or(Err("Preparing Post failed"))?; + let client = reqwest::ClientBuilder::new().build(). + or(Err(VcxError::from_msg(VcxErrorKind::PostMessageFailed, "Preparing Post failed")))?; debug!("Posting encrypted bundle to: \"{}\"", url); let mut response = @@ -33,7 +35,7 @@ pub fn post_u8(body_content: &Vec) -> Result, &'static str> { .send() .map_err(|err| { error!("error: {}", err); - "Could not connect" + VcxError::from_msg(VcxErrorKind::PostMessageFailed, "Could not connect") })?; trace!("Response Header: {:?}", response); @@ -43,11 +45,12 @@ pub fn post_u8(body_content: &Vec) -> Result, &'static str> { Ok(x) => info!("Request failed: {}", content), Err(x) => info!("could not read response"), }; - return Err("POST failed"); + return Err(VcxError::from_msg(VcxErrorKind::PostMessageFailed, format!("POST failed with: {}", content))); } let mut content = Vec::new(); - response.read_to_end(&mut content).or(Err("could not read response"))?; + response.read_to_end(&mut content) + .or(Err(VcxError::from_msg(VcxErrorKind::PostMessageFailed, "could not read response")))?; Ok(content) } diff --git a/vcx/libvcx/src/utils/json.rs b/vcx/libvcx/src/utils/json.rs index 7b0434d5eb..46c827df12 100644 --- a/vcx/libvcx/src/utils/json.rs +++ b/vcx/libvcx/src/utils/json.rs @@ -1,26 +1,10 @@ extern crate serde; extern crate serde_json; -use self::serde::{Serialize, Deserialize}; -use self::serde_json::Error; use serde_json::Value; use serde_json::Map; use std::string::String; -use utils::error; - - -pub trait JsonEncodable: Serialize + Sized { - fn to_json(&self) -> Result { - serde_json::to_string(self) - } -} - -pub trait JsonDecodable<'a>: Deserialize<'a> { - fn from_json(to_stringd: &'a str) -> Result { - serde_json::from_str(to_stringd) - } -} - +use error::prelude::*; pub trait KeyMatch { fn matches(&self, key: &String, context: &Vec) -> bool; @@ -36,20 +20,20 @@ impl KeyMatch for String { Rewrites keys in a serde value structor to new mapped values. Returns the remapped value. Leaves unmapped keys as they are. */ -pub fn mapped_key_rewrite(val: Value, remap: &Vec<(T, String)>) -> Result { +pub fn mapped_key_rewrite(val: Value, remap: &Vec<(T, String)>) -> VcxResult { let mut context: Vec = Default::default(); _mapped_key_rewrite(val, &mut context, remap) } -fn _mapped_key_rewrite(val: Value, context: &mut Vec, remap: &Vec<(T, String)>) -> Result { +fn _mapped_key_rewrite(val: Value, context: &mut Vec, remap: &Vec<(T, String)>) -> VcxResult { if let Value::Object(mut map) = val { let mut keys:Vec = _collect_keys(&map); while let Some(k) = keys.pop() { let mut value = map.remove(&k).ok_or_else(||{ warn!("Unexpected key value mutation"); - error::INVALID_JSON.code_num + VcxError::from_msg(VcxErrorKind::InvalidJson, "Unexpected key value mutation") })?; diff --git a/vcx/libvcx/src/utils/libindy/anoncreds.rs b/vcx/libvcx/src/utils/libindy/anoncreds.rs index 6d4821cc8f..5f7b0fda35 100644 --- a/vcx/libvcx/src/utils/libindy/anoncreds.rs +++ b/vcx/libvcx/src/utils/libindy/anoncreds.rs @@ -2,26 +2,28 @@ extern crate libc; use futures::Future; use serde_json; -use serde_json::{ map::Map, Value}; +use serde_json::{map::Map, Value}; use settings; -use utils::constants::{ LIBINDY_CRED_OFFER, REQUESTED_ATTRIBUTES, ATTRS, REV_STATE_JSON}; -use utils::error::{ INVALID_PROOF_REQUEST, INVALID_ATTRIBUTES_STRUCTURE, INVALID_CONFIGURATION, INVALID_JSON, DUPLICATE_SCHEMA, UNKNOWN_SCHEMA_REJECTION } ; -use utils::libindy::{ error_codes::map_rust_indy_sdk_error, mock_libindy_rc, wallet::get_wallet_handle }; +use utils::constants::{LIBINDY_CRED_OFFER, REQUESTED_ATTRIBUTES, ATTRS, REV_STATE_JSON}; +use utils::libindy::{error_codes::map_rust_indy_sdk_error, mock_libindy_rc, wallet::get_wallet_handle}; use utils::libindy::payments::{pay_for_txn, PaymentTxn}; -use utils::constants::{ SCHEMA_ID, SCHEMA_JSON, SCHEMA_TXN_TYPE, CRED_DEF_ID, CRED_DEF_JSON, CRED_DEF_TXN_TYPE, REV_REG_DEF_TXN_TYPE, REV_REG_DELTA_TXN_TYPE, REVOC_REG_TYPE, rev_def_json, REV_REG_ID, REV_REG_DELTA_JSON, REV_REG_JSON}; +use utils::libindy::ledger::{Response, parse_response}; +use utils::constants::{SCHEMA_ID, SCHEMA_JSON, SCHEMA_TXN_TYPE, CRED_DEF_ID, CRED_DEF_JSON, CRED_DEF_TXN_TYPE, REV_REG_DEF_TXN_TYPE, REV_REG_DELTA_TXN_TYPE, REVOC_REG_TYPE, rev_def_json, REV_REG_ID, REV_REG_DELTA_JSON, REV_REG_JSON}; use utils::libindy::ledger::{libindy_build_schema_request, libindy_build_get_schema_request, libindy_submit_request, libindy_parse_get_cred_def_response, libindy_parse_get_schema_response, libindy_build_create_credential_def_txn, libindy_build_get_credential_def_txn}; use indy::anoncreds; use indy::blob_storage; use indy::ledger; use time; +use error::prelude::*; + +const BLOB_STORAGE_TYPE: &str = "default"; pub fn libindy_verifier_verify_proof(proof_req_json: &str, proof_json: &str, schemas_json: &str, credential_defs_json: &str, rev_reg_defs_json: &str, - rev_regs_json: &str) -> Result { - + rev_regs_json: &str) -> VcxResult { //TODO there was timeout here (before future-based Rust wrapper) anoncreds::verifier_verify_proof(proof_req_json, proof_json, @@ -33,25 +35,27 @@ pub fn libindy_verifier_verify_proof(proof_req_json: &str, .map_err(map_rust_indy_sdk_error) } -pub fn libindy_create_and_store_revoc_reg(issuer_did: &str, cred_def_id: &str, tails_path: &str, max_creds: u32) -> Result<(String, String, String), u32> { +pub fn libindy_create_and_store_revoc_reg(issuer_did: &str, cred_def_id: &str, tails_path: &str, max_creds: u32) -> VcxResult<(String, String, String)> { trace!("creating revocation: {}, {}, {}", cred_def_id, tails_path, max_creds); + let tails_config = json!({"base_dir": tails_path,"uri_pattern": ""}).to_string(); - let writer = blob_storage::open_writer("default", &tails_config.to_string()) + + let writer = blob_storage::open_writer(BLOB_STORAGE_TYPE, &tails_config) .wait() - .map_err(|ec|map_rust_indy_sdk_error(ec))?; + .map_err(map_rust_indy_sdk_error)?; + let revoc_config = json!({"max_cred_num": max_creds,"issuance_type": "ISSUANCE_BY_DEFAULT"}).to_string(); anoncreds::issuer_create_and_store_revoc_reg(get_wallet_handle(), issuer_did, None, "tag1", cred_def_id, &revoc_config, writer) .wait() - .map_err(|ec|map_rust_indy_sdk_error(ec)) + .map_err(map_rust_indy_sdk_error) } pub fn libindy_create_and_store_credential_def(issuer_did: &str, schema_json: &str, tag: &str, sig_type: Option<&str>, - config_json: &str) -> Result<(String, String), u32> { - + config_json: &str) -> VcxResult<(String, String)> { anoncreds::issuer_create_and_store_credential_def(get_wallet_handle(), issuer_did, schema_json, @@ -62,14 +66,21 @@ pub fn libindy_create_and_store_credential_def(issuer_did: &str, .map_err(map_rust_indy_sdk_error) } -pub fn libindy_issuer_create_credential_offer(cred_def_id: &str) -> Result { +pub fn libindy_issuer_create_credential_offer(cred_def_id: &str) -> VcxResult { if settings::test_indy_mode_enabled() { let rc = mock_libindy_rc(); - if rc != 0 { return Err(rc) }; + if rc != 0 { return Err(VcxError::from(VcxErrorKind::InvalidState)); }; return Ok(LIBINDY_CRED_OFFER.to_string()); } anoncreds::issuer_create_credential_offer(get_wallet_handle(), - cred_def_id) + cred_def_id) + .wait() + .map_err(map_rust_indy_sdk_error) +} + +fn blob_storage_open_reader(base_dir: &str) -> VcxResult { + let tails_config = json!({"base_dir": base_dir,"uri_pattern": ""}).to_string(); + blob_storage::open_reader("default", &tails_config) .wait() .map_err(map_rust_indy_sdk_error) } @@ -78,17 +89,11 @@ pub fn libindy_issuer_create_credential(cred_offer_json: &str, cred_req_json: &str, cred_values_json: &str, rev_reg_id: Option, - tails_file: Option) -> Result<(String, Option, Option), u32>{ - + tails_file: Option) -> VcxResult<(String, Option, Option)> { let revocation = rev_reg_id.as_ref().map(String::as_str); let blob_handle = match tails_file { - Some(x) => { - let tails_config = json!({"base_dir": x,"uri_pattern": ""}).to_string(); - blob_storage::open_reader("default", &tails_config.to_string()) - .wait() - .map_err(map_rust_indy_sdk_error)? - }, + Some(x) => blob_storage_open_reader(&x)?, None => -1, }; anoncreds::issuer_create_credential(get_wallet_handle(), @@ -106,7 +111,7 @@ pub fn libindy_prover_create_proof(proof_req_json: &str, master_secret_id: &str, schemas_json: &str, credential_defs_json: &str, - revoc_states_json: Option<&str>) -> Result { + revoc_states_json: Option<&str>) -> VcxResult { let revoc_states_json = revoc_states_json.unwrap_or("{}"); anoncreds::prover_create_proof(get_wallet_handle(), proof_req_json, @@ -119,96 +124,92 @@ pub fn libindy_prover_create_proof(proof_req_json: &str, .map_err(map_rust_indy_sdk_error) } -fn fetch_credentials(search_handle: i32, requested_attributes: Map) -> Result { +fn fetch_credentials(search_handle: i32, requested_attributes: Map) -> VcxResult { let mut v: Value = json!({}); for item_referent in requested_attributes.keys().into_iter() { - v[ATTRS][item_referent] = serde_json::from_str(&anoncreds::prover_fetch_credentials_for_proof_req(search_handle, item_referent, 100).wait() - .map_err(map_rust_indy_sdk_error)?) - .map_err(|_| { - error!("Invalid Json Parsing of Object Returned from Libindy. Did Libindy change its structure?"); - INVALID_CONFIGURATION.code_num - })? + v[ATTRS][item_referent] = + serde_json::from_str(&anoncreds::prover_fetch_credentials_for_proof_req(search_handle, item_referent, 100).wait() + .map_err(map_rust_indy_sdk_error)?) + .map_err(|_| { + error!("Invalid Json Parsing of Object Returned from Libindy. Did Libindy change its structure?"); + VcxError::from_msg(VcxErrorKind::InvalidConfiguration, "Invalid Json Parsing of Object Returned from Libindy. Did Libindy change its structure?") + })? } + Ok(v.to_string()) } -fn close_search_handle(search_handle: i32) -> Result<(), u32> { - anoncreds::prover_close_credentials_search_for_proof_req(search_handle).wait().map_err(|ec| { - error!("Error closing search handle"); - map_rust_indy_sdk_error(ec) - }) +fn close_search_handle(search_handle: i32) -> VcxResult<()> { + anoncreds::prover_close_credentials_search_for_proof_req(search_handle) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn libindy_prover_get_credentials_for_proof_req(proof_req: &str) -> Result { +pub fn libindy_prover_get_credentials_for_proof_req(proof_req: &str) -> VcxResult { let wallet_handle = get_wallet_handle(); // this may be too redundant since Prover::search_credentials will validate the proof reqeuest already. - let proof_request_json:Map = serde_json::from_str(proof_req).map_err(|_| INVALID_PROOF_REQUEST.code_num)?; + let proof_request_json: Map = serde_json::from_str(proof_req) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidProofRequest, format!("Cannot deserialize ProofRequest")))?; // since the search_credentials_for_proof request validates that the proof_req is properly structured, this get() // fn should never fail, unless libindy changes their formats. - let requested_attributes:Option> = proof_request_json.get(REQUESTED_ATTRIBUTES).and_then(|v| { - serde_json::from_value(v.clone()).map_err(|_| { - error!("Invalid Json Parsing of Requested Attributes Retrieved From Libindy. Did Libindy change its structure?"); - }).ok() - }); + let requested_attributes: Option> = proof_request_json.get(REQUESTED_ATTRIBUTES) + .and_then(|v| { + serde_json::from_value(v.clone()) + .map_err(|_| { + error!("Invalid Json Parsing of Requested Attributes Retrieved From Libindy. Did Libindy change its structure?"); + }).ok() + }); match requested_attributes { Some(attrs) => { let search_handle = anoncreds::prover_search_credentials_for_proof_req(wallet_handle, proof_req, None) .wait() - .map_err(|ec| { - error!("Opening Indy Search for Credentials Failed"); - map_rust_indy_sdk_error(ec) - })?; + .map_err(map_rust_indy_sdk_error)?; let creds: String = fetch_credentials(search_handle, attrs)?; // should an error on closing a search handle throw an error, or just a warning? // for now we're are just outputting to the user that there is an issue, and continuing on. let _ = close_search_handle(search_handle); Ok(creds) - }, + } None => { - Err(INVALID_ATTRIBUTES_STRUCTURE.code_num) + Err(VcxError::from(VcxErrorKind::InvalidAttributesStructure)) } } - } pub fn libindy_prover_create_credential_req(prover_did: &str, credential_offer_json: &str, - credential_def_json: &str) -> Result<(String, String), u32> { + credential_def_json: &str) -> VcxResult<(String, String)> { if settings::test_indy_mode_enabled() { return Ok((::utils::constants::CREDENTIAL_REQ_STRING.to_owned(), String::new())); } let master_secret_name = settings::DEFAULT_LINK_SECRET_ALIAS; anoncreds::prover_create_credential_req(get_wallet_handle(), - prover_did, - credential_offer_json, - credential_def_json, - master_secret_name) + prover_did, + credential_offer_json, + credential_def_json, + master_secret_name) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_prover_create_revocation_state(rev_reg_def_json: &str, rev_reg_delta_json: &str, cred_rev_id: &str, tails_file: &str) -> Result { +pub fn libindy_prover_create_revocation_state(rev_reg_def_json: &str, rev_reg_delta_json: &str, cred_rev_id: &str, tails_file: &str) -> VcxResult { if settings::test_indy_mode_enabled() { return Ok(REV_STATE_JSON.to_string()); } - let tails_config = json!({"base_dir": tails_file,"uri_pattern": ""}).to_string(); - let blob_handle = blob_storage::open_reader("default", &tails_config.to_string()) - .wait() - .map_err(|ec|map_rust_indy_sdk_error(ec))?; - anoncreds::create_revocation_state(blob_handle, rev_reg_def_json, rev_reg_delta_json, 100, cred_rev_id) + let blob_handle = blob_storage_open_reader(tails_file)?; + + anoncreds::create_revocation_state(blob_handle, rev_reg_def_json, rev_reg_delta_json, 100, cred_rev_id) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_prover_update_revocation_state(rev_reg_def_json: &str, rev_state_json: &str, rev_reg_delta_json: &str, cred_rev_id: &str, tails_file: &str) -> Result { +pub fn libindy_prover_update_revocation_state(rev_reg_def_json: &str, rev_state_json: &str, rev_reg_delta_json: &str, cred_rev_id: &str, tails_file: &str) -> VcxResult { if settings::test_indy_mode_enabled() { return Ok(REV_STATE_JSON.to_string()); } - let tails_config = json!({"base_dir": tails_file,"uri_pattern": ""}).to_string(); - let blob_handle = blob_storage::open_reader("default", &tails_config.to_string()) - .wait() - .map_err(|ec|map_rust_indy_sdk_error(ec))?; - anoncreds::update_revocation_state(blob_handle, rev_state_json, rev_reg_def_json, rev_reg_delta_json, 100, cred_rev_id) + let blob_handle = blob_storage_open_reader(tails_file)?; + + anoncreds::update_revocation_state(blob_handle, rev_state_json, rev_reg_def_json, rev_reg_delta_json, 100, cred_rev_id) .wait() .map_err(map_rust_indy_sdk_error) } @@ -217,26 +218,24 @@ pub fn libindy_prover_store_credential(cred_id: Option<&str>, cred_req_meta: &str, cred_json: &str, cred_def_json: &str, - rev_reg_def_json: Option) -> Result { + rev_reg_def_json: Option<&str>) -> VcxResult { if settings::test_indy_mode_enabled() { return Ok("cred_id".to_string()); } - let revocation = rev_reg_def_json.as_ref().map(String::as_str); - anoncreds::prover_store_credential(get_wallet_handle(), - cred_id, - cred_req_meta, - cred_json, - cred_def_json, - revocation) + cred_id, + cred_req_meta, + cred_json, + cred_def_json, + rev_reg_def_json) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_prover_create_master_secret(master_secret_id: &str) -> Result { +pub fn libindy_prover_create_master_secret(master_secret_id: &str) -> VcxResult { if settings::test_indy_mode_enabled() { return Ok(settings::DEFAULT_LINK_SECRET_ALIAS.to_string()); } anoncreds::prover_create_master_secret(get_wallet_handle(), - Some(master_secret_id)) + Some(master_secret_id)) .wait() .map_err(map_rust_indy_sdk_error) } @@ -244,22 +243,17 @@ pub fn libindy_prover_create_master_secret(master_secret_id: &str) -> Result Result<(String, String), u32>{ - + attrs: &str) -> VcxResult<(String, String)> { anoncreds::issuer_create_schema(issuer_did, - name, - version, - attrs) + name, + version, + attrs) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_issuer_revoke_credential(tails_file: &str, rev_reg_id: &str, cred_rev_id: &str) -> Result { - - let tails_config = json!({"base_dir": tails_file,"uri_pattern": ""}).to_string(); - let blob_handle = blob_storage::open_reader("default", &tails_config) - .wait() - .map_err(map_rust_indy_sdk_error)?; +pub fn libindy_issuer_revoke_credential(tails_file: &str, rev_reg_id: &str, cred_rev_id: &str) -> VcxResult { + let blob_handle = blob_storage_open_reader(tails_file)?; anoncreds::issuer_revoke_credential(get_wallet_handle(), blob_handle, rev_reg_id, cred_rev_id) .wait() @@ -267,7 +261,7 @@ pub fn libindy_issuer_revoke_credential(tails_file: &str, rev_reg_id: &str, cred } pub fn libindy_build_revoc_reg_def_request(submitter_did: &str, - rev_reg_def_json: &str) -> Result { + rev_reg_def_json: &str) -> VcxResult { ledger::build_revoc_reg_def_request(submitter_did, rev_reg_def_json) .wait() .map_err(map_rust_indy_sdk_error) @@ -276,19 +270,19 @@ pub fn libindy_build_revoc_reg_def_request(submitter_did: &str, pub fn libindy_build_revoc_reg_entry_request(submitter_did: &str, rev_reg_id: &str, rev_def_type: &str, - value: &str) -> Result { + value: &str) -> VcxResult { ledger::build_revoc_reg_entry_request(submitter_did, rev_reg_id, rev_def_type, value) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_build_get_revoc_reg_def_request(submitter_did: &str, rev_reg_id: &str) -> Result { +pub fn libindy_build_get_revoc_reg_def_request(submitter_did: &str, rev_reg_id: &str) -> VcxResult { ledger::build_get_revoc_reg_def_request(Some(submitter_did), rev_reg_id) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_parse_get_revoc_reg_def_response(rev_reg_def_json: &str) -> Result<(String, String), u32> { +pub fn libindy_parse_get_revoc_reg_def_response(rev_reg_def_json: &str) -> VcxResult<(String, String)> { ledger::parse_get_revoc_reg_def_response(rev_reg_def_json) .wait() .map_err(map_rust_indy_sdk_error) @@ -297,7 +291,7 @@ pub fn libindy_parse_get_revoc_reg_def_response(rev_reg_def_json: &str) -> Resul pub fn libindy_build_get_revoc_reg_delta_request(submitter_did: &str, rev_reg_id: &str, from: i64, - to: i64) -> Result { + to: i64) -> VcxResult { ledger::build_get_revoc_reg_delta_request(Some(submitter_did), rev_reg_id, from, @@ -306,8 +300,7 @@ pub fn libindy_build_get_revoc_reg_delta_request(submitter_did: &str, .map_err(map_rust_indy_sdk_error) } -fn libindy_build_get_revoc_reg_request(submitter_did: &str, rev_reg_id: &str, timestamp: u64) - -> Result { +fn libindy_build_get_revoc_reg_request(submitter_did: &str, rev_reg_id: &str, timestamp: u64) -> VcxResult { ledger::build_get_revoc_reg_request(Some(submitter_did), rev_reg_id, timestamp as i64) @@ -315,22 +308,24 @@ fn libindy_build_get_revoc_reg_request(submitter_did: &str, rev_reg_id: &str, ti .map_err(map_rust_indy_sdk_error) } -fn libindy_parse_get_revoc_reg_response(get_rev_reg_resp: &str) -> Result<(String, String, u64), u32> { +fn libindy_parse_get_revoc_reg_response(get_rev_reg_resp: &str) -> VcxResult<(String, String, u64)> { ledger::parse_get_revoc_reg_response(get_rev_reg_resp) .wait() .map_err(map_rust_indy_sdk_error) } pub fn libindy_parse_get_revoc_reg_delta_response(get_rev_reg_delta_response: &str) - -> Result<(String, String, u64), u32> { + -> VcxResult<(String, String, u64)> { ledger::parse_get_revoc_reg_delta_response(get_rev_reg_delta_response) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn create_schema(name: &str, version: &str, data: &str) -> Result<(String, Option), u32> { +pub fn create_schema(name: &str, version: &str, data: &str) -> VcxResult<(String, Option)> { if settings::test_indy_mode_enabled() { - return Ok((SCHEMA_ID.to_string(), Some(PaymentTxn::from_parts(r#"["pay:null:9UFgyjuJxi1i1HD"]"#,r#"[{"amount":4,"extra":null,"recipient":"pay:null:xkIsxem0YNtHrRO"}]"#,1, false).unwrap(), ))); + let inputs = vec!["pay:null:9UFgyjuJxi1i1HD".to_string()]; + let outputs = serde_json::from_str::>(r#"[{"amount":4,"extra":null,"recipient":"pay:null:xkIsxem0YNtHrRO"}]"#).unwrap(); + return Ok((SCHEMA_ID.to_string(), Some(PaymentTxn::from_parts(inputs, outputs, 1, false)))); } let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; @@ -341,32 +336,16 @@ pub fn create_schema(name: &str, version: &str, data: &str) -> Result<(String, O let (payment, response) = pay_for_txn(&request, SCHEMA_TXN_TYPE)?; - _check_create_schema_response(&response)?; + _check_schema_response(&response)?; Ok((id, payment)) } -fn _check_create_schema_response(response: &str) -> Result<(), u32> { - let response: Value = serde_json::from_str(response).or(Err(INVALID_JSON.code_num))?; - - if let Some(_) = response.get("result") { return Ok(()) }; - - warn!("No result found in ledger txn. Must be Rejected"); - - if response["op"] == json!("REJECT") { - match response.get("reason") { - Some(r) => return Err(DUPLICATE_SCHEMA.code_num), - None => return Err(UNKNOWN_SCHEMA_REJECTION.code_num), - } - } - - Err(UNKNOWN_SCHEMA_REJECTION.code_num) -} - -pub fn get_schema_json(schema_id: &str) -> Result<(String, String), u32> { - if settings::test_indy_mode_enabled() { return Ok((SCHEMA_ID.to_string(), SCHEMA_JSON.to_string()))} +pub fn get_schema_json(schema_id: &str) -> VcxResult<(String, String)> { + if settings::test_indy_mode_enabled() { return Ok((SCHEMA_ID.to_string(), SCHEMA_JSON.to_string())); } let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; + libindy_build_get_schema_request(&submitter_did, schema_id) .and_then(|req| libindy_submit_request(&req)) .and_then(|response| libindy_parse_get_schema_response(&response)) @@ -376,9 +355,11 @@ pub fn create_cred_def(issuer_did: &str, schema_json: &str, tag: &str, sig_type: Option<&str>, - support_revocation: Option) -> Result<(String, Option), u32> { + support_revocation: Option) -> VcxResult<(String, Option)> { if settings::test_indy_mode_enabled() { - return Ok((CRED_DEF_ID.to_string(), Some(PaymentTxn::from_parts(r#"["pay:null:9UFgyjuJxi1i1HD"]"#,r#"[{"amount":4,"extra":null,"recipient":"pay:null:xkIsxem0YNtHrRO"}]"#,1, false).unwrap()))); + let inputs = vec!["pay:null:9UFgyjuJxi1i1HD".to_string()]; + let outputs = serde_json::from_str::>(r#"[{"amount":4,"extra":null,"recipient":"pay:null:xkIsxem0YNtHrRO"}]"#).unwrap(); + return Ok((CRED_DEF_ID.to_string(), Some(PaymentTxn::from_parts(inputs, outputs, 1, false)))); } let config_json = json!({"support_revocation": support_revocation.unwrap_or(false)}).to_string(); @@ -396,7 +377,7 @@ pub fn create_cred_def(issuer_did: &str, Ok((id, payment)) } -pub fn get_cred_def_json(cred_def_id: &str) -> Result<(String, String), u32> { +pub fn get_cred_def_json(cred_def_id: &str) -> VcxResult<(String, String)> { if settings::test_indy_mode_enabled() { return Ok((CRED_DEF_ID.to_string(), CRED_DEF_JSON.to_string())); } libindy_build_get_credential_def_txn(cred_def_id) @@ -405,17 +386,16 @@ pub fn get_cred_def_json(cred_def_id: &str) -> Result<(String, String), u32> { } pub fn create_rev_reg_def(issuer_did: &str, cred_def_id: &str, tails_file: &str, max_creds: u32) - -> Result<(String, String, String, Option), u32> { + -> VcxResult<(String, String, String, Option)> { debug!("creating revocation registry definition with issuer_did: {}, cred_def_id: {}, tails_file_path: {}, max_creds: {}", issuer_did, cred_def_id, tails_file, max_creds); if settings::test_indy_mode_enabled() { return Ok((REV_REG_ID.to_string(), rev_def_json(), "".to_string(), None)); } - let (rev_reg_id, rev_reg_def_json, rev_reg_entry_json) = libindy_create_and_store_revoc_reg( - issuer_did, - cred_def_id, - tails_file, - max_creds - )?; + let (rev_reg_id, rev_reg_def_json, rev_reg_entry_json) = + libindy_create_and_store_revoc_reg(issuer_did, + cred_def_id, + tails_file, + max_creds)?; let rev_reg_def_req = libindy_build_revoc_reg_def_request(issuer_did, &rev_reg_def_json)?; @@ -424,7 +404,7 @@ pub fn create_rev_reg_def(issuer_did: &str, cred_def_id: &str, tails_file: &str, Ok((rev_reg_id, rev_reg_def_json, rev_reg_entry_json, payment)) } -pub fn get_rev_reg_def_json(rev_reg_id: &str) -> Result<(String, String), u32> { +pub fn get_rev_reg_def_json(rev_reg_id: &str) -> VcxResult<(String, String)> { if settings::test_indy_mode_enabled() { return Ok((REV_REG_ID.to_string(), rev_def_json())); } let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; @@ -435,13 +415,13 @@ pub fn get_rev_reg_def_json(rev_reg_id: &str) -> Result<(String, String), u32> { } pub fn post_rev_reg_delta(issuer_did: &str, rev_reg_id: &str, rev_reg_entry_json: &str) - -> Result<(Option, String), u32> { - libindy_build_revoc_reg_entry_request(issuer_did, rev_reg_id, REVOC_REG_TYPE, rev_reg_entry_json) - .and_then(|req| pay_for_txn(&req, REV_REG_DELTA_TXN_TYPE)) + -> VcxResult<(Option, String)> { + let request = libindy_build_revoc_reg_entry_request(issuer_did, rev_reg_id, REVOC_REG_TYPE, rev_reg_entry_json)?; + pay_for_txn(&request, REV_REG_DELTA_TXN_TYPE) } pub fn get_rev_reg_delta_json(rev_reg_id: &str, from: Option, to: Option) - -> Result<(String, String, u64), u32> { + -> VcxResult<(String, String, u64)> { if settings::test_indy_mode_enabled() { return Ok((REV_REG_ID.to_string(), REV_REG_DELTA_JSON.to_string(), 1)); } let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; @@ -453,7 +433,7 @@ pub fn get_rev_reg_delta_json(rev_reg_id: &str, from: Option, to: Option Result<(String, String, u64), u32> { +pub fn get_rev_reg(rev_reg_id: &str, timestamp: u64) -> VcxResult<(String, String, u64)> { if settings::test_indy_mode_enabled() { return Ok((REV_REG_ID.to_string(), REV_REG_JSON.to_string(), 1)); } let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; @@ -462,10 +442,11 @@ pub fn get_rev_reg(rev_reg_id: &str, timestamp: u64) -> Result<(String, String, .and_then(|response| libindy_parse_get_revoc_reg_response(&response)) } -pub fn revoke_credential(tails_file: &str, rev_reg_id: &str, cred_rev_id: &str) - -> Result<(Option, String), u32> { +pub fn revoke_credential(tails_file: &str, rev_reg_id: &str, cred_rev_id: &str) -> VcxResult<(Option, String)> { if settings::test_indy_mode_enabled() { - return Ok((Some(PaymentTxn::from_parts(r#"["pay:null:9UFgyjuJxi1i1HD"]"#,r#"[{"amount":4,"extra":null,"recipient":"pay:null:xkIsxem0YNtHrRO"}]"#,1, false).unwrap()), REV_REG_DELTA_JSON.to_string())); + let inputs = vec!["pay:null:9UFgyjuJxi1i1HD".to_string()]; + let outputs = serde_json::from_str::>(r#"[{"amount":4,"extra":null,"recipient":"pay:null:xkIsxem0YNtHrRO"}]"#).unwrap(); + return Ok((Some(PaymentTxn::from_parts(inputs, outputs, 1, false)), REV_REG_DELTA_JSON.to_string())); } let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; @@ -476,13 +457,23 @@ pub fn revoke_credential(tails_file: &str, rev_reg_id: &str, cred_rev_id: &str) Ok((payment, delta)) } +fn _check_schema_response(response: &str) -> VcxResult<()> { + // TODO: saved backwardcampatibilyty but actually we can better handle response + match parse_response(response)? { + Response::Reply(_) => Ok(()), + Response::Reject(reject) => Err(VcxError::from_msg(VcxErrorKind::DuplicationSchema, format!("{:?}", reject))), + Response::ReqNACK(reqnack) => Err(VcxError::from_msg(VcxErrorKind::UnknownSchemaRejection, "Unknown Rejection of Schema Creation, refer to libindy documentation")) + } +} #[cfg(test)] pub mod tests { use super::*; use utils::get_temp_dir_path; + extern crate serde_json; extern crate rand; + use rand::Rng; use settings; use utils::constants::*; @@ -491,7 +482,7 @@ pub mod tests { #[cfg(feature = "pool_tests")] use utils::error::LIBINDY_INVALID_STRUCTURE; #[cfg(feature = "pool_tests")] - use utils::constants::{TEST_TAILS_FILE}; + use utils::constants::TEST_TAILS_FILE; pub fn create_schema(attr_list: &str) -> (String, String) { @@ -564,7 +555,6 @@ pub mod tests { } pub fn create_and_store_credential(attr_list: &str, revocation: bool) -> (String, String, String, String, String, String, String, String, Option, Option) { - let (schema_id, schema_json, cred_def_id, cred_def_json, offer, req, req_meta, rev_reg_id) = create_credential_req(attr_list, revocation); /* create cred */ @@ -573,7 +563,6 @@ pub mod tests { let (rev_def_json, tails_file) = if revocation { let (id, json) = get_rev_reg_def_json(&rev_reg_id.clone().unwrap()).unwrap(); (Some(json), Some(get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap().to_string().to_string())) - } else { (None, None) }; let (cred, cred_rev_id, _) = ::utils::libindy::anoncreds::libindy_issuer_create_credential(&offer, &req, &encoded_attributes, rev_reg_id.clone(), tails_file).unwrap(); @@ -628,7 +617,7 @@ pub mod tests { cred_def_id: cred_def_json, }).to_string(); - libindy_prover_get_credentials_for_proof_req(&proof_req).unwrap(); + libindy_prover_get_credentials_for_proof_req(&proof_req).unwrap(); let proof = libindy_prover_create_proof( &proof_req, @@ -670,7 +659,7 @@ pub mod tests { let schemas = json!({}).to_string(); let cred_defs = json!({}).to_string(); - libindy_prover_get_credentials_for_proof_req(&proof_req).unwrap(); + libindy_prover_get_credentials_for_proof_req(&proof_req).unwrap(); let proof = libindy_prover_create_proof( &proof_req, @@ -726,14 +715,14 @@ pub mod tests { let result = libindy_prover_get_credentials_for_proof_req(&proof_req); let result_malformed_json = libindy_prover_get_credentials_for_proof_req("{}"); let wallet_handle = get_wallet_handle(); - let proof_req_str:String = serde_json::to_string(&proof_req).unwrap(); + let proof_req_str: String = serde_json::to_string(&proof_req).unwrap(); assert!(result.is_ok()); assert_eq!(result_malformed_json.err(), Some(INVALID_ATTRIBUTES_STRUCTURE.code_num)); } #[cfg(feature = "pool_tests")] #[test] - fn test_issuer_revoke_credential(){ + fn test_issuer_revoke_credential() { init!("ledger"); let rc = libindy_issuer_revoke_credential(get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap(), "", ""); assert!(rc.is_err()); @@ -748,7 +737,7 @@ pub mod tests { #[test] fn test_create_cred_def() { init!("true"); - let (id, _) = create_cred_def("did", SCHEMAS_JSON, "tag_1", None, Some(false)).unwrap(); + let (id, _) = create_cred_def("did", SCHEMAS_JSON, "tag_1", None, Some(false)).unwrap(); assert_eq!(id, CRED_DEF_ID); } @@ -842,7 +831,7 @@ pub mod tests { #[cfg(feature = "pool_tests")] #[test] - fn from_pool_ledger_with_id(){ + fn from_pool_ledger_with_id() { use settings; init!("ledger"); let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); @@ -852,11 +841,10 @@ pub mod tests { let (id, retrieved_schema) = rc.unwrap(); assert!(retrieved_schema.contains(&schema_id)); - } #[test] - fn from_ledger_schema_id(){ + fn from_ledger_schema_id() { init!("true"); let (id, retrieved_schema) = get_schema_json(SCHEMA_ID).unwrap(); assert_eq!(&retrieved_schema, SCHEMA_JSON); @@ -865,7 +853,7 @@ pub mod tests { #[cfg(feature = "pool_tests")] #[test] - fn test_revoke_credential(){ + fn test_revoke_credential() { init!("ledger"); let (_, _, cred_def_id, _, _, _, _, cred_id, rev_reg_id, cred_rev_id) = ::utils::libindy::anoncreds::tests::create_and_store_credential(::utils::constants::DEFAULT_SCHEMA_ATTRS, true); @@ -874,13 +862,13 @@ pub mod tests { let (_, first_rev_reg_delta, first_timestamp) = get_rev_reg_delta_json(&rev_reg_id, None, None).unwrap(); let (_, test_same_delta, test_same_timestamp) = get_rev_reg_delta_json(&rev_reg_id, None, None).unwrap(); - assert_eq!(first_rev_reg_delta, test_same_delta); + assert_eq!(first_rev_reg_delta, test_same_delta); assert_eq!(first_timestamp, test_same_timestamp); let (payment, revoked_rev_reg_delta) = revoke_credential(get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap(), &rev_reg_id, cred_rev_id.unwrap().as_str()).unwrap(); // Delta should change after revocation - let (_, second_rev_reg_delta, _) = get_rev_reg_delta_json(&rev_reg_id, Some(first_timestamp+1), None).unwrap(); + let (_, second_rev_reg_delta, _) = get_rev_reg_delta_json(&rev_reg_id, Some(first_timestamp + 1), None).unwrap(); assert!(payment.is_some()); assert_ne!(first_rev_reg_delta, second_rev_reg_delta); diff --git a/vcx/libvcx/src/utils/libindy/crypto.rs b/vcx/libvcx/src/utils/libindy/crypto.rs index 9a8a0eab65..6fe24424eb 100644 --- a/vcx/libvcx/src/utils/libindy/crypto.rs +++ b/vcx/libvcx/src/utils/libindy/crypto.rs @@ -7,11 +7,12 @@ use utils::libindy::mock_libindy_rc; use utils::libindy::error_codes::map_rust_indy_sdk_error; use settings; use indy::crypto; +use error::prelude::*; -pub fn prep_msg(sender_vk: &str, recipient_vk: &str, msg: &[u8]) -> Result, u32> { +pub fn prep_msg(sender_vk: &str, recipient_vk: &str, msg: &[u8]) -> VcxResult> { if settings::test_indy_mode_enabled() { let rc = mock_libindy_rc(); - if rc != 0 { return Err(rc); }; + if rc != 0 { return Err(VcxError::from(VcxErrorKind::Common(rc))); }; return Ok(Vec::from(msg).to_owned()); } @@ -20,7 +21,7 @@ pub fn prep_msg(sender_vk: &str, recipient_vk: &str, msg: &[u8]) -> Result Result, u32> { +pub fn prep_anonymous_msg(recipient_vk: &str, msg: &[u8]) -> VcxResult> { if settings::test_indy_mode_enabled() { return Ok(Vec::from(msg).to_owned()); } crypto::anon_crypt(recipient_vk, msg) @@ -28,7 +29,7 @@ pub fn prep_anonymous_msg(recipient_vk: &str, msg: &[u8]) -> Result, u32 .map_err(map_rust_indy_sdk_error) } -pub fn parse_msg(recipient_vk: &str, msg: &[u8]) -> Result<(String, Vec), u32> { +pub fn parse_msg(recipient_vk: &str, msg: &[u8]) -> VcxResult<(String, Vec)> { if settings::test_indy_mode_enabled() { return Ok((::utils::constants::VERKEY.to_string(), Vec::from(msg).to_owned())); } crypto::auth_decrypt(::utils::libindy::wallet::get_wallet_handle(), recipient_vk, msg) @@ -36,7 +37,7 @@ pub fn parse_msg(recipient_vk: &str, msg: &[u8]) -> Result<(String, Vec), u3 .map_err(map_rust_indy_sdk_error) } -pub fn parse_anonymous_msg(recipient_vk: &str, msg: &[u8]) -> Result, u32> { +pub fn parse_anonymous_msg(recipient_vk: &str, msg: &[u8]) -> VcxResult> { if settings::test_indy_mode_enabled() { return Ok(Vec::from(msg).to_owned()); } crypto::anon_decrypt(::utils::libindy::wallet::get_wallet_handle(), recipient_vk, msg) @@ -44,7 +45,7 @@ pub fn parse_anonymous_msg(recipient_vk: &str, msg: &[u8]) -> Result, u3 .map_err(map_rust_indy_sdk_error) } -pub fn sign(my_vk: &str, msg: &[u8]) -> Result, u32> { +pub fn sign(my_vk: &str, msg: &[u8]) -> VcxResult> { if settings::test_indy_mode_enabled() { return Ok(Vec::from(msg).to_owned()); } crypto::sign(::utils::libindy::wallet::get_wallet_handle(), my_vk, msg) @@ -52,21 +53,21 @@ pub fn sign(my_vk: &str, msg: &[u8]) -> Result, u32> { .map_err(map_rust_indy_sdk_error) } -pub fn verify(vk: &str, msg: &[u8], signature: &[u8]) -> Result { - if settings::test_indy_mode_enabled() { return Ok(true) } +pub fn verify(vk: &str, msg: &[u8], signature: &[u8]) -> VcxResult { + if settings::test_indy_mode_enabled() { return Ok(true); } crypto::verify(vk, msg, signature) - .wait() - .map_err(map_rust_indy_sdk_error) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn pack_message(sender_vk: Option<&str>, receiver_keys: &str, msg: &[u8]) -> Result, u32> { +pub fn pack_message(sender_vk: Option<&str>, receiver_keys: &str, msg: &[u8]) -> VcxResult> { crypto::pack_message(::utils::libindy::wallet::get_wallet_handle(), msg, receiver_keys, sender_vk) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn unpack_message(msg: &[u8]) -> Result, u32> { +pub fn unpack_message(msg: &[u8]) -> VcxResult> { crypto::unpack_message(::utils::libindy::wallet::get_wallet_handle(), msg) .wait() .map_err(map_rust_indy_sdk_error) diff --git a/vcx/libvcx/src/utils/libindy/error_codes.rs b/vcx/libvcx/src/utils/libindy/error_codes.rs index c37568b247..31f68437db 100644 --- a/vcx/libvcx/src/utils/libindy/error_codes.rs +++ b/vcx/libvcx/src/utils/libindy/error_codes.rs @@ -2,8 +2,8 @@ extern crate num_traits; use indy::IndyError; use utils::error; -use std::ffi::NulError; use self::num_traits::int::PrimInt; +use error::prelude::{VcxError, VcxErrorKind}; pub fn map_indy_error(rtn: T, error_code: C) -> Result { if error_code == C::zero() { @@ -13,33 +13,20 @@ pub fn map_indy_error(rtn: T, error_code: C) -> Result { Err(map_indy_error_code(error_code)) } -// Todo - this will replace map_indy_error_code once we stop using our own indy cbs and move everything to rust-indy-sdk -// Todo - rename once it replaces map_indy_error -pub fn map_rust_indy_sdk_error(error_code: IndyError) -> u32 { - let error_code = error_code.error_code as u32; - if error_code >= error::UNKNOWN_ERROR.code_num { - return error_code; - } - - warn!("indy-sdk error code: {}", error_code); - - match error_code { - 100 ... 111 => error::INVALID_LIBINDY_PARAM.code_num, - 113 => error::LIBINDY_INVALID_STRUCTURE.code_num, - 114 => error::IOERROR.code_num, - 200 => error::INVALID_WALLET_HANDLE.code_num, - 203 => error::WALLET_ALREADY_EXISTS.code_num, - 204 => error::WALLET_NOT_FOUND.code_num, - 206 => error::WALLET_ALREADY_OPEN.code_num, - 212 => error::WALLET_RECORD_NOT_FOUND.code_num, - 213 => error::DUPLICATE_WALLET_RECORD.code_num, - 306 => error::CREATE_POOL_CONFIG.code_num, - 404 => error::DUPLICATE_MASTER_SECRET.code_num, - 407 => error::CREDENTIAL_DEF_ALREADY_CREATED.code_num, - 600 => error::DID_ALREADY_EXISTS_IN_WALLET.code_num, - 702 => error::INSUFFICIENT_TOKEN_AMOUNT.code_num, - - _ => error::UNKNOWN_LIBINDY_ERROR.code_num +pub fn map_rust_indy_sdk_error(error: IndyError) -> VcxError { + match error.error_code as u32 { + 200 => VcxError::from_msg(VcxErrorKind::InvalidWalletHandle, error.message), + 203 => VcxError::from_msg(VcxErrorKind::DuplicationWallet, error.message), + 204 => VcxError::from_msg(VcxErrorKind::WalletNotFound, error.message), + 206 => VcxError::from_msg(VcxErrorKind::WalletAlreadyOpen, error.message), + 212 => VcxError::from_msg(VcxErrorKind::WalletRecordNotFound, error.message), + 213 => VcxError::from_msg(VcxErrorKind::DuplicationWalletRecord, error.message), + 306 => VcxError::from_msg(VcxErrorKind::CreatePoolConfig, error.message), + 404 => VcxError::from_msg(VcxErrorKind::DuplicationMasterSecret, error.message), + 407 => VcxError::from_msg(VcxErrorKind::CredDefAlreadyCreated, error.message), + 600 => VcxError::from_msg(VcxErrorKind::DuplicationDid, error.message), + 702 => VcxError::from_msg(VcxErrorKind::InsufficientTokenAmount, error.message), + _ => VcxError::from_msg(VcxErrorKind::LiibndyError(error.error_code as u32), error.message) } } @@ -73,11 +60,6 @@ pub fn map_indy_error_code(error_code: C) -> u32 { } } -pub fn map_string_error(err: NulError) -> u32 { - error!("Invalid String: {:?}", err); - error::UNKNOWN_LIBINDY_ERROR.code_num -} - #[cfg(test)] pub mod tests { use super::*; diff --git a/vcx/libvcx/src/utils/libindy/ledger.rs b/vcx/libvcx/src/utils/libindy/ledger.rs index 3c8f7724f7..3a2e6bca41 100644 --- a/vcx/libvcx/src/utils/libindy/ledger.rs +++ b/vcx/libvcx/src/utils/libindy/ledger.rs @@ -9,25 +9,26 @@ use utils::libindy::{ pool::get_pool_handle, wallet::get_wallet_handle, }; -use utils::error; use indy::ledger; use utils::libindy::error_codes::map_rust_indy_sdk_error; +use error::prelude::*; -pub fn multisign_request(did: &str, request: &str) -> Result { - ledger::multi_sign_request(get_wallet_handle(), did, request) - .wait() - .map_err(map_rust_indy_sdk_error) +pub fn multisign_request(did: &str, request: &str) -> VcxResult { + ledger::multi_sign_request(get_wallet_handle(), did, request) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn libindy_sign_request(did: &str, request: &str) -> Result { +pub fn libindy_sign_request(did: &str, request: &str) -> VcxResult { ledger::sign_request(get_wallet_handle(), did, request) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_sign_and_submit_request(issuer_did: &str, request_json: &str) -> Result { +pub fn libindy_sign_and_submit_request(issuer_did: &str, request_json: &str) -> VcxResult { if settings::test_indy_mode_enabled() { return Ok(r#"{"rc":"success"}"#.to_string()); } - let pool_handle = get_pool_handle().or(Err(error::NO_POOL_OPEN.code_num))?; + + let pool_handle = get_pool_handle()?; let wallet_handle = get_wallet_handle(); ledger::sign_and_submit_request(pool_handle, wallet_handle, issuer_did, request_json) @@ -35,45 +36,46 @@ pub fn libindy_sign_and_submit_request(issuer_did: &str, request_json: &str) -> .map_err(map_rust_indy_sdk_error) } -pub fn libindy_submit_request(request_json: &str) -> Result { - let pool_handle = get_pool_handle().or(Err(error::NO_POOL_OPEN.code_num))?; +pub fn libindy_submit_request(request_json: &str) -> VcxResult { + let pool_handle = get_pool_handle()?; + //TODO there was timeout here (before future-based Rust wrapper) ledger::submit_request(pool_handle, request_json) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_build_get_txn_request(submitter_did: &str, sequence_num: i32) -> Result { +pub fn libindy_build_get_txn_request(submitter_did: &str, sequence_num: i32) -> VcxResult { ledger::build_get_txn_request(Some(submitter_did), None, sequence_num) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_build_schema_request(submitter_did: &str, data: &str) -> Result { +pub fn libindy_build_schema_request(submitter_did: &str, data: &str) -> VcxResult { ledger::build_schema_request(submitter_did, data) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_build_get_schema_request(submitter_did: &str, schema_id: &str) -> Result { +pub fn libindy_build_get_schema_request(submitter_did: &str, schema_id: &str) -> VcxResult { ledger::build_get_schema_request(Some(submitter_did), schema_id) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_parse_get_schema_response(get_schema_response: &str) -> Result<(String, String), u32> { +pub fn libindy_parse_get_schema_response(get_schema_response: &str) -> VcxResult<(String, String)> { ledger::parse_get_schema_response(get_schema_response) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_parse_get_cred_def_response(get_cred_def_response: &str) -> Result<(String, String), u32> { +pub fn libindy_parse_get_cred_def_response(get_cred_def_response: &str) -> VcxResult<(String, String)> { ledger::parse_get_cred_def_response(get_cred_def_response) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn libindy_build_get_credential_def_txn(cred_def_id: &str) -> Result{ +pub fn libindy_build_get_credential_def_txn(cred_def_id: &str) -> VcxResult { let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; ledger::build_get_cred_def_request(Some(&submitter_did), cred_def_id) .wait() @@ -81,8 +83,52 @@ pub fn libindy_build_get_credential_def_txn(cred_def_id: &str) -> Result Result{ + credential_def_json: &str) -> VcxResult { ledger::build_cred_def_request(submitter_did, credential_def_json) .wait() .map_err(map_rust_indy_sdk_error) } + +pub fn parse_response(response: &str) -> VcxResult { + serde_json::from_str::(response) + .to_vcx(VcxErrorKind::InvalidJson, "Cannot deserialize transaction response") +} + +#[serde(tag = "op")] +#[derive(Deserialize, Debug)] +pub enum Response { + #[serde(rename = "REQNACK")] + ReqNACK(Reject), + #[serde(rename = "REJECT")] + Reject(Reject), + #[serde(rename = "REPLY")] + Reply(Reply), +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Reject { + pub reason: String +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +pub enum Reply { + ReplyV0(ReplyV0), + ReplyV1(ReplyV1) +} + +#[derive(Debug, Deserialize)] +pub struct ReplyV0 { + pub result: serde_json::Value +} + +#[derive(Debug, Deserialize)] +pub struct ReplyV1 { + pub data: ReplyDataV1 +} + +#[derive(Debug, Deserialize)] +pub struct ReplyDataV1 { + pub result: serde_json::Value +} diff --git a/vcx/libvcx/src/utils/libindy/logger.rs b/vcx/libvcx/src/utils/libindy/logger.rs index 9c33ec2edb..b6db1f6865 100644 --- a/vcx/libvcx/src/utils/libindy/logger.rs +++ b/vcx/libvcx/src/utils/libindy/logger.rs @@ -2,13 +2,14 @@ extern crate log; use indy::logger; use utils::libindy::error_codes::map_rust_indy_sdk_error; +use error::prelude::*; -pub fn set_logger(logger: &'static log::Log) -> Result<(), u32> { +pub fn set_logger(logger: &'static log::Log) -> VcxResult<()> { logger::set_logger(logger) .map_err(map_rust_indy_sdk_error) } -pub fn set_default_logger(patter: Option<&str>) -> Result<(), u32> { +pub fn set_default_logger(patter: Option<&str>) -> VcxResult<()> { logger::set_default_logger(patter) .map_err(map_rust_indy_sdk_error) } \ No newline at end of file diff --git a/vcx/libvcx/src/utils/libindy/mod.rs b/vcx/libvcx/src/utils/libindy/mod.rs index c4c869bf5a..b09620cbef 100644 --- a/vcx/libvcx/src/utils/libindy/mod.rs +++ b/vcx/libvcx/src/utils/libindy/mod.rs @@ -17,6 +17,7 @@ extern crate libc; use settings; use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use std::sync::Mutex; +use error::prelude::*; lazy_static!{ static ref NEXT_LIBINDY_RC: Mutex> = Mutex::new(vec![]); @@ -36,7 +37,7 @@ pub fn next_u32_command_handle() -> u32 { (COMMAND_HANDLE_COUNTER.fetch_add(1, Ordering::SeqCst) + 1) as u32 } -pub fn init_pool() -> Result<(), u32> { +pub fn init_pool() -> VcxResult<()> { trace!("init_pool >>>"); if settings::test_indy_mode_enabled() {return Ok (()); } diff --git a/vcx/libvcx/src/utils/libindy/payments.rs b/vcx/libvcx/src/utils/libindy/payments.rs index 1ff5264fcc..c72ffed444 100644 --- a/vcx/libvcx/src/utils/libindy/payments.rs +++ b/vcx/libvcx/src/utils/libindy/payments.rs @@ -1,22 +1,17 @@ -extern crate libc; -extern crate serde_json; - use futures::Future; use utils::libindy::wallet::get_wallet_handle; use utils::constants::{SUBMIT_SCHEMA_RESPONSE, TRANSFER_TXN_TYPE}; -use utils::libindy::error_codes::map_rust_indy_sdk_error; +use utils::libindy::error_codes::{map_rust_indy_sdk_error}; #[allow(unused_imports)] use utils::libindy::ledger::{libindy_submit_request, libindy_sign_and_submit_request, libindy_sign_request}; -use utils::error; -use error::payment::PaymentError; -use error::ToErrorCode; use indy::payments; use std::fmt; use std::collections::HashMap; use serde_json::Value; use settings; +use error::prelude::*; static DEFAULT_FEES: &str = r#"{"0":0, "1":0, "101":2, "10001":0, "102":42, "103":0, "104":0, "105":0, "107":0, "108":0, "109":0, "110":0, "111":0, "112":0, "113":2, "114":2, "115":0, "116":0, "117":0, "118":0, "119":0}"#; @@ -59,7 +54,7 @@ pub struct Output { impl fmt::Display for WalletInfo { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match serde_json::to_string(&self) { + match ::serde_json::to_string(&self) { Ok(s) => write!(f, "{}", s), Err(e) => write!(f, "null"), } @@ -75,17 +70,13 @@ pub struct PaymentTxn { } impl PaymentTxn { - pub fn from_parts(inputs: &str, outputs: &str, amount: u64, credit: bool) -> Result { - let inputs: Vec = serde_json::from_str(&inputs) - .map_err(|err| { error::INVALID_JSON.code_num })?; - let outputs: Vec = serde_json::from_str(&outputs) - .map_err(|err| { error::INVALID_JSON.code_num })?; - Ok(PaymentTxn { + pub fn from_parts(inputs: Vec, outputs: Vec, amount: u64, credit: bool) -> PaymentTxn { + PaymentTxn { amount, credit, inputs, outputs, - }) + } } } @@ -93,7 +84,7 @@ pub fn build_test_address(address: &str) -> String { format!("pay:{}:{}", ::settings::get_payment_method(), address) } -pub fn create_address(seed: Option) -> Result { +pub fn create_address(seed: Option) -> VcxResult { trace!("create_address >>> seed: {:?}", seed); if settings::test_indy_mode_enabled() { @@ -101,8 +92,8 @@ pub fn create_address(seed: Option) -> Result { } let config = match seed { - Some(x) => format!("{{\"seed\":\"{}\"}}", x), - None => format!("{{}}"), + Some(x) => json!({"seed": x}).to_string(), + None => "{}".to_string(), }; payments::create_payment_address(get_wallet_handle() as i32, settings::get_payment_method().as_str(), &config) @@ -110,7 +101,7 @@ pub fn create_address(seed: Option) -> Result { .map_err(map_rust_indy_sdk_error) } -pub fn get_address_info(address: &str) -> Result { +pub fn get_address_info(address: &str) -> VcxResult { if settings::test_indy_mode_enabled() { let utxos = json!( [ @@ -129,7 +120,7 @@ pub fn get_address_info(address: &str) -> Result { ] ); - let utxo: Vec = serde_json::from_value(utxos).unwrap(); + let utxo: Vec = ::serde_json::from_value(utxos).unwrap(); return Ok(AddressInfo { address: address.to_string(), balance: _address_balance(&utxo), utxo }); } @@ -146,43 +137,44 @@ pub fn get_address_info(address: &str) -> Result { .wait() .map_err(map_rust_indy_sdk_error)?; - trace!("indy_parse_get_utxo_response() --> {}", response); - let utxo: Vec = serde_json::from_str(&response).or(Err(error::INVALID_JSON.code_num))?; + let utxo: Vec = ::serde_json::from_str(&response) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize payment sources response: {}", err)))?; + + let info = AddressInfo { address: address.to_string(), balance: _address_balance(&utxo), utxo }; - Ok(AddressInfo { address: address.to_string(), balance: _address_balance(&utxo), utxo }) + Ok(info) } -pub fn list_addresses() -> Result, u32> { +pub fn list_addresses() -> VcxResult> { if settings::test_indy_mode_enabled() { let addresses = json!([ build_test_address("9UFgyjuJxi1i1HD"), build_test_address("zR3GN9lfbCVtHjp") ]); - return Ok(serde_json::from_value(addresses).unwrap()); + return Ok(::serde_json::from_value(addresses).unwrap()); } let addresses = payments::list_payment_addresses(get_wallet_handle() as i32) .wait() .map_err(map_rust_indy_sdk_error)?; - trace!("--> {}", addresses); - Ok(serde_json::from_str(&addresses).or(Err(error::INVALID_JSON.code_num))?) + ::serde_json::from_str(&addresses) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize a list of payment addresses: {}", err))) } fn is_valid_address(address: &str, method: &str) -> bool { let prefix = format!("pay:{}", method); - address.starts_with(&prefix) } -pub fn get_wallet_token_info() -> Result { +pub fn get_wallet_token_info() -> VcxResult { trace!("get_wallet_token_info >>>"); let addresses = list_addresses()?; - let method = settings::get_config_value(settings::CONFIG_PAYMENT_METHOD)?; - let mut balance = 0; + let mut wallet_info = Vec::new(); + let mut balance = 0; for address in addresses.iter() { if is_valid_address(&address, &method) { @@ -204,123 +196,121 @@ pub fn get_wallet_token_info() -> Result { Ok(info) } -pub fn get_ledger_fees() -> Result { +pub fn get_ledger_fees() -> VcxResult { trace!("get_ledger_fees >>>"); if settings::test_indy_mode_enabled() { return Ok(DEFAULT_FEES.to_string()); } - let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).or(Err(error::INVALID_CONFIGURATION.code_num))?; + let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; - let response = match payments::build_get_txn_fees_req(get_wallet_handle() as i32, Some(&did), settings::get_payment_method().as_str()).wait() { - Ok(txn) => libindy_sign_and_submit_request(&did, &txn)?, - Err(x) => return Err(map_rust_indy_sdk_error(x)), - }; + let txn = payments::build_get_txn_fees_req(get_wallet_handle(), Some(&did), settings::get_payment_method().as_str()) + .wait() + .map_err(map_rust_indy_sdk_error)?; - let res = payments::parse_get_txn_fees_response(settings::get_payment_method().as_str(), &response) + let response = libindy_sign_and_submit_request(&did, &txn)?; + + payments::parse_get_txn_fees_response(settings::get_payment_method().as_str(), &response) .wait() - .map_err(map_rust_indy_sdk_error); - res + .map_err(map_rust_indy_sdk_error) } -pub fn pay_for_txn(req: &str, txn_type: &str) -> Result<(Option, String), u32> { +pub fn pay_for_txn(req: &str, txn_type: &str) -> VcxResult<(Option, String)> { debug!("pay_for_txn(req: {}, txn_type: {})", req, txn_type); if settings::test_indy_mode_enabled() { - let inputs = format!(r#"["{}"]"#, build_test_address("9UFgyjuJxi1i1HD")); - - let outputs = format!(r#"[ - {{ - "amount": 1, - "extra": null, - "recipient": "{}" - }} - ]"#, build_test_address("xkIsxem0YNtHrRO")); - - return Ok((Some(PaymentTxn::from_parts(&inputs, &outputs, 1, false).unwrap()), SUBMIT_SCHEMA_RESPONSE.to_string())); + let inputs = vec!["pay:null:9UFgyjuJxi1i1HD".to_string()]; + let outputs = serde_json::from_str::>(r#"[{"amount":1,"extra":null,"recipient":"pay:null:xkIsxem0YNtHrRO"}]"#).unwrap(); + return Ok((Some(PaymentTxn::from_parts(inputs, outputs, 1, false)), SUBMIT_SCHEMA_RESPONSE.to_string())); } let txn_price = get_txn_price(txn_type)?; if txn_price == 0 { - let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).or(Err(error::INVALID_CONFIGURATION.code_num))?; + let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; let txn_response = libindy_sign_and_submit_request(&did, req)?; Ok((None, txn_response)) } else { - let (refund, inputs, refund_address) = inputs(txn_price).map_err(|e| e.to_error_code())?; - - let output = outputs(refund, &refund_address, None, None).map_err(|e| e.to_error_code())?; + let (refund, inputs, refund_address) = inputs(txn_price)?; + let output = outputs(refund, &refund_address, None, None)?; let (fee_response, txn_response) = _submit_fees_request(req, &inputs, &output)?; - let payment = PaymentTxn::from_parts(&inputs, &output, txn_price, false)?; + let payment = PaymentTxn::from_parts(inputs, output, txn_price, false); Ok((Some(payment), txn_response)) } } -fn _submit_fees_request(req: &str, inputs: &str, outputs: &str) -> Result<(String, String), u32> { - let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).or(Err(error::INVALID_CONFIGURATION.code_num))?; +fn _serialize_inputs_and_outputs(inputs: &Vec, outputs: &Vec) -> VcxResult<(String, String)> { + let inputs = ::serde_json::to_string(inputs) + .to_vcx(VcxErrorKind::InvalidJson, "Cannot serialize inputs")?; + let outputs = ::serde_json::to_string(outputs) + .to_vcx(VcxErrorKind::InvalidJson, "Cannot serialize outputs")?; + Ok((inputs, outputs)) +} + +fn _submit_fees_request(req: &str, inputs: &Vec, outputs: &Vec) -> VcxResult<(String, String)> { + let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; + + let (inputs, outputs) = _serialize_inputs_and_outputs(inputs, outputs)?; let req = libindy_sign_request(&did, req)?; - let (response, payment_method) = match payments::add_request_fees(get_wallet_handle(), - Some(&did), - &req, - &inputs, - &outputs, - None).wait() { - Ok((req, payment_method)) => { - (libindy_submit_request(&req)?, payment_method) - } - Err(x) => return Err(map_rust_indy_sdk_error(x)), - }; + let (req, payment_method) = + payments::add_request_fees(get_wallet_handle(), + Some(&did), + &req, + &inputs, + &outputs, + None) + .wait() + .map_err(map_rust_indy_sdk_error)?; - let parsed_response = match payments::parse_response_with_fees(&payment_method, &response).wait() { - Ok(x) => x, - Err(x) => return Err(error::INVALID_LEDGER_RESPONSE.code_num), - }; + let response = libindy_submit_request(&req)?; + + let parsed_response = payments::parse_response_with_fees(&payment_method, &response) + .wait() + .or(Err(VcxError::from(VcxErrorKind::InvalidLedgerResponse)))?; Ok((parsed_response, response)) } -pub fn pay_a_payee(price: u64, address: &str) -> Result<(PaymentTxn, String), PaymentError> { +pub fn pay_a_payee(price: u64, address: &str) -> VcxResult<(PaymentTxn, String)> { trace!("pay_a_payee >>> price: {}, address {}", price, address); debug!("sending {} tokens to address {}", price, address); - let ledger_cost = get_txn_price(TRANSFER_TXN_TYPE).map_err(|e| PaymentError::CommonError(e))?; + let ledger_cost = get_txn_price(TRANSFER_TXN_TYPE)?; let (remainder, input, refund_address) = inputs(price + ledger_cost)?; - let output = outputs(remainder, &refund_address, Some(address.to_string()), Some(price))?; + let outputs = outputs(remainder, &refund_address, Some(address.to_string()), Some(price))?; - let payment = PaymentTxn::from_parts(&input, &output, price, false).map_err(|e| PaymentError::CommonError(e))?; - let my_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).or(Err(PaymentError::CommonError(error::INVALID_CONFIGURATION.code_num)))?; + let my_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; if settings::test_indy_mode_enabled() { - let inputs = format!(r#"["{}"]"#, build_test_address("9UFgyjuJxi1i1HD")); - - let outputs = format!(r#"[ - {{ - "amount": 1, - "extra": null, - "recipient": "{}" - }} - ]"#, build_test_address("xkIsxem0YNtHrRO")); + let inputs = vec![build_test_address("9UFgyjuJxi1i1HD")]; - return Ok((PaymentTxn::from_parts(&inputs, &outputs, 1, false).unwrap(), SUBMIT_SCHEMA_RESPONSE.to_string())); + let outputs = vec![Output { + source: None, + recipient: build_test_address("xkIsxem0YNtHrRO"), + amount: 1, + extra: None, + }]; + return Ok((PaymentTxn::from_parts(inputs, outputs, 1, false), SUBMIT_SCHEMA_RESPONSE.to_string())); } - match payments::build_payment_req(get_wallet_handle(), Some(&my_did), &input, &output, None).wait() { - Ok((request, payment_method)) => { - let result = libindy_submit_request(&request).map_err(|ec| PaymentError::CommonError(ec))?; - Ok((payment, result)) - } - Err(ec) => { - error!("error: {:?}", ec.message); - Err(PaymentError::CommonError(ec.error_code as u32)) - } - } + let (inputs_json, outputs_json) = _serialize_inputs_and_outputs(&input, &outputs)?; + + let (request, payment_method) = + payments::build_payment_req(get_wallet_handle(), Some(&my_did), &inputs_json, &outputs_json, None) + .wait() + .map_err(map_rust_indy_sdk_error)?; + + let result = libindy_submit_request(&request)?; + let payment = PaymentTxn::from_parts(input, outputs, price, false); + Ok((payment, result)) } -fn get_txn_price(txn_type: &str) -> Result { +fn get_txn_price(txn_type: &str) -> VcxResult { let ledger_fees = get_ledger_fees()?; - let fees: HashMap = serde_json::from_str(&ledger_fees).or(Err(error::INVALID_JSON.code_num))?; + let fees: HashMap = serde_json::from_str(&ledger_fees) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize fees: {}", err)))?; match fees.get(txn_type) { Some(x) => Ok(*x), @@ -332,15 +322,16 @@ fn _address_balance(address: &Vec) -> u64 { address.iter().fold(0, |balance, utxo| balance + utxo.amount) } -pub fn inputs(cost: u64) -> Result<(u64, String, String), PaymentError> { +pub fn inputs(cost: u64) -> VcxResult<(u64, Vec, String)> { let mut inputs: Vec = Vec::new(); let mut balance = 0; - let wallet_info: WalletInfo = get_wallet_token_info().map_err(|ec| PaymentError::CommonError(ec))?; let mut refund_address = String::new(); + let wallet_info: WalletInfo = get_wallet_token_info()?; + if wallet_info.balance < cost { warn!("not enough tokens in wallet to pay: balance: {}, cost: {}", wallet_info.balance, cost); - return Err(PaymentError::InsufficientFunds()); + return Err(VcxError::from_msg(VcxErrorKind::InsufficientTokenAmount, format!("Not enough tokens in wallet to pay: balance: {}, cost: {}", wallet_info.balance, cost))); } // Todo: explore 'smarter' ways of selecting utxos ie bitcoin algorithms etc @@ -348,39 +339,35 @@ pub fn inputs(cost: u64) -> Result<(u64, String, String), PaymentError> { refund_address = address.address.clone(); 'inner: for utxo in address.utxo.iter() { if balance < cost { - inputs.push(utxo.source.clone().ok_or(PaymentError::InsufficientFunds())?.to_string()); + inputs.push(utxo.source.clone().ok_or(VcxErrorKind::InsufficientTokenAmount)?.to_string()); balance += utxo.amount; } else { break 'outer } } } let remainder = balance - cost; - let inputs = serde_json::to_string(&inputs).or(Err(PaymentError::InvalidWalletJson()))?; Ok((remainder, inputs, refund_address)) } -pub fn outputs(remainder: u64, refund_address: &str, payee_address: Option, payee_amount: Option) -> Result { +pub fn outputs(remainder: u64, refund_address: &str, payee_address: Option, payee_amount: Option) -> VcxResult> { // In the future we might provide a way for users to specify multiple output address for their remainder tokens // As of now, we only handle one output address which we create let mut outputs = Vec::new(); if remainder > 0 { - outputs.push(json!({ "recipient": refund_address, "amount": remainder })); + outputs.push(Output { source: None, recipient: refund_address.to_string(), amount: remainder, extra: None }); } if let Some(address) = payee_address { - outputs.push(json!({ - "recipient": address, - "amount": payee_amount, - })); + outputs.push(Output { source: None, recipient: address, amount: payee_amount.unwrap_or(0), extra: None }); } - Ok(serde_json::to_string(&outputs).or(Err(PaymentError::InvalidWalletJson()))?) + Ok(outputs) } // This is used for testing purposes only!!! -pub fn mint_tokens_and_set_fees(number_of_addresses: Option, tokens_per_address: Option, fees: Option, seed: Option) -> Result<(), u32> { +pub fn mint_tokens_and_set_fees(number_of_addresses: Option, tokens_per_address: Option, fees: Option, seed: Option) -> VcxResult<()> { trace!("mint_tokens_and_set_fees >>> number_of_addresses: {:?}, tokens_per_address: {:?}, fees: {:?}, seed: {:?}", number_of_addresses, tokens_per_address, fees, seed); @@ -392,9 +379,9 @@ pub fn mint_tokens_and_set_fees(number_of_addresses: Option, tokens_per_add None }; - let (did_2, _) = add_new_trustee_did()?; - let (did_3, _) = add_new_trustee_did()?; - let (did_4, _) = add_new_trustee_did()?; + let (did_2, _) = add_new_trustee_did(); + let (did_3, _) = add_new_trustee_did(); + let (did_4, _) = add_new_trustee_did(); let number_of_addresses = number_of_addresses.unwrap_or(1); @@ -439,17 +426,15 @@ pub fn mint_tokens_and_set_fees(number_of_addresses: Option, tokens_per_add Ok(()) } -fn add_new_trustee_did() -> Result<(String, String), u32> { +fn add_new_trustee_did() -> (String, String) { use indy::ledger; let institution_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); let (did, verkey) = ::utils::libindy::signus::create_and_store_my_did(None).unwrap(); - let req_nym = ledger::build_nym_request(&institution_did, &did, Some(&verkey), None, Some("TRUSTEE")) - .wait() - .map_err(map_rust_indy_sdk_error)?; - ::utils::libindy::ledger::libindy_sign_and_submit_request(&institution_did, &req_nym)?; - Ok((did, verkey)) + let req_nym = ledger::build_nym_request(&institution_did, &did, Some(&verkey), None, Some("TRUSTEE")).wait().unwrap(); + ::utils::libindy::ledger::libindy_sign_and_submit_request(&institution_did, &req_nym).unwrap(); + (did, verkey) } #[cfg(test)] diff --git a/vcx/libvcx/src/utils/libindy/pool.rs b/vcx/libvcx/src/utils/libindy/pool.rs index 7c52f8ebc8..fe5df39d28 100644 --- a/vcx/libvcx/src/utils/libindy/pool.rs +++ b/vcx/libvcx/src/utils/libindy/pool.rs @@ -1,13 +1,10 @@ -extern crate libc; - use futures::Future; -use utils::error; use std::sync::RwLock; use settings; use indy::pool; -use indy::ErrorCode; use utils::libindy::error_codes::map_rust_indy_sdk_error; +use error::prelude::*; lazy_static! { static ref POOL_HANDLE: RwLock> = RwLock::new(None); @@ -18,48 +15,43 @@ pub fn change_pool_handle(handle: Option){ *h = handle; } -pub fn set_protocol_version() -> u32 { - match pool::set_protocol_version(settings::get_protocol_version()).wait() { - Ok(_) => error::SUCCESS.code_num, - Err(_) => error::UNKNOWN_LIBINDY_ERROR.code_num, - } +pub fn set_protocol_version() -> VcxResult<()> { + pool::set_protocol_version(settings::get_protocol_version()) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn create_pool_ledger_config(pool_name: &str, path: &str) -> Result<(), u32> { - let pool_config = format!(r#"{{"genesis_txn":"{}"}}"#, path); +pub fn create_pool_ledger_config(pool_name: &str, path: &str) -> VcxResult<()> { + let pool_config = json!({"genesis_txn": path}).to_string(); - match pool::create_pool_ledger_config(pool_name, Some(&pool_config)).wait() { - Ok(_) => Ok(()), - Err(x) => if x.error_code != ErrorCode::PoolLedgerConfigAlreadyExistsError { - Err(error::UNKNOWN_LIBINDY_ERROR.code_num) - } else { - Ok(()) - } - } + pool::create_pool_ledger_config(pool_name, Some(&pool_config)) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn open_pool_ledger(pool_name: &str, config: Option<&str>) -> Result { +pub fn open_pool_ledger(pool_name: &str, config: Option<&str>) -> VcxResult { - set_protocol_version(); + set_protocol_version()?; - //TODO there was timeout here (before future-based Rust wrapper) - match pool::open_pool_ledger(pool_name, config).wait().map_err(map_rust_indy_sdk_error) { - Ok(x) => { - change_pool_handle(Some(x)); - Ok(x as u32) - }, - Err(_) => Err(error::UNKNOWN_LIBINDY_ERROR.code_num), - } + let handle = pool::open_pool_ledger(pool_name, config) + .wait() + .map_err(map_rust_indy_sdk_error)?; + + change_pool_handle(Some(handle)); + Ok(handle as u32) } -pub fn close() -> Result<(), u32> { +pub fn close() -> VcxResult<()> { let handle = get_pool_handle()?; change_pool_handle(None); + //TODO there was timeout here (before future-based Rust wrapper) - pool::close_pool_ledger(handle).wait().map_err(map_rust_indy_sdk_error) + pool::close_pool_ledger(handle) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn delete(pool_name: &str) -> Result<(), u32> { +pub fn delete(pool_name: &str) -> VcxResult<()> { trace!("delete >>> pool_name: {}", pool_name); if settings::test_indy_mode_enabled() { @@ -67,11 +59,15 @@ pub fn delete(pool_name: &str) -> Result<(), u32> { return Ok(()) } - pool::delete_pool_ledger(pool_name).wait().map_err(map_rust_indy_sdk_error) + pool::delete_pool_ledger(pool_name) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn get_pool_handle() -> Result { - Ok(POOL_HANDLE.read().or(Err(error::NO_POOL_OPEN.code_num))?.ok_or(error::NO_POOL_OPEN.code_num)?) +pub fn get_pool_handle() -> VcxResult { + POOL_HANDLE.read() + .or(Err(VcxError::from(VcxErrorKind::NoPoolOpen)))? + .ok_or(VcxError::from(VcxErrorKind::NoPoolOpen)) } #[cfg(test)] diff --git a/vcx/libvcx/src/utils/libindy/signus.rs b/vcx/libvcx/src/utils/libindy/signus.rs index 5469030d0f..f122eec3b1 100644 --- a/vcx/libvcx/src/utils/libindy/signus.rs +++ b/vcx/libvcx/src/utils/libindy/signus.rs @@ -1,28 +1,29 @@ -extern crate libc; - use futures::Future; use settings; use utils::libindy::error_codes::map_rust_indy_sdk_error; +use utils::libindy::wallet::get_wallet_handle; use indy::did; +use error::prelude::*; -pub fn create_and_store_my_did(seed: Option<&str>) -> Result<(String, String), u32> { +pub fn create_and_store_my_did(seed: Option<&str>) -> VcxResult<(String, String)> { if settings::test_indy_mode_enabled() { return Ok((::utils::constants::DID.to_string(), ::utils::constants::VERKEY.to_string())); } - let my_did_json = seed.map_or("{}".to_string(), |seed| format!("{{\"seed\":\"{}\" }}", seed)); - did::create_and_store_my_did(::utils::libindy::wallet::get_wallet_handle(), &my_did_json) + let my_did_json = seed.map_or(json!({}), |seed| json!({"seed": seed})); + + did::create_and_store_my_did(get_wallet_handle(), &my_did_json.to_string()) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn get_local_verkey(did: &str) -> Result { +pub fn get_local_verkey(did: &str) -> VcxResult { if settings::test_indy_mode_enabled() { return Ok(::utils::constants::VERKEY.to_string()); } - did::key_for_local_did(::utils::libindy::wallet::get_wallet_handle(), did) + did::key_for_local_did(get_wallet_handle(), did) .wait() .map_err(map_rust_indy_sdk_error) } diff --git a/vcx/libvcx/src/utils/libindy/wallet.rs b/vcx/libvcx/src/utils/libindy/wallet.rs index f07aaba807..de6f71dbd2 100644 --- a/vcx/libvcx/src/utils/libindy/wallet.rs +++ b/vcx/libvcx/src/utils/libindy/wallet.rs @@ -5,27 +5,33 @@ use futures::Future; use settings; use utils::libindy::error_codes::map_rust_indy_sdk_error; -use utils::error; -use error::wallet::WalletError; use indy::wallet; use indy::ErrorCode; use std::path::Path; +use error::prelude::*; + pub static mut WALLET_HANDLE: i32 = 0; +pub fn set_wallet_handle(handle: i32) -> i32 { + unsafe { WALLET_HANDLE = handle; } + unsafe { WALLET_HANDLE } +} + pub fn get_wallet_handle() -> i32 { unsafe { WALLET_HANDLE } } -pub fn create_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>, storage_creds: Option<&str>) -> Result<(), u32> { +pub fn create_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>, storage_creds: Option<&str>) -> VcxResult<()> { trace!("creating wallet: {}", wallet_name); let config = settings::get_wallet_config(wallet_name, wallet_type, storage_config); let credentials = settings::get_wallet_credentials(storage_creds); - match wallet::create_wallet(&config, &credentials).wait() { + match wallet::create_wallet(&config, &credentials) + .wait() { Ok(x) => Ok(()), - Err(x) => if x.error_code != ErrorCode::WalletAlreadyExistsError && x.error_code != ErrorCode::Success { + Err(x) => if x.error_code != ErrorCode::WalletAlreadyExistsError { warn!("could not create wallet {}: {:?}", wallet_name, x.message); - Err(error::INVALID_WALLET_CREATION.code_num) + Err(VcxError::from(VcxErrorKind::WalletCreate)) } else { warn!("could not create wallet {}: {:?}", wallet_name, x.message); Ok(()) @@ -33,11 +39,10 @@ pub fn create_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_confi } } -pub fn open_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>, storage_creds: Option<&str>) -> Result { +pub fn open_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>, storage_creds: Option<&str>) -> VcxResult { trace!("open_wallet >>> wallet_name: {}", wallet_name); if settings::test_indy_mode_enabled() { - unsafe {WALLET_HANDLE = 1;} - return Ok(1); + return Ok(set_wallet_handle(1)); } let config = settings::get_wallet_config(wallet_name, wallet_type, storage_config); @@ -48,54 +53,55 @@ pub fn open_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: .wait() .map_err(map_rust_indy_sdk_error)?; - unsafe { WALLET_HANDLE = handle; } + set_wallet_handle(handle); Ok(handle) } -pub fn init_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>, storage_creds: Option<&str>) -> Result { +pub fn init_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>, storage_creds: Option<&str>) -> VcxResult { if settings::test_indy_mode_enabled() { - unsafe {WALLET_HANDLE = 1;} - return Ok(1); + return Ok(set_wallet_handle(1)); } create_wallet(wallet_name, wallet_type, storage_config, storage_creds)?; open_wallet(wallet_name, wallet_type, storage_config, storage_creds) } -pub fn close_wallet() -> Result<(), u32> { +pub fn close_wallet() -> VcxResult<()> { trace!("close_wallet >>>"); if settings::test_indy_mode_enabled() { - unsafe { WALLET_HANDLE = 0; } + set_wallet_handle(0); return Ok(()); } - let result = wallet::close_wallet(get_wallet_handle()).wait().map_err(map_rust_indy_sdk_error); - unsafe { WALLET_HANDLE = 0; } + let result = wallet::close_wallet(get_wallet_handle()) + .wait() + .map_err(map_rust_indy_sdk_error); + + set_wallet_handle(0); result } -pub fn delete_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>, storage_creds: Option<&str>) -> Result<(), u32> { +pub fn delete_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>, storage_creds: Option<&str>) -> VcxResult<()> { trace!("delete_wallet >>> wallet_name: {}", wallet_name); if settings::test_indy_mode_enabled() { - unsafe { WALLET_HANDLE = 0;} - return Ok(()) + set_wallet_handle(0); + return Ok(()); } - match close_wallet() { - Ok(_) => (), - Err(x) => (), - }; + close_wallet().ok(); let config = settings::get_wallet_config(wallet_name, wallet_type, storage_config); - wallet::delete_wallet(&config,&settings::get_wallet_credentials(storage_creds)).wait().map_err(map_rust_indy_sdk_error) + wallet::delete_wallet(&config, &settings::get_wallet_credentials(storage_creds)) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn add_record(xtype: &str, id: &str, value: &str, tags: Option<&str>) -> Result<(), u32> { +pub fn add_record(xtype: &str, id: &str, value: &str, tags: Option<&str>) -> VcxResult<()> { trace!("add_record >>> xtype: {}, id: {}, value: {}, tags: {:?}", xtype, id, value, tags); - if settings::test_indy_mode_enabled() { return Ok(()) } + if settings::test_indy_mode_enabled() { return Ok(()); } wallet::add_wallet_record(get_wallet_handle(), xtype, id, value, tags) .wait() @@ -103,11 +109,11 @@ pub fn add_record(xtype: &str, id: &str, value: &str, tags: Option<&str>) -> Res } -pub fn get_record(xtype: &str, id: &str, options: &str) -> Result { +pub fn get_record(xtype: &str, id: &str, options: &str) -> VcxResult { trace!("get_record >>> xtype: {}, id: {}, options: {}", xtype, id, options); if settings::test_indy_mode_enabled() { - return Ok(r#"{"id":"123","type":"record type","value":"record value","tags":null}"#.to_string()) + return Ok(r#"{"id":"123","type":"record type","value":"record value","tags":null}"#.to_string()); } wallet::get_wallet_record(get_wallet_handle(), xtype, id, options) @@ -115,60 +121,60 @@ pub fn get_record(xtype: &str, id: &str, options: &str) -> Result { .map_err(map_rust_indy_sdk_error) } -pub fn delete_record(xtype: &str, id: &str) -> Result<(), u32> { +pub fn delete_record(xtype: &str, id: &str) -> VcxResult<()> { trace!("delete_record >>> xtype: {}, id: {}", xtype, id); - if settings::test_indy_mode_enabled() { return Ok(()) } + if settings::test_indy_mode_enabled() { return Ok(()); } + wallet::delete_wallet_record(get_wallet_handle(), xtype, id) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn update_record_value(xtype: &str, id: &str, value: &str) -> Result<(), u32> { +pub fn update_record_value(xtype: &str, id: &str, value: &str) -> VcxResult<()> { trace!("update_record_value >>> xtype: {}, id: {}, value: {}", xtype, id, value); - if settings::test_indy_mode_enabled() { return Ok(()) } + if settings::test_indy_mode_enabled() { return Ok(()); } + wallet::update_wallet_record_value(get_wallet_handle(), xtype, id, value) .wait() .map_err(map_rust_indy_sdk_error) } -pub fn export(wallet_handle: i32, path: &Path, backup_key: &str) -> Result<(), WalletError> { +pub fn export(wallet_handle: i32, path: &Path, backup_key: &str) -> VcxResult<()> { trace!("export >>> wallet_handle: {}, path: {:?}, backup_key: ****", wallet_handle, path); let export_config = json!({ "key": backup_key, "path": &path}).to_string(); - match wallet::export_wallet(wallet_handle, &export_config).wait() { - Ok(_) => Ok(()), - Err(e) => Err(WalletError::CommonError(map_rust_indy_sdk_error(e))), - } + wallet::export_wallet(wallet_handle, &export_config) + .wait() + .map_err(map_rust_indy_sdk_error) } -pub fn import(config: &str) -> Result<(), WalletError> { +pub fn import(config: &str) -> VcxResult<()> { trace!("import >>> config {}", config); - settings::process_config_string(config).map_err(|e| WalletError::CommonError(e))?; + settings::process_config_string(config)?; let key = settings::get_config_value(settings::CONFIG_WALLET_KEY) - .map_err(|e| WalletError::CommonError(e))?; + .or(Err(VcxError::from(VcxErrorKind::MissingWalletKey)))?; let name = settings::get_config_value(settings::CONFIG_WALLET_NAME) - .map_err(|e| WalletError::CommonError(error::MISSING_WALLET_NAME.code_num))?; + .or(Err(VcxError::from(VcxErrorKind::MissingWalletName)))?; let exported_wallet_path = settings::get_config_value(settings::CONFIG_EXPORTED_WALLET_PATH) - .or(Err(WalletError::CommonError(error::MISSING_EXPORTED_WALLET_PATH.code_num)))?; + .or(Err(VcxError::from(VcxErrorKind::MissingExportedWalletPath)))?; let backup_key = settings::get_config_value(settings::CONFIG_WALLET_BACKUP_KEY) - .or(Err(WalletError::CommonError(error::MISSING_BACKUP_KEY.code_num)))?; + .or(Err(VcxError::from(VcxErrorKind::MissingBackupKey)))?; let config = settings::get_wallet_config(&name, None, None); let credentials = settings::get_wallet_credentials(None); let import_config = json!({"key": backup_key, "path": exported_wallet_path }).to_string(); - match wallet::import_wallet(&config, &credentials, &import_config).wait() { - Ok(_) => Ok(()), - Err(e) => Err(WalletError::CommonError(map_rust_indy_sdk_error(e))), - } + wallet::import_wallet(&config, &credentials, &import_config) + .wait() + .map_err(map_rust_indy_sdk_error) } #[cfg(test)] @@ -221,7 +227,7 @@ pub mod tests { #[test] fn test_wallet() { init!("false"); - assert!( get_wallet_handle() > 0); + assert!(get_wallet_handle() > 0); assert_eq!(error::INVALID_WALLET_CREATION.code_num, init_wallet(&String::from(""), None, None, None).unwrap_err()); } @@ -291,7 +297,7 @@ pub mod tests { #[test] fn test_import_fails_with_missing_configs() { - settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE,"false"); + settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE, "false"); ::api::vcx::vcx_shutdown(true); // Invalid json @@ -335,7 +341,7 @@ pub mod tests { } #[test] - fn test_import_wallet_fails_with_invalid_path(){ + fn test_import_wallet_fails_with_invalid_path() { settings::set_defaults(); let wallet_name = "test_import_wallet_fails_with_invalid_path"; settings::set_config_value(settings::CONFIG_WALLET_NAME, wallet_name); @@ -466,7 +472,6 @@ pub mod tests { let rc = delete_record(record_type, id); assert_eq!(rc, Err(error::WALLET_RECORD_NOT_FOUND.code_num)); - } #[test] diff --git a/vcx/libvcx/src/utils/logger.rs b/vcx/libvcx/src/utils/logger.rs index 634d0a9698..efaa3f46b0 100644 --- a/vcx/libvcx/src/utils/logger.rs +++ b/vcx/libvcx/src/utils/logger.rs @@ -22,7 +22,8 @@ use std::ffi::CString; #[cfg(target_os = "android")] use self::android_logger::Filter; use utils::cstring::CStringUtils; -use utils::error::LOGGING_ERROR; +use error::prelude::*; + use utils::libindy; @@ -60,12 +61,15 @@ impl LibvcxLogger { LibvcxLogger { context, enabled, log, flush } } - pub fn init(context: *const CVoid, enabled: Option, log: LogCB, flush: Option) -> Result<(), u32> { + pub fn init(context: *const CVoid, enabled: Option, log: LogCB, flush: Option) -> VcxResult<()> { trace!("LibvcxLogger::init >>>"); let logger = LibvcxLogger::new(context, enabled, log, flush); - log::set_boxed_logger(Box::new(logger)).map_err(|_| LOGGING_ERROR.code_num)?; + log::set_boxed_logger(Box::new(logger)) + .map_err(|err| VcxError::from_msg(VcxErrorKind::LoggingError, format!("Setting logger failed with: {}", err)))?; log::set_max_level(LevelFilter::Trace); - libindy::logger::set_logger(log::logger()).map_err(|_| LOGGING_ERROR.code_num)?; + libindy::logger::set_logger(log::logger()) + .map_err(|err| err.map(VcxErrorKind::LoggingError, "Setting logger failed"))?; + unsafe { LOGGER_STATE = LoggerState::Custom; CONTEXT = context; @@ -147,7 +151,7 @@ impl LibvcxDefaultLogger { } } - pub fn init(pattern: Option) -> Result<(), u32> { + pub fn init(pattern: Option) -> VcxResult<()> { trace!("LibvcxDefaultLogger::init >>> pattern: {:?}", pattern); let pattern = pattern.or(env::var("RUST_LOG").ok()); @@ -182,7 +186,7 @@ impl LibvcxDefaultLogger { Ok(_) => {} Err(e) => { error!("Error in logging init: {:?}", e); - return Err(LOGGING_ERROR.code_num); + return Err(VcxError::from_msg(VcxErrorKind::LoggingError, format!("Cannot init logger: {:?}", e))) } } } diff --git a/vcx/libvcx/src/utils/openssl.rs b/vcx/libvcx/src/utils/openssl.rs index b168a613d8..b5dd290e0b 100644 --- a/vcx/libvcx/src/utils/openssl.rs +++ b/vcx/libvcx/src/utils/openssl.rs @@ -2,7 +2,9 @@ extern crate openssl; use self::openssl::sha::sha256; use self::openssl::bn::BigNum; use utils::error::BIG_NUMBER_ERROR; -pub fn encode(s: &str ) -> Result { +use error::prelude::*; + +pub fn encode(s: &str ) -> VcxResult { match s.parse::() { Ok(_) => Ok(s.to_string()), Err(_) => { @@ -11,14 +13,14 @@ pub fn encode(s: &str ) -> Result { Ok(b) => b, Err(_) => { warn!("{}", BIG_NUMBER_ERROR.message); - return Err(BIG_NUMBER_ERROR.code_num) + return Err(VcxError::from(VcxErrorKind::EncodeError)) } }; match bignum.to_dec_str() { Ok(s) => Ok(s.to_string()), Err(_) => { warn!("{}", BIG_NUMBER_ERROR.message); - Err(BIG_NUMBER_ERROR.code_num) + Err(VcxError::from(VcxErrorKind::EncodeError)) } } } From 2cc8ed38da37c4493255d974de5a44b7d7731adf Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Thu, 21 Feb 2019 15:49:09 +0300 Subject: [PATCH 05/28] Updated vcx test to support new error handling Signed-off-by: artem.ivanov --- vcx/libvcx/src/api/connection.rs | 3 +- vcx/libvcx/src/api/credential.rs | 7 +- vcx/libvcx/src/api/credential_def.rs | 2 +- vcx/libvcx/src/api/issuer_credential.rs | 4 +- vcx/libvcx/src/api/logger.rs | 2 +- vcx/libvcx/src/api/mod.rs | 2 - vcx/libvcx/src/api/schema.rs | 2 +- vcx/libvcx/src/api/utils.rs | 2 +- vcx/libvcx/src/api/vcx.rs | 22 +- vcx/libvcx/src/connection.rs | 212 ++++++++---------- vcx/libvcx/src/credential.rs | 186 +++++++-------- vcx/libvcx/src/credential_def.rs | 31 +-- vcx/libvcx/src/credential_request.rs | 7 +- vcx/libvcx/src/disclosed_proof.rs | 142 ++++++------ vcx/libvcx/src/error/mod.rs | 15 ++ vcx/libvcx/src/issuer_credential.rs | 107 ++++----- vcx/libvcx/src/lib.rs | 2 + vcx/libvcx/src/messages/agent_utils.rs | 7 +- vcx/libvcx/src/messages/create_key.rs | 2 +- vcx/libvcx/src/messages/get_message.rs | 2 +- vcx/libvcx/src/messages/invite.rs | 15 -- vcx/libvcx/src/messages/payload.rs | 5 +- .../src/messages/proofs/proof_message.rs | 19 +- .../src/messages/proofs/proof_request.rs | 30 ++- vcx/libvcx/src/messages/send_message.rs | 4 +- vcx/libvcx/src/messages/validation.rs | 8 +- vcx/libvcx/src/object_cache/mod.rs | 2 - vcx/libvcx/src/proof.rs | 107 ++++----- vcx/libvcx/src/schema.rs | 51 ++--- vcx/libvcx/src/settings.rs | 72 +++--- vcx/libvcx/src/utils/libindy/anoncreds.rs | 22 +- vcx/libvcx/src/utils/libindy/cache.rs | 2 +- vcx/libvcx/src/utils/libindy/callback.rs | 2 +- vcx/libvcx/src/utils/libindy/crypto.rs | 4 +- vcx/libvcx/src/utils/libindy/error_codes.rs | 16 +- vcx/libvcx/src/utils/libindy/ledger.rs | 13 +- vcx/libvcx/src/utils/libindy/mod.rs | 2 - vcx/libvcx/src/utils/libindy/payments.rs | 37 ++- vcx/libvcx/src/utils/libindy/pool.rs | 20 +- vcx/libvcx/src/utils/libindy/signus.rs | 2 +- vcx/libvcx/src/utils/libindy/wallet.rs | 54 +++-- ...Q9NFxbjUiZSYVXBZtivbWiPL2BkHBGsMJ3oaHTzvcc | Bin 0 -> 642 bytes ...ukoFz4wtPe6TUHdZftnbszX8gZPyDTukWpB2iwnxMa | Bin 0 -> 642 bytes 43 files changed, 550 insertions(+), 696 deletions(-) create mode 100644 vcx/libvcx/tails.txt/6LQ9NFxbjUiZSYVXBZtivbWiPL2BkHBGsMJ3oaHTzvcc create mode 100644 vcx/libvcx/tails.txt/CAukoFz4wtPe6TUHdZftnbszX8gZPyDTukWpB2iwnxMa diff --git a/vcx/libvcx/src/api/connection.rs b/vcx/libvcx/src/api/connection.rs index e069adbc75..46d3f765da 100644 --- a/vcx/libvcx/src/api/connection.rs +++ b/vcx/libvcx/src/api/connection.rs @@ -7,7 +7,6 @@ use utils::error::error_string; use utils::threadpool::spawn; use std::ptr; use connection::{get_source_id, create_connection, create_connection_with_invite, connect, to_string, get_state, release, is_valid_handle, update_state, from_string, get_invite_details, delete_connection}; -use error::prelude::*; /// Delete a Connection object and release its handle /// @@ -31,7 +30,7 @@ pub extern fn vcx_connection_delete_connection(command_handle: u32, check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); if !is_valid_handle(connection_handle) { - return VcxErrorKind::InvalidConnectionHandle.into() + return error::INVALID_CONNECTION_HANDLE.code_num } trace!("vcx_connection_delete_connection(command_handle: {}, connection_handle: {})", command_handle, connection_handle); spawn(move|| { diff --git a/vcx/libvcx/src/api/credential.rs b/vcx/libvcx/src/api/credential.rs index 89ffb04027..b655912ad6 100644 --- a/vcx/libvcx/src/api/credential.rs +++ b/vcx/libvcx/src/api/credential.rs @@ -1,6 +1,6 @@ extern crate libc; -extern crate serde_json; +use serde_json; use self::libc::c_char; use utils::cstring::CStringUtils; use utils::error; @@ -9,7 +9,6 @@ use connection; use credential; use std::ptr; use utils::threadpool::spawn; -use error::prelude::*; /// Retrieves Payment Info from a Credential /// @@ -131,7 +130,7 @@ pub extern fn vcx_get_credential(command_handle: u32, check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); if !credential::is_valid_handle(credential_handle) { - return VcxErrorKind::InvalidCredentialHandle.into() + return error::INVALID_CREDENTIAL_HANDLE.code_num } let source_id = credential::get_source_id(credential_handle).unwrap_or_default(); @@ -737,7 +736,7 @@ mod tests { cb.receive(Some(Duration::from_secs(10))).unwrap().unwrap(); let cb = return_types_u32::Return_U32_STR::new().unwrap(); - assert_eq!(vcx_get_credential(cb.command_handle, bad_handle, Some(cb.get_callback())), VcxErrorKind::InvalidCredentialHandle.into()); + assert_eq!(vcx_get_credential(cb.command_handle, bad_handle, Some(cb.get_callback())), error::INVALID_CREDENTIAL_HANDLE.code_num); let handle = credential::from_string(DEFAULT_SERIALIZED_CREDENTIAL).unwrap(); let cb = return_types_u32::Return_U32_STR::new().unwrap(); diff --git a/vcx/libvcx/src/api/credential_def.rs b/vcx/libvcx/src/api/credential_def.rs index ac1dae5c1c..b4ea3ff54a 100644 --- a/vcx/libvcx/src/api/credential_def.rs +++ b/vcx/libvcx/src/api/credential_def.rs @@ -1,6 +1,6 @@ extern crate libc; -extern crate serde_json; +use serde_json; use self::libc::c_char; use utils::cstring::CStringUtils; use utils::error; diff --git a/vcx/libvcx/src/api/issuer_credential.rs b/vcx/libvcx/src/api/issuer_credential.rs index dede6ae0a3..93486c285d 100644 --- a/vcx/libvcx/src/api/issuer_credential.rs +++ b/vcx/libvcx/src/api/issuer_credential.rs @@ -1,6 +1,6 @@ extern crate libc; -extern crate serde_json; +use serde_json; use self::libc::c_char; use utils::cstring::CStringUtils; use utils::error; @@ -800,7 +800,7 @@ mod tests { init!("false"); //settings::set_defaults(); let credential = issuer_credential::tests::create_standard_issuer_credential(); - let s = credential.to_string(); + let s = credential.to_string().unwrap(); let handle = issuer_credential::from_string(&s).unwrap(); let cb = return_types_u32::Return_U32_STR::new().unwrap(); vcx_issuer_credential_get_payment_txn(cb.command_handle, handle, Some(cb.get_callback())); diff --git a/vcx/libvcx/src/api/logger.rs b/vcx/libvcx/src/api/logger.rs index 48a6bd4789..4a02320afa 100644 --- a/vcx/libvcx/src/api/logger.rs +++ b/vcx/libvcx/src/api/logger.rs @@ -1,5 +1,5 @@ extern crate libc; -extern crate indy_sys; + use utils::logger::{ EnabledCB, FlushCB, LibvcxLogger, LibvcxDefaultLogger, LogCB, LOGGER_STATE, CVoid }; use utils::cstring::CStringUtils; use self::libc::{c_char}; diff --git a/vcx/libvcx/src/api/mod.rs b/vcx/libvcx/src/api/mod.rs index 15904f8807..104d2cc97c 100644 --- a/vcx/libvcx/src/api/mod.rs +++ b/vcx/libvcx/src/api/mod.rs @@ -1,5 +1,3 @@ -extern crate libc; - pub mod vcx; pub mod connection; pub mod issuer_credential; diff --git a/vcx/libvcx/src/api/schema.rs b/vcx/libvcx/src/api/schema.rs index b5742246cf..1a239c8985 100644 --- a/vcx/libvcx/src/api/schema.rs +++ b/vcx/libvcx/src/api/schema.rs @@ -1,6 +1,6 @@ extern crate libc; -extern crate serde_json; +use serde_json; use self::libc::c_char; use utils::cstring::CStringUtils; use utils::error; diff --git a/vcx/libvcx/src/api/utils.rs b/vcx/libvcx/src/api/utils.rs index 4806fe99c9..132c4ac5f6 100644 --- a/vcx/libvcx/src/api/utils.rs +++ b/vcx/libvcx/src/api/utils.rs @@ -1,6 +1,6 @@ extern crate libc; -extern crate serde_json; +use serde_json; use self::libc::c_char; use messages; use std::ptr; diff --git a/vcx/libvcx/src/api/vcx.rs b/vcx/libvcx/src/api/vcx.rs index 3d2a64cc25..931476cbb0 100644 --- a/vcx/libvcx/src/api/vcx.rs +++ b/vcx/libvcx/src/api/vcx.rs @@ -1,5 +1,4 @@ extern crate libc; -extern crate serde_json; use utils::version_constants; use self::libc::c_char; @@ -274,6 +273,7 @@ pub extern fn vcx_mint_tokens(seed: *const c_char, fees: *const c_char) { mod tests { use super::*; + use error::prelude::*; use std::time::Duration; use std::ptr; use std::thread; @@ -394,7 +394,7 @@ mod tests { let rc = cb.receive(Some(Duration::from_secs(10))); thread::sleep(Duration::from_secs(1)); assert!(rc.is_err()); - assert_eq!(get_pool_handle(), Err(error::NO_POOL_OPEN.code_num)); + assert_eq!(get_pool_handle().unwrap_err().kind(), VcxErrorKind::NoPoolOpen); assert_eq!(wallet::get_wallet_handle(), 0); wallet::delete_wallet(wallet_name, None, None, None).unwrap(); } @@ -520,7 +520,7 @@ mod tests { //Verify shutdown was successful vcx_shutdown(true); - assert_eq!(settings::get_config_value("wallet_name"), Err(error::INVALID_CONFIGURATION.code_num)); + assert_eq!(settings::get_config_value("wallet_name").unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); // Init for the second time works ::utils::devsetup::tests::setup_ledger_env(); @@ -653,7 +653,7 @@ mod tests { settings::CONFIG_EXPORTED_WALLET_PATH: export_path, settings::CONFIG_WALLET_BACKUP_KEY: settings::DEFAULT_WALLET_BACKUP_KEY, }).to_string(); - assert_eq!(import(&import_config), Err(::error::wallet::WalletError::CommonError(error::WALLET_ALREADY_EXISTS.code_num))); + assert_eq!(import(&import_config).unwrap_err().kind(), VcxErrorKind::DuplicationWallet); delete_import_wallet_path(export_path); vcx_shutdown(true); @@ -707,13 +707,13 @@ mod tests { let credential = ::credential::credential_create_with_offer("name", ::utils::constants::CREDENTIAL_OFFER_JSON).unwrap(); vcx_shutdown(true); - assert_eq!(::connection::release(connection),Err(::error::connection::ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); - assert_eq!(::issuer_credential::release(issuer_credential),Err(::error::issuer_cred::IssuerCredError::InvalidHandle())); - assert_eq!(::schema::release(schema).err(),Some(::error::schema::SchemaError::InvalidHandle())); - assert_eq!(::proof::release(proof).err(),Some(::error::proof::ProofError::InvalidHandle())); - assert_eq!(::credential_def::release(credentialdef),Err(::error::cred_def::CredDefError::InvalidHandle())); - assert_eq!(::credential::release(credential), Err(::error::credential::CredentialError::CommonError(error::INVALID_CREDENTIAL_HANDLE.code_num))); - assert_eq!(::disclosed_proof::release(disclosed_proof), Result::Err(error::INVALID_DISCLOSED_PROOF_HANDLE.code_num)); + assert_eq!(::connection::release(connection).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle); + assert_eq!(::issuer_credential::release(issuer_credential).unwrap_err().kind(), VcxErrorKind::InvalidIssuerCredentialHandle); + assert_eq!(::schema::release(schema).unwrap_err().kind(), VcxErrorKind::InvalidSchemaHandle); + assert_eq!(::proof::release(proof).unwrap_err().kind(), VcxErrorKind::InvalidProofHandle); + assert_eq!(::credential_def::release(credentialdef).unwrap_err().kind(), VcxErrorKind::InvalidCredDefHandle); + assert_eq!(::credential::release(credential).unwrap_err().kind(), VcxErrorKind::InvalidCredentialHandle); + assert_eq!(::disclosed_proof::release(disclosed_proof).unwrap_err().kind(), VcxErrorKind::InvalidDisclosedProofHandle); assert_eq!(wallet::get_wallet_handle(), 0); } diff --git a/vcx/libvcx/src/connection.rs b/vcx/libvcx/src/connection.rs index 107e1bddf6..39cd3a61b6 100644 --- a/vcx/libvcx/src/connection.rs +++ b/vcx/libvcx/src/connection.rs @@ -1,28 +1,24 @@ -extern crate rand; -extern crate serde_json; -extern crate rmp_serde; -extern crate serde; -extern crate libc; +use serde_json; +use serde_json::Value; +use rmp_serde; + +use std::collections::HashMap; -use utils::error; -use utils::libindy::signus::create_and_store_my_did; -use utils::libindy::crypto; -use utils::json::mapped_key_rewrite; use api::VcxStateType; use settings; -use messages::GeneralMessage; use messages; -use messages::{MessageStatusCode, RemoteMessageType}; +use messages::{GeneralMessage, MessageStatusCode, RemoteMessageType, ObjectWithVersion}; use messages::invite::{InviteDetail, SenderDetail, Payload as ConnectionPayload, AcceptanceDetails}; use messages::payload::{Payloads, Thread}; use messages::get_message::Message; -use serde_json::Value; -use utils::json::KeyMatch; use object_cache::ObjectCache; -use utils::constants::DEFAULT_SERIALIZE_VERSION; -use std::collections::HashMap; use error::prelude::*; -use messages::ObjectWithVersion; +use utils::error; +use utils::libindy::signus::create_and_store_my_did; +use utils::libindy::crypto; +use utils::json::mapped_key_rewrite; +use utils::constants::DEFAULT_SERIALIZE_VERSION; +use utils::json::KeyMatch; lazy_static! { static ref CONNECTION_MAP: ObjectCache = Default::default(); @@ -81,7 +77,8 @@ impl Connection { .agent_vk(&self.agent_vk)? .public_did(self.public_did.as_ref().map(String::as_str))? .thread(&Thread::new())? - .send_secure()?; + .send_secure() + .map_err(|err| err.extend("Cannot send invite"))?; self.state = VcxStateType::VcxStateOfferSent; self.invite_detail = Some(invite); @@ -98,7 +95,8 @@ impl Connection { .to_vk(&self.pw_verkey)? .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? - .send_secure()?; + .send_secure() + .map_err(|err| err.extend("Cannot delete connection"))?; self.state = VcxStateType::VcxStateNone; @@ -109,12 +107,7 @@ impl Connection { debug!("accepting invite for connection {}", self.source_id); let details: &InviteDetail = self.invite_detail.as_ref() - .ok_or_else(|| { - warn!("{} can not connect without invite details", self.source_id); - // TODO: Refactor Error - // TODO: Implement Correct Error - VcxError::from_msg(VcxErrorKind::GeneralConnectionError, "Invite details not found") - })?; + .ok_or(VcxError::from_msg(VcxErrorKind::GeneralConnectionError, format!("Invite details not found for: {}", self.source_id)))?; messages::accept_invite() .to(&self.pw_did)? @@ -126,9 +119,11 @@ impl Connection { .answer_status_code(&MessageStatusCode::Accepted)? .reply_to(&details.conn_req_id)? .thread(&self._build_thread_accept_invite(&details))? - .send_secure()?; + .send_secure() + .map_err(|err| err.extend("Cannot accept invite"))?; self.state = VcxStateType::VcxStateAccepted; + Ok(error::SUCCESS.code_num) } @@ -154,7 +149,7 @@ impl Connection { warn!("connection {} in state {} not ready to connect", self.source_id, self.state as u32); // TODO: Refactor Error // TODO: Implement Correct Error - Err(VcxError::from_msg(VcxErrorKind::GeneralConnectionError, "Connection is not ready to connect")) + Err(VcxError::from_msg(VcxErrorKind::GeneralConnectionError, format!("Connection {} in state {} not ready to connect", self.source_id, self.state as u32))) } } } @@ -222,7 +217,8 @@ impl Connection { let (for_did, for_verkey) = messages::create_keys() .for_did(&self.pw_did)? .for_verkey(&self.pw_verkey)? - .send_secure()?; + .send_secure() + .map_err(|err| err.extend("Cannot create pairwise keys"))?; debug!("create key for connection: {} with did {:?}, vk: {:?}", self.source_id, for_did, for_verkey); self.set_agent_did(&for_did); @@ -244,7 +240,8 @@ impl Connection { .name(&name)? .logo_url(&settings::get_config_value(settings::CONFIG_INSTITUTION_LOGO_URL)?)? .use_public_did(&self.public_did)? - .send_secure()?; + .send_secure() + .map_err(|err| err.extend("Cannot update agent profile"))?; } Ok(error::SUCCESS.code_num) @@ -258,73 +255,73 @@ pub fn is_valid_handle(handle: u32) -> bool { pub fn set_agent_did(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_agent_did(did)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_agent_did(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_agent_did().clone()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_pw_did(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_pw_did().clone()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn set_pw_did(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_pw_did(did)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_their_pw_did(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_their_pw_did().to_string()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn set_their_pw_did(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_their_pw_did(did)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn set_their_public_did(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_their_public_did(did)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_their_public_did(handle: u32) -> VcxResult> { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_their_public_did()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_their_pw_verkey(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_their_pw_verkey().to_string()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn set_their_pw_verkey(handle: u32, did: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_their_pw_verkey(did)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_uuid(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_uuid().to_string()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn set_uuid(handle: u32, uuid: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_uuid(uuid)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } // TODO: Add NO_ENDPOINT error to connection error @@ -337,58 +334,55 @@ pub fn get_endpoint(handle: u32) -> VcxResult { pub fn set_endpoint(handle: u32, endpoint: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_endpoint(endpoint)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_agent_verkey(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_agent_verkey().clone()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn set_agent_verkey(handle: u32, verkey: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_agent_verkey(verkey)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_pw_verkey(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_pw_verkey().clone()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn set_pw_verkey(handle: u32, verkey: &str) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_pw_verkey(verkey)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_state(handle: u32) -> u32 { - match CONNECTION_MAP.get(handle, |cxn| { + CONNECTION_MAP.get(handle, |cxn| { debug!("get state for connection {}", cxn.get_source_id()); - Ok(cxn.get_state().clone()) - }) { - Ok(s) => s, - Err(_) => 0, - } + }).unwrap_or(0) } pub fn set_state(handle: u32, state: VcxStateType) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { Ok(cxn.set_state(state)) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn get_source_id(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |cxn| { Ok(cxn.get_source_id().clone()) - }) + }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn create_connection(source_id: &str) -> VcxResult { trace!("create_connection >>> source_id: {}", source_id); + let (pw_did, pw_verkey) = create_and_store_my_did(None)?; debug!("did: {} verkey: {}, source id: {}", pw_did, pw_verkey, source_id); @@ -411,23 +405,22 @@ pub fn create_connection(source_id: &str) -> VcxResult { }; CONNECTION_MAP.add(c) - .map_err(|_| VcxError::from_msg(VcxErrorKind::CreateConnection, "Cannot create connection")) + .or(Err(VcxError::from(VcxErrorKind::CreateConnection))) } pub fn create_connection_with_invite(source_id: &str, details: &str) -> VcxResult { debug!("create connection {} with invite {}", source_id, details); let details: Value = serde_json::from_str(&details) - .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize invite")))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize invite details: {}", err)))?; let invite_details: InviteDetail = match serde_json::from_value(details.clone()) { Ok(x) => x, Err(x) => { // Try converting to abbreviated let details = unabbrv_event_detail(details)?; - let invite_details = serde_json::from_value(details) - .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize invite detail")))?; - invite_details + serde_json::from_value(details) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize invite details: {}", err)))? } }; @@ -455,25 +448,25 @@ pub fn parse_acceptance_details(handle: u32, message: &Message) -> VcxResult { - let payload = messages::to_u8(&payload); - // TODO: check returned verkey - let (_, payload) = crypto::parse_msg(&my_vk, &payload)?; + let (_, payload) = crypto::parse_msg(&my_vk, &messages::to_u8(&payload)) + .map_err(|err| err.map(VcxErrorKind::InvalidMessagePack, "Cannot decrypt connection payload"))?; let response: ConnectionPayload = rmp_serde::from_slice(&payload[..]) - .map_err(|err| { - error!("Could not parse outer msg: {}", err); - VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot parse payload: {}", err)) - })?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot parse connection payload: {}", err)))?; let payload = messages::to_u8(&response.msg); - // TODO: Refactor Error - messages::invite::parse_invitation_acceptance_details(payload) + + let response: AcceptanceDetails = rmp_serde::from_slice(&payload[..]) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot deserialize AcceptanceDetails: {}", err)))?; + + Ok(response.sender_detail) } settings::ProtocolTypes::V2 => { let (payload, _) = Payloads::decrypt_payload_v2(&my_vk, &payload)?; let response: AcceptanceDetails = serde_json::from_str(&payload) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize AcceptanceDetails: {}", err)))?; + Ok(response.sender_detail) } } @@ -500,18 +493,15 @@ pub fn update_state(handle: u32) -> VcxResult { .agent_did(&agent_did)? .agent_vk(&agent_vk)? .send_secure() - .map_err(|err| { - error!("could not update state for handle {}: {}", handle, err); - // TODO: Refactor Error - VcxError::from_msg(VcxErrorKind::PostMessageFailed, format!("Could not update state for handle {}", handle)) - })?; + .map_err(|err| err.map(VcxErrorKind::PostMessageFailed, format!("Could not update state for handle {}", handle)))?; debug!("connection {} update state response: {:?}", get_source_id(handle).unwrap_or_default(), response); if get_state(handle) == VcxStateType::VcxStateOfferSent as u32 || get_state(handle) == VcxStateType::VcxStateInitialized as u32 { - for i in response { - if i.status_code == MessageStatusCode::Accepted && i.msg_type == RemoteMessageType::ConnReqAnswer { - // TODO: Refactor Error - let details = parse_acceptance_details(handle, &i)?; + for message in response { + if message.status_code == MessageStatusCode::Accepted && message.msg_type == RemoteMessageType::ConnReqAnswer { + let details = parse_acceptance_details(handle, &message) + .map_err(|err| err.extend("Cannot parse acceptance details"))?; + set_their_pw_did(handle, &details.did).ok(); set_their_pw_verkey(handle, &details.verkey).ok(); set_state(handle, VcxStateType::VcxStateAccepted).ok(); @@ -553,18 +543,15 @@ pub fn connect(handle: u32, options: Option) -> VcxResult { pub fn to_string(handle: u32) -> VcxResult { CONNECTION_MAP.get(handle, |t| { - // TODO: Make this an error.to_error_code and back again? Connection::to_string(&t) }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } pub fn from_string(connection_data: &str) -> VcxResult { let derived_connection: Connection = Connection::from_str(connection_data)?; - - let new_handle = CONNECTION_MAP.add(derived_connection)?; - debug!("inserting handle {} source_id {} into connection table", new_handle, get_source_id(new_handle).unwrap_or_default()); - - Ok(new_handle) + let handle = CONNECTION_MAP.add(derived_connection)?; + debug!("inserting handle {} source_id {} into connection table", handle, get_source_id(handle).unwrap_or_default()); + Ok(handle) } pub fn release(handle: u32) -> VcxResult<()> { @@ -590,7 +577,7 @@ pub fn get_invite_details(handle: u32, abbreviated: bool) -> VcxResult { .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidInviteDetail, format!("Cannot serialize InviteDetail: {}", err)))?; let abbr = abbrv_event_detail(details)?; serde_json::to_string(&abbr) - .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidInviteDetail, format!("Cannot serialize InviteDetail: {}", err))) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidInviteDetail, format!("Cannot serialize abbreviated InviteDetail: {}", err))) } } }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) @@ -599,7 +586,6 @@ pub fn get_invite_details(handle: u32, abbreviated: bool) -> VcxResult { pub fn set_invite_details(handle: u32, invite_detail: &InviteDetail) -> VcxResult<()> { CONNECTION_MAP.get_mut(handle, |cxn| { cxn.set_invite_detail(invite_detail.clone()); - // TODO: Verify that this is ok to do...seems not rusty. Ok(()) }).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle))) } @@ -608,7 +594,6 @@ pub fn set_invite_details(handle: u32, invite_detail: &InviteDetail) -> VcxResul // Code to convert InviteDetails to Abbreviated String //********** - impl KeyMatch for (String, Option) { fn matches(&self, key: &String, context: &Vec) -> bool { if key.eq(&self.0) { @@ -680,7 +665,7 @@ fn abbrv_event_detail(val: Value) -> VcxResult { fn unabbrv_event_detail(val: Value) -> VcxResult { mapped_key_rewrite(val, &UNABBREVIATIONS) - .map_err(|err| VcxError::from_msg(VcxErrorKind::Common(err.into()), "Cannot unabbreviate event detail")) + .map_err(|err| err.extend("Cannot unabbreviate event detail")) } @@ -726,8 +711,7 @@ pub mod tests { fn test_build_connection_failures() { init!("true"); settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE, "false"); - assert_eq!(create_connection("This Should Fail").err(), - Some(ConnectionError::CommonError(error::INVALID_WALLET_HANDLE.code_num))); + assert_eq!(create_connection("This Should Fail").unwrap_err().kind(), VcxErrorKind::InvalidWalletHandle); assert!(create_connection_with_invite("This Should Fail", "BadDetailsFoobar").is_err()); } @@ -736,7 +720,7 @@ pub mod tests { init!("indy"); let handle = create_connection("invalid").unwrap(); let rc = connect(handle, None); - assert_eq!(rc.unwrap_err(), ConnectionError::CommonError(error::POST_MSG_FAILURE.code_num)); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::PostMessageFailed); } #[test] @@ -769,8 +753,7 @@ pub mod tests { #[test] fn test_connection_release_fails() { let rc = release(1); - assert_eq!(rc.err(), - Some(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle); } #[test] @@ -815,8 +798,7 @@ pub mod tests { update_state(handle).unwrap(); let details = get_invite_details(handle, true).unwrap(); assert!(details.contains("\"dp\":")); - assert_eq!(get_invite_details(12345, true).err(), - Some(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); + assert_eq!(get_invite_details(12345, true).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle); } #[test] @@ -857,7 +839,7 @@ pub mod tests { fn test_bad_wallet_connection_fails() { init!("true"); settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE, "false"); - assert_eq!(create_connection("test_bad_wallet_connection_fails").unwrap_err().to_error_code(), error::INVALID_WALLET_HANDLE.code_num); + assert_eq!(create_connection("test_bad_wallet_connection_fails").unwrap_err().kind(), VcxErrorKind::InvalidWalletHandle); } #[test] @@ -915,7 +897,7 @@ pub mod tests { Ok(_) => assert_eq!(0, 1), // we should not receive this // TODO: Refactor Error // TODO: Fix this test to be a correct Error Type - Err(e) => assert_eq!(e, ConnectionError::CommonError(1019)), + Err(e) => assert_eq!(e.kind(), VcxErrorKind::InvalidMessagePack), } } @@ -991,11 +973,11 @@ pub mod tests { let h4 = create_connection("rel4").unwrap(); let h5 = create_connection("rel5").unwrap(); release_all(); - assert_eq!(release(h1).err(), Some(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); - assert_eq!(release(h2).err(), Some(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); - assert_eq!(release(h3).err(), Some(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); - assert_eq!(release(h4).err(), Some(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); - assert_eq!(release(h5).err(), Some(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); + assert_eq!(release(h1).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle); + assert_eq!(release(h2).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle); + assert_eq!(release(h3).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle); + assert_eq!(release(h4).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle); + assert_eq!(release(h5).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle); } #[test] @@ -1021,13 +1003,12 @@ pub mod tests { let bad_details = r#"{"id":"mtfjmda","s":{"d":"abc"},"l":"abc","n":"Evernym","v":"avc"},"sa":{"d":"abc","e":"abc","v":"abc"},"sc":"MS-101","sm":"message created","t":"there"}"#; match create_connection_with_invite("alice", &bad_details) { Ok(_) => panic!("should have failed"), - Err(x) => assert_eq!(x, ConnectionError::CommonError(error::INVALID_JSON.code_num)), + Err(x) => assert_eq!(x.kind(), VcxErrorKind::InvalidJson), }; } #[test] fn test_connect_with_invalid_details() { - use error::connection::ConnectionError; init!("true"); let test_name = "test_connect_with_invalid_details"; @@ -1050,28 +1031,27 @@ pub mod tests { let handle = CONNECTION_MAP.add(c).unwrap(); - assert_eq!(connect(handle, Some("{}".to_string())).err(), Some(ConnectionError::CommonError(error::CONNECTION_ERROR.code_num))); + assert_eq!(connect(handle, Some("{}".to_string())).unwrap_err().kind(), VcxErrorKind::GeneralConnectionError);; // from_string throws a ConnectionError - assert_eq!(from_string("").err(), Some(ConnectionError::CommonError(1016))); + assert_eq!(from_string("").unwrap_err().kind(), VcxErrorKind::InvalidJson);; // release throws a connection Error - assert_eq!(release(1234).err(), - Some(ConnectionError::CommonError(error::INVALID_CONNECTION_HANDLE.code_num))); + assert_eq!(release(1234).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; } #[test] fn test_void_functions_actually_have_results() { - assert_eq!(set_their_pw_verkey(1, "blah").err(), Some(ConnectionError::InvalidHandle())); - assert_eq!(set_state(1, VcxStateType::VcxStateNone).err(), Some(ConnectionError::InvalidHandle())); - assert_eq!(set_pw_did(1, "blah").err(), Some(ConnectionError::InvalidHandle())); - assert_eq!(set_their_pw_did(1, "blah").err(), Some(ConnectionError::InvalidHandle())); - assert_eq!(set_uuid(1, "blah").err(), Some(ConnectionError::InvalidHandle())); - assert_eq!(set_endpoint(1, "blah").err(), Some(ConnectionError::InvalidHandle())); - assert_eq!(set_agent_verkey(1, "blah").err(), Some(ConnectionError::InvalidHandle())); + assert_eq!(set_their_pw_verkey(1, "blah").unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; + assert_eq!(set_state(1, VcxStateType::VcxStateNone).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; + assert_eq!(set_pw_did(1, "blah").unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; + assert_eq!(set_their_pw_did(1, "blah").unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; + assert_eq!(set_uuid(1, "blah").unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; + assert_eq!(set_endpoint(1, "blah").unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; + assert_eq!(set_agent_verkey(1, "blah").unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; let details: InviteDetail = serde_json::from_str(INVITE_DETAIL_STRING).unwrap(); - assert_eq!(set_invite_details(1, &details).err(), Some(ConnectionError::InvalidHandle())); - assert_eq!(set_pw_verkey(1, "blah").err(), Some(ConnectionError::InvalidHandle())); + assert_eq!(set_invite_details(1, &details).unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; + assert_eq!(set_pw_verkey(1, "blah").unwrap_err().kind(), VcxErrorKind::InvalidConnectionHandle);; } #[test] @@ -1079,6 +1059,6 @@ pub mod tests { init!("true"); let details = r#"{"id":"njjmmdg","s":{"d":"JZho9BzVAEk8jJ1hwrrDiZ","dp":{"d":"JDF8UHPBTXigvtJWeeMJzx","k":"AP5SzUaHHhF5aLmyKHB3eTqUaREGKyVttwo5T4uwEkM4","s":"JHSvITBMZiTEhpK61EDIWjQOLnJ8iGQ3FT1nfyxNNlxSngzp1eCRKnGC/RqEWgtot9M5rmTC8QkZTN05GGavBg=="},"l":"https://robohash.org/123","n":"Evernym","v":"AaEDsDychoytJyzk4SuzHMeQJGCtQhQHDitaic6gtiM1"},"sa":{"d":"YRuVCckY6vfZfX9kcQZe3u","e":"52.38.32.107:80/agency/msg","v":"J8Yct6FwmarXjrE2khZesUXRVVSVczSoa9sFaGe6AD2v"},"sc":"MS-101","sm":"message created","t":"there"}"#; let handle = create_connection_with_invite("alice", &details).unwrap(); - assert_eq!(release(handle), Ok(())); + assert_eq!(release(handle).unwrap(), ()); } } diff --git a/vcx/libvcx/src/credential.rs b/vcx/libvcx/src/credential.rs index 6d7fcb2717..138a56d551 100644 --- a/vcx/libvcx/src/credential.rs +++ b/vcx/libvcx/src/credential.rs @@ -1,33 +1,23 @@ -extern crate rand; -extern crate serde_json; -extern crate libc; -extern crate serde; -extern crate rmp_serde; +use serde_json; +use serde_json::Value; use object_cache::ObjectCache; use api::VcxStateType; -use utils::error; use issuer_credential::{CredentialOffer, CredentialMessage, PaymentInfo}; - use credential_request::CredentialRequest; - use messages; use messages::{GeneralMessage, RemoteMessageType, ObjectWithVersion}; use messages::payload::{Payloads, PayloadKinds, Thread}; - +use messages::get_message; +use connection; +use settings; use utils::libindy::anoncreds::{libindy_prover_create_credential_req, libindy_prover_store_credential}; use utils::libindy::anoncreds; use utils::libindy::payments::{pay_a_payee, PaymentTxn}; - -use connection; - -use settings; +use utils::error; use utils::constants::DEFAULT_SERIALIZE_VERSION; - -use serde_json::Value; use error::prelude::*; - lazy_static! { static ref HANDLE_MAP: ObjectCache = Default::default(); } @@ -52,7 +42,7 @@ impl Default for Credential { credential: None, payment_info: None, payment_txn: None, - thread: Thread::new(), + thread: Some(Thread::new()), } } } @@ -76,7 +66,7 @@ pub struct Credential { cred_id: Option, payment_info: Option, payment_txn: Option, - thread: Thread + thread: Option } impl Credential { @@ -84,7 +74,7 @@ impl Credential { trace!("Credential::build_request >>> my_did: {}, their_did: {}", my_did, their_did); if self.state != VcxStateType::VcxStateRequestReceived { - return Err(VcxError::from_msg(VcxErrorKind::NotReady, format!("credential {} has invalid state {} for sending credentialRequest", self.source_id, self.state as u32))); + return Err(VcxError::from_msg(VcxErrorKind::NotReady, format!("credential {} has invalid state {} for sending credential request", self.source_id, self.state as u32))); } let prover_did = self.my_did.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidDid))?; @@ -99,7 +89,8 @@ impl Credential { let (req, req_meta) = libindy_prover_create_credential_req(&prover_did, &credential_offer.libindy_offer, - &cred_def_json)?; + &cred_def_json) + .map_err(|err| err.extend("Cannot create credential request"))?; Ok(CredentialRequest { libindy_cred_req: req, @@ -161,13 +152,10 @@ impl Credential { .msg_type(&RemoteMessageType::CredReq)? .agent_did(local_agent_did)? .agent_vk(local_agent_vk)? - .edge_agent_payload(&local_my_vk, &local_their_vk, &cred_req_json, PayloadKinds::CredReq, Some(self.thread.clone()))? + .edge_agent_payload(&local_my_vk, &local_their_vk, &cred_req_json, PayloadKinds::CredReq, self.thread.clone())? .ref_msg_id(&offer_msg_id)? .send_secure() - .map_err(|err| { - warn!("{} could not send proof: {}", self.source_id, err); - err - })?; + .map_err(|err| err.extend(format!("{} could not send proof", self.source_id)))?; self.msg_uid = Some(response.get_msg_uid()?); self.state = VcxStateType::VcxStateOfferSent; @@ -182,12 +170,13 @@ impl Credential { let my_vk = self.my_vk.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; let msg_uid = self.msg_uid.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidCredentialHandle))?; - let (_, payload) = messages::get_message::get_ref_msg(msg_uid, my_did, my_vk, agent_did, agent_vk)?; + let (_, payload) = get_message::get_ref_msg(msg_uid, my_did, my_vk, agent_did, agent_vk)?; let (credential, thread) = Payloads::decrypt(&my_vk, &payload)?; if let Some(_) = thread { - self.thread.increment_receiver(self.their_did.as_ref().map(String::as_str).unwrap_or("")); + let their_did = self.their_did.as_ref().map(String::as_str).unwrap_or(""); + self.thread.as_mut().map(|thread| thread.increment_receiver(their_did)); } let credential_msg: CredentialMessage = serde_json::from_str(&credential) @@ -196,7 +185,8 @@ impl Credential { let cred_req: &CredentialRequest = self.credential_request.as_ref() .ok_or(VcxError::from_msg(VcxErrorKind::InvalidCredential, "Cannot find CredentialRequest"))?; - let (_, cred_def_json) = anoncreds::get_cred_def_json(&cred_req.cred_def_id)?; + let (_, cred_def_json) = anoncreds::get_cred_def_json(&cred_req.cred_def_id) + .map_err(|err| err.extend("Cannot get credential definition"))?; self.credential = Some(credential); self.cred_id = Some(libindy_prover_store_credential(None, @@ -231,8 +221,7 @@ impl Credential { fn get_state(&self) -> u32 { trace!("Credential::get_state >>>"); - let state = self.state as u32; - state + self.state as u32 } fn get_credential(&self) -> VcxResult { @@ -265,32 +254,26 @@ impl Credential { self.cred_id.as_ref().map(String::as_str).unwrap_or("").to_string() } - fn set_payment_info(&self, json: &mut serde_json::Map) { + fn set_payment_info(&self, json: &mut serde_json::Map) { if let Some(ref payment_info) = self.payment_info { - json.insert("price".to_string(), serde_json::Value::String(payment_info.price.to_string())); - json.insert("payment_address".to_string(), serde_json::Value::String(payment_info.payment_addr.to_string())); + json.insert("price".to_string(), Value::String(payment_info.price.to_string())); + json.insert("payment_address".to_string(), Value::String(payment_info.payment_addr.to_string())); }; } fn to_cred_string(&self, cred: &str) -> String { - let cred = { - let mut json = serde_json::Map::new(); - json.insert("credential_id".to_string(), serde_json::Value::String(self.get_credential_id())); - json.insert("credential".to_string(), serde_json::Value::String(cred.to_string())); - self.set_payment_info(&mut json); - serde_json::Value::from(json).to_string() - }; - cred + let mut json = serde_json::Map::new(); + json.insert("credential_id".to_string(), Value::String(self.get_credential_id())); + json.insert("credential".to_string(), Value::String(cred.to_string())); + self.set_payment_info(&mut json); + serde_json::Value::from(json).to_string() } fn to_cred_offer_string(&self, cred_offer: &str) -> String { - let cred_offer = { - let mut json = serde_json::Map::new(); - json.insert("credential_offer".to_string(), serde_json::Value::String(cred_offer.to_string())); - self.set_payment_info(&mut json); - serde_json::Value::from(json).to_string() - }; - cred_offer + let mut json = serde_json::Map::new(); + json.insert("credential_offer".to_string(), Value::String(cred_offer.to_string())); + self.set_payment_info(&mut json); + serde_json::Value::from(json).to_string() } fn set_source_id(&mut self, id: &str) { self.source_id = id.to_string(); } @@ -306,10 +289,6 @@ impl Credential { } } - fn set_credential_offer(&mut self, offer: CredentialOffer) { - self.credential_offer = Some(offer); - } - fn is_payment_required(&self) -> bool { self.payment_info.is_some() } @@ -341,7 +320,7 @@ impl Credential { fn from_str(data: &str) -> VcxResult { ObjectWithVersion::deserialize(data) .map(|obj: ObjectWithVersion| obj.data) - .map_err(|err| err.extend("Cannot deserialize Schema")) + .map_err(|err| err.extend("Cannot deserialize Credential")) } } @@ -362,9 +341,9 @@ pub fn credential_create_with_offer(source_id: &str, offer: &str) -> VcxResult VcxResu if settings::test_agency_mode_enabled() { ::utils::httpclient::set_next_u8_response(::utils::constants::NEW_CREDENTIAL_OFFER_RESPONSE.to_vec()); } - let message = messages::get_message::get_connection_messages(&my_did, - &my_vk, - &agent_did, - &agent_vk, - Some(vec![msg_id.to_string()]))?; - - if message[0].msg_type == RemoteMessageType::CredOffer { - let payload = message.get(0).and_then(|msg| msg.payload.as_ref()) - .ok_or(VcxError::from(VcxErrorKind::InvalidMessagePack))?; + let message = get_message::get_connection_messages(&my_did, + &my_vk, + &agent_did, + &agent_vk, + Some(vec![msg_id.to_string()])) + .map_err(|err| err.extend("Cannot get messages"))?; - let (offer, thread) = Payloads::decrypt(&my_vk, &payload)?; - - let (mut offer, payment_info) = parse_json_offer(&offer)?; + if message[0].msg_type != RemoteMessageType::CredOffer { + return Err(VcxError::from_msg(VcxErrorKind::InvalidMessages, "Invalid message type")); + } - offer.msg_ref_id = Some(message[0].uid.to_owned()); + let payload = message.get(0).and_then(|msg| msg.payload.as_ref()) + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidMessagePack, "Payload not found"))?; - if let Some(tr) = thread { - offer.thread_id = tr.thid.clone(); - } - let mut payload = Vec::new(); - payload.push(json!(offer)); - if let Some(p) = payment_info { payload.push(json!(p)); } + let payload = _set_cred_offer_ref_message(&payload, &my_vk, &message[0].uid)?; - serde_json::to_string_pretty(&payload) - .or(Err(VcxError::from(VcxErrorKind::InvalidMessages))) - } else { - Err(VcxError::from(VcxErrorKind::InvalidMessages)) - } + serde_json::to_string_pretty(&payload) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidMessages, format!("Cannot serialize credential offer: {}", err))) } pub fn get_credential_offer_messages(connection_handle: u32) -> VcxResult { @@ -477,11 +446,12 @@ pub fn get_credential_offer_messages(connection_handle: u32) -> VcxResult VcxResult VcxResult, my_vk: &str, msg_id: &str) -> VcxResult> { + let (offer, thread) = Payloads::decrypt(my_vk, payload)?; + + let (mut offer, payment_info) = parse_json_offer(&offer)?; + + offer.msg_ref_id = Some(msg_id.to_owned()); + if let Some(tr) = thread { + offer.thread_id = tr.thid.clone(); + } + + let mut payload = Vec::new(); + payload.push(json!(offer)); + if let Some(p) = payment_info { payload.push(json!(p)); } + + Ok(payload) +} + pub fn parse_json_offer(offer: &str) -> VcxResult<(CredentialOffer, Option)> { let paid_offer: Value = serde_json::from_str(offer) - .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidCredential, format!("Cannot deserialize offer: {}", err)))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize offer: {}", err)))?; let mut payment: Option = None; let mut offer: Option = None; @@ -522,16 +498,16 @@ pub fn parse_json_offer(offer: &str) -> VcxResult<(CredentialOffer, Option VcxResult<()> { @@ -624,7 +600,7 @@ pub mod tests { #[test] fn test_credential_defaults() { let credential = Credential::default(); - assert_eq!(credential.build_request("test1", "test2").err(), Some(CredentialError::NotReady())); + assert_eq!(credential.build_request("test1", "test2").unwrap_err().kind(), VcxErrorKind::NotReady); } #[test] @@ -637,7 +613,7 @@ pub mod tests { fn test_credential_create_with_bad_offer() { match credential_create_with_offer("test_credential_create_with_bad_offer", BAD_CREDENTIAL_OFFER) { Ok(_) => panic!("should have failed with bad credential offer"), - Err(x) => assert_eq!(x.to_error_code(), error::INVALID_JSON.code_num), + Err(x) => assert_eq!(x.kind(), VcxErrorKind::InvalidJson) }; } @@ -646,7 +622,7 @@ pub mod tests { let handle = credential_create_with_offer("test_credential_serialize_deserialize", ::utils::constants::CREDENTIAL_OFFER_JSON).unwrap(); let credential_string = to_string(handle).unwrap(); release(handle).unwrap(); - assert_eq!(release(handle).err(), Some(CredentialError::InvalidHandle())); + assert_eq!(release(handle).unwrap_err().kind(), VcxErrorKind::InvalidCredentialHandle); let handle = from_string(&credential_string).unwrap(); let cred1: Credential = Credential::from_str(&credential_string).unwrap(); assert_eq!(cred1.get_state(), 3); @@ -707,7 +683,7 @@ pub mod tests { init!("true"); let cred: Credential = Credential::from_str(DEFAULT_SERIALIZED_CREDENTIAL).unwrap(); assert!(cred.payment_info.is_none()); - assert_eq!(cred.submit_payment().err(), Some(CredentialError::NoPaymentInformation())); + assert_eq!(cred.submit_payment().unwrap_err().kind(), VcxErrorKind::NoPaymentInformation); } #[test] @@ -726,7 +702,7 @@ pub mod tests { let handle2 = from_string(DEFAULT_SERIALIZED_CREDENTIAL).unwrap(); assert!(!is_payment_required(handle2).unwrap()); let invalid_handle = 12345; - assert_eq!(is_payment_required(invalid_handle).err(), Some(CredentialError::InvalidHandle())); + assert_eq!(is_payment_required(invalid_handle).unwrap_err().kind(), VcxErrorKind::InvalidCredentialHandle); } #[test] diff --git a/vcx/libvcx/src/credential_def.rs b/vcx/libvcx/src/credential_def.rs index bdb33b7bb4..9ee001cbc6 100644 --- a/vcx/libvcx/src/credential_def.rs +++ b/vcx/libvcx/src/credential_def.rs @@ -1,9 +1,11 @@ -use utils::libindy::payments::PaymentTxn; -use utils::libindy::anoncreds; +use serde_json; + use object_cache::ObjectCache; use messages::ObjectWithVersion; use error::prelude::*; use utils::constants::DEFAULT_SERIALIZE_VERSION; +use utils::libindy::payments::PaymentTxn; +use utils::libindy::anoncreds; lazy_static! { static ref CREDENTIALDEF_MAP: ObjectCache = Default::default(); @@ -36,7 +38,7 @@ impl CredentialDef { pub fn from_str(data: &str) -> VcxResult { ObjectWithVersion::deserialize(data) .map(|obj: ObjectWithVersion| obj.data) - .map_err(|err| err.extend("Cannot deserialize CredentialDefinition")) + .map_err(|err| err.map(VcxErrorKind::CreateCredDef,"Cannot deserialize CredentialDefinition")) } pub fn to_string(&self) -> VcxResult { @@ -61,7 +63,7 @@ impl CredentialDef { fn get_cred_def_payment_txn(&self) -> VcxResult { self.cred_def_payment_txn.clone() - .ok_or(err_msg(VcxErrorKind::NoPaymentInformation, "Payment information not found")) + .ok_or(VcxError::from(VcxErrorKind::NoPaymentInformation)) } fn get_rev_reg_def_payment_txn(&self) -> Option { self.rev_reg_def_payment_txn.clone() } @@ -88,7 +90,7 @@ pub fn create_new_credentialdef(source_id: String, &schema_json, &tag, None, - revocation_details.support_revocation) .map_err(|err| { + revocation_details.support_revocation).map_err(|err| { if err.kind() == VcxErrorKind::CredDefAlreadyCreated { error!("Credential Definition for issuer_did {} already in wallet", issuer_did); err @@ -139,8 +141,7 @@ pub fn create_new_credentialdef(source_id: String, tails_file: revocation_details.tails_file, }; - let handle = CREDENTIALDEF_MAP.add(cred_def) - .map_err(|_| VcxError::from_msg(VcxErrorKind::CreateCredDef, "Cannot create credential definition"))?; + let handle = CREDENTIALDEF_MAP.add(cred_def).or(Err(VcxError::from(VcxErrorKind::CreateCredDef)))?; Ok(handle) } @@ -323,7 +324,7 @@ pub mod tests { schema_id, "tag_1".to_string(), r#"{"support_revocation":true}"#.to_string()); - assert_eq!(rc, Err(CredDefError::InvalidRevocationDetails())); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::InvalidRevocationDetails); } #[cfg(feature = "pool_tests")] @@ -402,7 +403,7 @@ pub mod tests { "tag_1".to_string(), r#"{"support_revocation":false}"#.to_string()); - assert_eq!(rc.err(), Some(CredDefError::CredDefAlreadyCreatedError())); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::CredDefAlreadyCreated); } #[test] @@ -433,7 +434,7 @@ pub mod tests { let credentialdef1: CredentialDef = CredentialDef::from_str(&credentialdef_data).unwrap(); let credentialdef2: CredentialDef = CredentialDef::from_str(&new_credentialdef_data).unwrap(); assert_eq!(credentialdef1, credentialdef2); - assert_eq!(CredentialDef::from_str("{}").err(), Some(CredDefError::CreateCredDefError())); + assert_eq!(CredentialDef::from_str("{}").unwrap_err().kind(), VcxErrorKind::CreateCredDef); } #[test] @@ -445,11 +446,11 @@ pub mod tests { let h4 = create_new_credentialdef("SourceId".to_string(), CREDENTIAL_DEF_NAME.to_string(), ISSUER_DID.to_string(), SCHEMA_ID.to_string(), "tag".to_string(), "{}".to_string()).unwrap(); let h5 = create_new_credentialdef("SourceId".to_string(), CREDENTIAL_DEF_NAME.to_string(), ISSUER_DID.to_string(), SCHEMA_ID.to_string(), "tag".to_string(), "{}".to_string()).unwrap(); release_all(); - assert_eq!(release(h1), Err(CredDefError::InvalidHandle())); - assert_eq!(release(h2), Err(CredDefError::InvalidHandle())); - assert_eq!(release(h3), Err(CredDefError::InvalidHandle())); - assert_eq!(release(h4), Err(CredDefError::InvalidHandle())); - assert_eq!(release(h5), Err(CredDefError::InvalidHandle())); + assert_eq!(release(h1).unwrap_err().kind(), VcxErrorKind::InvalidCredDefHandle); + assert_eq!(release(h2).unwrap_err().kind(), VcxErrorKind::InvalidCredDefHandle); + assert_eq!(release(h3).unwrap_err().kind(), VcxErrorKind::InvalidCredDefHandle); + assert_eq!(release(h4).unwrap_err().kind(), VcxErrorKind::InvalidCredDefHandle); + assert_eq!(release(h5).unwrap_err().kind(), VcxErrorKind::InvalidCredDefHandle); } #[test] diff --git a/vcx/libvcx/src/credential_request.rs b/vcx/libvcx/src/credential_request.rs index 2b768f526b..d6f85f3b62 100644 --- a/vcx/libvcx/src/credential_request.rs +++ b/vcx/libvcx/src/credential_request.rs @@ -1,9 +1,3 @@ -extern crate serde_json; - -static ISSUER_DID: &'static str = "issuer_did"; -static SEQUENCE_NUMBER: &'static str = "schema_seq_no"; -static BLINDED_MS: &'static str = "blinded_ms"; -static PROVER_DID: &'static str = "prover_did"; #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub struct CredentialRequest { @@ -38,6 +32,7 @@ impl CredentialRequest { #[cfg(test)] mod tests { use super::*; + use serde_json; use utils::constants::{CREDENTIAL_REQ_STRING, CRED_REQ, CRED_REQ_META}; static TEMP_ISSUER_DID: &'static str = "4reqXeZVm7JZAffAoaNLsb"; diff --git a/vcx/libvcx/src/disclosed_proof.rs b/vcx/libvcx/src/disclosed_proof.rs index ab20581b8c..1a19e3ac5f 100644 --- a/vcx/libvcx/src/disclosed_proof.rs +++ b/vcx/libvcx/src/disclosed_proof.rs @@ -1,29 +1,26 @@ -extern crate serde_json; +use serde_json; +use serde_json::Value; use std::collections::HashMap; +use time; + use object_cache::ObjectCache; use api::VcxStateType; -use utils::error; use connection; use messages; -use messages::GeneralMessage; -use messages::RemoteMessageType; -use messages::ObjectWithVersion; +use messages::{GeneralMessage, RemoteMessageType, ObjectWithVersion}; use messages::payload::{Payloads, PayloadKinds, Thread}; use messages::proofs::proof_message::ProofMessage; use messages::proofs::proof_request::{ProofRequestMessage, ProofRequestData, NonRevokedInterval}; -use time; +use messages::get_message::Message; use error::prelude::*; - -use utils::libindy::anoncreds; -use utils::libindy::anoncreds::{get_rev_reg_def_json, get_rev_reg_delta_json}; - use settings; -use utils::httpclient; +use utils::{httpclient, error}; use utils::constants::{DEFAULT_SERIALIZE_VERSION, CREDS_FROM_PROOF_REQ, DEFAULT_GENERATED_PROOF}; use utils::libindy::cache::{get_rev_reg_cache, set_rev_reg_cache, RevRegCache, RevState}; +use utils::libindy::anoncreds; +use utils::libindy::anoncreds::{get_rev_reg_def_json, get_rev_reg_delta_json}; -use serde_json::Value; lazy_static! { static ref HANDLE_MAP: ObjectCache = Default::default(); @@ -44,7 +41,7 @@ impl Default for DisclosedProof { their_vk: None, agent_did: None, agent_vk: None, - thread: Thread::new() + thread: Some(Thread::new()) } } } @@ -62,7 +59,7 @@ pub struct DisclosedProof { their_vk: Option, agent_did: Option, agent_vk: Option, - thread: Thread + thread: Option } #[derive(Debug, Deserialize, Serialize)] @@ -130,18 +127,12 @@ fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) - } fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) -> VcxResult> { - if let Some(ref attr) = proof_req.requested_attributes.get(attr_name) { - if let Some(ref interval) = attr.non_revoked { - return Ok(Some(NonRevokedInterval { from: interval.from, to: interval.to })); - } else if let Some(ref interval) = proof_req.non_revoked { - return Ok(Some(NonRevokedInterval { from: interval.from, to: interval.to })); - } + let attr = proof_req.requested_attributes.get(attr_name) + .ok_or(VcxError::from(VcxErrorKind::InvalidProofCredentialData))?; - return Ok(None); - } - // Todo: Handle case for predicates + Ok(attr.non_revoked.clone().or(proof_req.non_revoked.clone().or(None))) - Err(VcxError::from(VcxErrorKind::InvalidProofCredentialData)) + // Todo: Handle case for predicates } // Also updates timestamp in credentials_identifiers @@ -337,8 +328,8 @@ impl DisclosedProof { debug!("generating proof {}", self.source_id); if settings::test_indy_mode_enabled() { return Ok(error::SUCCESS.code_num); } - let proof_req = self.proof_request.as_ref() - .ok_or(VcxError::from(VcxErrorKind::CreateProof))?; + let proof_req = self.proof_request.as_ref().ok_or(VcxError::from(VcxErrorKind::CreateProof))?; + let proof_req_data_json = serde_json::to_string(&proof_req.proof_request_data) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize proof request: {}", err)))?; @@ -368,13 +359,12 @@ impl DisclosedProof { debug!("sending proof {} via connection: {}", self.source_id, connection::get_source_id(connection_handle).unwrap_or_default()); // There feels like there's a much more rusty way to do the below. - self.my_did = Some(connection::get_pw_did(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); - self.my_vk = Some(connection::get_pw_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); - self.agent_did = Some(connection::get_agent_did(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); - self.agent_vk = Some(connection::get_agent_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); - self.their_did = Some(connection::get_their_pw_did(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); - self.their_vk = Some(connection::get_their_pw_verkey(connection_handle).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))?); - + self.my_did = Some(connection::get_pw_did(connection_handle)?); + self.my_vk = Some(connection::get_pw_verkey(connection_handle)?); + self.agent_did = Some(connection::get_agent_did(connection_handle)?); + self.agent_vk = Some(connection::get_agent_verkey(connection_handle)?); + self.their_did = Some(connection::get_their_pw_did(connection_handle)?); + self.their_vk = Some(connection::get_their_pw_verkey(connection_handle)?); debug!("verifier_did: {:?} -- verifier_vk: {:?} -- agent_did: {:?} -- agent_vk: {:?} -- remote_vk: {:?}", self.my_did, @@ -402,7 +392,8 @@ impl DisclosedProof { true => DEFAULT_GENERATED_PROOF.to_string(), }; - self.thread.increment_receiver(self.their_did.as_ref().map(String::as_str).unwrap_or("")); + let their_did = self.their_did.as_ref().map(String::as_str).unwrap_or(""); + self.thread.as_mut().map(|thread| thread.increment_receiver(their_did)); messages::send_message() .to(local_my_did)? @@ -410,14 +401,11 @@ impl DisclosedProof { .msg_type(&RemoteMessageType::Proof)? .agent_did(local_agent_did)? .agent_vk(local_agent_vk)? - .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof, Some(self.thread.clone())) + .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof, self.thread.clone()) .or(Err(VcxError::from(VcxErrorKind::GeneralConnectionError)))? .ref_msg_id(ref_msg_uid)? .send_secure() - .map_err(|err| { - warn!("could not send proof: {}", err); - err - })?; + .map_err(|err| err.extend("Could not send proof"))?; self.state = VcxStateType::VcxStateAccepted; return Ok(error::SUCCESS.code_num); @@ -446,7 +434,7 @@ impl DisclosedProof { //******************************************** fn handle_err(err: VcxError) -> VcxError { if err.kind() == VcxErrorKind::InvalidHandle { - VcxError::from(VcxErrorKind::InvalidProofHandle) + VcxError::from(VcxErrorKind::InvalidDisclosedProofHandle) } else { err } @@ -545,16 +533,8 @@ pub fn get_proof_request(connection_handle: u32, msg_id: &str) -> VcxResult VcxResult { + let payload = message.payload.as_ref() + .ok_or(VcxError::from(VcxErrorKind::InvalidHttpResponse))?; + + let (request, thread) = Payloads::decrypt(&my_vk, payload)?; + + let mut request: ProofRequestMessage = serde_json::from_str(&request) + .or(Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)))?; + + request.thread_id = thread.and_then(|tr| tr.thid.clone()); + request.msg_ref_id = Some(message.uid.to_owned()); + + Ok(request) +} + pub fn get_source_id(handle: u32) -> VcxResult { HANDLE_MAP.get(handle, |obj| { Ok(obj.get_source_id().clone()) @@ -647,8 +635,7 @@ mod tests { #[test] fn test_create_fails() { init!("true"); - assert_eq!(create_proof("1", "{}").err(), - Some(ProofError::CommonError(error::INVALID_JSON.code_num))); + assert_eq!(create_proof("1", "{}").unwrap_err().kind(), VcxErrorKind::InvalidJson); } #[test] @@ -688,8 +675,7 @@ mod tests { #[test] fn test_deserialize_fails() { - assert_eq!(from_string("{}").err(), - Some(ProofError::CommonError(error::INVALID_JSON.code_num))); + assert_eq!(from_string("{}").unwrap_err().kind(), VcxErrorKind::InvalidJson); } #[test] @@ -697,7 +683,7 @@ mod tests { init!("true"); let proof: DisclosedProof = Default::default(); - assert_eq!(proof.build_schemas_json(&Vec::new()), Ok("{}".to_string())); + assert_eq!(proof.build_schemas_json(&Vec::new()).unwrap(), "{}".to_string()); let cred1 = CredInfo { requested_attr: "height_1".to_string(), @@ -744,8 +730,7 @@ mod tests { timestamp: None, }]; let proof: DisclosedProof = Default::default(); - assert_eq!(proof.build_schemas_json(&credential_ids).err(), - Some(ProofError::InvalidSchema())); + assert_eq!(proof.build_schemas_json(&credential_ids).unwrap_err().kind(), VcxErrorKind::InvalidSchema); } #[test] @@ -797,8 +782,7 @@ mod tests { timestamp: None, }]; let proof: DisclosedProof = Default::default(); - assert_eq!(proof.build_cred_def_json(&credential_ids).err(), - Some(ProofError::InvalidCredData())); + assert_eq!(proof.build_cred_def_json(&credential_ids).unwrap_err().kind(), VcxErrorKind::InvalidProofCredentialData); } #[test] @@ -951,7 +935,7 @@ mod tests { init!("false"); let proof: DisclosedProof = Default::default(); - assert_eq!(proof.retrieve_credentials(), Err(ProofError::ProofNotReadyError())); + assert_eq!(proof.retrieve_credentials().unwrap_err().kind(), VcxErrorKind::NotReady); } #[test] @@ -1040,12 +1024,12 @@ mod tests { #[test] fn test_credential_def_identifiers_failure() { // selected credentials has incorrect json - assert_eq!(credential_def_identifiers("", &proof_req_no_interval()), Err(ProofError::InvalidJson())); + assert_eq!(credential_def_identifiers("", &proof_req_no_interval()).unwrap_err().kind(), VcxErrorKind::InvalidJson); // No Creds - assert_eq!(credential_def_identifiers("{}", &proof_req_no_interval()), Ok(Vec::new())); - assert_eq!(credential_def_identifiers(r#"{"attrs":{}}"#, &proof_req_no_interval()), Ok(Vec::new())); + assert_eq!(credential_def_identifiers("{}", &proof_req_no_interval()).unwrap(), Vec::new()); + assert_eq!(credential_def_identifiers(r#"{"attrs":{}}"#, &proof_req_no_interval()).unwrap(), Vec::new()); // missing cred info let selected_credentials: Value = json!({ @@ -1056,7 +1040,7 @@ mod tests { } }); - assert_eq!(credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()), Err(ProofError::InvalidCredData())); + assert_eq!(credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()).unwrap_err().kind(), VcxErrorKind::InvalidProofCredentialData); // Optional Revocation let mut selected_credentials: Value = json!({ @@ -1123,11 +1107,11 @@ mod tests { }, "predicates":{ } }); - assert_eq!(credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()), Err(ProofError::InvalidCredData())); + assert_eq!(credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()).unwrap_err().kind(), VcxErrorKind::InvalidProofCredentialData); // Schema Id is null selected_credentials["attrs"]["height_1"]["cred_info"]["schema_id"] = serde_json::Value::Null; - assert_eq!(credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()), Err(ProofError::InvalidCredData())); + assert_eq!(credential_def_identifiers(&selected_credentials.to_string(), &proof_req_no_interval()).unwrap_err().kind(), VcxErrorKind::InvalidProofCredentialData); } #[cfg(feature = "pool_tests")] @@ -1252,7 +1236,7 @@ mod tests { init!("ledger"); // empty vector - assert_eq!(build_rev_states_json(Vec::new().as_mut()), Ok("{}".to_string())); + assert_eq!(build_rev_states_json(Vec::new().as_mut()).unwrap(), "{}".to_string()); // no rev_reg_id let cred1 = CredInfo { @@ -1266,7 +1250,7 @@ mod tests { revocation_interval: None, timestamp: None, }; - assert_eq!(build_rev_states_json(vec![cred1].as_mut()), Ok("{}".to_string())); + assert_eq!(build_rev_states_json(vec![cred1].as_mut()).unwrap(), "{}".to_string()); } #[cfg(feature = "pool_tests")] @@ -1492,17 +1476,17 @@ mod tests { let proof_req: ProofRequestData = serde_json::from_value(proof_req).unwrap(); // Attribute not found in proof req - assert_eq!(_get_revocation_interval("not here", &proof_req), Err(ProofError::InvalidCredData())); + assert_eq!(_get_revocation_interval("not here", &proof_req).unwrap_err().kind(), VcxErrorKind::InvalidProofCredentialData); // attribute interval overrides proof request interval let interval = Some(NonRevokedInterval { from: Some(123), to: Some(456) }); - assert_eq!(_get_revocation_interval("address1_1", &proof_req), Ok(interval)); + assert_eq!(_get_revocation_interval("address1_1", &proof_req).unwrap(), interval); // when attribute interval is None, defaults to proof req interval let interval = Some(NonRevokedInterval { from: Some(098), to: Some(123) }); - assert_eq!(_get_revocation_interval("zip_2", &proof_req), Ok(interval)); + assert_eq!(_get_revocation_interval("zip_2", &proof_req).unwrap(), interval); // No interval provided for attribute or proof req - assert_eq!(_get_revocation_interval("address1_1", &proof_req_no_interval()), Ok(None)); + assert_eq!(_get_revocation_interval("address1_1", &proof_req_no_interval()).unwrap(), None); } } diff --git a/vcx/libvcx/src/error/mod.rs b/vcx/libvcx/src/error/mod.rs index bc68823c11..342c4492f7 100644 --- a/vcx/libvcx/src/error/mod.rs +++ b/vcx/libvcx/src/error/mod.rs @@ -29,6 +29,12 @@ pub enum VcxErrorKind { NotReady, #[fail(display = "IO Error, possibly creating a backup wallet")] IOError, + #[fail(display = "Object (json, config, key, credential and etc...) passed to libindy has invalid structure")] + LibindyInvalidStructure, + #[fail(display = "Waiting for callback timed out")] + TimeoutLibindy, + #[fail(display = "Parameter passed to libindy was invalid")] + InvalidLibindyParam, // Connection #[fail(display = "Cannot create connection")] @@ -87,6 +93,8 @@ pub enum VcxErrorKind { // Proof #[fail(display = "Invalid proof handle")] InvalidProofHandle, + #[fail(display = "Invalid disclosed proof handle")] + InvalidDisclosedProofHandle, #[fail(display = "Proof had invalid format")] InvalidProof, #[fail(display = "Schema was invalid or corrupt")] @@ -186,6 +194,8 @@ pub enum VcxErrorKind { Common(u32), #[fail(display = "Liibndy error {}", 0)] LiibndyError(u32), + #[fail(display = "Unknown libindy error")] + UnknownLiibndyError, } #[derive(Debug)] @@ -282,6 +292,9 @@ impl From for ErrorCode { VcxErrorKind::InvalidRevocationDetails => error::INVALID_REVOCATION_DETAILS.code_num, VcxErrorKind::GeneralConnectionError => error::CONNECTION_ERROR.code_num, VcxErrorKind::IOError => error::IOERROR.code_num, + VcxErrorKind::LibindyInvalidStructure => error::LIBINDY_INVALID_STRUCTURE.code_num, + VcxErrorKind::TimeoutLibindy => error::TIMEOUT_LIBINDY_ERROR.code_num, + VcxErrorKind::InvalidLibindyParam => error::INVALID_LIBINDY_PARAM.code_num, VcxErrorKind::CreateConnection => error::CREATE_CONNECTION_ERROR.code_num, VcxErrorKind::InvalidConnectionHandle => error::INVALID_CONNECTION_HANDLE.code_num, VcxErrorKind::InvalidInviteDetail => error::INVALID_INVITE_DETAILS.code_num, @@ -298,6 +311,7 @@ impl From for ErrorCode { VcxErrorKind::InvalidCredential => error::INVALID_CREDENTIAL_JSON.code_num, VcxErrorKind::InsufficientTokenAmount => error::INSUFFICIENT_TOKEN_AMOUNT.code_num, VcxErrorKind::InvalidProofHandle => error::INVALID_PROOF_HANDLE.code_num, + VcxErrorKind::InvalidDisclosedProofHandle => error::INVALID_DISCLOSED_PROOF_HANDLE.code_num, VcxErrorKind::InvalidProof => error::INVALID_PROOF.code_num, VcxErrorKind::InvalidSchema => error::INVALID_SCHEMA.code_num, VcxErrorKind::InvalidProofCredentialData => error::INVALID_PROOF_CREDENTIAL_DATA.code_num, @@ -342,6 +356,7 @@ impl From for ErrorCode { VcxErrorKind::InvalidMessages => error::INVALID_MESSAGES.code_num, VcxErrorKind::MissingExportedWalletPath => error::MISSING_EXPORTED_WALLET_PATH.code_num, VcxErrorKind::MissingBackupKey => error::MISSING_BACKUP_KEY.code_num, + VcxErrorKind::UnknownLiibndyError => error::UNKNOWN_LIBINDY_ERROR.code_num, VcxErrorKind::Common(num) => num, VcxErrorKind::LiibndyError(num) => num, } diff --git a/vcx/libvcx/src/issuer_credential.rs b/vcx/libvcx/src/issuer_credential.rs index 47710a5dc0..ed77dd2ef8 100644 --- a/vcx/libvcx/src/issuer_credential.rs +++ b/vcx/libvcx/src/issuer_credential.rs @@ -1,3 +1,5 @@ +use serde_json; + use std::collections::HashMap; use api::VcxStateType; use messages; @@ -7,12 +9,10 @@ use messages::payload::{Payloads, PayloadKinds, Thread}; use connection; use credential_request::CredentialRequest; use utils::error; -use utils::libindy::payments; -use utils::libindy::anoncreds; -use utils::constants::CRED_MSG; +use utils::libindy::{payments, anoncreds}; +use utils::constants::{CRED_MSG, DEFAULT_SERIALIZE_VERSION}; use utils::openssl::encode; use utils::libindy::payments::PaymentTxn; -use utils::constants::DEFAULT_SERIALIZE_VERSION; use object_cache::ObjectCache; use error::prelude::*; @@ -59,7 +59,7 @@ pub struct IssuerCredential { remote_did: String, //their_pw_did for this relationship remote_vk: String, - thread: Thread + thread: Option } #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] @@ -114,7 +114,7 @@ impl PaymentInfo { } pub fn to_string(&self) -> VcxResult { - ::serde_json::to_string(&self) + serde_json::to_string(&self) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize payment info"))) } } @@ -162,7 +162,7 @@ impl IssuerCredential { payload.push(cred_json); - let payload = ::serde_json::to_string(&payload) + let payload = serde_json::to_string(&payload) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize payload: {}", err)))?; debug!("credential offer data: {}", payload); @@ -172,17 +172,14 @@ impl IssuerCredential { .to(&self.issued_did)? .to_vk(&self.issued_vk)? .msg_type(&RemoteMessageType::CredOffer)? - .edge_agent_payload(&self.issued_vk, &self.remote_vk, &payload, PayloadKinds::CredOffer, Some(self.thread.clone()))? + .edge_agent_payload(&self.issued_vk, &self.remote_vk, &payload, PayloadKinds::CredOffer, self.thread.clone())? .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? .set_title(&title)? .set_detail(&title)? .status_code(&MessageStatusCode::Accepted)? .send_secure() - .map_err(|err| { - warn!("could not send credentialOffer: {}", err); - err - })?; + .map_err(|err| err.extend("could not send credential offer"))?; self.msg_uid = response.get_msg_uid()?; self.state = VcxStateType::VcxStateOfferSent; @@ -215,7 +212,7 @@ impl IssuerCredential { CRED_MSG.to_string() } else { let cred = self.generate_credential(&attrs_with_encodings, &to)?; - ::serde_json::to_string(&cred).or(Err(VcxError::from(VcxErrorKind::InvalidCredential)))? + serde_json::to_string(&cred).or(Err(VcxError::from(VcxErrorKind::InvalidCredential)))? }; debug!("credential data: {}", data); @@ -225,22 +222,19 @@ impl IssuerCredential { .and_then(|cred_req| cred_req.msg_ref_id.as_ref()) .ok_or(VcxError::from(VcxErrorKind::InvalidCredentialRequest))?; - self.thread.sender_order += 1; + self.thread.as_mut().map(|thread| thread.sender_order += 1); let response = messages::send_message() .to(&self.issued_did)? .to_vk(&self.issued_vk)? .msg_type(&RemoteMessageType::Cred)? .status_code(&MessageStatusCode::Accepted)? - .edge_agent_payload(&self.issued_vk, &self.remote_vk, &data, PayloadKinds::Cred, Some(self.thread.clone()))? + .edge_agent_payload(&self.issued_vk, &self.remote_vk, &data, PayloadKinds::Cred, self.thread.clone())? .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? .ref_msg_id(cred_req_msg_id)? .send_secure() - .map_err(|err| { - warn!("could not send credential: {}", err); - err - })?; + .map_err(|err| err.extend("could not send credential offer"))?; self.msg_uid = response.get_msg_uid()?; self.state = VcxStateType::VcxStateAccepted; @@ -272,13 +266,14 @@ impl IssuerCredential { let (payload, thread) = Payloads::decrypt(&self.issued_vk, &payload) .map_err(|err| VcxError::from_msg(VcxErrorKind::Common(err.into()), "Cannot decrypt CredentialOffer payload"))?; - let mut cred_req: CredentialRequest = ::serde_json::from_str(&payload) + let mut cred_req: CredentialRequest = serde_json::from_str(&payload) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize CredentialRequest: {}", err)))?; cred_req.msg_ref_id = Some(offer_uid); if let Some(tr) = thread { - self.thread.increment_receiver(self.remote_did.as_str()); + let remote_did = self.remote_did.as_str(); + self.thread.as_mut().map(|thread| thread.increment_receiver(remote_did)); } self.credential_request = Some(cred_req); @@ -401,12 +396,12 @@ impl IssuerCredential { Ok(()) } - fn get_payment_txn(&self) -> VcxResult { + fn get_payment_txn(&self) -> VcxResult { trace!("IssuerCredential::get_payment_txn >>>"); match self.payment_address { Some(ref payment_address) if self.price > 0 => { - Ok(payments::PaymentTxn { + Ok(PaymentTxn { amount: self.price, credit: true, inputs: vec![payment_address.to_string()], @@ -451,7 +446,7 @@ impl IssuerCredential { */ pub fn encode_attributes(attributes: &str) -> VcxResult { - let mut attributes: HashMap = ::serde_json::from_str(attributes) + let mut attributes: HashMap = serde_json::from_str(attributes) .map_err(|err| { warn!("Invalid Json for Attribute data"); VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize credential attributes: {}", err)) @@ -463,7 +458,7 @@ pub fn encode_attributes(attributes: &str) -> VcxResult { let first_attr: &str = match attr_data { // old style input such as {"address2":["101 Wilson Lane"]} serde_json::Value::Array(array_type) => { - let attrib_value: &str = match array_type.get(0).and_then(::serde_json::Value::as_str) { + let attrib_value: &str = match array_type.get(0).and_then(serde_json::Value::as_str) { Some(x) => x, None => { warn!("Cannot encode attribute: {}", error::INVALID_ATTRIBUTES_STRUCTURE.message); @@ -476,7 +471,7 @@ pub fn encode_attributes(attributes: &str) -> VcxResult { } // new style input such as {"address2":"101 Wilson Lane"} - ::serde_json::Value::String(str_type) => str_type, + serde_json::Value::String(str_type) => str_type, // anything else is an error _ => { warn!("Invalid Json for Attribute data"); @@ -493,7 +488,7 @@ pub fn encode_attributes(attributes: &str) -> VcxResult { dictionary.insert(attr, attrib_values); } - ::serde_json::to_string_pretty(&dictionary) + serde_json::to_string_pretty(&dictionary) .map_err(|err| { warn!("Invalid Json for Attribute data"); VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Invalid Json for Attribute data: {}", err)) @@ -512,7 +507,7 @@ pub fn get_offer_uid(handle: u32) -> VcxResult { }) } -pub fn get_payment_txn(handle: u32) -> VcxResult { +pub fn get_payment_txn(handle: u32) -> VcxResult { ISSUER_CREDENTIAL_MAP.get(handle, |i| { i.get_payment_txn() }) @@ -560,7 +555,7 @@ pub fn issuer_credential_create(cred_def_handle: u32, agent_vk: String::new(), cred_def_id, cred_def_handle, - thread: Thread::new(), + thread: Some(Thread::new()), }; new_issuer_credential.validate_credential_offer()?; @@ -631,7 +626,7 @@ pub fn revoke_credential(handle: u32) -> VcxResult<()> { } pub fn convert_to_map(s: &str) -> VcxResult> { - ::serde_json::from_str(s) + serde_json::from_str(s) .map_err(|err| { warn!("{}", error::INVALID_ATTRIBUTES_STRUCTURE.message); VcxError::from_msg(VcxErrorKind::InvalidAttributesStructure, error::INVALID_ATTRIBUTES_STRUCTURE.message) @@ -653,6 +648,7 @@ pub fn get_source_id(handle: u32) -> VcxResult { #[cfg(test)] pub mod tests { use super::*; + use serde_json::Value; use settings; use connection::tests::build_test_connection; use credential_request::CredentialRequest; @@ -665,7 +661,6 @@ pub mod tests { wallet::get_wallet_handle, wallet}, get_temp_dir_path, }; - use error::{issuer_cred::IssuerCredError}; static DEFAULT_CREDENTIAL_NAME: &str = "Credential"; static DEFAULT_CREDENTIAL_ID: &str = "defaultCredentialId"; @@ -729,12 +724,7 @@ pub mod tests { agent_vk: VERKEY.to_string(), cred_def_id: CRED_DEF_ID.to_string(), cred_def_handle: 0, - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }; issuer_credential } @@ -790,12 +780,7 @@ pub mod tests { agent_vk: String::new(), cred_def_id, cred_def_handle, - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }; let payment = issuer_credential.generate_payment_info().unwrap(); @@ -903,8 +888,7 @@ pub mod tests { let connection_handle = build_test_connection(); set_libindy_rc(error::TIMEOUT_LIBINDY_ERROR.code_num); - assert_eq!(credential.send_credential(connection_handle), - Err(IssuerCredError::CommonError(error::TIMEOUT_LIBINDY_ERROR.code_num))); + assert_eq!(credential.send_credential(connection_handle).unwrap_err().kind(), VcxErrorKind::Common(1038)); assert_eq!(credential.msg_uid, "1234"); assert_eq!(credential.state, VcxStateType::VcxStateRequestReceived); // Retry sending the credential, use the mocked http. Show that you can retry sending the credential @@ -965,12 +949,7 @@ pub mod tests { remote_vk: VERKEY.to_string(), agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }; ::utils::httpclient::set_next_u8_response(CREDENTIAL_REQ_RESPONSE.to_vec()); @@ -1016,7 +995,7 @@ pub mod tests { error!("basic_add_attribute_encoding test should raise error."); assert_ne!(1, 1); } - Err(e) => assert_eq!(e, IssuerCredError::CommonError(error::INVALID_JSON.code_num)), + Err(e) => assert_eq!(e.kind(), VcxErrorKind::InvalidJson) } } @@ -1041,19 +1020,19 @@ pub mod tests { let h4 = issuer_credential_create(::credential_def::tests::create_cred_def_fake(), "1".to_string(), "8XFh8yBzrpJQmNyZzgoTqB".to_owned(), "credential_name".to_string(), "{\"attr\":\"value\"}".to_owned(), 1).unwrap(); let h5 = issuer_credential_create(::credential_def::tests::create_cred_def_fake(), "1".to_string(), "8XFh8yBzrpJQmNyZzgoTqB".to_owned(), "credential_name".to_string(), "{\"attr\":\"value\"}".to_owned(), 1).unwrap(); release_all(); - assert_eq!(release(h1), Err(IssuerCredError::InvalidHandle())); - assert_eq!(release(h2), Err(IssuerCredError::InvalidHandle())); - assert_eq!(release(h3), Err(IssuerCredError::InvalidHandle())); - assert_eq!(release(h4), Err(IssuerCredError::InvalidHandle())); - assert_eq!(release(h5), Err(IssuerCredError::InvalidHandle())); + assert_eq!(release(h1).unwrap_err().kind(), VcxErrorKind::InvalidIssuerCredentialHandle); + assert_eq!(release(h2).unwrap_err().kind(), VcxErrorKind::InvalidIssuerCredentialHandle); + assert_eq!(release(h3).unwrap_err().kind(), VcxErrorKind::InvalidIssuerCredentialHandle); + assert_eq!(release(h4).unwrap_err().kind(), VcxErrorKind::InvalidIssuerCredentialHandle); + assert_eq!(release(h5).unwrap_err().kind(), VcxErrorKind::InvalidIssuerCredentialHandle); } #[test] fn test_errors() { init!("false"); let invalid_handle = 478620; - assert_eq!(to_string(invalid_handle).err(), Some(IssuerCredError::CommonError(error::INVALID_OBJ_HANDLE.code_num))); - assert_eq!(release(invalid_handle).err(), Some(IssuerCredError::InvalidHandle())); + assert_eq!(to_string(invalid_handle).unwrap_err().kind(), VcxErrorKind::InvalidHandle); + assert_eq!(release(invalid_handle).unwrap_err().kind(), VcxErrorKind::InvalidIssuerCredentialHandle); } #[test] @@ -1097,11 +1076,11 @@ pub mod tests { // Err - Wrong payment amount credential.price = 200; - assert_eq!(credential.verify_payment(), Err(error::INSUFFICIENT_TOKEN_AMOUNT.code_num)); + assert_eq!(credential.verify_payment().unwrap_err().kind(), VcxErrorKind::InsufficientTokenAmount); // Err - address not set credential.payment_address = None; - assert_eq!(credential.verify_payment(), Err(error::INVALID_PAYMENT_ADDRESS.code_num)); + assert_eq!(credential.verify_payment().unwrap_err().kind(), VcxErrorKind::InvalidPaymentAddress); } #[test] @@ -1135,15 +1114,15 @@ pub mod tests { credential.tails_file = Some(get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap().to_string()); credential.cred_rev_id = None; credential.rev_reg_id = None; - assert_eq!(credential.revoke_cred(), Err(IssuerCredError::InvalidRevocationInfo())); + assert_eq!(credential.revoke_cred().unwrap_err().kind(), VcxErrorKind::InvalidRevocationDetails); credential.tails_file = None; credential.cred_rev_id = Some(CRED_REV_ID.to_string()); credential.rev_reg_id = None; - assert_eq!(credential.revoke_cred(), Err(IssuerCredError::InvalidRevocationInfo())); + assert_eq!(credential.revoke_cred().unwrap_err().kind(), VcxErrorKind::InvalidRevocationDetails); credential.tails_file = None; credential.cred_rev_id = None; credential.rev_reg_id = Some(REV_REG_ID.to_string()); - assert_eq!(credential.revoke_cred(), Err(IssuerCredError::InvalidRevocationInfo())); + assert_eq!(credential.revoke_cred().unwrap_err().kind(), VcxErrorKind::InvalidRevocationDetails); credential.tails_file = Some(get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap().to_string()); credential.cred_rev_id = Some(CRED_REV_ID.to_string()); diff --git a/vcx/libvcx/src/lib.rs b/vcx/libvcx/src/lib.rs index 491d842e84..beec8db679 100644 --- a/vcx/libvcx/src/lib.rs +++ b/vcx/libvcx/src/lib.rs @@ -33,6 +33,8 @@ extern crate uuid; extern crate failure; +extern crate rmp_serde; + #[macro_use] pub mod utils; pub mod settings; diff --git a/vcx/libvcx/src/messages/agent_utils.rs b/vcx/libvcx/src/messages/agent_utils.rs index b0a86c1728..d0e998298f 100644 --- a/vcx/libvcx/src/messages/agent_utils.rs +++ b/vcx/libvcx/src/messages/agent_utils.rs @@ -1,7 +1,7 @@ use settings; -use utils::constants::*; use messages::{A2AMessage, A2AMessageV1, A2AMessageV2, A2AMessageKinds, prepare_message_for_agency, parse_response_from_agency}; use messages::message_type::MessageTypes; +use utils::constants::*; use utils::{error, httpclient}; use utils::libindy::{wallet, anoncreds}; use utils::libindy::signus::create_and_store_my_did; @@ -426,9 +426,6 @@ mod tests { settings::set_defaults(); settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE, "true"); - match update_agent_info("123", "value") { - Ok(_) => assert_eq!(0, 0), - Err(x) => assert_eq!(x, 0), // should fail here - }; + update_agent_info("123", "value").unwrap(); } } diff --git a/vcx/libvcx/src/messages/create_key.rs b/vcx/libvcx/src/messages/create_key.rs index cae42c0f99..655df183d6 100644 --- a/vcx/libvcx/src/messages/create_key.rs +++ b/vcx/libvcx/src/messages/create_key.rs @@ -161,7 +161,7 @@ mod tests { fn test_create_key_set_invalid_did_errors() { let for_did = "11235yBzrpJQmNyZzgoT"; let res = create_keys().for_did(for_did).unwrap_err(); - assert_eq!(res, error::INVALID_DID.code_num); + assert_eq!(res.kind(), VcxErrorKind::InvalidDid); } } diff --git a/vcx/libvcx/src/messages/get_message.rs b/vcx/libvcx/src/messages/get_message.rs index 10c3db8d4c..e1d4021caa 100644 --- a/vcx/libvcx/src/messages/get_message.rs +++ b/vcx/libvcx/src/messages/get_message.rs @@ -470,7 +470,7 @@ mod tests { // Agency returns a bad request response for invalid dids let invalid_did = "abc".to_string(); let bad_req = download_messages(Some(vec![invalid_did]), None, None); - assert_eq!(bad_req, Err(error::POST_MSG_FAILURE.code_num)); + assert_eq!(bad_req.unwrap_err().kind(), VcxErrorKind::PostMessageFailed); teardown!("agency"); } } diff --git a/vcx/libvcx/src/messages/invite.rs b/vcx/libvcx/src/messages/invite.rs index 1e9722610d..b7d7226fd8 100644 --- a/vcx/libvcx/src/messages/invite.rs +++ b/vcx/libvcx/src/messages/invite.rs @@ -516,13 +516,6 @@ pub struct AcceptanceDetails { pub sender_detail: SenderDetail, } -pub fn parse_invitation_acceptance_details(payload: Vec) -> VcxResult { - debug!("parsing invitation acceptance details: {:?}", payload); - let response: AcceptanceDetails = rmp_serde::from_slice(&payload[..]) - .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot deserialize AcceptanceDetails: {}", err)))?; - Ok(response.sender_detail) -} - #[cfg(test)] mod tests { use super::*; @@ -562,12 +555,4 @@ mod tests { assert_eq!(result, invite); assert_eq!(url, "http://localhost:9001/agency/invite/WRUzXXuFVTYkT8CjSZpFvT?uid=NjcwOWU"); } - - #[test] - fn test_parse_invitation_acceptance_details() { - let payload = vec![129, 172, 115, 101, 110, 100, 101, 114, 68, 101, 116, 97, 105, 108, 131, 163, 68, 73, 68, 182, 67, 113, 85, 88, 113, 53, 114, 76, 105, 117, 82, 111, 100, 55, 68, 67, 52, 97, 86, 84, 97, 115, 166, 118, 101, 114, 75, 101, 121, 217, 44, 67, 70, 86, 87, 122, 118, 97, 103, 113, 65, 99, 117, 50, 115, 114, 68, 106, 117, 106, 85, 113, 74, 102, 111, 72, 65, 80, 74, 66, 111, 65, 99, 70, 78, 117, 49, 55, 113, 117, 67, 66, 57, 118, 71, 176, 97, 103, 101, 110, 116, 75, 101, 121, 68, 108, 103, 80, 114, 111, 111, 102, 131, 168, 97, 103, 101, 110, 116, 68, 73, 68, 182, 57, 54, 106, 111, 119, 113, 111, 84, 68, 68, 104, 87, 102, 81, 100, 105, 72, 49, 117, 83, 109, 77, 177, 97, 103, 101, 110, 116, 68, 101, 108, 101, 103, 97, 116, 101, 100, 75, 101, 121, 217, 44, 66, 105, 118, 78, 52, 116, 114, 53, 78, 88, 107, 69, 103, 119, 66, 56, 81, 115, 66, 51, 109, 109, 109, 122, 118, 53, 102, 119, 122, 54, 85, 121, 53, 121, 112, 122, 90, 77, 102, 115, 74, 56, 68, 122, 169, 115, 105, 103, 110, 97, 116, 117, 114, 101, 217, 88, 77, 100, 115, 99, 66, 85, 47, 99, 89, 75, 72, 49, 113, 69, 82, 66, 56, 80, 74, 65, 43, 48, 51, 112, 121, 65, 80, 65, 102, 84, 113, 73, 80, 74, 102, 52, 84, 120, 102, 83, 98, 115, 110, 81, 86, 66, 68, 84, 115, 67, 100, 119, 122, 75, 114, 52, 54, 120, 87, 116, 80, 43, 78, 65, 68, 73, 57, 88, 68, 71, 55, 50, 50, 103, 113, 86, 80, 77, 104, 117, 76, 90, 103, 89, 67, 103, 61, 61]; - println!("payload: {:?}", payload); - let response = parse_invitation_acceptance_details(payload).unwrap(); - println!("response: {:?}", response); - } } diff --git a/vcx/libvcx/src/messages/payload.rs b/vcx/libvcx/src/messages/payload.rs index 4555e9d2e6..4975351096 100644 --- a/vcx/libvcx/src/messages/payload.rs +++ b/vcx/libvcx/src/messages/payload.rs @@ -85,10 +85,7 @@ impl Payloads { let (_, data) = crypto::parse_msg(&my_vk, &to_u8(payload))?; let my_payload: PayloadV1 = rmp_serde::from_slice(&data[..]) - .map_err(|err| { - error!("could not deserialize bundle with i8 or u8: {}", err); - VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot decrypt payload: {}", err)) - })?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot decrypt payload: {}", err)))?; Ok((my_payload.msg, None)) } ProtocolTypes::V2 => { diff --git a/vcx/libvcx/src/messages/proofs/proof_message.rs b/vcx/libvcx/src/messages/proofs/proof_message.rs index 09bfa6a8c1..07e0707826 100644 --- a/vcx/libvcx/src/messages/proofs/proof_message.rs +++ b/vcx/libvcx/src/messages/proofs/proof_message.rs @@ -1,14 +1,7 @@ -extern crate serde_json; - +use serde_json; use serde_json::Value; use error::prelude::*; -static ISSUER_DID: &'static str = "issuer_did"; -static SEQUENCE_NUMBER: &'static str = "schema_seq_no"; -static PROVER_DID: &'static str = "prover_did"; -static MSG_FROM_API: &str = r#"{"proofs":{"claim::71b6070f-14ba-45fa-876d-1fe8491fe5d4":{"proof":{"primary_proof":{"eq_proof":{"revealed_attrs":{"sex":"5944657099558967239210949258394887428692050081607692519917050011144233115103","name":"1139481716457488690172217916278103335"},"a_prime":"55115757663642844902979276276581544287881791112969892277372135316353511833640150801244335663890109536491278379177551666081054765286807563008348637104046950934828407012194403360724040287698135607556244297972578864339500981366412262454282194811242239615009347165118318516694216754501345324782597475927199400880006212632553233049354866295429520527445980181939247828351677971991914388778860092824318440481574181300185829423762990910739241691289976584754979812272223819007422499654272590946235912914032826994670588466080422906806402660885408376207875827950805200378568062518210110828954480363081643567615791016011737856977","e":"34976147138641338975844073241645969211530343885520088294714132974884138611036204288689212378023649179372520412699253155486970203797562324","v":"961473607552945346906354315658276499450491951690969023699851664262072769313929148332129868528140265952852653009499943891795293148107502144091334703992581737220352761140064276811372868396353572957613845323343723271098601244774874235526135299483412285009916812621185291842845156342501611029106982811773616231232684804116984093651972537804480090649736612551759833591251845595059217608938213987633789344584340351801507541774726753840600143685051258161251666953243698589585559347435011414292427590918153421953579895479604685390401357681887618798200391305919594609949167659780330698000168295871428737686822637913218269005987492318466661186509308179489615192663542904993253626728197630057096161118638090776180812895097232529119979970798938360220605280817954648588493778338816318524451785027916181454650102696493927306340658666852294316562458212054696739343800993703515542777264448535624584845146378512183572107830260813929222999","m":{},"m1":"75548120024969192086664289521241751069844239013520403238642886571169851979005373784309432586593371476370934469326730539754613694936161784687213609047455188306625204249706249661640538349287762196100659095340756990269587317065862046598569445591945049204366911309949910119711238973099702616527117177036784698661","m2":"287944186286321709724396773443214682376883853676549188669693055373059354657799325692443906346632814001611911026063358134413175852024773765930829079850890920811398176944587192618"},"ge_proofs":[]},"non_revoc_proof":null},"schema_seq_no":103,"issuer_did":"V4SGRU86Z58d6TV7PBUe6f"}},"aggregated_proof":{"c_hash":"63330487197040957750863022608534150304998351350639315143102570772502292901825","c_list":[[1,180,153,212,162,132,5,189,14,181,140,112,236,109,182,76,91,6,161,215,62,207,205,135,86,211,49,197,215,198,104,201,14,22,48,6,112,170,31,191,110,118,121,15,62,114,126,249,221,107,114,161,163,234,19,233,150,236,182,217,195,6,218,217,193,6,94,160,33,23,103,147,109,221,81,38,138,20,225,141,68,37,142,10,225,79,164,119,168,250,188,186,47,229,165,8,237,230,14,35,53,176,97,28,82,105,87,210,117,16,154,222,66,11,96,172,90,13,239,190,29,71,11,88,53,36,219,139,67,21,136,58,161,164,97,106,56,230,55,157,59,35,187,235,154,194,111,93,168,135,67,15,97,136,38,169,87,142,32,255,50,247,111,83,44,88,251,99,6,226,182,170,146,229,118,164,118,228,235,51,137,168,135,50,1,14,1,201,72,175,102,241,149,117,88,83,84,37,205,130,26,155,124,158,211,89,112,33,46,24,94,93,202,8,127,172,214,178,6,156,79,188,132,223,239,127,200,158,95,247,139,101,51,162,168,175,74,1,67,201,94,108,192,14,130,109,217,248,193,10,142,37,95,231,227,251,209]]},"requested_proof":{"revealed_attrs":{"attr2_uuid":["claim::71b6070f-14ba-45fa-876d-1fe8491fe5d4","male","5944657099558967239210949258394887428692050081607692519917050011144233115103"],"attr1_uuid":["claim::71b6070f-14ba-45fa-876d-1fe8491fe5d4","Alex","1139481716457488690172217916278103335"]},"unrevealed_attrs":{},"self_attested_attrs":{},"predicates":{}},"remoteDid":"KP8AaEBc368CMK1PqZaEzX","userPairwiseDid":"PofTCeegEXT7S2aAePhM6a"}"#; - - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub struct ProofMessage { version: Option, @@ -114,22 +107,22 @@ pub mod tests { init!("true"); let mut proof = ProofMessage::new(); proof.libindy_proof = "".to_string(); - assert_eq!(proof.get_credential_info(), Err(ProofError::InvalidJson())); + assert_eq!(proof.get_credential_info().unwrap_err().kind(), VcxErrorKind::InvalidJson); proof.libindy_proof = "{}".to_string(); - assert_eq!(proof.get_credential_info(), Ok(Vec::new())); + assert_eq!(proof.get_credential_info().unwrap(), Vec::new()); proof.libindy_proof = json!({"identifiers": []}).to_string(); - assert_eq!(proof.get_credential_info(), Ok(Vec::new())); + assert_eq!(proof.get_credential_info().unwrap(), Vec::new()); proof.libindy_proof = json!({"identifiers": [{}]}).to_string(); - assert_eq!(proof.get_credential_info(), Err(ProofError::InvalidCredData())); + assert_eq!(proof.get_credential_info().unwrap_err().kind(), VcxErrorKind::InvalidProofCredentialData); proof.libindy_proof = json!({"identifiers": [{ "schema_id": null, "cred_def_id": null, }]}).to_string(); - assert_eq!(proof.get_credential_info(), Err(ProofError::InvalidCredData())); + assert_eq!(proof.get_credential_info().unwrap_err().kind(), VcxErrorKind::InvalidProofCredentialData); proof.libindy_proof = json!({"identifiers": [{ "schema_id": SCHEMA_ID, diff --git a/vcx/libvcx/src/messages/proofs/proof_request.rs b/vcx/libvcx/src/messages/proofs/proof_request.rs index df4deea51c..9ab6299140 100644 --- a/vcx/libvcx/src/messages/proofs/proof_request.rs +++ b/vcx/libvcx/src/messages/proofs/proof_request.rs @@ -1,15 +1,13 @@ -extern crate rust_base58; -extern crate serde_json; +use serde_json; use std::collections::HashMap; use std::vec::Vec; + use messages::validation; use error::prelude::*; static PROOF_REQUEST: &str = "PROOF_REQUEST"; static PROOF_DATA: &str = "proof_request_data"; -static REQUESTED_ATTRS: &str = "requested_attributes"; -static REQUESTED_PREDICATES: &str = "requested_predicates"; #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, PartialOrd)] struct ProofType { @@ -257,16 +255,16 @@ mod tests { let mid = 98; let mut request = proof_request() - .type_version(version) - .tid(tid) - .mid(mid) - .nonce(nonce) - .proof_name(data_name) - .proof_data_version(data_version) - .requested_attrs(REQUESTED_ATTRS) - .requested_predicates(REQUESTED_PREDICATES) - .to_timestamp(Some(100)) - .from_timestamp(Some(1)) + .type_version(version).unwrap() + .tid(tid).unwrap() + .mid(mid).unwrap() + .nonce(nonce).unwrap() + .proof_name(data_name).unwrap() + .proof_data_version(data_version).unwrap() + .requested_attrs(REQUESTED_ATTRS).unwrap() + .requested_predicates(REQUESTED_PREDICATES).unwrap() + .to_timestamp(Some(100)).unwrap() + .from_timestamp(Some(1)).unwrap() .clone(); let serialized_msg = request.serialize_message().unwrap(); @@ -288,7 +286,7 @@ mod tests { check_req_attrs.insert("age".to_string(), attr_info1); check_req_attrs.insert("name".to_string(), attr_info2); - let request = proof_request().requested_attrs(REQUESTED_ATTRS).clone(); + let request = proof_request().requested_attrs(REQUESTED_ATTRS).unwrap().clone(); assert_eq!(request.proof_request_data.requested_attributes, check_req_attrs); } @@ -298,7 +296,7 @@ mod tests { let attr_info1: PredicateInfo = serde_json::from_str(r#"{ "name":"age","p_type":"GE","p_value":22, "restrictions":[ { "schema_id": "6XFh8yBzrpJQmNyZzgoTqB:2:schema_name:0.0.11", "schema_name":"Faber Student Info", "schema_version":"1.0", "schema_issuer_did":"6XFh8yBzrpJQmNyZzgoTqB", "issuer_did":"8XFh8yBzrpJQmNyZzgoTqB", "cred_def_id": "8XFh8yBzrpJQmNyZzgoTqB:3:CL:1766" }, { "schema_id": "5XFh8yBzrpJQmNyZzgoTqB:2:schema_name:0.0.11", "schema_name":"BYU Student Info", "schema_version":"1.0", "schema_issuer_did":"5XFh8yBzrpJQmNyZzgoTqB", "issuer_did":"66Fh8yBzrpJQmNyZzgoTqB", "cred_def_id": "66Fh8yBzrpJQmNyZzgoTqB:3:CL:1766" } ] }"#).unwrap(); check_predicates.insert("age".to_string(), attr_info1); - let request = proof_request().requested_predicates(REQUESTED_PREDICATES).clone(); + let request = proof_request().requested_predicates(REQUESTED_PREDICATES).unwrap().clone(); assert_eq!(request.proof_request_data.requested_predicates, check_predicates); } diff --git a/vcx/libvcx/src/messages/send_message.rs b/vcx/libvcx/src/messages/send_message.rs index d34f0c565a..c5b203cd04 100644 --- a/vcx/libvcx/src/messages/send_message.rs +++ b/vcx/libvcx/src/messages/send_message.rs @@ -280,7 +280,7 @@ mod tests { }; let uid = response.get_msg_uid().unwrap_err(); - assert_eq!(error::INVALID_JSON.code_num, uid); + assert_eq!(VcxErrorKind::InvalidJson, uid.kind()); } #[cfg(feature = "agency")] @@ -308,7 +308,7 @@ mod tests { match send_generic_message(handle, "this is the message", "type", "title") { Ok(x) => panic!("test shoudl fail: {}", x), - Err(x) => assert_eq!(x, error::NOT_READY.code_num), + Err(x) => assert_eq!(x.kind(), VcxErrorKind::NotReady), }; } } diff --git a/vcx/libvcx/src/messages/validation.rs b/vcx/libvcx/src/messages/validation.rs index 157535e0ad..1dbbae808b 100644 --- a/vcx/libvcx/src/messages/validation.rs +++ b/vcx/libvcx/src/messages/validation.rs @@ -68,7 +68,7 @@ mod tests { fn test_did_is_b58_but_invalid_length() { let to_did = "8XFh8yBzrpJQmNyZzgoT"; match validate_did(&to_did) { - Err(x) => assert_eq!(x, error::INVALID_DID.code_num), + Err(x) => assert_eq!(x.kind(), VcxErrorKind::InvalidDid), Ok(x) => panic!("Should be invalid did"), } } @@ -77,7 +77,7 @@ mod tests { fn test_validate_did_with_non_base58() { let to_did = "8*Fh8yBzrpJQmNyZzgoTqB"; match validate_did(&to_did) { - Err(x) => assert_eq!(x, error::NOT_BASE58.code_num), + Err(x) => assert_eq!(x.kind(), VcxErrorKind::NotBase58), Ok(x) => panic!("Should be invalid did"), } } @@ -95,7 +95,7 @@ mod tests { fn test_verkey_is_b58_but_invalid_length() { let verkey = "8XFh8yBzrpJQmNyZzgoT"; match validate_verkey(&verkey) { - Err(x) => assert_eq!(x, error::INVALID_VERKEY.code_num), + Err(x) => assert_eq!(x.kind(), VcxErrorKind::InvalidVerkey), Ok(x) => panic!("Should be invalid verkey"), } } @@ -104,7 +104,7 @@ mod tests { fn test_validate_verkey_with_non_base58() { let verkey = "*kVTa7SCJ5SntpYyX7CSb2pcBhiVGT9kWSagA8a9T69A"; match validate_verkey(&verkey) { - Err(x) => assert_eq!(x, error::NOT_BASE58.code_num), + Err(x) => assert_eq!(x.kind(), VcxErrorKind::NotBase58), Ok(x) => panic!("Should be invalid verkey"), } } diff --git a/vcx/libvcx/src/object_cache/mod.rs b/vcx/libvcx/src/object_cache/mod.rs index 5332b8059e..41f83171f6 100644 --- a/vcx/libvcx/src/object_cache/mod.rs +++ b/vcx/libvcx/src/object_cache/mod.rs @@ -1,5 +1,3 @@ -extern crate rand; - use rand::Rng; use std::sync::Mutex; use std::sync::MutexGuard; diff --git a/vcx/libvcx/src/proof.rs b/vcx/libvcx/src/proof.rs index dc1f09ffe8..c925922892 100644 --- a/vcx/libvcx/src/proof.rs +++ b/vcx/libvcx/src/proof.rs @@ -1,24 +1,19 @@ -extern crate rand; -extern crate serde_json; -extern crate libc; -extern crate openssl; +use serde_json; +use serde_json::Value; +use openssl; +use openssl::bn::{BigNum, BigNumRef}; -use self::openssl::bn::{BigNum, BigNumRef}; use settings; use connection; use api::{VcxStateType, ProofStateType}; -use messages::proofs::proof_message::{ProofMessage, CredInfo}; use messages; -use messages::RemoteMessageType; -use messages::ObjectWithVersion; +use messages::proofs::proof_message::{ProofMessage, CredInfo}; +use messages::{RemoteMessageType, ObjectWithVersion, GeneralMessage}; use messages::payload::{Payloads, PayloadKinds, Thread}; use messages::proofs::proof_request::ProofRequestMessage; -use messages::GeneralMessage; use utils::error; use utils::constants::*; -use utils::libindy::anoncreds::libindy_verifier_verify_proof; use utils::libindy::anoncreds; -use serde_json::Value; use utils::constants::DEFAULT_SERIALIZE_VERSION; use object_cache::ObjectCache; use error::prelude::*; @@ -55,7 +50,7 @@ pub struct Proof { agent_did: String, agent_vk: String, revocation_interval: RevocationInterval, - thread: Thread + thread: Option } impl Proof { @@ -76,15 +71,15 @@ impl Proof { if settings::test_indy_mode_enabled() { return Ok(error::SUCCESS.code_num); } debug!("starting libindy proof verification for {}", self.source_id); - let valid = libindy_verifier_verify_proof(proof_req_json, - proof_json, - schemas_json, - credential_defs_json, - rev_reg_defs_json, - rev_regs_json).map_err(|err| { + let valid = anoncreds::libindy_verifier_verify_proof(proof_req_json, + proof_json, + schemas_json, + credential_defs_json, + rev_reg_defs_json, + rev_regs_json).map_err(|err| { error!("Error: {}, Proof {} wasn't valid", err, self.source_id); self.proof_state = ProofStateType::ProofInvalid; - VcxError::from(VcxErrorKind::InvalidProof) + err.map(VcxErrorKind::InvalidProof, error::INVALID_PROOF.message) })?; if !valid { @@ -285,8 +280,9 @@ impl Proof { .set_title(&title)? .set_detail(&title)? .agent_vk(&self.agent_vk)? - .edge_agent_payload(&self.prover_vk, &self.remote_vk, &proof_request, PayloadKinds::ProofRequest, Some(self.thread.clone())).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))? - .send_secure()?; + .edge_agent_payload(&self.prover_vk, &self.remote_vk, &proof_request, PayloadKinds::ProofRequest, self.thread.clone()).or(Err(VcxError::from(VcxErrorKind::InvalidConnectionHandle)))? + .send_secure() + .map_err(|err| err.extend("Cannot send proof request"))?; self.msg_uid = response.get_msg_uid()?; self.state = VcxStateType::VcxStateOfferSent; @@ -317,7 +313,8 @@ impl Proof { }; if let Some(tr) = thread { - self.thread.increment_receiver(self.remote_did.as_str()); + let remote_did = self.remote_did.as_str(); + self.thread.as_mut().map(|thread| thread.increment_receiver(remote_did)); } self.state = VcxStateType::VcxStateAccepted; @@ -407,7 +404,7 @@ pub fn create_proof(source_id: String, agent_did: String::new(), agent_vk: String::new(), revocation_interval: revocation_details, - thread: Thread::new(), + thread: Some(Thread::new()), }; new_proof.validate_proof_request()?; @@ -514,7 +511,6 @@ mod tests { use utils::httpclient; use connection::tests::build_test_connection; use utils::libindy::{pool, set_libindy_rc}; - use std::collections::HashMap; static PROOF_MSG: &str = r#"{"msg_type":"proof","version":"0.1","to_did":"BnRXf8yDMUwGyZVDkSENeq","from_did":"GxtnGN6ypZYgEqcftSQFnC","proof_request_id":"cCanHnpFAD","proofs":{"claim::e5fec91f-d03d-4513-813c-ab6db5715d55":{"proof":{"primary_proof":{"eq_proof":{"revealed_attrs":{"state":"96473275571522321025213415717206189191162"},"a_prime":"22605045280481376895214546474258256134055560453004805058368015338423404000586901936329279496160366852115900235316791489357953785379851822281248296428005020302405076144264617943389810572564188437603815231794326272302243703078443007359698858400857606408856314183672828086906560155576666631125808137726233827430076624897399072853872527464581329767287002222137559918765406079546649258389065217669558333867707240780369514832185660287640444094973804045885379406641474693993903268791773620198293469768106363470543892730424494655747935463337367735239405840517696064464669905860189004121807576749786474060694597244797343224031","e":"70192089123105616042684481760592174224585053817450673797400202710878562748001698340846985261463026529360990669802293480312441048965520897","v":"1148619141217957986496757711054111791862691178309410923416837802801708689012670430650138736456223586898110113348220116209094530854607083005898964558239710027534227973983322542548800291320747321452329327824406430787211689678096549398458892087551551587767498991043777397791000822007896620414888602588897806008609113730393639807814070738699614969916095861363383223421727858670289337712185089527052065958362840287749622133424503902085247641830693297082507827948006947829401008622239294382186995101394791468192083810475776455445579931271665980788474331866572497866962452476638881287668931141052552771328556458489781734943404258692308937784221642452132005267809852656378394530342203469943982066011466088478895643800295937901139711103301249691253510784029114718919483272055970725860849610885050165709968510696738864528287788491998027072378656038991754015693216663830793243584350961586874315757599094357535856429087122365865868729","m":{"address2":"11774234640096848605908744857306447015748098256395922562149769943967941106193320512788344020652220849708117081570187385467979956319507248530701654682748372348387275979419669108338","city":"4853213962270369118453000522408430296589146124488849630769837449684434138367659379663124155088827069418193027370932024893343033367076071757003149452226758383807126385017161888440","address1":"12970590675851114145396120869959510754345567924518524026685086869487243290925032320159287997675756075512889990901552679591155319959039145119122576164798225386578339739435869622811","zip":"8333721522340131864419931745588776943042067606218561135102011966361165456174036379901390244538991611895455576519950813910672825465382312504250936740379785802177629077591444977329"},"m1":"92853615502250003546205004470333326341901175168428906399291824325990659330595200000112546157141090642053863739870044907457400076448073272490169488870502566172795456430489790324815765612798273406119873266684053517977802902202155082987833343670942161987285661291655743810590661447300059024966135828466539810035","m2":"14442362430453309930284822850357071315613831915865367971974791350454381198894252834180803515368579729220423713315556807632571621646127926114010380486713602821529657583905131582938"},"ge_proofs":[]},"non_revoc_proof":null},"schema_seq_no":15,"issuer_did":"4fUDR9R7fjwELRvH9JT6HH"}},"aggregated_proof":{"c_hash":"68430476900085482958838239880418115228681348197588159723604944078288347793331","c_list":[[179,17,2,242,194,227,92,203,28,32,255,113,112,20,5,243,9,111,220,111,21,210,116,12,167,119,253,181,37,40,143,215,140,42,179,97,75,229,96,94,54,248,206,3,48,14,61,219,160,122,139,227,166,183,37,43,197,200,28,220,217,10,65,42,6,195,124,44,164,65,114,206,51,231,254,156,170,141,21,153,50,251,237,65,147,97,243,17,157,116,213,201,80,119,106,70,88,60,55,36,33,160,135,106,60,212,191,235,116,57,78,177,61,86,44,226,205,100,134,118,93,6,26,58,220,66,232,166,202,62,90,174,231,207,19,239,233,223,70,191,199,100,157,62,139,176,28,184,9,70,116,199,142,237,198,183,12,32,53,84,207,202,77,56,97,177,154,169,223,201,212,163,212,101,184,255,215,167,16,163,136,44,25,123,49,15,229,41,149,133,159,86,106,208,234,73,207,154,194,162,141,63,159,145,94,47,174,51,225,91,243,2,221,202,59,11,212,243,197,208,116,42,242,131,221,137,16,169,203,215,239,78,254,150,42,169,202,132,172,106,179,130,178,130,147,24,173,213,151,251,242,44,54,47,208,223]]},"requested_proof":{"revealed_attrs":{"sdf":["claim::e5fec91f-d03d-4513-813c-ab6db5715d55","UT","96473275571522321025213415717206189191162"]},"unrevealed_attrs":{},"self_attested_attrs":{},"predicates":{}}}"#; @@ -546,12 +542,7 @@ mod tests { agent_vk: VERKEY.to_string(), revocation_interval: RevocationInterval { from: None, to: None }, - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }) } @@ -714,13 +705,7 @@ mod tests { agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), revocation_interval: RevocationInterval { from: None, to: None }, - - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }); httpclient::set_next_u8_response(PROOF_RESPONSE.to_vec()); @@ -756,13 +741,7 @@ mod tests { agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), revocation_interval: RevocationInterval { from: None, to: None }, - - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }); httpclient::set_next_u8_response(PROOF_RESPONSE.to_vec()); @@ -899,11 +878,11 @@ mod tests { let h4 = create_proof("1".to_string(), REQUESTED_ATTRS.to_owned(), REQUESTED_PREDICATES.to_owned(), r#"{"support_revocation":false}"#.to_string(), "Optional".to_owned()).unwrap(); let h5 = create_proof("1".to_string(), REQUESTED_ATTRS.to_owned(), REQUESTED_PREDICATES.to_owned(), r#"{"support_revocation":false}"#.to_string(), "Optional".to_owned()).unwrap(); release_all(); - assert_eq!(release(h1).err(), Some(ProofError::InvalidHandle())); - assert_eq!(release(h2).err(), Some(ProofError::InvalidHandle())); - assert_eq!(release(h3).err(), Some(ProofError::InvalidHandle())); - assert_eq!(release(h4).err(), Some(ProofError::InvalidHandle())); - assert_eq!(release(h5).err(), Some(ProofError::InvalidHandle())); + assert_eq!(release(h1).unwrap_err().kind(), VcxErrorKind::InvalidProofHandle); + assert_eq!(release(h2).unwrap_err().kind(), VcxErrorKind::InvalidProofHandle); + assert_eq!(release(h3).unwrap_err().kind(), VcxErrorKind::InvalidProofHandle); + assert_eq!(release(h4).unwrap_err().kind(), VcxErrorKind::InvalidProofHandle); + assert_eq!(release(h5).unwrap_err().kind(), VcxErrorKind::InvalidProofHandle); } #[ignore] @@ -937,12 +916,7 @@ mod tests { agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), revocation_interval: RevocationInterval { from: None, to: None }, - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }; let rc = proof.proof_validation(); assert!(rc.is_ok()); @@ -968,7 +942,7 @@ mod tests { r#"{"support_revocation":false}"#.to_string(), "Optional".to_owned()).unwrap(); set_libindy_rc(error::TIMEOUT_LIBINDY_ERROR.code_num); - assert_eq!(send_proof_request(handle, connection_handle).err(), Some(ProofError::CommonError(error::TIMEOUT_LIBINDY_ERROR.code_num))); + assert_eq!(send_proof_request(handle, connection_handle).unwrap_err().kind(), VcxErrorKind::TimeoutLibindy); assert_eq!(get_state(handle).unwrap(), VcxStateType::VcxStateInitialized as u32); assert_eq!(get_proof_uuid(handle).unwrap(), ""); @@ -1010,21 +984,17 @@ mod tests { #[test] fn test_proof_errors() { - use utils::error::{INVALID_JSON, POST_MSG_FAILURE}; init!("false"); let mut proof = create_boxed_proof(); - assert_eq!(proof.validate_proof_indy("{}", "{}", "{}", "{}", "", "").err(), - Some(ProofError::InvalidProof())); + assert_eq!(proof.validate_proof_indy("{}", "{}", "{}", "{}", "", "").unwrap_err().kind(), VcxErrorKind::InvalidProof);; let bad_handle = 100000; // TODO: Do something to guarantee that this handle is bad - assert_eq!(proof.send_proof_request(bad_handle).err(), - Some(ProofError::ProofNotReadyError())); + assert_eq!(proof.send_proof_request(bad_handle).unwrap_err().kind(), VcxErrorKind::NotReady); // TODO: Add test that returns a INVALID_PROOF_CREDENTIAL_DATA - assert_eq!(proof.get_proof_request_status().err(), - Some(ProofError::ProofMessageError(POST_MSG_FAILURE.code_num))); + assert_eq!(proof.get_proof_request_status().unwrap_err().kind(), VcxErrorKind::PostMessageFailed);; let empty = r#""#; @@ -1032,14 +1002,13 @@ mod tests { empty.to_string(), "{}".to_string(), r#"{"support_revocation":false}"#.to_string(), - "my name".to_string()).err(), - Some(ProofError::CommonError(INVALID_JSON.code_num))); + "my name".to_string()).unwrap_err().kind(), VcxErrorKind::InvalidJson);; - assert_eq!(to_string(bad_handle).err(), Some(ProofError::CommonError(error::INVALID_OBJ_HANDLE.code_num))); - assert_eq!(get_source_id(bad_handle).err(), Some(ProofError::CommonError(error::INVALID_OBJ_HANDLE.code_num))); - assert_eq!(from_string(empty).err(), Some(ProofError::CommonError(INVALID_JSON.code_num))); + assert_eq!(to_string(bad_handle).unwrap_err().kind(), VcxErrorKind::InvalidHandle);; + assert_eq!(get_source_id(bad_handle).unwrap_err().kind(), VcxErrorKind::InvalidHandle);; + assert_eq!(from_string(empty).unwrap_err().kind(), VcxErrorKind::InvalidJson);; let mut proof_good = create_boxed_proof(); - assert_eq!(proof_good.get_proof_request_status().err(), Some(ProofError::ProofMessageError(POST_MSG_FAILURE.code_num))); + assert_eq!(proof_good.get_proof_request_status().unwrap_err().kind(), VcxErrorKind::PostMessageFailed); } #[cfg(feature = "agency")] diff --git a/vcx/libvcx/src/schema.rs b/vcx/libvcx/src/schema.rs index 58318700fa..6da705a36c 100644 --- a/vcx/libvcx/src/schema.rs +++ b/vcx/libvcx/src/schema.rs @@ -1,7 +1,8 @@ use serde_json; -use settings; use std::string::ToString; + +use settings; use utils::libindy::anoncreds; use utils::libindy::payments::PaymentTxn; use utils::constants::DEFAULT_SERIALIZE_VERSION; @@ -28,13 +29,10 @@ pub struct CreateSchema { schema_id: String, name: String, source_id: String, - sequence_num: u32, payment_txn: Option, } impl CreateSchema { - pub fn get_sequence_num(&self) -> u32 { self.sequence_num } - pub fn get_source_id(&self) -> &String { &self.source_id } pub fn get_schema_id(&self) -> &String { &self.schema_id } @@ -42,7 +40,7 @@ impl CreateSchema { fn get_payment_txn(&self) -> VcxResult { trace!("CreateSchema::get_payment_txn >>>"); self.payment_txn.clone() - .ok_or(err_msg(VcxErrorKind::NoPaymentInformation, "Payment information not found")) + .ok_or(VcxError::from(VcxErrorKind::NoPaymentInformation)) } fn to_string(&self) -> VcxResult { @@ -70,19 +68,17 @@ pub fn create_new_schema(source_id: &str, debug!("created schema on ledger with id: {}", schema_id); - let new_schema = CreateSchema { + let schema = CreateSchema { source_id: source_id.to_string(), name, data: serde_json::from_str(&data).unwrap_or_default(), version, schema_id, - //Todo: Take sequence number out. Id will be used instead - sequence_num: 0, payment_txn, }; - SCHEMA_MAP.add(new_schema) - .map_err(|_| VcxError::from_msg(VcxErrorKind::CreateSchema, "Cannot create schema")) // TODO: looks useless + SCHEMA_MAP.add(schema) + .or(Err(VcxError::from(VcxErrorKind::CreateSchema))) } @@ -92,7 +88,7 @@ pub fn get_schema_attrs(source_id: String, schema_id: String) -> VcxResult<(u32, let submitter_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID)?; let (schema_id, schema_data_json) = anoncreds::get_schema_json(&schema_id) - .map_err(|err| err.map(VcxErrorKind::InvalidSchemaSeqNo, "No Schema for that schema sequence number"))?; + .map_err(|err| err.map(VcxErrorKind::InvalidSchemaSeqNo, "Schema not found"))?; let schema_data: SchemaData = serde_json::from_str(&schema_data_json) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize schema: {}", err)))?; @@ -100,7 +96,6 @@ pub fn get_schema_attrs(source_id: String, schema_id: String) -> VcxResult<(u32, let schema = CreateSchema { source_id, schema_id, - sequence_num: 0, name: schema_data.name, version: schema_data.version, data: schema_data.attr_names, @@ -110,7 +105,7 @@ pub fn get_schema_attrs(source_id: String, schema_id: String) -> VcxResult<(u32, let schema_json = schema.to_string()?; let handle = SCHEMA_MAP.add(schema) - .map_err(|_| VcxError::from_msg(VcxErrorKind::CreateSchema, "Cannot create schema"))?; // TODO: looks useless + .or(Err(VcxError::from(VcxErrorKind::CreateSchema)))?; Ok((handle, schema_json)) } @@ -125,21 +120,15 @@ pub fn to_string(handle: u32) -> VcxResult { }) } -pub fn get_sequence_num(handle: u32) -> VcxResult { - SCHEMA_MAP.get(handle, |s| { - Ok(s.get_sequence_num()) - }) -} - pub fn get_source_id(handle: u32) -> VcxResult { SCHEMA_MAP.get(handle, |s| { - Ok(s.get_source_id().clone()) + Ok(s.get_source_id().to_string()) }) } pub fn get_schema_id(handle: u32) -> VcxResult { SCHEMA_MAP.get(handle, |s| { - Ok(s.get_schema_id().clone()) + Ok(s.get_schema_id().to_string()) }) } @@ -191,10 +180,9 @@ pub mod tests { schema_id: SCHEMA_ID.to_string(), source_id: "testId".to_string(), name: "schema_name".to_string(), - sequence_num: 306, payment_txn: None, }; - let value: serde_json::Value = serde_json::from_str(&create_schema.to_string()).unwrap(); + let value: serde_json::Value = serde_json::from_str(&create_schema.to_string().unwrap()).unwrap(); assert_eq!(value["version"], "1.0"); let create_schema: CreateSchema = serde_json::from_str(&value["data"].to_string()).unwrap(); assert_eq!(create_schema.source_id, source_id); @@ -234,7 +222,7 @@ pub mod tests { "name".to_string(), "1.0".to_string(), "".to_string()); - assert_eq!(schema, Err(SchemaError::CommonError(error::INVALID_LIBINDY_PARAM.code_num))) + assert_eq!(schema.unwrap_err().kind(), VcxErrorKind::InvalidLibindyParam) } #[cfg(feature = "pool_tests")] @@ -287,7 +275,7 @@ pub mod tests { assert!(rc.is_ok()); let rc = create_new_schema("id", did.clone(), schema_name.clone(), schema_version.clone(), data.clone()); - assert_eq!(rc, Err(SchemaError::DuplicateSchema())); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::DuplicationSchema) } #[test] @@ -302,18 +290,17 @@ pub mod tests { let h4 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(), data.to_string()).unwrap(); let h5 = create_new_schema("1", did.to_string(), "name".to_string(), version.to_string(), data.to_string()).unwrap(); release_all(); - assert_eq!(release(h1).err(), Some(SchemaError::InvalidHandle())); - assert_eq!(release(h2).err(), Some(SchemaError::InvalidHandle())); - assert_eq!(release(h3).err(), Some(SchemaError::InvalidHandle())); - assert_eq!(release(h4).err(), Some(SchemaError::InvalidHandle())); - assert_eq!(release(h5).err(), Some(SchemaError::InvalidHandle())); + assert_eq!(release(h1).unwrap_err().kind(), VcxErrorKind::InvalidSchemaHandle); + assert_eq!(release(h2).unwrap_err().kind(), VcxErrorKind::InvalidSchemaHandle); + assert_eq!(release(h3).unwrap_err().kind(), VcxErrorKind::InvalidSchemaHandle); + assert_eq!(release(h4).unwrap_err().kind(), VcxErrorKind::InvalidSchemaHandle); + assert_eq!(release(h5).unwrap_err().kind(), VcxErrorKind::InvalidSchemaHandle); } #[test] fn test_errors() { init!("false"); - assert_eq!(get_sequence_num(145661).err(), Some(SchemaError::CommonError(error::INVALID_OBJ_HANDLE.code_num))); - assert_eq!(to_string(13435178).err(), Some(SchemaError::CommonError(error::INVALID_OBJ_HANDLE.code_num))); + assert_eq!(to_string(13435178).unwrap_err().kind(), VcxErrorKind::InvalidHandle); } #[test] diff --git a/vcx/libvcx/src/settings.rs b/vcx/libvcx/src/settings.rs index 5bb3c9acd7..21a5974d66 100644 --- a/vcx/libvcx/src/settings.rs +++ b/vcx/libvcx/src/settings.rs @@ -136,8 +136,8 @@ pub fn validate_config(config: &HashMap) -> VcxResult { validate_optional_config_val(config.get(CONFIG_REMOTE_TO_SDK_DID), VcxErrorKind::InvalidDid, validation::validate_did)?; validate_optional_config_val(config.get(CONFIG_REMOTE_TO_SDK_VERKEY), VcxErrorKind::InvalidVerkey, validation::validate_verkey)?; - validate_optional_config_val(config.get(CONFIG_AGENCY_ENDPOINT), VcxErrorKind::InvalidDid, Url::parse)?; - validate_optional_config_val(config.get(CONFIG_INSTITUTION_LOGO_URL), VcxErrorKind::InvalidVerkey, Url::parse)?; + validate_optional_config_val(config.get(CONFIG_AGENCY_ENDPOINT), VcxErrorKind::InvalidUrl, Url::parse)?; + validate_optional_config_val(config.get(CONFIG_INSTITUTION_LOGO_URL), VcxErrorKind::InvalidUrl, Url::parse)?; Ok(error::SUCCESS.code_num) } @@ -254,7 +254,9 @@ pub fn get_config_value(key: &str) -> VcxResult { pub fn set_config_value(key: &str, value: &str) { trace!("set_config_value >>> key: {}, value: {}", key, value); - SETTINGS.write().unwrap().insert(key.to_string(), value.to_string()); + SETTINGS + .write().unwrap() + .insert(key.to_string(), value.to_string()); } pub fn get_wallet_config(wallet_name: &str, wallet_type: Option<&str>, storage_config: Option<&str>) -> String { @@ -384,7 +386,7 @@ pub mod tests { #[test] fn test_bad_path() { let path = "garbage.txt"; - assert_eq!(process_config_file(&path), Err(error::INVALID_CONFIGURATION.code_num)); + assert_eq!(process_config_file(&path).unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); } #[test] @@ -408,7 +410,7 @@ pub mod tests { }).to_string(); write_config_to_file(&content, config_path).unwrap(); - assert_eq!(read_config_file(config_path), Ok(content)); + assert_eq!(read_config_file(config_path).unwrap(), content); } #[test] @@ -432,7 +434,7 @@ pub mod tests { }).to_string(); write_config_to_file(&content, config_path).unwrap(); - assert_eq!(process_config_file(config_path), Ok(error::SUCCESS.code_num)); + assert_eq!(process_config_file(config_path).unwrap(), error::SUCCESS.code_num); assert_eq!(get_config_value("institution_name").unwrap(), "evernym enterprise".to_string()); } @@ -454,7 +456,7 @@ pub mod tests { "wallet_key":"key" }).to_string(); - assert_eq!(process_config_string(&content), Ok(error::SUCCESS.code_num)); + assert_eq!(process_config_string(&content).unwrap(), error::SUCCESS.code_num); } #[test] @@ -476,7 +478,7 @@ pub mod tests { "institution_verkey": "444MFrZjXDoi2Vc8Mm14Ys112tEZdDegBZZoembFEATE", }).to_string(); let config: HashMap = serde_json::from_str(&content).unwrap(); - assert_eq!(validate_config(&config), Ok(error::SUCCESS.code_num)); + assert_eq!(validate_config(&config).unwrap(), error::SUCCESS.code_num); } #[test] @@ -486,51 +488,51 @@ pub mod tests { let valid_ver = DEFAULT_VERKEY; let mut config: HashMap = HashMap::new(); - assert_eq!(validate_config(&config), Err(error::MISSING_WALLET_KEY.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::MissingWalletKey); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_INSTITUTION_DID.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_DID.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidDid); config.drain(); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_INSTITUTION_VERKEY.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_VERKEY.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidVerkey); config.drain(); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_AGENCY_DID.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_DID.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidDid); config.drain(); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_AGENCY_VERKEY.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_VERKEY.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidVerkey); config.drain(); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_SDK_TO_REMOTE_DID.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_DID.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidDid); config.drain(); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_SDK_TO_REMOTE_VERKEY.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_VERKEY.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidVerkey); config.drain(); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_REMOTE_TO_SDK_DID.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_DID.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidDid); config.drain(); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_SDK_TO_REMOTE_VERKEY.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_VERKEY.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidVerkey); config.drain(); config.insert(CONFIG_WALLET_KEY.to_string(), "password".to_string()); config.insert(CONFIG_INSTITUTION_LOGO_URL.to_string(), invalid.to_string()); - assert_eq!(validate_config(&config), Err(error::INVALID_URL.code_num)); + assert_eq!(validate_config(&config).unwrap_err().kind(), VcxErrorKind::InvalidUrl); config.drain(); } @@ -542,17 +544,17 @@ pub mod tests { config.insert("invalid".to_string(), "invalid_url".to_string()); //Success - assert_eq!(validate_optional_config_val(config.get("valid"), error::INVALID_URL.code_num, closure), - Ok(error::SUCCESS.code_num)); + assert_eq!(validate_optional_config_val(config.get("valid"), VcxErrorKind::InvalidUrl, closure).unwrap(), + error::SUCCESS.code_num); // Success with No config - assert_eq!(validate_optional_config_val(config.get("unknown"), error::INVALID_URL.code_num, closure), - Ok(error::SUCCESS.code_num)); + assert_eq!(validate_optional_config_val(config.get("unknown"), VcxErrorKind::InvalidUrl, closure).unwrap(), + error::SUCCESS.code_num); // Fail with failed fn call assert_eq!(validate_optional_config_val(config.get("invalid"), - error::INVALID_URL.code_num, - closure), Err(error::INVALID_URL.code_num)); + VcxErrorKind::InvalidUrl, + closure).unwrap_err().kind(), VcxErrorKind::InvalidUrl); } #[test] @@ -561,7 +563,7 @@ pub mod tests { let value1 = "value1".to_string(); // Fails with invalid key - assert_eq!(get_config_value(&key), Err(error::INVALID_CONFIGURATION.code_num)); + assert_eq!(get_config_value(&key).unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); set_config_value(&key, &value1); assert_eq!(get_config_value(&key).unwrap(), value1); @@ -571,20 +573,20 @@ pub mod tests { fn test_payment_plugin_validation() { clear_config(); set_config_value(CONFIG_PAYMENT_METHOD, "null"); - assert_eq!(validate_payment_method(), Ok(())); + assert_eq!(validate_payment_method().unwrap(), ()); } #[test] fn test_payment_plugin_validation_empty_string() { clear_config(); set_config_value(CONFIG_PAYMENT_METHOD, ""); - assert_eq!(validate_payment_method(), Err(error::MISSING_PAYMENT_METHOD.code_num)); + assert_eq!(validate_payment_method().unwrap_err().kind(), VcxErrorKind::MissingPaymentMethod); } #[test] fn test_payment_plugin_validation_missing_option() { clear_config(); - assert_eq!(validate_payment_method(), Err(error::MISSING_PAYMENT_METHOD.code_num)); + assert_eq!(validate_payment_method().unwrap_err().kind(), VcxErrorKind::MissingPaymentMethod); } #[test] @@ -598,7 +600,7 @@ pub mod tests { "wallet_key":"key", }).to_string(); - assert_eq!(process_config_string(&content), Ok(error::SUCCESS.code_num)); + assert_eq!(process_config_string(&content).unwrap(), error::SUCCESS.code_num); assert_eq!(get_config_value("pool_name").unwrap(), "pool1".to_string()); assert_eq!(get_config_value("config_name").unwrap(), "config1".to_string()); @@ -610,11 +612,11 @@ pub mod tests { clear_config(); // Fails after config is cleared - assert_eq!(get_config_value("pool_name"), Err(error::INVALID_CONFIGURATION.code_num)); - assert_eq!(get_config_value("config_name"), Err(error::INVALID_CONFIGURATION.code_num)); - assert_eq!(get_config_value("wallet_name"), Err(error::INVALID_CONFIGURATION.code_num)); - assert_eq!(get_config_value("institution_name"), Err(error::INVALID_CONFIGURATION.code_num)); - assert_eq!(get_config_value("genesis_path"), Err(error::INVALID_CONFIGURATION.code_num)); - assert_eq!(get_config_value("wallet_key"), Err(error::INVALID_CONFIGURATION.code_num)); + assert_eq!(get_config_value("pool_name").unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); + assert_eq!(get_config_value("config_name").unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); + assert_eq!(get_config_value("wallet_name").unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); + assert_eq!(get_config_value("institution_name").unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); + assert_eq!(get_config_value("genesis_path").unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); + assert_eq!(get_config_value("wallet_key").unwrap_err().kind(), VcxErrorKind::InvalidConfiguration); } } diff --git a/vcx/libvcx/src/utils/libindy/anoncreds.rs b/vcx/libvcx/src/utils/libindy/anoncreds.rs index 5f7b0fda35..1d72bfeeb4 100644 --- a/vcx/libvcx/src/utils/libindy/anoncreds.rs +++ b/vcx/libvcx/src/utils/libindy/anoncreds.rs @@ -1,19 +1,15 @@ -extern crate libc; - use futures::Future; use serde_json; use serde_json::{map::Map, Value}; +use indy::{anoncreds, blob_storage, ledger}; +use time; + use settings; use utils::constants::{LIBINDY_CRED_OFFER, REQUESTED_ATTRIBUTES, ATTRS, REV_STATE_JSON}; use utils::libindy::{error_codes::map_rust_indy_sdk_error, mock_libindy_rc, wallet::get_wallet_handle}; use utils::libindy::payments::{pay_for_txn, PaymentTxn}; -use utils::libindy::ledger::{Response, parse_response}; +use utils::libindy::ledger::*; use utils::constants::{SCHEMA_ID, SCHEMA_JSON, SCHEMA_TXN_TYPE, CRED_DEF_ID, CRED_DEF_JSON, CRED_DEF_TXN_TYPE, REV_REG_DEF_TXN_TYPE, REV_REG_DELTA_TXN_TYPE, REVOC_REG_TYPE, rev_def_json, REV_REG_ID, REV_REG_DELTA_JSON, REV_REG_JSON}; -use utils::libindy::ledger::{libindy_build_schema_request, libindy_build_get_schema_request, libindy_submit_request, libindy_parse_get_cred_def_response, libindy_parse_get_schema_response, libindy_build_create_credential_def_txn, libindy_build_get_credential_def_txn}; -use indy::anoncreds; -use indy::blob_storage; -use indy::ledger; -use time; use error::prelude::*; const BLOB_STORAGE_TYPE: &str = "default"; @@ -480,8 +476,6 @@ pub mod tests { use std::thread; use std::time::Duration; #[cfg(feature = "pool_tests")] - use utils::error::LIBINDY_INVALID_STRUCTURE; - #[cfg(feature = "pool_tests")] use utils::constants::TEST_TAILS_FILE; @@ -567,7 +561,7 @@ pub mod tests { let (cred, cred_rev_id, _) = ::utils::libindy::anoncreds::libindy_issuer_create_credential(&offer, &req, &encoded_attributes, rev_reg_id.clone(), tails_file).unwrap(); /* store cred */ - let cred_id = ::utils::libindy::anoncreds::libindy_prover_store_credential(None, &req_meta, &cred, &cred_def_json, rev_def_json).unwrap(); + let cred_id = ::utils::libindy::anoncreds::libindy_prover_store_credential(None, &req_meta, &cred, &cred_def_json, rev_def_json.as_ref().map(String::as_str)).unwrap(); (schema_id, schema_json, cred_def_id, cred_def_json, offer, req, req_meta, cred_id, rev_reg_id, cred_rev_id) } @@ -697,7 +691,7 @@ pub mod tests { init!("ledger"); let proof_req = "{"; let result = libindy_prover_get_credentials_for_proof_req(&proof_req); - assert_eq!(result.err(), Some(INVALID_PROOF_REQUEST.code_num)); + assert_eq!(result.unwrap_err().kind(), VcxErrorKind::InvalidProofRequest); let proof_req = json!({ "nonce":"123432421212", "name":"proof_req_1", @@ -717,7 +711,7 @@ pub mod tests { let wallet_handle = get_wallet_handle(); let proof_req_str: String = serde_json::to_string(&proof_req).unwrap(); assert!(result.is_ok()); - assert_eq!(result_malformed_json.err(), Some(INVALID_ATTRIBUTES_STRUCTURE.code_num)); + assert_eq!(result_malformed_json.unwrap_err().kind(), VcxErrorKind::InvalidAttributesStructure); } #[cfg(feature = "pool_tests")] @@ -772,7 +766,7 @@ pub mod tests { let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); let rc = create_rev_reg_def(&did, &cred_def_id, get_temp_dir_path(Some("path.txt")).to_str().unwrap(), 2); - assert_eq!(rc, Err(LIBINDY_INVALID_STRUCTURE.code_num)); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::LibindyInvalidStructure); } #[cfg(feature = "pool_tests")] diff --git a/vcx/libvcx/src/utils/libindy/cache.rs b/vcx/libvcx/src/utils/libindy/cache.rs index 077d3c43dc..ac20cf219a 100644 --- a/vcx/libvcx/src/utils/libindy/cache.rs +++ b/vcx/libvcx/src/utils/libindy/cache.rs @@ -1,4 +1,4 @@ -extern crate serde_json; +use serde_json; use utils::libindy::wallet::{add_record, get_record, update_record_value}; diff --git a/vcx/libvcx/src/utils/libindy/callback.rs b/vcx/libvcx/src/utils/libindy/callback.rs index 3cecbdb082..8d58c1851e 100644 --- a/vcx/libvcx/src/utils/libindy/callback.rs +++ b/vcx/libvcx/src/utils/libindy/callback.rs @@ -1,4 +1,4 @@ -extern crate libc; +extern crate libc; use self::libc::c_char; use std::ffi::CStr; diff --git a/vcx/libvcx/src/utils/libindy/crypto.rs b/vcx/libvcx/src/utils/libindy/crypto.rs index 6fe24424eb..0eb2c6618a 100644 --- a/vcx/libvcx/src/utils/libindy/crypto.rs +++ b/vcx/libvcx/src/utils/libindy/crypto.rs @@ -1,12 +1,10 @@ /* test isn't ready until > libindy 1.0.1 */ -extern crate libc; - use futures::Future; +use indy::crypto; use utils::libindy::mock_libindy_rc; use utils::libindy::error_codes::map_rust_indy_sdk_error; use settings; -use indy::crypto; use error::prelude::*; pub fn prep_msg(sender_vk: &str, recipient_vk: &str, msg: &[u8]) -> VcxResult> { diff --git a/vcx/libvcx/src/utils/libindy/error_codes.rs b/vcx/libvcx/src/utils/libindy/error_codes.rs index 31f68437db..58dc3ef802 100644 --- a/vcx/libvcx/src/utils/libindy/error_codes.rs +++ b/vcx/libvcx/src/utils/libindy/error_codes.rs @@ -1,8 +1,9 @@ extern crate num_traits; +use self::num_traits::int::PrimInt; + use indy::IndyError; use utils::error; -use self::num_traits::int::PrimInt; use error::prelude::{VcxError, VcxErrorKind}; pub fn map_indy_error(rtn: T, error_code: C) -> Result { @@ -15,6 +16,9 @@ pub fn map_indy_error(rtn: T, error_code: C) -> Result { pub fn map_rust_indy_sdk_error(error: IndyError) -> VcxError { match error.error_code as u32 { + 100 ... 111 => VcxError::from_msg(VcxErrorKind::InvalidLibindyParam, error.message), + 113 => VcxError::from_msg(VcxErrorKind::LibindyInvalidStructure, error.message), + 114 => VcxError::from_msg(VcxErrorKind::IOError, error.message), 200 => VcxError::from_msg(VcxErrorKind::InvalidWalletHandle, error.message), 203 => VcxError::from_msg(VcxErrorKind::DuplicationWallet, error.message), 204 => VcxError::from_msg(VcxErrorKind::WalletNotFound, error.message), @@ -26,7 +30,7 @@ pub fn map_rust_indy_sdk_error(error: IndyError) -> VcxError { 407 => VcxError::from_msg(VcxErrorKind::CredDefAlreadyCreated, error.message), 600 => VcxError::from_msg(VcxErrorKind::DuplicationDid, error.message), 702 => VcxError::from_msg(VcxErrorKind::InsufficientTokenAmount, error.message), - _ => VcxError::from_msg(VcxErrorKind::LiibndyError(error.error_code as u32), error.message) + _ => VcxError::from_msg(VcxErrorKind::UnknownLiibndyError, error.message) } } @@ -88,10 +92,10 @@ pub mod tests { indy_backtrace: None, }; - assert_eq!(map_rust_indy_sdk_error(err100), error::INVALID_LIBINDY_PARAM.code_num); - assert_eq!(map_rust_indy_sdk_error(err107), error::INVALID_LIBINDY_PARAM.code_num); - assert_eq!(map_rust_indy_sdk_error(err111), error::INVALID_LIBINDY_PARAM.code_num); + assert_eq!(map_rust_indy_sdk_error(err100).kind(), VcxErrorKind::InvalidLibindyParam); + assert_eq!(map_rust_indy_sdk_error(err107).kind(), VcxErrorKind::InvalidLibindyParam); + assert_eq!(map_rust_indy_sdk_error(err111).kind(), VcxErrorKind::InvalidLibindyParam); // Test that RC 112 falls out of the range 100...112 - assert_ne!(map_rust_indy_sdk_error(err112), error::INVALID_LIBINDY_PARAM.code_num); + assert_ne!(map_rust_indy_sdk_error(err112).kind(), VcxErrorKind::InvalidLibindyParam); } } diff --git a/vcx/libvcx/src/utils/libindy/ledger.rs b/vcx/libvcx/src/utils/libindy/ledger.rs index 3a2e6bca41..c98da66b87 100644 --- a/vcx/libvcx/src/utils/libindy/ledger.rs +++ b/vcx/libvcx/src/utils/libindy/ledger.rs @@ -1,15 +1,10 @@ -extern crate libc; -extern crate time; -extern crate serde_json; - +use serde_json; use futures::Future; +use indy::ledger; use settings; -use utils::libindy::{ - pool::get_pool_handle, - wallet::get_wallet_handle, -}; -use indy::ledger; +use utils::libindy::pool::get_pool_handle; +use utils::libindy::wallet::get_wallet_handle; use utils::libindy::error_codes::map_rust_indy_sdk_error; use error::prelude::*; diff --git a/vcx/libvcx/src/utils/libindy/mod.rs b/vcx/libvcx/src/utils/libindy/mod.rs index b09620cbef..10f29cd8fe 100644 --- a/vcx/libvcx/src/utils/libindy/mod.rs +++ b/vcx/libvcx/src/utils/libindy/mod.rs @@ -12,8 +12,6 @@ pub mod logger; pub mod error_codes; -extern crate libc; - use settings; use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use std::sync::Mutex; diff --git a/vcx/libvcx/src/utils/libindy/payments.rs b/vcx/libvcx/src/utils/libindy/payments.rs index c72ffed444..c2f8cccb90 100644 --- a/vcx/libvcx/src/utils/libindy/payments.rs +++ b/vcx/libvcx/src/utils/libindy/payments.rs @@ -1,15 +1,14 @@ use futures::Future; - -use utils::libindy::wallet::get_wallet_handle; -use utils::constants::{SUBMIT_SCHEMA_RESPONSE, TRANSFER_TXN_TYPE}; -use utils::libindy::error_codes::{map_rust_indy_sdk_error}; -#[allow(unused_imports)] -use utils::libindy::ledger::{libindy_submit_request, libindy_sign_and_submit_request, libindy_sign_request}; - use indy::payments; +use serde_json::Value; + use std::fmt; use std::collections::HashMap; -use serde_json::Value; + +use utils::libindy::wallet::get_wallet_handle; +use utils::libindy::ledger::{libindy_submit_request, libindy_sign_and_submit_request, libindy_sign_request}; +use utils::libindy::error_codes::{map_rust_indy_sdk_error}; +use utils::constants::{SUBMIT_SCHEMA_RESPONSE, TRANSFER_TXN_TYPE}; use settings; use error::prelude::*; @@ -560,19 +559,19 @@ pub mod tests { let pay_addr_2 = build_test_address("2"); // Success - Exact amount - let expected_inputs = format!(r#"["{}","{}","{}","{}"]"#, pay_addr_1, pay_addr_2, pay_addr_1, pay_addr_2); + let expected_inputs = vec![pay_addr_1.clone(), pay_addr_2.clone(), pay_addr_1.clone(), pay_addr_2.clone()]; assert_eq!(inputs(6).unwrap(), (0, expected_inputs, build_test_address("zR3GN9lfbCVtHjp"))); // Success - utxo with remainder tokens - let expected_inputs = format!(r#"["{}","{}","{}","{}"]"#, pay_addr_1, pay_addr_2, pay_addr_1, pay_addr_2); + let expected_inputs = vec![pay_addr_1.clone(), pay_addr_2.clone(), pay_addr_1.clone(), pay_addr_2.clone()]; assert_eq!(inputs(5).unwrap(), (1, expected_inputs, build_test_address("zR3GN9lfbCVtHjp"))); // Success - requesting amount that partial address (1 of 2 utxos) can satisfy - let expected_inputs = format!(r#"["{}"]"#, pay_addr_1); + let expected_inputs = vec![pay_addr_1.clone()]; assert_eq!(inputs(1).unwrap(), (0, expected_inputs, build_test_address("9UFgyjuJxi1i1HD"))); // Err - request more than wallet contains - assert_eq!(inputs(7).err(), Some(PaymentError::InsufficientFunds())); + assert_eq!(inputs(7).err().unwrap().kind(), VcxErrorKind::InsufficientTokenAmount); } #[test] @@ -581,12 +580,12 @@ pub mod tests { let mut cost = 5; let (remainder, _, refund_address) = inputs(cost).unwrap(); - let mut expected_output = format!(r#"[{{"amount":1,"recipient":"{}"}}]"#, refund_address); + let mut expected_output: Vec = ::serde_json::from_str(&format!(r#"[{{"amount":1,"recipient":"{}"}}]"#, refund_address)).unwrap(); assert_eq!(outputs(remainder, &refund_address, None, None).unwrap(), expected_output); // No remainder so don't create an address in outputs cost = 6; - expected_output = r#"[]"#.to_string(); + expected_output = vec![]; let (remainder, _, refund_address) = inputs(cost).unwrap(); assert_eq!(remainder, 0); assert_eq!(outputs(remainder, &refund_address, None, None).unwrap(), expected_output); @@ -599,7 +598,7 @@ pub mod tests { let payee_amount = 11; let payee_address = build_test_address("payee_address"); let refund_address = build_test_address("refund_address"); - let expected_output = format!(r#"[{{"amount":4,"recipient":"{}"}},{{"amount":11,"recipient":"{}"}}]"#, refund_address, payee_address); + let expected_output: Vec = ::serde_json::from_str(&format!(r#"[{{"amount":4,"recipient":"{}"}},{{"amount":11,"recipient":"{}"}}]"#, refund_address, payee_address)).unwrap(); assert_eq!(outputs(4, refund_address.as_str(), Some(payee_address), Some(payee_amount)).unwrap(), expected_output); } @@ -675,7 +674,7 @@ pub mod tests { let price = get_my_balance() + 5; let result_from_paying = pay_a_payee(price, payment_address); - assert_eq!(result_from_paying.err(), Some(PaymentError::InsufficientFunds())); + assert_eq!(result_from_paying.err().unwrap().kind(), VcxErrorKind::InsufficientTokenAmount); assert_eq!(get_my_balance(), 5); } @@ -690,7 +689,7 @@ pub mod tests { let result_from_paying = pay_a_payee(0, payment_address); assert!(result_from_paying.is_err()); - assert_eq!(result_from_paying.err(), Some(PaymentError::CommonError(error::UNKNOWN_LIBINDY_ERROR.code_num))); + assert_eq!(result_from_paying.err().unwrap().kind(), VcxErrorKind::LiibndyError(100)); // TODO: FIXME } #[cfg(feature = "pool_tests")] @@ -720,7 +719,7 @@ pub mod tests { let price = get_my_balance() - not_enough_for_ledger_fee; assert!(price > 0); let result_from_paying = pay_a_payee(price, payment_address); - assert_eq!(result_from_paying.err(), Some(PaymentError::CommonError(error::INSUFFICIENT_TOKEN_AMOUNT.code_num))); + assert_eq!(result_from_paying.err().unwrap().kind(), VcxErrorKind::InsufficientTokenAmount); } #[cfg(feature = "pool_tests")] @@ -756,7 +755,7 @@ pub mod tests { assert_eq!(remainder, remaining_balance); let output = outputs(remainder, &refund_address, None, None).unwrap(); - assert_eq!(output, format!(r#"[{{"amount":{},"recipient":"{}"}}]"#, remaining_balance, refund_address)); + let expected_output: Vec = ::serde_json::from_str(&format!(r#"[{{"amount":{},"recipient":"{}"}}]"#, remaining_balance, refund_address)).unwrap(); let rc = _submit_fees_request(&req, &inputs, &output).unwrap(); let end_wallet = get_wallet_token_info().unwrap(); diff --git a/vcx/libvcx/src/utils/libindy/pool.rs b/vcx/libvcx/src/utils/libindy/pool.rs index fe5df39d28..8b65400116 100644 --- a/vcx/libvcx/src/utils/libindy/pool.rs +++ b/vcx/libvcx/src/utils/libindy/pool.rs @@ -1,8 +1,9 @@ use futures::Future; +use indy::{pool, ErrorCode}; use std::sync::RwLock; + use settings; -use indy::pool; use utils::libindy::error_codes::map_rust_indy_sdk_error; use error::prelude::*; @@ -10,7 +11,7 @@ lazy_static! { static ref POOL_HANDLE: RwLock> = RwLock::new(None); } -pub fn change_pool_handle(handle: Option){ +pub fn change_pool_handle(handle: Option) { let mut h = POOL_HANDLE.write().unwrap(); *h = handle; } @@ -24,13 +25,18 @@ pub fn set_protocol_version() -> VcxResult<()> { pub fn create_pool_ledger_config(pool_name: &str, path: &str) -> VcxResult<()> { let pool_config = json!({"genesis_txn": path}).to_string(); - pool::create_pool_ledger_config(pool_name, Some(&pool_config)) - .wait() - .map_err(map_rust_indy_sdk_error) + match pool::create_pool_ledger_config(pool_name, Some(&pool_config)) + .wait() { + Ok(x) => Ok(()), + Err(x) => if x.error_code != ErrorCode::PoolLedgerConfigAlreadyExistsError { + Err(VcxError::from(VcxErrorKind::UnknownLiibndyError)) + } else { + Ok(()) + } + } } pub fn open_pool_ledger(pool_name: &str, config: Option<&str>) -> VcxResult { - set_protocol_version()?; let handle = pool::open_pool_ledger(pool_name, config) @@ -56,7 +62,7 @@ pub fn delete(pool_name: &str) -> VcxResult<()> { if settings::test_indy_mode_enabled() { change_pool_handle(None); - return Ok(()) + return Ok(()); } pool::delete_pool_ledger(pool_name) diff --git a/vcx/libvcx/src/utils/libindy/signus.rs b/vcx/libvcx/src/utils/libindy/signus.rs index f122eec3b1..9b7b7409b7 100644 --- a/vcx/libvcx/src/utils/libindy/signus.rs +++ b/vcx/libvcx/src/utils/libindy/signus.rs @@ -1,9 +1,9 @@ use futures::Future; +use indy::did; use settings; use utils::libindy::error_codes::map_rust_indy_sdk_error; use utils::libindy::wallet::get_wallet_handle; -use indy::did; use error::prelude::*; pub fn create_and_store_my_did(seed: Option<&str>) -> VcxResult<(String, String)> { diff --git a/vcx/libvcx/src/utils/libindy/wallet.rs b/vcx/libvcx/src/utils/libindy/wallet.rs index de6f71dbd2..a148e09ab4 100644 --- a/vcx/libvcx/src/utils/libindy/wallet.rs +++ b/vcx/libvcx/src/utils/libindy/wallet.rs @@ -1,12 +1,9 @@ -extern crate libc; -extern crate serde_json; - use futures::Future; +use indy::{wallet, ErrorCode}; use settings; use utils::libindy::error_codes::map_rust_indy_sdk_error; -use indy::wallet; -use indy::ErrorCode; + use std::path::Path; use error::prelude::*; @@ -180,7 +177,7 @@ pub fn import(config: &str) -> VcxResult<()> { #[cfg(test)] pub mod tests { use super::*; - use utils::{get_temp_dir_path, error}; + use utils::{get_temp_dir_path}; use std::thread; use std::time::Duration; use utils::devsetup::tests::setup_wallet_env; @@ -228,13 +225,13 @@ pub mod tests { fn test_wallet() { init!("false"); assert!(get_wallet_handle() > 0); - assert_eq!(error::INVALID_WALLET_CREATION.code_num, init_wallet(&String::from(""), None, None, None).unwrap_err()); + assert_eq!(VcxErrorKind::WalletCreate, init_wallet(&String::from(""), None, None, None).unwrap_err().kind()); } #[test] fn test_wallet_for_unknown_type() { init!("false"); - assert_eq!(error::INVALID_WALLET_CREATION.code_num, init_wallet("test_wallet_for_unknown_type", Some("UNKNOWN_WALLET_TYPE"), None, None).unwrap_err()); + assert_eq!(VcxErrorKind::WalletCreate, init_wallet("test_wallet_for_unknown_type", Some("UNKNOWN_WALLET_TYPE"), None, None).unwrap_err().kind()); } #[test] @@ -248,7 +245,7 @@ pub mod tests { // Open fails without Wallet Key Derivation set ::api::vcx::vcx_shutdown(false); - assert_eq!(open_wallet(wallet_n, None, None, None), Err(error::UNKNOWN_LIBINDY_ERROR.code_num)); + assert_eq!(open_wallet(wallet_n, None, None, None).unwrap_err().kind(), VcxErrorKind::UnknownLiibndyError); // Open works when set settings::set_config_value(settings::CONFIG_WALLET_KEY, settings::DEFAULT_WALLET_KEY); @@ -257,7 +254,7 @@ pub mod tests { // Delete fails ::api::vcx::vcx_shutdown(false); - assert_eq!(delete_wallet(wallet_n, None, None, None), Err(error::UNKNOWN_LIBINDY_ERROR.code_num)); + assert_eq!(delete_wallet(wallet_n, None, None, None).unwrap_err().kind(), VcxErrorKind::UnknownLiibndyError); // Delete works settings::set_config_value(settings::CONFIG_WALLET_KEY, settings::DEFAULT_WALLET_KEY); @@ -289,7 +286,7 @@ pub mod tests { open_wallet(&settings::DEFAULT_WALLET_NAME, None, None, None).unwrap(); // If wallet was successfully imported, there will be an error trying to add this duplicate record - assert_eq!(add_record(xtype, id, value, None), Err(error::DUPLICATE_WALLET_RECORD.code_num)); + assert_eq!(add_record(xtype, id, value, None).unwrap_err().kind(), VcxErrorKind::DuplicationWalletRecord); thread::sleep(Duration::from_secs(1)); ::api::vcx::vcx_shutdown(true); delete_import_wallet_path(export_path); @@ -301,25 +298,30 @@ pub mod tests { ::api::vcx::vcx_shutdown(true); // Invalid json - assert_eq!(import(""), Err(WalletError::CommonError(error::INVALID_JSON.code_num))); + let res = import("").unwrap_err(); + assert_eq!(res.kind(), VcxErrorKind::InvalidJson); let mut config = json!({}); // Missing wallet_key - assert_eq!(import(&config.to_string()), Err(WalletError::CommonError(error::MISSING_WALLET_KEY.code_num))); + let res = import(&config.to_string()).unwrap_err(); + assert_eq!(res.kind(), VcxErrorKind::MissingWalletKey); config[settings::CONFIG_WALLET_KEY] = serde_json::to_value("wallet_key1").unwrap(); // Missing wallet name - assert_eq!(import(&config.to_string()), Err(WalletError::CommonError(error::MISSING_WALLET_NAME.code_num))); + let res = import(&config.to_string()).unwrap_err(); + assert_eq!(res.kind(), VcxErrorKind::MissingWalletName); config[settings::CONFIG_WALLET_NAME] = serde_json::to_value("wallet_name1").unwrap(); // Missing exported_wallet_path - assert_eq!(import(&config.to_string()), Err(WalletError::CommonError(error::MISSING_EXPORTED_WALLET_PATH.code_num))); + let res = import(&config.to_string()).unwrap_err(); + assert_eq!(res.kind(), VcxErrorKind::MissingExportedWalletPath); config[settings::CONFIG_EXPORTED_WALLET_PATH] = serde_json::to_value( get_temp_dir_path(Some(settings::DEFAULT_EXPORTED_WALLET_PATH)).to_str().unwrap() ).unwrap(); // Missing backup_key - assert_eq!(import(&config.to_string()), Err(WalletError::CommonError(error::MISSING_BACKUP_KEY.code_num))); + let res = import(&config.to_string()).unwrap_err(); + assert_eq!(res.kind(), VcxErrorKind::MissingBackupKey); } #[test] @@ -334,7 +336,8 @@ pub mod tests { settings::CONFIG_EXPORTED_WALLET_PATH: export_path, settings::CONFIG_WALLET_BACKUP_KEY: settings::DEFAULT_WALLET_BACKUP_KEY, }).to_string(); - assert_eq!(import(&import_config), Err(WalletError::CommonError(error::WALLET_ALREADY_EXISTS.code_num))); + let res = import(&import_config).unwrap_err(); + assert_eq!(res.kind(), VcxErrorKind::DuplicationWallet); ::api::vcx::vcx_shutdown(true); delete_import_wallet_path(export_path); @@ -356,7 +359,8 @@ pub mod tests { settings::CONFIG_EXPORTED_WALLET_PATH: "DIFFERENT_PATH", settings::CONFIG_WALLET_BACKUP_KEY: backup_key, }).to_string(); - assert_eq!(import(&import_config), Err(WalletError::CommonError(error::IOERROR.code_num))); + let res = import(&import_config).unwrap_err(); + assert_eq!(res.kind(), VcxErrorKind::IOError); ::api::vcx::vcx_shutdown(true); delete_import_wallet_path(dir); @@ -380,7 +384,8 @@ pub mod tests { settings::CONFIG_EXPORTED_WALLET_PATH: export_path, settings::CONFIG_WALLET_BACKUP_KEY: bad_backup, }).to_string(); - assert_eq!(import(&import_config), Err(WalletError::CommonError(error::LIBINDY_INVALID_STRUCTURE.code_num))); + let res = import(&import_config).unwrap_err(); + assert_eq!(res.kind(), VcxErrorKind::LibindyInvalidStructure); ::api::vcx::vcx_shutdown(true); delete_import_wallet_path(export_path); @@ -409,7 +414,7 @@ pub mod tests { add_record(record_type, id, record, None).unwrap(); let rc = add_record(record_type, id, record, None); - assert_eq!(rc, Err(error::DUPLICATE_WALLET_RECORD.code_num)); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::DuplicationWalletRecord); } #[test] @@ -440,7 +445,8 @@ pub mod tests { let wallet_n = "test_retrieve_missing_record_fails"; let rc = get_record(record_type, id, &options); - assert_eq!(rc, Err(error::WALLET_RECORD_NOT_FOUND.code_num)); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::WalletRecordNotFound); + } #[test] @@ -471,7 +477,7 @@ pub mod tests { let id = "123"; let rc = delete_record(record_type, id); - assert_eq!(rc, Err(error::WALLET_RECORD_NOT_FOUND.code_num)); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::WalletRecordNotFound); } #[test] @@ -491,7 +497,7 @@ pub mod tests { add_record(record_type, id, record, None).unwrap(); delete_record(record_type, id).unwrap(); let rc = get_record(record_type, id, &options); - assert_eq!(rc, Err(error::WALLET_RECORD_NOT_FOUND.code_num)); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::WalletRecordNotFound); } #[test] @@ -504,7 +510,7 @@ pub mod tests { let wallet_n = "test_update_record_value_fails_with_no_initial_record"; let rc = update_record_value(record_type, id, record); - assert_eq!(rc, Err(error::WALLET_RECORD_NOT_FOUND.code_num)); + assert_eq!(rc.unwrap_err().kind(), VcxErrorKind::WalletRecordNotFound); } #[test] diff --git a/vcx/libvcx/tails.txt/6LQ9NFxbjUiZSYVXBZtivbWiPL2BkHBGsMJ3oaHTzvcc b/vcx/libvcx/tails.txt/6LQ9NFxbjUiZSYVXBZtivbWiPL2BkHBGsMJ3oaHTzvcc new file mode 100644 index 0000000000000000000000000000000000000000..702f3801e3bc7987b17314ba08ff37640cc0148a GIT binary patch literal 642 zcmV-|0)71e0tZ-yg`JeMH08J7iqJyZ65by^3K;I$N$M*cmOCT=z$7T<(=Vl>WAIuW z9>)4Yd<3K$Hf@E?!HR^w)3yUm^Az2WJIx=dZwpi(BxI3-&&E6%`|qcZ4`MJh+xRii z=^VPUsWI4IRs$oM+H%dKzA(Y3tMkCB0EI7}3+VdwSQ!e!+;jj}*<}^uM)Omt$U3D~ z#3f2xM4KpbbY{5ErU$sQc)wFzyR%Am&a9Av<6wS!VvOm@Bmebp9Y(qh&;W66Df*Um z-IbIk#RSmAe{oN0HtbG2>!qC=VcJ7fPaYT`3q6%smr5CqblM^{WEiB0b12E<268D# zjn)~WITDzvVXFNcN0J{pT^e~UW8~7&z^i2$RL_W~u_tMZa}kB+jXFh84W<&h$6(oxYYHi;Sb3FGSfIg;^+FFZ310* zIt!<;-P$SrzZ2cWBIv|Wtm}o@8OfCsP2ur8ViQb8K@)`+cXrdjmjg$zy6M}tC}MW6 zhCYDVPvv!kEN39(Jmlq(5_XteDH@uupQlCl9B+;w>VVC;X-h;r&+jkkCUZp-$0^BQ z=_9l>>D?UQ4D%gL)j*44vJ=EY+XtN#5e@!3GQGny+#!T25hz2uxuK2Noasp9VW%b` z(%2Os7jP9N`%PfeVu`~`X>zxKv$ c|InYP?tjns!|c~NGAocS(*19)#2fi3O0?cN!T<k`;f@n3oHnHsWL&9)ep={-5%n4tr2}zWQPOf<$@w`zu2K`sqE&HL30T{_;K87wVbG0?>>N2?^j}(5 zs@!0=r6fg3Py_F?*vZX^6`ousQz&p4mQf% z>k@P3Z9nH|Tlh)G0#G_$*icrq1Z0M!{;3oO;y&m!bDKp=d8u|%aK cpMuC8lPmYelR!kf1e?~02sL*KMRey?q3B^VfdBvi literal 0 HcmV?d00001 From fc37b38c277c4fa9821905f7397ca99575b08cf1 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Thu, 21 Feb 2019 18:49:55 +0300 Subject: [PATCH 06/28] Added API function to get error message Signed-off-by: artem.ivanov --- vcx/libvcx/src/api/connection.rs | 100 +++++----- vcx/libvcx/src/api/credential.rs | 77 ++++---- vcx/libvcx/src/api/credential_def.rs | 53 +++-- vcx/libvcx/src/api/disclosed_proof.rs | 83 ++++---- vcx/libvcx/src/api/issuer_credential.rs | 81 ++++---- vcx/libvcx/src/api/logger.rs | 29 ++- vcx/libvcx/src/api/proof.rs | 58 +++--- vcx/libvcx/src/api/return_types_u32.rs | 4 +- vcx/libvcx/src/api/schema.rs | 57 +++--- vcx/libvcx/src/api/utils.rs | 193 ++++++++++++------- vcx/libvcx/src/api/vcx.rs | 134 +++++++------ vcx/libvcx/src/api/wallet.rs | 116 ++++++----- vcx/libvcx/src/error/mod.rs | 45 ++++- vcx/libvcx/src/lib.rs | 2 + vcx/libvcx/src/utils/ccallback.rs | 2 +- vcx/libvcx/src/utils/cstring.rs | 14 +- vcx/libvcx/src/utils/libindy/callback_u32.rs | 4 +- 17 files changed, 561 insertions(+), 491 deletions(-) diff --git a/vcx/libvcx/src/api/connection.rs b/vcx/libvcx/src/api/connection.rs index 46d3f765da..2a51ba000b 100644 --- a/vcx/libvcx/src/api/connection.rs +++ b/vcx/libvcx/src/api/connection.rs @@ -1,12 +1,10 @@ -extern crate libc; - -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use utils::threadpool::spawn; use std::ptr; use connection::{get_source_id, create_connection, create_connection_with_invite, connect, to_string, get_state, release, is_valid_handle, update_state, from_string, get_invite_details, delete_connection}; +use error::prelude::*; /// Delete a Connection object and release its handle /// @@ -28,15 +26,16 @@ pub extern fn vcx_connection_delete_connection(command_handle: u32, err: u32)>) -> u32 { info!("vcx_delete_connection >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + if !is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } trace!("vcx_connection_delete_connection(command_handle: {}, connection_handle: {})", command_handle, connection_handle); spawn(move|| { match delete_connection(connection_handle) { Ok(_) => { - trace!("vcx_connection_delete_connection_cb(command_handle: {}, rc: {})", command_handle, 0); + trace!("vcx_connection_delete_connection_cb(command_handle: {}, rc: {})", command_handle, error::SUCCESS.message); cb(command_handle, error::SUCCESS.code_num); }, Err(e) => { @@ -69,14 +68,16 @@ pub extern fn vcx_connection_create(command_handle: u32, cb: Option) -> u32 { info!("vcx_connection_create >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + trace!("vcx_connection_create(command_handle: {}, source_id: {})", command_handle, source_id); + spawn(move|| { match create_connection(&source_id) { Ok(handle) => { trace!("vcx_connection_create_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), handle, source_id); + command_handle, error::SUCCESS.message, handle, source_id); cb(command_handle, error::SUCCESS.code_num, handle); }, Err(x) => { @@ -112,15 +113,15 @@ pub extern fn vcx_connection_create_with_invite(command_handle: u32, cb: Option) -> u32 { info!("vcx_connection_create_with_invite >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(invite_details, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(invite_details, VcxErrorKind::InvalidOption); trace!("vcx_connection_create_with_invite(command_handle: {}, source_id: {})", command_handle, source_id); spawn(move|| { match create_connection_with_invite(&source_id, &invite_details) { Ok(handle) => { trace!("vcx_connection_create_with_invite_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), handle, source_id); + command_handle, error::SUCCESS.message, handle, source_id); cb(command_handle, error::SUCCESS.code_num, handle); }, Err(x) => { @@ -158,15 +159,15 @@ pub extern fn vcx_connection_connect(command_handle:u32, cb: Option) -> u32 { info!("vcx_connection_connect >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !is_valid_handle(connection_handle) { error!("vcx_connection_get_state - invalid handle"); - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } let options = if !connection_options.is_null() { - check_useful_opt_c_str!(connection_options, error::INVALID_OPTION.code_num); + check_useful_opt_c_str!(connection_options, VcxErrorKind::InvalidOption); connection_options.to_owned() } else { @@ -183,13 +184,13 @@ pub extern fn vcx_connection_connect(command_handle:u32, match get_invite_details(connection_handle,true) { Ok(x) => { trace!("vcx_connection_connect_cb(command_handle: {}, connection_handle: {}, rc: {}, details: {}), source_id: {:?}", - command_handle, connection_handle, error_string(0), x, source_id); + command_handle, connection_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); }, Err(e) => { warn!("vcx_connection_connect_cb(command_handle: {}, connection_handle: {}, rc: {}, details: {}), source_id: {:?}", - command_handle, connection_handle, error_string(0), "null", source_id); + command_handle, connection_handle, error::SUCCESS.message, "null", source_id); // TODO: why Success????? cb(command_handle, error::SUCCESS.code_num, ptr::null_mut()); }, } @@ -224,7 +225,7 @@ pub extern fn vcx_connection_serialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_connection_serialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = get_source_id(connection_handle).unwrap_or_default(); trace!("vcx_connection_serialize(command_handle: {}, connection_handle: {}), source_id: {:?}", @@ -232,14 +233,14 @@ pub extern fn vcx_connection_serialize(command_handle: u32, if !is_valid_handle(connection_handle) { error!("vcx_connection_get_state - invalid handle"); - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } spawn(move|| { match to_string(connection_handle) { Ok(json) => { trace!("vcx_connection_serialize_cb(command_handle: {}, connection_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, connection_handle, error_string(0), json, source_id); + command_handle, connection_handle, error::SUCCESS.message, json, source_id); let msg = CStringUtils::string_to_cstring(json); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); }, @@ -273,8 +274,8 @@ pub extern fn vcx_connection_deserialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_connection_deserialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(connection_data, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(connection_data, VcxErrorKind::InvalidOption); trace!("vcx_connection_deserialize(command_handle: {}, connection_data: {})", command_handle, connection_data); @@ -283,7 +284,7 @@ pub extern fn vcx_connection_deserialize(command_handle: u32, Ok(x) => { let source_id = get_source_id(x).unwrap_or_default(); trace!("vcx_connection_deserialize_cb(command_handle: {}, rc: {}, handle: {}), source_id: {:?}", - command_handle, error_string(0), x, source_id); + command_handle, error::SUCCESS.message, x, source_id); (error::SUCCESS.code_num, x) }, Err(x) => { @@ -319,7 +320,7 @@ pub extern fn vcx_connection_update_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_connection_update_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = get_source_id(connection_handle).unwrap_or_default(); trace!("vcx_connection_update_state(command_handle: {}, connection_handle: {}), source_id: {:?}", @@ -327,19 +328,18 @@ pub extern fn vcx_connection_update_state(command_handle: u32, if !is_valid_handle(connection_handle) { error!("vcx_connection_get_state - invalid handle"); - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } spawn(move|| { let rc = match update_state(connection_handle) { Ok(x) => { trace!("vcx_connection_update_state_cb(command_handle: {}, rc: {}, connection_handle: {}, state: {}), source_id: {:?}", - command_handle, error_string(0), connection_handle, get_state(connection_handle), source_id); + command_handle, error::SUCCESS.message, connection_handle, get_state(connection_handle), source_id); x }, Err(x) => { warn!("vcx_connection_update_state_cb(command_handle: {}, rc: {}, connection_handle: {}, state: {}), source_id: {:?}", - // TODO: Refactor Error command_handle, x, connection_handle, get_state(connection_handle), source_id); x.into() }, @@ -369,7 +369,7 @@ pub extern fn vcx_connection_get_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_connection_get_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = get_source_id(connection_handle).unwrap_or_default(); trace!("vcx_connection_get_state(command_handle: {}, connection_handle: {}), source_id: {:?}", @@ -377,12 +377,12 @@ pub extern fn vcx_connection_get_state(command_handle: u32, if !is_valid_handle(connection_handle) { error!("vcx_connection_get_state - invalid handle"); - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } spawn(move|| { trace!("vcx_connection_get_state_cb(command_handle: {}, rc: {}, connection_handle: {}, state: {}), source_id: {:?}", - command_handle, error_string(0), connection_handle, get_state(connection_handle), source_id); + command_handle, error::SUCCESS.message, connection_handle, get_state(connection_handle), source_id); cb(command_handle, error::SUCCESS.code_num, get_state(connection_handle)); Ok(()) @@ -411,7 +411,7 @@ pub extern fn vcx_connection_invite_details(command_handle: u32, cb: Option) -> u32 { info!("vcx_connection_invite_details >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = get_source_id(connection_handle).unwrap_or_default(); trace!("vcx_connection_invite_details(command_handle: {}, connection_handle: {}, abbreviated: {}), source_id: {:?}", @@ -419,14 +419,14 @@ pub extern fn vcx_connection_invite_details(command_handle: u32, if !is_valid_handle(connection_handle) { error!("vcx_connection_get_state - invalid handle"); - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } spawn(move|| { match get_invite_details(connection_handle, abbreviated){ Ok(str) => { trace!("vcx_connection_invite_details_cb(command_handle: {}, connection_handle: {}, rc: {}, details: {}), source_id: {:?}", - command_handle, connection_handle, error_string(0), str, source_id); + command_handle, connection_handle, error::SUCCESS.message, str, source_id); let msg = CStringUtils::string_to_cstring(str); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); }, @@ -471,10 +471,10 @@ pub extern fn vcx_connection_send_message(command_handle: u32, cb: Option) -> u32 { info!("vcx_message_send >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(msg, error::INVALID_OPTION.code_num); - check_useful_c_str!(msg_type, error::INVALID_OPTION.code_num); - check_useful_c_str!(msg_title, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(msg, VcxErrorKind::InvalidOption); + check_useful_c_str!(msg_type, VcxErrorKind::InvalidOption); + check_useful_c_str!(msg_title, VcxErrorKind::InvalidOption); trace!("vcx_message_send(command_handle: {}, connection_handle: {}, msg: {}, msg_type: {}, msg_title: {})", command_handle, connection_handle, msg, msg_type, msg_title); @@ -483,7 +483,7 @@ pub extern fn vcx_connection_send_message(command_handle: u32, match ::messages::send_message::send_generic_message(connection_handle, &msg, &msg_type, &msg_title) { Ok(x) => { trace!("vcx_connection_send_message_cb(command_handle: {}, rc: {}, msg_id: {})", - command_handle, error::error_string(0), x); + command_handle, error::SUCCESS.message, x); let msg_id = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg_id.as_ptr()); @@ -530,15 +530,15 @@ pub extern fn vcx_connection_sign_data(command_handle: u32, trace!("vcx_connection_sign_data: >>> connection_handle: {}, data_raw: {:?}, data_len: {}", connection_handle, data_raw, data_len); - check_useful_c_byte_array!(data_raw, data_len, error::INVALID_OPTION.code_num, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_byte_array!(data_raw, data_len, VcxErrorKind::InvalidOption, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_connection_sign_data: entities >>> connection_handle: {}, data_raw: {:?}, data_len: {}", connection_handle, data_raw, data_len); if !is_valid_handle(connection_handle) { error!("vcx_connection_sign - invalid handle"); - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } let vk = match ::connection::get_pw_verkey(connection_handle) { @@ -550,7 +550,7 @@ pub extern fn vcx_connection_sign_data(command_handle: u32, match ::utils::libindy::crypto::sign(&vk, &data_raw) { Ok(x) => { trace!("vcx_connection_sign_data_cb(command_handle: {}, connection_handle: {}, rc: {}, signature: {:?})", - command_handle, connection_handle, error_string(0), x); + command_handle, connection_handle, error::SUCCESS.message, x); let (signature_raw, signature_len) = ::utils::cstring::vec_to_pointer(&x); cb(command_handle, error::SUCCESS.code_num, signature_raw, signature_len); @@ -602,16 +602,16 @@ pub extern fn vcx_connection_verify_signature(command_handle: u32, trace!("vcx_connection_verify_signature: >>> connection_handle: {}, data_raw: {:?}, data_len: {}, signature_raw: {:?}, signature_len: {}", connection_handle, data_raw, data_len, signature_raw, signature_len); - check_useful_c_byte_array!(data_raw, data_len, error::INVALID_OPTION.code_num, error::INVALID_OPTION.code_num); - check_useful_c_byte_array!(signature_raw, signature_len, error::INVALID_OPTION.code_num, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_byte_array!(data_raw, data_len, VcxErrorKind::InvalidOption, VcxErrorKind::InvalidOption); + check_useful_c_byte_array!(signature_raw, signature_len, VcxErrorKind::InvalidOption, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_connection_verify_signature: entities >>> connection_handle: {}, data_raw: {:?}, data_len: {}, signature_raw: {:?}, signature_len: {}", connection_handle, data_raw, data_len, signature_raw, signature_len); if !is_valid_handle(connection_handle) { error!("vcx_connection_verify_signature - invalid handle"); - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } let vk = match ::connection::get_their_pw_verkey(connection_handle) { @@ -623,7 +623,7 @@ pub extern fn vcx_connection_verify_signature(command_handle: u32, match ::utils::libindy::crypto::verify(&vk, &data_raw, &signature_raw) { Ok(x) => { trace!("vcx_connection_verify_signature_cb(command_handle: {}, rc: {}, valid: {})", - command_handle, error_string(0), x); + command_handle, error::SUCCESS.message, x); cb(command_handle, error::SUCCESS.code_num, x); }, @@ -656,7 +656,7 @@ pub extern fn vcx_connection_release(connection_handle: u32) -> u32 { match release(connection_handle) { Ok(_) => { trace!("vcx_connection_release(connection_handle: {}, rc: {}), source_id: {:?}", - connection_handle, error_string(error::SUCCESS.code_num), source_id); + connection_handle, error::SUCCESS.message, source_id); error::SUCCESS.code_num }, Err(e) => { diff --git a/vcx/libvcx/src/api/credential.rs b/vcx/libvcx/src/api/credential.rs index b655912ad6..fe82c8bef3 100644 --- a/vcx/libvcx/src/api/credential.rs +++ b/vcx/libvcx/src/api/credential.rs @@ -1,14 +1,12 @@ -extern crate libc; - use serde_json; -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use connection; use credential; use std::ptr; use utils::threadpool::spawn; +use error::prelude::*; /// Retrieves Payment Info from a Credential /// @@ -28,7 +26,7 @@ pub extern fn vcx_credential_get_payment_info(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_get_payment_info >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); spawn(move || { match credential::get_payment_information(credential_handle) { Ok(p) => { @@ -82,9 +80,9 @@ pub extern fn vcx_credential_create_with_offer(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_create_with_offer >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(offer, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(offer, VcxErrorKind::InvalidOption); trace!("vcx_credential_create_with_offer(command_handle: {}, source_id: {}, offer: {})", command_handle, source_id, offer); @@ -93,7 +91,7 @@ pub extern fn vcx_credential_create_with_offer(command_handle: u32, match credential::credential_create_with_offer(&source_id, &offer) { Ok(x) => { trace!("vcx_credential_create_with_offer_cb(command_handle: {}, source_id: {}, rc: {}, handle: {})", - command_handle, source_id, error_string(0), x); + command_handle, source_id, error::SUCCESS.message, x); cb(command_handle, error::SUCCESS.code_num, x) } Err(x) => { @@ -128,9 +126,9 @@ pub extern fn vcx_get_credential(command_handle: u32, cb: Option) -> u32 { info!("vcx_get_credential >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !credential::is_valid_handle(credential_handle) { - return error::INVALID_CREDENTIAL_HANDLE.code_num + return VcxError::from(VcxErrorKind::InvalidCredentialHandle).into() } let source_id = credential::get_source_id(credential_handle).unwrap_or_default(); @@ -182,9 +180,9 @@ pub extern fn vcx_credential_create_with_msgid(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_create_with_msgid >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(msg_id, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(msg_id, VcxErrorKind::InvalidOption); trace!("vcx_credential_create_with_msgid(command_handle: {}, source_id: {}, connection_handle: {}, msg_id: {})", command_handle, source_id, connection_handle, msg_id); @@ -200,7 +198,7 @@ pub extern fn vcx_credential_create_with_msgid(command_handle: u32, }; let c_offer = CStringUtils::string_to_cstring(offer_string); trace!("vcx_credential_create_with_offer_cb(command_handle: {}, source_id: {}, rc: {}, handle: {}) source_id: {}", - command_handle, source_id, error_string(0), handle, source_id); + command_handle, source_id, error::SUCCESS.message, handle, source_id); cb(command_handle, error::SUCCESS.code_num, handle, c_offer.as_ptr()) } Err(e) => { @@ -240,14 +238,14 @@ pub extern fn vcx_credential_send_request(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_send_request >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !credential::is_valid_handle(credential_handle) { - return error::INVALID_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidCredentialHandle).into() } if !connection::is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } let source_id = credential::get_source_id(credential_handle).unwrap_or_default(); @@ -291,10 +289,10 @@ pub extern fn vcx_credential_get_offers(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_get_offers >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !connection::is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } trace!("vcx_credential_get_offers(command_handle: {}, connection_handle: {})", @@ -339,10 +337,10 @@ pub extern fn vcx_credential_update_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_update_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !credential::is_valid_handle(credential_handle) { - return error::INVALID_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidCredentialHandle).into() } let source_id = credential::get_source_id(credential_handle).unwrap_or_default(); @@ -362,7 +360,7 @@ pub extern fn vcx_credential_update_state(command_handle: u32, let state = match credential::get_state(credential_handle) { Ok(s) => { trace!("vcx_credential_update_state_cb(command_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, error_string(0), s, source_id); + command_handle, error::SUCCESS.message, s, source_id); cb(command_handle, error::SUCCESS.code_num, s) } Err(e) => { @@ -394,10 +392,10 @@ pub extern fn vcx_credential_get_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_get_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !credential::is_valid_handle(handle) { - return error::INVALID_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidCredentialHandle).into() } let source_id = credential::get_source_id(handle).unwrap_or_default(); @@ -408,7 +406,7 @@ pub extern fn vcx_credential_get_state(command_handle: u32, match credential::get_state(handle) { Ok(s) => { trace!("vcx_credential_get_state_cb(command_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, error_string(0), s, source_id); + command_handle, error::SUCCESS.message, s, source_id); cb(command_handle, error::SUCCESS.code_num, s) } Err(e) => { @@ -442,10 +440,10 @@ pub extern fn vcx_credential_serialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_serialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !credential::is_valid_handle(handle) { - return error::INVALID_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidCredentialHandle).into() } let source_id = credential::get_source_id(handle).unwrap_or_default(); @@ -456,7 +454,7 @@ pub extern fn vcx_credential_serialize(command_handle: u32, match credential::to_string(handle) { Ok(x) => { trace!("vcx_credential_serialize_cb(command_handle: {}, rc: {}, data: {}), source_id: {:?}", - command_handle, error_string(0), x, source_id); + command_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); } @@ -491,8 +489,8 @@ pub extern fn vcx_credential_deserialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_deserialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(credential_data, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(credential_data, VcxErrorKind::InvalidOption); trace!("vcx_credential_deserialize(command_handle: {}, credential_data: {})", command_handle, credential_data); @@ -501,9 +499,9 @@ pub extern fn vcx_credential_deserialize(command_handle: u32, match credential::from_string(&credential_data) { Ok(x) => { trace!("vcx_credential_deserialize_cb(command_handle: {}, rc: {}, credential_handle: {}) source_id: {}", - command_handle, error_string(0), x, credential::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, credential::get_source_id(x).unwrap_or_default()); - cb(command_handle, 0, x); + cb(command_handle, error::SUCCESS.code_num, x); } Err(x) => { error!("vcx_credential_deserialize_cb(command_handle: {}, rc: {}, credential_handle: {}) source_id: {}", @@ -533,7 +531,7 @@ pub extern fn vcx_credential_release(handle: u32) -> u32 { match credential::release(handle) { Ok(_) => { trace!("vcx_credential_release(handle: {}, rc: {}), source_id: {:?}", - handle, error_string(0), source_id); + handle, error::SUCCESS.message, source_id); error::SUCCESS.code_num } @@ -569,7 +567,7 @@ pub extern fn vcx_credential_get_payment_txn(command_handle: u32, cb: Option) -> u32 { info!("vcx_credential_get_payment_txn >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = credential::get_source_id(handle).unwrap_or_default(); trace!("vcx_credential_get_payment_txn(command_handle: {}) source_id: {}", command_handle, source_id); @@ -580,15 +578,16 @@ pub extern fn vcx_credential_get_payment_txn(command_handle: u32, match serde_json::to_string(&x) { Ok(x) => { trace!("vcx_credential_get_payment_txn_cb(command_handle: {}, rc: {}, : {}), source_id: {}", - command_handle, error_string(0), x, credential::get_source_id(handle).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, credential::get_source_id(handle).unwrap_or_default()); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, 0, msg.as_ptr()); } - Err(_) => { + Err(e) => { + let err = VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize payment txn: {:?}", e)); error!("vcx_credential_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {}", - command_handle, error_string(error::INVALID_JSON.code_num), "null", credential::get_source_id(handle).unwrap_or_default()); - cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); + command_handle, err, "null", credential::get_source_id(handle).unwrap_or_default()); + cb(command_handle, err.into(), ptr::null_mut()); } } } diff --git a/vcx/libvcx/src/api/credential_def.rs b/vcx/libvcx/src/api/credential_def.rs index b4ea3ff54a..1b30dc6024 100644 --- a/vcx/libvcx/src/api/credential_def.rs +++ b/vcx/libvcx/src/api/credential_def.rs @@ -1,14 +1,12 @@ -extern crate libc; - use serde_json; -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use std::ptr; use credential_def; use settings; use utils::threadpool::spawn; +use error::prelude::*; /// Create a new CredentialDef object that can create credential definitions on the ledger /// @@ -49,15 +47,15 @@ pub extern fn vcx_credentialdef_create(command_handle: u32, cb: Option) -> u32 { info!("vcx_credentialdef_create >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(credentialdef_name, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(schema_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(tag, error::INVALID_OPTION.code_num); - check_useful_c_str!(revocation_details, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(credentialdef_name, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(schema_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(tag, VcxErrorKind::InvalidOption); + check_useful_c_str!(revocation_details, VcxErrorKind::InvalidOption); let issuer_did: String = if !issuer_did.is_null() { - check_useful_c_str!(issuer_did, error::INVALID_OPTION.code_num); + check_useful_c_str!(issuer_did, VcxErrorKind::InvalidOption); issuer_did.to_owned() } else { match settings::get_config_value(settings::CONFIG_INSTITUTION_DID) { @@ -84,7 +82,7 @@ pub extern fn vcx_credentialdef_create(command_handle: u32, revocation_details) { Ok(x) => { trace!("vcx_credential_def_create_cb(command_handle: {}, rc: {}, credentialdef_handle: {}), source_id: {:?}", - command_handle, error_string(0), x, credential_def::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, credential_def::get_source_id(x).unwrap_or_default()); (error::SUCCESS.code_num, x) }, Err(x) => { @@ -118,21 +116,21 @@ pub extern fn vcx_credentialdef_serialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_credentialdef_serialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = credential_def::get_source_id(credentialdef_handle).unwrap_or_default(); trace!("vcx_credentialdef_serialize(command_handle: {}, credentialdef_handle: {}), source_id: {:?}", command_handle, credentialdef_handle, source_id); if !credential_def::is_valid_handle(credentialdef_handle) { - return error::INVALID_CREDENTIAL_DEF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidCredDefHandle).into() }; spawn(move|| { match credential_def::to_string(credentialdef_handle) { Ok(x) => { trace!("vcx_credentialdef_serialize_cb(command_handle: {}, credentialdef_handle: {}, rc: {}, state: {}), source_id: {:?}", - command_handle, credentialdef_handle, error_string(0), x, source_id); + command_handle, credentialdef_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); }, @@ -166,8 +164,8 @@ pub extern fn vcx_credentialdef_deserialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_credentialdef_deserialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(credentialdef_data, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(credentialdef_data, VcxErrorKind::InvalidOption); trace!("vcx_credentialdef_deserialize(command_handle: {}, credentialdef_data: {})", command_handle, credentialdef_data); @@ -175,7 +173,7 @@ pub extern fn vcx_credentialdef_deserialize(command_handle: u32, let (rc, handle) = match credential_def::from_string(&credentialdef_data) { Ok(x) => { trace!("vcx_credentialdef_deserialize_cb(command_handle: {}, rc: {}, handle: {}), source_id: {}", - command_handle, error_string(0), x, credential_def::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, credential_def::get_source_id(x).unwrap_or_default()); (error::SUCCESS.code_num, x) }, Err(e) => { @@ -207,19 +205,19 @@ pub extern fn vcx_credentialdef_get_cred_def_id(command_handle: u32, cb: Option) -> u32 { info!("vcx_credentialdef_get_cred_def_id >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = credential_def::get_source_id(cred_def_handle).unwrap_or_default(); trace!("vcx_credentialdef_get_cred_def_id(command_handle: {}, cred_def_handle: {}) source_id: {}", command_handle, cred_def_handle, source_id); if !credential_def::is_valid_handle(cred_def_handle) { - return error::INVALID_CREDENTIAL_DEF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidCredDefHandle).into() } spawn(move|| { match credential_def::get_cred_def_id(cred_def_handle) { Ok(x) => { trace!("vcx_credentialdef_get_cred_def_id(command_handle: {}, cred_def_handle: {}, rc: {}, cred_def_id: {}) source_id: {}", - command_handle, cred_def_handle, error_string(0), x, source_id); + command_handle, cred_def_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); }, @@ -260,7 +258,7 @@ pub extern fn vcx_credentialdef_get_payment_txn(command_handle: u32, cb: Option) -> u32 { info!("vcx_credentialdef_get_payment_txn >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = credential_def::get_source_id(handle).unwrap_or_default(); trace!("vcx_credentialdef_get_payment_txn(command_handle: {}) source_id: {}", command_handle, source_id); @@ -271,15 +269,16 @@ pub extern fn vcx_credentialdef_get_payment_txn(command_handle: u32, match serde_json::to_string(&x) { Ok(x) => { trace!("vcx_credentialdef_get_payment_txn_cb(command_handle: {}, rc: {}, : {}), source_id: {}", - command_handle, error_string(0), x, credential_def::get_source_id(handle).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, credential_def::get_source_id(handle).unwrap_or_default()); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, 0, msg.as_ptr()); } - Err(_) => { + Err(e) => { + let err = VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize payment txn: {:?}", e)); error!("vcx_credentialdef_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {}", - command_handle, error::INVALID_JSON.message, "null", credential_def::get_source_id(handle).unwrap_or_default()); - cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); + command_handle, err, "null", credential_def::get_source_id(handle).unwrap_or_default()); + cb(command_handle, err.into(), ptr::null_mut()); } } }, @@ -311,7 +310,7 @@ pub extern fn vcx_credentialdef_release(credentialdef_handle: u32) -> u32 { match credential_def::release(credentialdef_handle) { Ok(_) => { trace!("vcx_credentialdef_release(credentialdef_handle: {}, rc: {}), source_id: {}", - credentialdef_handle, error_string(0), source_id); + credentialdef_handle, error::SUCCESS.message, source_id); error::SUCCESS.code_num }, diff --git a/vcx/libvcx/src/api/disclosed_proof.rs b/vcx/libvcx/src/api/disclosed_proof.rs index 98cf066a54..0e862da96b 100644 --- a/vcx/libvcx/src/api/disclosed_proof.rs +++ b/vcx/libvcx/src/api/disclosed_proof.rs @@ -1,13 +1,11 @@ -extern crate libc; - -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use connection; use disclosed_proof; use std::ptr; use utils::threadpool::spawn; +use error::prelude::*; /// Create a proof for fulfilling a corresponding proof request /// @@ -30,9 +28,9 @@ pub extern fn vcx_disclosed_proof_create_with_request(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_create_with_request >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(proof_req, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(proof_req, VcxErrorKind::InvalidOption); trace!("vcx_disclosed_proof_create_with_request(command_handle: {}, source_id: {}, proof_req: {})", command_handle, source_id, proof_req); @@ -41,7 +39,7 @@ pub extern fn vcx_disclosed_proof_create_with_request(command_handle: u32, match disclosed_proof::create_proof(&source_id, &proof_req) { Ok(x) => { trace!("vcx_disclosed_proof_create_with_request_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle,error::SUCCESS.message, x, source_id); cb(command_handle, 0, x); } Err(x) => { @@ -82,9 +80,9 @@ pub extern fn vcx_disclosed_proof_create_with_msgid(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_create_with_msgid >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(msg_id, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(msg_id, VcxErrorKind::InvalidOption); trace!("vcx_disclosed_proof_create_with_msgid(command_handle: {}, source_id: {}, connection_handle: {}, msg_id: {})", command_handle, source_id, connection_handle, msg_id); @@ -95,7 +93,7 @@ pub extern fn vcx_disclosed_proof_create_with_msgid(command_handle: u32, match disclosed_proof::create_proof(&source_id, &request) { Ok(handle) => { trace!("vcx_disclosed_proof_create_with_msgid_cb(command_handle: {}, rc: {}, handle: {}, proof_req: {}) source_id: {}", - command_handle, error_string(0), handle, request, source_id); + command_handle, error::SUCCESS.message, handle, request, source_id); let msg = CStringUtils::string_to_cstring(request); cb(command_handle, error::SUCCESS.code_num, handle, msg.as_ptr()) } @@ -136,14 +134,14 @@ pub extern fn vcx_disclosed_proof_send_proof(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_send_proof >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !disclosed_proof::is_valid_handle(proof_handle) { - return error::INVALID_DISCLOSED_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidDisclosedProofHandle).into() } if !connection::is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); @@ -154,7 +152,7 @@ pub extern fn vcx_disclosed_proof_send_proof(command_handle: u32, let err = match disclosed_proof::send_proof(proof_handle, connection_handle) { Ok(x) => { trace!("vcx_disclosed_proof_send_proof_cb(command_handle: {}, rc: {}) source_id: {}", - command_handle, error_string(0), source_id); + command_handle, error::SUCCESS.message, source_id); cb(command_handle, error::SUCCESS.code_num); } Err(x) => { @@ -187,10 +185,10 @@ pub extern fn vcx_disclosed_proof_get_requests(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_get_requests >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !connection::is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } trace!("vcx_disclosed_proof_get_requests(command_handle: {}, connection_handle: {})", @@ -200,13 +198,13 @@ pub extern fn vcx_disclosed_proof_get_requests(command_handle: u32, match disclosed_proof::get_proof_request_messages(connection_handle, None) { Ok(x) => { trace!("vcx_disclosed_proof_get_requests_cb(command_handle: {}, rc: {}, msg: {})", - command_handle, error_string(0), x); + command_handle, error::SUCCESS.message, x); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); } Err(x) => { error!("vcx_disclosed_proof_get_requests_cb(command_handle: {}, rc: {}, msg: {})", - command_handle, error_string(0), x); + command_handle, error::SUCCESS.message, x); cb(command_handle, x.into(), ptr::null_mut()); } }; @@ -234,10 +232,10 @@ pub extern fn vcx_disclosed_proof_get_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_get_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !disclosed_proof::is_valid_handle(proof_handle) { - return error::INVALID_DISCLOSED_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidDisclosedProofHandle).into() } let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); @@ -248,7 +246,7 @@ pub extern fn vcx_disclosed_proof_get_state(command_handle: u32, match disclosed_proof::get_state(proof_handle) { Ok(s) => { trace!("vcx_disclosed_proof_get_state_cb(command_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, error_string(0), s, source_id); + command_handle, error::SUCCESS.message, s, source_id); cb(command_handle, error::SUCCESS.code_num, s) } Err(e) => { @@ -281,10 +279,10 @@ pub extern fn vcx_disclosed_proof_update_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_update_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !disclosed_proof::is_valid_handle(proof_handle) { - return error::INVALID_DISCLOSED_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidDisclosedProofHandle).into() } let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); @@ -295,7 +293,7 @@ pub extern fn vcx_disclosed_proof_update_state(command_handle: u32, match disclosed_proof::update_state(proof_handle) { Ok(s) => { trace!("vcx_disclosed_proof_update_state_cb(command_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, error_string(0), s, source_id); + command_handle, error::SUCCESS.message, s, source_id); cb(command_handle, error::SUCCESS.code_num, s) } Err(e) => { @@ -328,10 +326,10 @@ pub extern fn vcx_disclosed_proof_serialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_serialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !disclosed_proof::is_valid_handle(proof_handle) { - return error::INVALID_DISCLOSED_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidDisclosedProofHandle).into() } let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); @@ -342,7 +340,7 @@ pub extern fn vcx_disclosed_proof_serialize(command_handle: u32, match disclosed_proof::to_string(proof_handle) { Ok(x) => { trace!("vcx_disclosed_proof_serialize_cb(command_handle: {}, rc: {}, data: {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); } @@ -377,8 +375,8 @@ pub extern fn vcx_disclosed_proof_deserialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_deserialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(proof_data, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(proof_data, VcxErrorKind::InvalidOption); trace!("vcx_disclosed_proof_deserialize(command_handle: {}, proof_data: {})", command_handle, proof_data); @@ -387,7 +385,7 @@ pub extern fn vcx_disclosed_proof_deserialize(command_handle: u32, match disclosed_proof::from_string(&proof_data) { Ok(x) => { trace!("vcx_disclosed_proof_deserialize_cb(command_handle: {}, rc: {}, proof_handle: {}) source_id: {}", - command_handle, error_string(0), x, disclosed_proof::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, disclosed_proof::get_source_id(x).unwrap_or_default()); cb(command_handle, 0, x); } @@ -421,10 +419,10 @@ pub extern fn vcx_disclosed_proof_retrieve_credentials(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_retrieve_credentials >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !disclosed_proof::is_valid_handle(proof_handle) { - return error::INVALID_DISCLOSED_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidDisclosedProofHandle).into() } let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); @@ -435,7 +433,7 @@ pub extern fn vcx_disclosed_proof_retrieve_credentials(command_handle: u32, match disclosed_proof::retrieve_credentials(proof_handle) { Ok(x) => { trace!("vcx_disclosed_proof_retrieve_credentials(command_handle: {}, rc: {}, data: {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); } @@ -500,12 +498,12 @@ pub extern fn vcx_disclosed_proof_generate_proof(command_handle: u32, cb: Option) -> u32 { info!("vcx_disclosed_proof_generate_proof >>>"); - check_useful_c_str!(selected_credentials, error::INVALID_OPTION.code_num); - check_useful_c_str!(self_attested_attrs, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(selected_credentials, VcxErrorKind::InvalidOption); + check_useful_c_str!(self_attested_attrs, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !disclosed_proof::is_valid_handle(proof_handle) { - return error::INVALID_DISCLOSED_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidDisclosedProofHandle).into() } let source_id = disclosed_proof::get_source_id(proof_handle).unwrap_or_default(); @@ -516,7 +514,7 @@ pub extern fn vcx_disclosed_proof_generate_proof(command_handle: u32, match disclosed_proof::generate_proof(proof_handle, selected_credentials, self_attested_attrs) { Ok(_) => { trace!("vcx_disclosed_proof_generate_proof(command_handle: {}, rc: {}) source_id: {}", - command_handle, error::SUCCESS.code_num, source_id); + command_handle, error::SUCCESS.message, source_id); cb(command_handle, error::SUCCESS.code_num); } Err(x) => { @@ -547,10 +545,9 @@ pub extern fn vcx_disclosed_proof_release(handle: u32) -> u32 { let source_id = disclosed_proof::get_source_id(handle).unwrap_or_default(); match disclosed_proof::release(handle) { Ok(_) => { - let success_err_code = error::SUCCESS.code_num; trace!("vcx_disclosed_proof_release(handle: {}, rc: {}), source_id: {:?}", - handle, error_string(success_err_code), source_id); - success_err_code + handle, error::SUCCESS.message, source_id); + error::SUCCESS.code_num } Err(e) => { error!("vcx_disclosed_proof_release(handle: {}, rc: {}), source_id: {:?}", diff --git a/vcx/libvcx/src/api/issuer_credential.rs b/vcx/libvcx/src/api/issuer_credential.rs index 93486c285d..d6e1d099a8 100644 --- a/vcx/libvcx/src/api/issuer_credential.rs +++ b/vcx/libvcx/src/api/issuer_credential.rs @@ -1,15 +1,13 @@ -extern crate libc; - use serde_json; -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use connection; use settings; use issuer_credential; use std::ptr; use utils::threadpool::spawn; +use error::prelude::*; /// Create a Issuer Credential object that provides a credential for an enterprise's user /// Assumes a credential definition has been written to the ledger. @@ -48,14 +46,14 @@ pub extern fn vcx_issuer_create_credential(command_handle: u32, cb: Option) -> u32 { info!("vcx_issuer_create_credential >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(credential_data, error::INVALID_OPTION.code_num); - check_useful_c_str!(credential_name, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(price, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(credential_data, VcxErrorKind::InvalidOption); + check_useful_c_str!(credential_name, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(price, VcxErrorKind::InvalidOption); let issuer_did: String = if !issuer_did.is_null() { - check_useful_c_str!(issuer_did, error::INVALID_OPTION.code_num); + check_useful_c_str!(issuer_did, VcxErrorKind::InvalidOption); issuer_did.to_owned() } else { match settings::get_config_value(settings::CONFIG_INSTITUTION_DID) { @@ -66,11 +64,11 @@ pub extern fn vcx_issuer_create_credential(command_handle: u32, let price: u64 = match price.parse::() { Ok(x) => x, - Err(_) => return error::INVALID_OPTION.code_num, + Err(err) => return VcxError::from_msg(VcxErrorKind::InvalidOption, format!("Cannot parse price: {}", err)).into(), }; if !::credential_def::is_valid_handle(cred_def_handle) { - return error::INVALID_CREDENTIAL_DEF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidCredDefHandle).into() } trace!("vcx_issuer_create_credential(command_handle: {}, source_id: {}, cred_def_handle: {}, issuer_did: {}, credential_data: {}, credential_name: {})", @@ -85,7 +83,7 @@ pub extern fn vcx_issuer_create_credential(command_handle: u32, let (rc, handle) = match issuer_credential::issuer_credential_create(cred_def_handle, source_id, issuer_did, credential_name, credential_data, price) { Ok(x) => { trace!("vcx_issuer_create_credential_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), x, issuer_credential::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, issuer_credential::get_source_id(x).unwrap_or_default()); (error::SUCCESS.code_num, x) } Err(x) => { @@ -123,25 +121,25 @@ pub extern fn vcx_issuer_send_credential_offer(command_handle: u32, cb: Option) -> u32 { info!("vcx_issuer_send_credential_offer >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_issuer_send_credential(command_handle: {}, credential_handle: {}, connection_handle: {}) source_id: {}", command_handle, credential_handle, connection_handle, source_id); if !issuer_credential::is_valid_handle(credential_handle) { - return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidIssuerCredentialHandle).into() } if !connection::is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } spawn(move || { let err = match issuer_credential::send_credential_offer(credential_handle, connection_handle) { Ok(x) => { trace!("vcx_issuer_send_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {}", - command_handle, credential_handle, error_string(x), source_id); + command_handle, credential_handle, error::SUCCESS.message, source_id); x } Err(x) => { @@ -176,21 +174,21 @@ pub extern fn vcx_issuer_credential_update_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_issuer_credential_update_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_issuer_credential_update_state(command_handle: {}, credential_handle: {}) source_id: {}", command_handle, credential_handle, source_id); if !issuer_credential::is_valid_handle(credential_handle) { - return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidIssuerCredentialHandle).into() } spawn(move || { match issuer_credential::update_state(credential_handle) { Ok(x) => { trace!("vcx_issuer_credential_update_state_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, credential_handle, error_string(0), x, source_id); + command_handle, credential_handle, error::SUCCESS.message, x, source_id); cb(command_handle, error::SUCCESS.code_num, x); } Err(x) => { @@ -223,21 +221,21 @@ pub extern fn vcx_issuer_credential_get_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_issuer_credential_get_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); trace!("vcx_issuer_credential_get_state(command_handle: {}, credential_handle: {}) source_id: {}", command_handle, credential_handle, source_id); if !issuer_credential::is_valid_handle(credential_handle) { - return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidIssuerCredentialHandle).into() } spawn(move || { match issuer_credential::get_state(credential_handle) { Ok(x) => { trace!("vcx_issuer_credential_get_state_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, credential_handle, 0, x, source_id); + command_handle, credential_handle, error::SUCCESS.message, x, source_id); cb(command_handle, error::SUCCESS.code_num, x); } Err(x) => { @@ -285,14 +283,14 @@ pub extern fn vcx_issuer_send_credential(command_handle: u32, cb: Option) -> u32 { info!("vcx_issuer_send_credential >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !issuer_credential::is_valid_handle(credential_handle) { - return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidIssuerCredentialHandle).into() } if !connection::is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); @@ -302,7 +300,7 @@ pub extern fn vcx_issuer_send_credential(command_handle: u32, let err = match issuer_credential::send_credential(credential_handle, connection_handle) { Ok(x) => { trace!("vcx_issuer_send_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {}", - command_handle, credential_handle, error_string(x), source_id); + command_handle, credential_handle, error::SUCCESS.message, source_id); x } Err(x) => { @@ -343,10 +341,10 @@ pub extern fn vcx_issuer_credential_serialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_issuer_credential_serialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !issuer_credential::is_valid_handle(credential_handle) { - return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidIssuerCredentialHandle).into() } let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); @@ -356,7 +354,7 @@ pub extern fn vcx_issuer_credential_serialize(command_handle: u32, match issuer_credential::to_string(credential_handle) { Ok(x) => { trace!("vcx_issuer_credential_serialize_cb(command_handle: {}, credential_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, credential_handle, error_string(0), x, source_id); + command_handle, credential_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); } @@ -390,8 +388,8 @@ pub extern fn vcx_issuer_credential_deserialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_issuer_credential_deserialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(credential_data, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(credential_data, VcxErrorKind::InvalidOption); trace!("vcx_issuer_credential_deserialize(command_handle: {}, credential_data: {})", command_handle, credential_data); @@ -399,7 +397,7 @@ pub extern fn vcx_issuer_credential_deserialize(command_handle: u32, let (rc, handle) = match issuer_credential::from_string(&credential_data) { Ok(x) => { trace!("vcx_issuer_credential_deserialize_cb(command_handle: {}, rc: {}, handle: {}), source_id: {}", - command_handle, error_string(0), x, issuer_credential::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, issuer_credential::get_source_id(x).unwrap_or_default()); (error::SUCCESS.code_num, x) } Err(x) => { @@ -431,7 +429,7 @@ pub extern fn vcx_issuer_credential_release(credential_handle: u32) -> u32 { match issuer_credential::release(credential_handle) { Ok(_) => { trace!("(vcx_issuer_credential_release credential_handle: {}, rc: {}), source_id: {}", - credential_handle, error_string(0), source_id); + credential_handle, error::SUCCESS.message, source_id); error::SUCCESS.code_num } Err(e) => { @@ -466,7 +464,7 @@ pub extern fn vcx_issuer_credential_get_payment_txn(command_handle: u32, cb: Option) -> u32 { info!("vcx_issuer_credential_get_payment_txn >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = issuer_credential::get_source_id(handle).unwrap_or_default(); trace!("vcx_issuer_credential_get_payment_txn(command_handle: {}) source_id: {}", command_handle, source_id); @@ -477,15 +475,16 @@ pub extern fn vcx_issuer_credential_get_payment_txn(command_handle: u32, match serde_json::to_string(&x) { Ok(x) => { trace!("vcx_issuer_credential_get_payment_txn_cb(command_handle: {}, rc: {}, : {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, 0, msg.as_ptr()); } Err(e) => { + let err = VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize payment txn: {}", e)); error!("vcx_issuer_credential_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}) source_id: {}", - command_handle, error::INVALID_JSON.message, "null", source_id); - cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); + command_handle, err, "null", source_id); + cb(command_handle, err.into(), ptr::null_mut()); } } } @@ -517,10 +516,10 @@ pub extern fn vcx_issuer_credential_get_payment_txn(command_handle: u32, pub extern fn vcx_issuer_revoke_credential(command_handle: u32, credential_handle: u32, cb: Option) -> u32 { - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); if !issuer_credential::is_valid_handle(credential_handle) { - return error::INVALID_ISSUER_CREDENTIAL_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidIssuerCredentialHandle).into() } let source_id = issuer_credential::get_source_id(credential_handle).unwrap_or_default(); @@ -531,7 +530,7 @@ pub extern fn vcx_issuer_revoke_credential(command_handle: u32, let err = match issuer_credential::revoke_credential(credential_handle) { Ok(_) => { info!("vcx_issuer_revoke_credential_cb(command_handle: {}, credential_handle: {}, rc: {}) source_id: {}", - command_handle, credential_handle, error_string(error::SUCCESS.code_num), source_id); + command_handle, credential_handle, error::SUCCESS.message, source_id); error::SUCCESS.code_num } Err(x) => { diff --git a/vcx/libvcx/src/api/logger.rs b/vcx/libvcx/src/api/logger.rs index 4a02320afa..8b1e659b06 100644 --- a/vcx/libvcx/src/api/logger.rs +++ b/vcx/libvcx/src/api/logger.rs @@ -1,10 +1,8 @@ -extern crate libc; - -use utils::logger::{ EnabledCB, FlushCB, LibvcxLogger, LibvcxDefaultLogger, LogCB, LOGGER_STATE, CVoid }; +use libc::c_char; +use utils::logger::{EnabledCB, FlushCB, LibvcxLogger, LibvcxDefaultLogger, LogCB, LOGGER_STATE, CVoid}; use utils::cstring::CStringUtils; -use self::libc::{c_char}; - -use utils::error::{ INVALID_CONFIGURATION, SUCCESS }; +use utils::error::SUCCESS; +use error::prelude::*; /// Set default logger implementation. /// @@ -22,7 +20,7 @@ use utils::error::{ INVALID_CONFIGURATION, SUCCESS }; pub extern fn vcx_set_default_logger(pattern: *const c_char) -> u32 { info!("vcx_set_default_logger >>>"); - check_useful_opt_c_str!(pattern, INVALID_CONFIGURATION.code_num); + check_useful_opt_c_str!(pattern, VcxErrorKind::InvalidConfiguration); trace!("vcx_set_default_logger(pattern: {:?})", pattern); @@ -30,11 +28,11 @@ pub extern fn vcx_set_default_logger(pattern: *const c_char) -> u32 { Ok(_) => { debug!("Logger Successfully Initialized"); SUCCESS.code_num - }, + } Err(ec) => { error!("Logger Failed To Initialize: {}", ec); ec.into() - }, + } } } @@ -59,17 +57,18 @@ pub extern fn vcx_set_logger(context: *const CVoid, trace!("vcx_set_logger( context: {:?}, enabled: {:?}, log: {:?}, flush: {:?}", context, enabled, log, flush); - check_useful_c_callback!(log, SUCCESS.code_num); + check_useful_c_callback!(log, VcxErrorKind::InvalidOption); + let res = LibvcxLogger::init(context, enabled, log, flush); match res { Ok(_) => { debug!("Logger Successfully Initialized"); SUCCESS.code_num - }, + } Err(ec) => { error!("Logger Failed To Initialize: {}", ec); ec.into() - }, + } } } @@ -89,9 +88,9 @@ pub extern fn vcx_set_logger(context: *const CVoid, /// This is tested in wrapper tests (python3) #[no_mangle] pub extern fn vcx_get_logger(context_p: *mut *const CVoid, - enabled_cb_p: *mut Option, - log_cb_p: *mut Option, - flush_cb_p: *mut Option) -> u32 { + enabled_cb_p: *mut Option, + log_cb_p: *mut Option, + flush_cb_p: *mut Option) -> u32 { info!("vcx_get_logger >>>"); trace!("vcx_get_logger >>> context_p: {:?}, enabled_cb_p: {:?}, log_cb_p: {:?}, flush_cb_p: {:?}", context_p, enabled_cb_p, log_cb_p, flush_cb_p); diff --git a/vcx/libvcx/src/api/proof.rs b/vcx/libvcx/src/api/proof.rs index 9b7c6a2907..b8d2247c19 100644 --- a/vcx/libvcx/src/api/proof.rs +++ b/vcx/libvcx/src/api/proof.rs @@ -1,13 +1,11 @@ -extern crate libc; - -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use proof; use connection; use std::ptr; use utils::threadpool::spawn; +use error::prelude::*; /// Create a new Proof object that requests a proof for an enterprise /// @@ -76,12 +74,12 @@ pub extern fn vcx_proof_create(command_handle: u32, cb: Option) -> u32 { info!("vcx_proof_create >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(requested_attrs, error::INVALID_OPTION.code_num); - check_useful_c_str!(requested_predicates, error::INVALID_OPTION.code_num); - check_useful_c_str!(name, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(revocation_interval, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(requested_attrs, VcxErrorKind::InvalidOption); + check_useful_c_str!(requested_predicates, VcxErrorKind::InvalidOption); + check_useful_c_str!(name, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(revocation_interval, VcxErrorKind::InvalidOption); trace!("vcx_proof_create(command_handle: {}, source_id: {}, requested_attrs: {}, requested_predicates: {}, revocation_interval: {}, name: {})", command_handle, source_id, requested_attrs, requested_predicates, revocation_interval, name); @@ -90,7 +88,7 @@ pub extern fn vcx_proof_create(command_handle: u32, let ( rc, handle) = match proof::create_proof(source_id, requested_attrs, requested_predicates, revocation_interval, name) { Ok(x) => { trace!("vcx_proof_create_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), x, proof::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, proof::get_source_id(x).unwrap_or_default()); (error::SUCCESS.code_num, x) }, Err(x) => { @@ -124,21 +122,21 @@ pub extern fn vcx_proof_update_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_proof_update_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_proof_update_state(command_handle: {}, proof_handle: {}) source_id: {}", command_handle, proof_handle, source_id); if !proof::is_valid_handle(proof_handle) { - return error::INVALID_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidProofHandle).into() } spawn(move|| { match proof::update_state(proof_handle) { Ok(x) => { trace!("vcx_proof_update_state_cb(command_handle: {}, rc: {}, proof_handle: {}, state: {}) source_id: {}", - command_handle, error_string(0), proof_handle, x, source_id); + command_handle, error::SUCCESS.message, proof_handle, x, source_id); cb(command_handle, error::SUCCESS.code_num, x); }, Err(x) => { @@ -171,21 +169,21 @@ pub extern fn vcx_proof_get_state(command_handle: u32, cb: Option) -> u32 { info!("vcx_proof_get_state >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_proof_get_state(command_handle: {}, proof_handle: {}), source_id: {}", command_handle, proof_handle, source_id); if !proof::is_valid_handle(proof_handle) { - return error::INVALID_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidProofHandle).into() } spawn(move|| { match proof::get_state(proof_handle) { Ok(x) => { trace!("vcx_proof_get_state_cb(command_handle: {}, rc: {}, proof_handle: {}, state: {}) source_id: {}", - command_handle, error_string(0), proof_handle, x, source_id); + command_handle, error::SUCCESS.message, proof_handle, x, source_id); cb(command_handle, error::SUCCESS.code_num, x); }, Err(x) => { @@ -218,20 +216,20 @@ pub extern fn vcx_proof_serialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_proof_serialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_proof_serialize(command_handle: {}, proof_handle: {}) source_id: {}", command_handle, proof_handle, source_id); if !proof::is_valid_handle(proof_handle) { - return error::INVALID_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidProofHandle).into() }; spawn(move|| { match proof::to_string(proof_handle) { Ok(x) => { trace!("vcx_proof_serialize_cb(command_handle: {}, proof_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, proof_handle, error_string(0), x, source_id); + command_handle, proof_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); }, @@ -265,8 +263,8 @@ pub extern fn vcx_proof_deserialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_proof_deserialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(proof_data, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(proof_data, VcxErrorKind::InvalidOption); trace!("vcx_proof_deserialize(command_handle: {}, proof_data: {})", command_handle, proof_data); @@ -275,7 +273,7 @@ pub extern fn vcx_proof_deserialize(command_handle: u32, let (rc, handle) = match proof::from_string(&proof_data) { Ok(x) => { trace!("vcx_proof_deserialize_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), x, proof::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, proof::get_source_id(x).unwrap_or_default()); (error::SUCCESS.code_num, x) }, Err(x) => { @@ -307,7 +305,7 @@ pub extern fn vcx_proof_release(proof_handle: u32) -> u32 { match proof::release(proof_handle) { Ok(_) => { trace!("vcx_proof_release(proof_handle: {}, rc: {}), source_id: {}", - proof_handle, error_string(0), source_id); + proof_handle, error::SUCCESS.message, source_id); error::SUCCESS.code_num }, Err(e) => { @@ -338,17 +336,17 @@ pub extern fn vcx_proof_send_request(command_handle: u32, cb: Option) -> u32 { info!("vcx_proof_send_request >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_proof_send_request(command_handle: {}, proof_handle: {}, connection_handle: {}) source_id: {}", command_handle, proof_handle, connection_handle, source_id); if !proof::is_valid_handle(proof_handle) { - return error::INVALID_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidProofHandle).into() } if !connection::is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } spawn(move|| { @@ -393,17 +391,17 @@ pub extern fn vcx_get_proof(command_handle: u32, cb: Option) -> u32 { info!("vcx_get_proof >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = proof::get_source_id(proof_handle).unwrap_or_default(); trace!("vcx_get_proof(command_handle: {}, proof_handle: {}, connection_handle: {}) source_id: {}", command_handle, proof_handle, connection_handle, source_id); if !proof::is_valid_handle(proof_handle) { - return error::INVALID_PROOF_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidProofHandle).into() } if !connection::is_valid_handle(connection_handle) { - return error::INVALID_CONNECTION_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidConnectionHandle).into() } spawn(move|| { diff --git a/vcx/libvcx/src/api/return_types_u32.rs b/vcx/libvcx/src/api/return_types_u32.rs index 2d6460bc93..80296d82da 100644 --- a/vcx/libvcx/src/api/return_types_u32.rs +++ b/vcx/libvcx/src/api/return_types_u32.rs @@ -1,6 +1,4 @@ -extern crate libc; - -use self::libc::c_char; +use libc::c_char; use std::sync::mpsc::Receiver; use std::sync::mpsc::RecvTimeoutError; use utils::libindy::next_u32_command_handle; diff --git a/vcx/libvcx/src/api/schema.rs b/vcx/libvcx/src/api/schema.rs index 1a239c8985..dfda960cd5 100644 --- a/vcx/libvcx/src/api/schema.rs +++ b/vcx/libvcx/src/api/schema.rs @@ -1,14 +1,12 @@ -extern crate libc; - use serde_json; -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use std::ptr; use schema; use settings; use utils::threadpool::spawn; +use error::prelude::*; /// Create a new Schema object that can create or look up schemas on the ledger /// @@ -41,11 +39,11 @@ pub extern fn vcx_schema_create(command_handle: u32, cb: Option) -> u32 { info!("vcx_schema_create >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(schema_name, error::INVALID_OPTION.code_num); - check_useful_c_str!(version, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(schema_data, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(schema_name, VcxErrorKind::InvalidOption); + check_useful_c_str!(version, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(schema_data, VcxErrorKind::InvalidOption); let issuer_did = match settings::get_config_value(settings::CONFIG_INSTITUTION_DID) { Ok(x) => x, @@ -62,7 +60,7 @@ pub extern fn vcx_schema_create(command_handle: u32, schema_data) { Ok(x) => { trace!(target: "vcx", "vcx_schema_create_cb(command_handle: {}, rc: {}, handle: {}) source_id: {}", - command_handle, error_string(0), x, source_id); + command_handle, error::SUCCESS.message, x, source_id); cb(command_handle, error::SUCCESS.code_num, x); } Err(x) => { @@ -96,21 +94,21 @@ pub extern fn vcx_schema_serialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_schema_serialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let source_id = schema::get_source_id(schema_handle).unwrap_or_default(); trace!("vcx_schema_serialize(command_handle: {}, schema_handle: {}) source_id: {}", command_handle, schema_handle, source_id); if !schema::is_valid_handle(schema_handle) { - return error::INVALID_SCHEMA_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidSchemaHandle).into() }; spawn(move || { match schema::to_string(schema_handle) { Ok(x) => { trace!("vcx_schema_serialize_cb(command_handle: {}, schema_handle: {}, rc: {}, state: {}) source_id: {}", - command_handle, schema_handle, error_string(0), x, source_id); + command_handle, schema_handle, error::SUCCESS.message, x, source_id); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); } @@ -144,15 +142,15 @@ pub extern fn vcx_schema_deserialize(command_handle: u32, cb: Option) -> u32 { info!("vcx_schema_deserialize >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(schema_data, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(schema_data, VcxErrorKind::InvalidOption); trace!("vcx_schema_deserialize(command_handle: {}, schema_data: {})", command_handle, schema_data); spawn(move || { match schema::from_string(&schema_data) { Ok(x) => { trace!("vcx_schema_deserialize_cb(command_handle: {}, rc: {}, handle: {}), source_id: {}", - command_handle, error_string(0), x, schema::get_source_id(x).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, schema::get_source_id(x).unwrap_or_default()); cb(command_handle, error::SUCCESS.code_num, x); } Err(x) => { @@ -183,7 +181,7 @@ pub extern fn vcx_schema_release(schema_handle: u32) -> u32 { match schema::release(schema_handle) { Ok(_) => { trace!("vcx_schema_release(schema_handle: {}, rc: {}), source_id: {}", - schema_handle, error_string(0), source_id); + schema_handle, error::SUCCESS.message, source_id); error::SUCCESS.code_num } Err(e) => { @@ -209,18 +207,18 @@ pub extern fn vcx_schema_get_schema_id(command_handle: u32, cb: Option) -> u32 { info!("vcx_schema_get_schema_id >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_schema_get_schema_id(command_handle: {}, schema_handle: {})", command_handle, schema_handle); if !schema::is_valid_handle(schema_handle) { - return error::INVALID_SCHEMA_HANDLE.code_num; + return VcxError::from(VcxErrorKind::InvalidSchemaHandle).into() } spawn(move || { match schema::get_schema_id(schema_handle) { Ok(x) => { trace!("vcx_schema_get_schema_id(command_handle: {}, schema_handle: {}, rc: {}, schema_seq_no: {})", - command_handle, schema_handle, error_string(0), x); + command_handle, schema_handle, error::SUCCESS.message, x); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); } @@ -257,9 +255,9 @@ pub extern fn vcx_schema_get_attributes(command_handle: u32, cb: Option) -> u32 { info!("vcx_schema_get_attributes >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(source_id, error::INVALID_OPTION.code_num); - check_useful_c_str!(schema_id, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(source_id, VcxErrorKind::InvalidOption); + check_useful_c_str!(schema_id, VcxErrorKind::InvalidOption); trace!("vcx_schema_get_attributes(command_handle: {}, source_id: {}, schema_id: {})", command_handle, source_id, schema_id); @@ -269,7 +267,7 @@ pub extern fn vcx_schema_get_attributes(command_handle: u32, let data: serde_json::Value = serde_json::from_str(&data).unwrap(); let data = data["data"].clone(); trace!("vcx_schema_get_attributes_cb(command_handle: {}, rc: {}, handle: {}, attrs: {})", - command_handle, error_string(0), handle, data); + command_handle, error::SUCCESS.message, handle, data); let msg = CStringUtils::string_to_cstring(data.to_string()); cb(command_handle, error::SUCCESS.code_num, handle, msg.as_ptr()); } @@ -310,7 +308,7 @@ pub extern fn vcx_schema_get_payment_txn(command_handle: u32, cb: Option) -> u32 { info!("vcx_schema_get_payment_txn >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_schema_get_payment_txn(command_handle: {})", command_handle); @@ -320,15 +318,16 @@ pub extern fn vcx_schema_get_payment_txn(command_handle: u32, match serde_json::to_string(&x) { Ok(x) => { trace!("vcx_schema_get_payment_txn_cb(command_handle: {}, rc: {}, : {}), source_id: {:?}", - command_handle, error_string(0), x, schema::get_source_id(handle).unwrap_or_default()); + command_handle, error::SUCCESS.message, x, schema::get_source_id(handle).unwrap_or_default()); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, 0, msg.as_ptr()); } - Err(_) => { + Err(e) => { + let err = VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize payment txn: {}", e)); error!("vcx_schema_get_payment_txn_cb(command_handle: {}, rc: {}, txn: {}), source_id: {:?}", - command_handle, error::INVALID_JSON.message, "null", schema::get_source_id(handle).unwrap_or_default()); - cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); + command_handle, err, "null", schema::get_source_id(handle).unwrap_or_default()); + cb(command_handle, err.into(), ptr::null_mut()); } } } diff --git a/vcx/libvcx/src/api/utils.rs b/vcx/libvcx/src/api/utils.rs index 132c4ac5f6..64c32753fc 100644 --- a/vcx/libvcx/src/api/utils.rs +++ b/vcx/libvcx/src/api/utils.rs @@ -1,16 +1,14 @@ -extern crate libc; - use serde_json; -use self::libc::c_char; +use libc::c_char; use messages; use std::ptr; use utils::httpclient; use utils::constants::*; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use utils::threadpool::spawn; use std::thread; +use error::prelude::*; #[derive(Deserialize, Debug, Clone)] pub struct UpdateAgentInfo { @@ -26,26 +24,32 @@ pub struct UpdateAgentInfo { /// /// #Returns /// Configuration (wallet also populated), on error returns NULL - #[no_mangle] pub extern fn vcx_provision_agent(config: *const c_char) -> *mut c_char { info!("vcx_provision_agent >>>"); - check_useful_c_str!(config, ptr::null_mut()); + let config = match CStringUtils::c_str_to_string(config) { + Ok(Some(val)) => val, + _ => { + let _res: u32 = VcxError::from_msg(VcxErrorKind::InvalidOption, "Invalid pointer has been passed").into(); + return ptr::null_mut(); + } + }; trace!("vcx_provision_agent(config: {})", config); match messages::agent_utils::connect_register_provision(&config) { Err(e) => { error!("Provision Agent Error {}.", e); + let _res: u32 = e.into(); return ptr::null_mut(); - }, + } Ok(s) => { debug!("Provision Agent Successful"); let msg = CStringUtils::string_to_cstring(s); msg.into_raw() - }, + } } } @@ -61,31 +65,30 @@ pub extern fn vcx_provision_agent(config: *const c_char) -> *mut c_char { /// /// #Returns /// Configuration (wallet also populated), on error returns NULL - #[no_mangle] -pub extern fn vcx_agent_provision_async(command_handle : u32, - config: *const c_char, - cb: Option) -> u32 { +pub extern fn vcx_agent_provision_async(command_handle: u32, + config: *const c_char, + cb: Option) -> u32 { info!("vcx_agent_provision_async >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(config, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(config, VcxErrorKind::InvalidOption); trace!("vcx_agent_provision_async(command_handle: {}, json: {})", - command_handle, config); + command_handle, config); - thread::spawn(move|| { + thread::spawn(move || { match messages::agent_utils::connect_register_provision(&config) { Err(e) => { error!("vcx_agent_provision_async_cb(command_handle: {}, rc: {}, config: NULL", command_handle, e); cb(command_handle, e.into(), ptr::null_mut()); - }, + } Ok(s) => { trace!("vcx_agent_provision_async_cb(command_handle: {}, rc: {}, config: {})", - command_handle, error_string(0), s); + command_handle, error::SUCCESS.message, s); let msg = CStringUtils::string_to_cstring(s); cb(command_handle, 0, msg.as_ptr()); - }, + } } }); @@ -103,38 +106,37 @@ pub extern fn vcx_agent_provision_async(command_handle : u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_agent_update_info(command_handle: u32, json: *const c_char, cb: Option) -> u32 { info!("vcx_agent_update_info >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(json, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(json, VcxErrorKind::InvalidOption); trace!("vcx_agent_update_info(command_handle: {}, json: {})", - command_handle, json); + command_handle, json); let agent_info: UpdateAgentInfo = match serde_json::from_str(&json) { Ok(x) => x, - Err(x) => { - return error::INVALID_OPTION.code_num - }, + Err(e) => { + return VcxError::from_msg(VcxErrorKind::InvalidOption, format!("Cannot deserialize agent info: {}", e)).into(); + } }; - spawn(move|| { - match messages::agent_utils::update_agent_info(&agent_info.id, &agent_info.value){ + spawn(move || { + match messages::agent_utils::update_agent_info(&agent_info.id, &agent_info.value) { Ok(x) => { trace!("vcx_agent_update_info_cb(command_handle: {}, rc: {})", - command_handle, error::error_string(0)); + command_handle, error::SUCCESS.message); cb(command_handle, error::SUCCESS.code_num); - }, + } Err(e) => { error!("vcx_agent_update_info_cb(command_handle: {}, rc: {})", - command_handle, e); + command_handle, e); cb(command_handle, e.into()); - }, + } }; Ok(()) @@ -152,31 +154,30 @@ pub extern fn vcx_agent_update_info(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_ledger_get_fees(command_handle: u32, cb: Option) -> u32 { info!("vcx_ledger_get_fees >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_ledger_get_fees(command_handle: {})", - command_handle); + command_handle); - spawn(move|| { + spawn(move || { match ::utils::libindy::payments::get_ledger_fees() { Ok(x) => { trace!("vcx_ledger_get_fees_cb(command_handle: {}, rc: {}, fees: {})", - command_handle, error::error_string(0), x); + command_handle, error::SUCCESS.message, x); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, + } Err(e) => { warn!("vcx_ledget_get_fees_cb(command_handle: {}, rc: {}, fees: {})", command_handle, e, "null"); cb(command_handle, e.into(), ptr::null_mut()); - }, + } }; Ok(()) @@ -218,7 +219,6 @@ pub extern fn vcx_set_next_agency_response(message_index: u32) { /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_messages_download(command_handle: u32, message_status: *const c_char, @@ -227,10 +227,10 @@ pub extern fn vcx_messages_download(command_handle: u32, cb: Option) -> u32 { info!("vcx_messages_download >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let message_status = if !message_status.is_null() { - check_useful_c_str!(message_status, error::INVALID_OPTION.code_num); + check_useful_c_str!(message_status, VcxErrorKind::InvalidOption); let v: Vec<&str> = message_status.split(',').collect(); let v = v.iter().map(|s| s.to_string()).collect::>(); Some(v.to_owned()) @@ -239,7 +239,7 @@ pub extern fn vcx_messages_download(command_handle: u32, }; let uids = if !uids.is_null() { - check_useful_c_str!(uids, error::INVALID_OPTION.code_num); + check_useful_c_str!(uids, VcxErrorKind::InvalidOption); let v: Vec<&str> = uids.split(',').collect(); let v = v.iter().map(|s| s.to_string()).collect::>(); Some(v.to_owned()) @@ -248,7 +248,7 @@ pub extern fn vcx_messages_download(command_handle: u32, }; let pw_dids = if !pw_dids.is_null() { - check_useful_c_str!(pw_dids, error::INVALID_OPTION.code_num); + check_useful_c_str!(pw_dids, VcxErrorKind::InvalidOption); let v: Vec<&str> = pw_dids.split(',').collect(); let v = v.iter().map(|s| s.to_string()).collect::>(); Some(v.to_owned()) @@ -257,33 +257,34 @@ pub extern fn vcx_messages_download(command_handle: u32, }; trace!("vcx_messages_download(command_handle: {}, message_status: {:?}, uids: {:?})", - command_handle, message_status, uids); + command_handle, message_status, uids); - spawn(move|| { + spawn(move || { match ::messages::get_message::download_messages(pw_dids, message_status, uids) { Ok(x) => { - match serde_json::to_string(&x) { + match serde_json::to_string(&x) { Ok(x) => { trace!("vcx_messages_download_cb(command_handle: {}, rc: {}, messages: {})", - command_handle, error::error_string(0), x); + command_handle, error::SUCCESS.message, x); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); - }, - Err(_) => { + } + Err(e) => { + let err = VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize messages: {}", e)); warn!("vcx_messages_download_cb(command_handle: {}, rc: {}, messages: {})", - command_handle, error_string(error::INVALID_JSON.code_num), "null"); + command_handle, err, "null"); - cb(command_handle, error::INVALID_JSON.code_num, ptr::null_mut()); - }, + cb(command_handle, err.into(), ptr::null_mut()); + } }; - }, + } Err(e) => { warn!("vcx_messages_download_cb(command_handle: {}, rc: {}, messages: {})", command_handle, e, "null"); cb(command_handle, e.into(), ptr::null_mut()); - }, + } }; Ok(()) @@ -306,7 +307,6 @@ pub extern fn vcx_messages_download(command_handle: u32, /// /// #Returns /// Error code as a u32 - #[no_mangle] pub extern fn vcx_messages_update_status(command_handle: u32, message_status: *const c_char, @@ -314,27 +314,27 @@ pub extern fn vcx_messages_update_status(command_handle: u32, cb: Option) -> u32 { info!("vcx_messages_update_status >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(message_status, error::INVALID_OPTION.code_num); - check_useful_c_str!(msg_json, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(message_status, VcxErrorKind::InvalidOption); + check_useful_c_str!(msg_json, VcxErrorKind::InvalidOption); trace!("vcx_messages_set_status(command_handle: {}, message_status: {:?}, uids: {:?})", - command_handle, message_status, msg_json); + command_handle, message_status, msg_json); - spawn(move|| { + spawn(move || { match ::messages::update_message::update_agency_messages(&message_status, &msg_json) { Ok(_) => { trace!("vcx_messages_set_status_cb(command_handle: {}, rc: {})", - command_handle, error::error_string(0)); + command_handle, error::SUCCESS.message); cb(command_handle, error::SUCCESS.code_num); - }, + } Err(e) => { warn!("vcx_messages_set_status_cb(command_handle: {}, rc: {})", command_handle, e); cb(command_handle, e.into()); - }, + } }; Ok(()) @@ -343,9 +343,36 @@ pub extern fn vcx_messages_update_status(command_handle: u32, error::SUCCESS.code_num } +/// Get details for last occurred error. +/// +/// This function should be called in two places to handle both cases of error occurrence: +/// 1) synchronous - in the same application thread +/// 2) asynchronous - inside of function callback +/// +/// NOTE: Error is stored until the next one occurs in the same execution thread or until asynchronous callback finished. +/// Returning pointer has the same lifetime. +/// +/// #Params +/// * `error_json_p` - Reference that will contain error details (if any error has occurred before) +/// in the format: +/// { +/// "backtrace": Optional - error backtrace. +/// Collecting of backtrace can be enabled by setting environment variable `RUST_BACKTRACE=1` +/// "message": str - human-readable error description +/// } +/// +#[no_mangle] +pub extern fn vcx_get_current_error(error_json_p: *mut *const c_char) { + trace!("vcx_get_current_error >>> error_json_p: {:?}", error_json_p); + + let error = get_current_error_c_json(); + unsafe { *error_json_p = error }; + + trace!("vcx_get_current_error: <<<"); +} + #[cfg(test)] mod tests { - use super::*; use std::ffi::CString; use std::time::Duration; @@ -356,12 +383,12 @@ mod tests { fn test_provision_agent() { init!("true"); - let json_string = r#"{"agency_url":"https://enym-eagency.pdev.evernym.com","agency_did":"Ab8TvZa3Q19VNkQVzAWVL7","agency_verkey":"5LXaR43B1aQyeh94VBP8LG1Sgvjk7aNfqiksBCSjwqbf","wallet_name":"test_provision_agent","agent_seed":null,"enterprise_seed":null,"wallet_key":null}"#; + let json_string = r#"{"agency_url":"https://enym-eagency.pdev.evernym.com","agency_did":"Ab8TvZa3Q19VNkQVzAWVL7","agency_verkey":"5LXaR43B1aQyeh94VBP8LG1Sgvjk7aNfqiksBCSjwqbf","wallet_name":"test_provision_agent","agent_seed":null,"enterprise_seed":null,"wallet_key":"key"}"#; let c_json = CString::new(json_string).unwrap().into_raw(); let result = vcx_provision_agent(c_json); + let result = CStringUtils::c_str_to_string(result).unwrap().unwrap(); - check_useful_c_str!(result,()); assert!(result.len() > 0); } @@ -475,4 +502,36 @@ mod tests { error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); } + + #[test] + fn get_current_error_works_for_no_error() { + let mut error_json_p: *const c_char = ptr::null(); + + vcx_get_current_error(&mut error_json_p); + assert_eq!(None, CStringUtils::c_str_to_string(error_json_p).unwrap()); + } + + #[test] + fn get_current_error_works_for_sync_error() { + vcx_provision_agent(ptr::null()); + + let mut error_json_p: *const c_char = ptr::null(); + vcx_get_current_error(&mut error_json_p); + assert!(CStringUtils::c_str_to_string(error_json_p).unwrap().is_some()); + } + + #[test] + fn get_current_error_works_for_async_error() { + extern fn cb(storage_handle: u32, + err: u32, + config: *const c_char) { + let mut error_json_p: *const c_char = ptr::null(); + vcx_get_current_error(&mut error_json_p); + assert!(CStringUtils::c_str_to_string(error_json_p).unwrap().is_some()); + } + + let config = CString::new("{}").unwrap(); + vcx_agent_provision_async(0, config.as_ptr(), Some(cb)); + } } + diff --git a/vcx/libvcx/src/api/vcx.rs b/vcx/libvcx/src/api/vcx.rs index 931476cbb0..e4967febf1 100644 --- a/vcx/libvcx/src/api/vcx.rs +++ b/vcx/libvcx/src/api/vcx.rs @@ -1,14 +1,12 @@ -extern crate libc; - use utils::version_constants; -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::libindy::{wallet, pool}; use utils::error; use settings; use std::ffi::CString; use utils::threadpool::spawn; - +use error::prelude::*; /// Initializes VCX with config settings /// @@ -26,24 +24,24 @@ use utils::threadpool::spawn; #[no_mangle] pub extern fn vcx_init_with_config(command_handle: u32, config: *const c_char, - cb: Option) -> u32 { + cb: Option) -> u32 { info!("vcx_init_with_config >>>"); - check_useful_c_str!(config,error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(config,VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_init(command_handle: {}, config: {:?})", command_handle, config); if config == "ENABLE_TEST_MODE" { - settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE,"true"); + settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE, "true"); settings::set_defaults(); } else { match settings::process_config_string(&config) { Err(e) => { error!("Invalid configuration specified: {}", e); return e.into(); - }, + } Ok(_) => (), } }; @@ -65,53 +63,52 @@ pub extern fn vcx_init_with_config(command_handle: u32, /// #Returns /// Error code as a u32 #[no_mangle] -pub extern fn vcx_init (command_handle: u32, - config_path:*const c_char, - cb: Option) -> u32 { +pub extern fn vcx_init(command_handle: u32, + config_path: *const c_char, + cb: Option) -> u32 { info!("vcx_init >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_init(command_handle: {}, config_path: {:?})", command_handle, config_path); if !config_path.is_null() { - check_useful_c_str!(config_path,error::INVALID_OPTION.code_num); + check_useful_c_str!(config_path,VcxErrorKind::InvalidOption); if config_path == "ENABLE_TEST_MODE" { - settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE,"true"); + settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE, "true"); settings::set_defaults(); } else { match settings::process_config_file(&config_path) { Err(e) => { - return error::INVALID_CONFIGURATION.code_num; - }, + return VcxError::from_msg(VcxErrorKind::InvalidConfiguration, "Cannot initialize with given config path.").into(); + } Ok(_) => { match settings::validate_payment_method() { Ok(_) => (), Err(e) => return e.into() } - }, + } }; } } else { error!("Cannot initialize with given config path: config path is null."); - return error::INVALID_CONFIGURATION.code_num; + return VcxError::from_msg(VcxErrorKind::InvalidConfiguration, "Cannot initialize with given config path: config path is null.").into(); } _finish_init(command_handle, cb) } fn _finish_init(command_handle: u32, cb: extern fn(xcommand_handle: u32, err: u32)) -> u32 { - ::utils::threadpool::init(); settings::log_settings(); if wallet::get_wallet_handle() > 0 { error!("Library was already initialized"); - return error::ALREADY_INITIALIZED.code_num; + return VcxError::from_msg(VcxErrorKind::AlreadyInitialized, "Library was already initialized").into(); } // Wallet name was already validated let wallet_name = match settings::get_config_value(settings::CONFIG_WALLET_NAME) { @@ -129,23 +126,23 @@ fn _finish_init(command_handle: u32, cb: extern fn(xcommand_handle: u32, err: u3 trace!("libvcx version: {}{}", version_constants::VERSION, version_constants::REVISION); - spawn(move|| { + spawn(move || { if settings::get_config_value(settings::CONFIG_GENESIS_PATH).is_ok() { match ::utils::libindy::init_pool() { Ok(_) => (), Err(e) => { error!("Init Pool Error {}.", e); - return Ok(cb(command_handle, e.into())) - }, + return Ok(cb(command_handle, e.into())); + } } } - match wallet::open_wallet(&wallet_name, wallet_type.as_ref().map(String::as_str), - storage_config.as_ref().map(String::as_str), storage_creds.as_ref().map(String::as_str)) { + match wallet::open_wallet(&wallet_name, wallet_type.as_ref().map(String::as_str), + storage_config.as_ref().map(String::as_str), storage_creds.as_ref().map(String::as_str)) { Ok(_) => { debug!("Init Wallet Successful"); cb(command_handle, error::SUCCESS.code_num); - }, + } Err(e) => { error!("Init Wallet Error {}.", e); cb(command_handle, e.into()); @@ -157,7 +154,7 @@ fn _finish_init(command_handle: u32, cb: extern fn(xcommand_handle: u32, err: u3 error::SUCCESS.code_num } -lazy_static!{ +lazy_static! { pub static ref VERSION_STRING: CString = CString::new(format!("{}{}", version_constants::VERSION, version_constants::REVISION)).unwrap(); } @@ -182,13 +179,13 @@ pub extern fn vcx_shutdown(delete: bool) -> u32 { trace!("vcx_shutdown(delete: {})", delete); match wallet::close_wallet() { - Ok(_) => {}, - Err(_) => {}, + Ok(_) => {} + Err(_) => {} }; match pool::close() { - Ok(_) => {}, - Err(_) => {}, + Ok(_) => {} + Err(_) => {} }; ::schema::release_all(); @@ -235,8 +232,8 @@ pub extern fn vcx_error_c_message(error_code: u32) -> *const c_char { pub extern fn vcx_update_institution_info(name: *const c_char, logo_url: *const c_char) -> u32 { info!("vcx_update_institution_info >>>"); - check_useful_c_str!(name, error::INVALID_CONFIGURATION.code_num); - check_useful_c_str!(logo_url, error::INVALID_CONFIGURATION.code_num); + check_useful_c_str!(name, VcxErrorKind::InvalidOption); + check_useful_c_str!(logo_url, VcxErrorKind::InvalidOption); trace!("vcx_update_institution_info(name: {}, logo_url: {})", name, logo_url); settings::set_config_value(::settings::CONFIG_INSTITUTION_NAME, &name); @@ -249,19 +246,22 @@ pub extern fn vcx_update_institution_info(name: *const c_char, logo_url: *const pub extern fn vcx_mint_tokens(seed: *const c_char, fees: *const c_char) { info!("vcx_mint_tokens >>>"); + // TODO: CHEC let seed = if !seed.is_null() { - check_useful_opt_c_str!(seed, ()); - seed.to_owned() - } - else { + match CStringUtils::c_str_to_string(seed) { + Ok(opt_val) => opt_val.map(String::from), + Err(_) => return () + } + } else { None }; let fees = if !fees.is_null() { - check_useful_opt_c_str!(fees, ()); - fees.to_owned() - } - else { + match CStringUtils::c_str_to_string(fees) { + Ok(opt_val) => opt_val.map(String::from), + Err(_) => return () + } + } else { None }; trace!("vcx_mint_tokens(seed: {:?}, fees: {:?})", seed, fees); @@ -271,16 +271,14 @@ pub extern fn vcx_mint_tokens(seed: *const c_char, fees: *const c_char) { #[cfg(test)] mod tests { - use super::*; - use error::prelude::*; use std::time::Duration; use std::ptr; use std::thread; use utils::{ libindy::{ - wallet::{import, tests::export_test_wallet, tests::delete_import_wallet_path}, - pool::get_pool_handle + wallet::{import, tests::export_test_wallet, tests::delete_import_wallet_path}, + pool::get_pool_handle }, get_temp_dir_path }; @@ -357,8 +355,8 @@ mod tests { let cb = return_types_u32::Return_U32::new().unwrap(); assert_eq!(vcx_init_with_config(cb.command_handle, - CString::new(content).unwrap().into_raw(), - Some(cb.get_callback())), + CString::new(content).unwrap().into_raw(), + Some(cb.get_callback())), error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); // Assert pool was initialized @@ -372,8 +370,8 @@ mod tests { vcx_shutdown(true); use std::fs; use std::io::Write; - settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE,"false"); - settings::set_config_value(settings::CONFIG_WALLET_KEY,settings::DEFAULT_WALLET_KEY); + settings::set_config_value(settings::CONFIG_ENABLE_TEST_MODE, "false"); + settings::set_config_value(settings::CONFIG_WALLET_KEY, settings::DEFAULT_WALLET_KEY); // Write invalid genesis.txn let mut f = fs::File::create(get_temp_dir_path(Some(::utils::constants::GENESIS_PATH)).to_str().unwrap()).unwrap(); @@ -549,8 +547,8 @@ mod tests { let cb = return_types_u32::Return_U32::new().unwrap(); assert_eq!(vcx_init(cb.command_handle, - CString::new(config_path).unwrap().into_raw(), - Some(cb.get_callback())), + CString::new(config_path).unwrap().into_raw(), + Some(cb.get_callback())), error::ALREADY_INITIALIZED.code_num); } @@ -621,7 +619,7 @@ mod tests { assert_eq!(cb.receive(Some(Duration::from_secs(10))).err(), Some(error::WALLET_NOT_FOUND.code_num)); delete_import_wallet_path(export_path); - settings::set_config_value(settings::CONFIG_WALLET_NAME,settings::DEFAULT_WALLET_NAME); + settings::set_config_value(settings::CONFIG_WALLET_NAME, settings::DEFAULT_WALLET_NAME); vcx_shutdown(true); } @@ -666,13 +664,13 @@ mod tests { let config_path = ""; let cb = return_types_u32::Return_U32::new().unwrap(); assert_eq!(vcx_init(cb.command_handle, - CString::new(config_path).unwrap().into_raw(), - Some(cb.get_callback())), + CString::new(config_path).unwrap().into_raw(), + Some(cb.get_callback())), error::INVALID_OPTION.code_num); match get_pool_handle() { - Ok(h) => {pool::close().unwrap();}, - Err(_) => {}, + Ok(h) => { pool::close().unwrap(); } + Err(_) => {} }; } @@ -682,8 +680,8 @@ mod tests { init!("true"); let cb = return_types_u32::Return_U32::new().unwrap(); assert_eq!(vcx_init(cb.command_handle, - ptr::null(), - Some(cb.get_callback())), + ptr::null(), + Some(cb.get_callback())), error::INVALID_CONFIGURATION.code_num); } @@ -699,11 +697,11 @@ mod tests { let data = r#"["name","male"]"#; let connection = ::connection::tests::build_test_connection(); - let credentialdef = ::credential_def::create_new_credentialdef("SID".to_string(),"NAME".to_string(),"4fUDR9R7fjwELRvH9JT6HH".to_string(), "id".to_string(), "tag".to_string(),"{}".to_string() ).unwrap(); - let issuer_credential = ::issuer_credential::issuer_credential_create(credentialdef,"1".to_string(),"8XFh8yBzrpJQmNyZzgoTqB".to_owned(),"credential_name".to_string(),"{\"attr\":\"value\"}".to_owned(), 1).unwrap(); - let proof = ::proof::create_proof("1".to_string(),"[]".to_string(), "[]".to_string(),r#"{"support_revocation":false}"#.to_string(), "Optional".to_owned()).unwrap(); - let schema = ::schema::create_new_schema("5", "VsKV7grR1BUE29mG2Fm2kX".to_string(),"name".to_string(), "0.1".to_string(), data.to_string()).unwrap(); - let disclosed_proof = ::disclosed_proof::create_proof("id",::utils::constants::PROOF_REQUEST_JSON).unwrap(); + let credentialdef = ::credential_def::create_new_credentialdef("SID".to_string(), "NAME".to_string(), "4fUDR9R7fjwELRvH9JT6HH".to_string(), "id".to_string(), "tag".to_string(), "{}".to_string()).unwrap(); + let issuer_credential = ::issuer_credential::issuer_credential_create(credentialdef, "1".to_string(), "8XFh8yBzrpJQmNyZzgoTqB".to_owned(), "credential_name".to_string(), "{\"attr\":\"value\"}".to_owned(), 1).unwrap(); + let proof = ::proof::create_proof("1".to_string(), "[]".to_string(), "[]".to_string(), r#"{"support_revocation":false}"#.to_string(), "Optional".to_owned()).unwrap(); + let schema = ::schema::create_new_schema("5", "VsKV7grR1BUE29mG2Fm2kX".to_string(), "name".to_string(), "0.1".to_string(), data.to_string()).unwrap(); + let disclosed_proof = ::disclosed_proof::create_proof("id", ::utils::constants::PROOF_REQUEST_JSON).unwrap(); let credential = ::credential::credential_create_with_offer("name", ::utils::constants::CREDENTIAL_OFFER_JSON).unwrap(); vcx_shutdown(true); @@ -721,16 +719,16 @@ mod tests { fn test_error_c_message() { init!("true"); let c_message = CStringUtils::c_str_to_string(vcx_error_c_message(0)).unwrap().unwrap(); - assert_eq!(c_message,error::SUCCESS.message); + assert_eq!(c_message, error::SUCCESS.message); let c_message = CStringUtils::c_str_to_string(vcx_error_c_message(1001)).unwrap().unwrap(); - assert_eq!(c_message,error::UNKNOWN_ERROR.message); + assert_eq!(c_message, error::UNKNOWN_ERROR.message); let c_message = CStringUtils::c_str_to_string(vcx_error_c_message(100100)).unwrap().unwrap(); - assert_eq!(c_message,error::UNKNOWN_ERROR.message); + assert_eq!(c_message, error::UNKNOWN_ERROR.message); let c_message = CStringUtils::c_str_to_string(vcx_error_c_message(1021)).unwrap().unwrap(); - assert_eq!(c_message,error::INVALID_ATTRIBUTES_STRUCTURE.message); + assert_eq!(c_message, error::INVALID_ATTRIBUTES_STRUCTURE.message); } #[test] diff --git a/vcx/libvcx/src/api/wallet.rs b/vcx/libvcx/src/api/wallet.rs index dfed0ad29b..70fa45870c 100644 --- a/vcx/libvcx/src/api/wallet.rs +++ b/vcx/libvcx/src/api/wallet.rs @@ -1,16 +1,13 @@ -extern crate libc; - -use self::libc::c_char; +use libc::c_char; use utils::cstring::CStringUtils; use utils::error; -use utils::error::error_string; use utils::libindy::payments::{pay_a_payee, get_wallet_token_info, create_address}; use utils::libindy::wallet::{export, import, get_wallet_handle}; use utils::libindy::wallet; use std::path::Path; use utils::threadpool::spawn; use std::thread; - +use error::prelude::*; /// Get the total balance from all addresses contained in the configured wallet /// @@ -31,7 +28,7 @@ pub extern fn vcx_wallet_get_token_info(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_get_token_info >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_get_token_info(command_handle: {}, payment_handle: {})", command_handle, payment_handle); @@ -74,9 +71,9 @@ pub extern fn vcx_wallet_create_payment_address(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_create_payment_address >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); let seed = if !seed.is_null() { - check_useful_opt_c_str!(seed, error::INVALID_OPTION.code_num); + check_useful_opt_c_str!(seed, VcxErrorKind::InvalidOption); seed } else { None @@ -89,7 +86,7 @@ pub extern fn vcx_wallet_create_payment_address(command_handle: u32, match create_address(seed) { Ok(x) => { trace!("vcx_wallet_create_payment_address_cb(command_handle: {}, rc: {}, address: {})", - command_handle, error_string(0), x); + command_handle, error::SUCCESS.message, x); let msg = CStringUtils::string_to_cstring(x); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); @@ -147,11 +144,11 @@ pub extern fn vcx_wallet_add_record(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_add_record >>>"); - check_useful_c_str!(type_, error::INVALID_OPTION.code_num); - check_useful_c_str!(id, error::INVALID_OPTION.code_num); - check_useful_c_str!(value, error::INVALID_OPTION.code_num); - check_useful_c_str!(tags_json, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(type_, VcxErrorKind::InvalidOption); + check_useful_c_str!(id, VcxErrorKind::InvalidOption); + check_useful_c_str!(value, VcxErrorKind::InvalidOption); + check_useful_c_str!(tags_json, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_add_record(command_handle: {}, type_: {}, id: {}, value: {}, tags_json: {})", command_handle, type_, id, value, tags_json); @@ -160,7 +157,7 @@ pub extern fn vcx_wallet_add_record(command_handle: u32, match wallet::add_record(&type_, &id, &value, Some(&tags_json)) { Ok(x) => { trace!("vcx_wallet_add_record(command_handle: {}, rc: {})", - command_handle, error_string(0)); + command_handle, error::SUCCESS.message); cb(command_handle, error::SUCCESS.code_num); }, @@ -204,10 +201,10 @@ pub extern fn vcx_wallet_update_record_value(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_update_record_value >>>"); - check_useful_c_str!(type_, error::INVALID_OPTION.code_num); - check_useful_c_str!(id, error::INVALID_OPTION.code_num); - check_useful_c_str!(value, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(type_, VcxErrorKind::InvalidOption); + check_useful_c_str!(id, VcxErrorKind::InvalidOption); + check_useful_c_str!(value, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_update_record_value(command_handle: {}, type_: {}, id: {}, value: {})", command_handle, type_, id, value); @@ -216,7 +213,7 @@ pub extern fn vcx_wallet_update_record_value(command_handle: u32, match wallet::update_record_value(&type_, &id, &value) { Ok(x) => { trace!("vcx_wallet_update_record_value(command_handle: {}, rc: {})", - command_handle, error_string(0)); + command_handle, error::SUCCESS.message); cb(command_handle, error::SUCCESS.code_num); }, @@ -260,10 +257,10 @@ pub extern fn vcx_wallet_update_record_tags(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_update_record_tags >>>"); - check_useful_c_str!(type_, error::INVALID_OPTION.code_num); - check_useful_c_str!(id, error::INVALID_OPTION.code_num); - check_useful_c_str!(tags, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(type_, VcxErrorKind::InvalidOption); + check_useful_c_str!(id, VcxErrorKind::InvalidOption); + check_useful_c_str!(tags, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_update_record_tags(command_handle: {}, type_: {}, id: {}, tags: {})", command_handle, type_, id, tags); @@ -303,10 +300,10 @@ pub extern fn vcx_wallet_add_record_tags(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_add_record_tags >>>"); - check_useful_c_str!(type_, error::INVALID_OPTION.code_num); - check_useful_c_str!(id, error::INVALID_OPTION.code_num); - check_useful_c_str!(tags, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(type_, VcxErrorKind::InvalidOption); + check_useful_c_str!(id, VcxErrorKind::InvalidOption); + check_useful_c_str!(tags, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_add_record_tags(command_handle: {}, type_: {}, id: {}, tags: {})", command_handle, type_, id, tags); @@ -345,10 +342,10 @@ pub extern fn vcx_wallet_delete_record_tags(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_delete_record_tags >>>"); - check_useful_c_str!(type_, error::INVALID_OPTION.code_num); - check_useful_c_str!(id, error::INVALID_OPTION.code_num); - check_useful_c_str!(tags, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(type_, VcxErrorKind::InvalidOption); + check_useful_c_str!(id, VcxErrorKind::InvalidOption); + check_useful_c_str!(tags, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_delete_record_tags(command_handle: {}, type_: {}, id: {}, tags: {})", command_handle, type_, id, tags); @@ -386,10 +383,10 @@ pub extern fn vcx_wallet_get_record(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_get_record >>>"); - check_useful_c_str!(type_, error::INVALID_OPTION.code_num); - check_useful_c_str!(id, error::INVALID_OPTION.code_num); - check_useful_c_str!(options_json, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(type_, VcxErrorKind::InvalidOption); + check_useful_c_str!(id, VcxErrorKind::InvalidOption); + check_useful_c_str!(options_json, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_get_record(command_handle: {}, type_: {}, id: {}, options: {})", command_handle, type_, id, options_json); @@ -398,7 +395,7 @@ pub extern fn vcx_wallet_get_record(command_handle: u32, match wallet::get_record(&type_, &id, &options_json) { Ok(x) => { trace!("vcx_wallet_get_record(command_handle: {}, rc: {}, record_json: {})", - command_handle, error_string(0), x); + command_handle, error::SUCCESS.message, x); let msg = CStringUtils::string_to_cstring(x); @@ -443,9 +440,9 @@ pub extern fn vcx_wallet_delete_record(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_delete_record >>>"); - check_useful_c_str!(type_, error::INVALID_OPTION.code_num); - check_useful_c_str!(id, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(type_, VcxErrorKind::InvalidOption); + check_useful_c_str!(id, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_delete_record(command_handle: {}, type_: {}, id: {})", command_handle, type_, id); @@ -454,7 +451,7 @@ pub extern fn vcx_wallet_delete_record(command_handle: u32, match wallet::delete_record(&type_, &id) { Ok(x) => { trace!("vcx_wallet_delete_record(command_handle: {}, rc: {})", - command_handle, error_string(0)); + command_handle, error::SUCCESS.message); cb(command_handle, error::SUCCESS.code_num); }, @@ -498,13 +495,13 @@ pub extern fn vcx_wallet_send_tokens(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_send_tokens >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(recipient, error::INVALID_OPTION.code_num); - check_useful_c_str!(tokens, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(recipient, VcxErrorKind::InvalidOption); + check_useful_c_str!(tokens, VcxErrorKind::InvalidOption); let tokens: u64 = match tokens.parse::() { Ok(x) => x, - Err(_) => return error::INVALID_OPTION.code_num, + Err(e) => return VcxError::from_msg(VcxErrorKind::InvalidOption, format!("Cannot parse tokens: {}", e)).into(), }; trace!("vcx_wallet_send_tokens(command_handle: {}, payment_handle: {}, tokens: {}, recipient: {})", command_handle, payment_handle, tokens, recipient); @@ -513,7 +510,7 @@ pub extern fn vcx_wallet_send_tokens(command_handle: u32, match pay_a_payee(tokens, &recipient) { Ok((payment, msg)) => { trace!("vcx_wallet_send_tokens_cb(command_handle: {}, rc: {}, receipt: {})", - command_handle, error_string(0), msg); + command_handle, error::SUCCESS.message, msg); let msg = CStringUtils::string_to_cstring(msg); cb(command_handle, error::SUCCESS.code_num, msg.as_ptr()); }, @@ -568,7 +565,7 @@ pub extern fn vcx_wallet_open_search(command_handle: i32, search_handle: i32)>) -> u32 { info!("vcx_wallet_open_search >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); use utils::constants::DEFAULT_SEARCH_HANDLE; spawn(move|| { @@ -607,7 +604,7 @@ pub extern fn vcx_wallet_search_next_records(command_handle: i32, records_json: *const c_char)>) -> u32 { info!("vcx_wallet_search_next_records >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_search_next_records(command_handle: {}, wallet_search_handle: {})", command_handle, wallet_search_handle); @@ -641,13 +638,13 @@ pub extern fn vcx_wallet_close_search(command_handle: u32, cb: Option) -> u32 { info!("vcx_wallet_close_search >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_close_search(command_handle: {}, search_handle: {})", command_handle, search_handle); spawn(move|| { trace!("vcx_wallet_close_search(command_handle: {}, rc: {})", - command_handle, error_string(0)); + command_handle, error::SUCCESS.message); cb(command_handle, error::SUCCESS.code_num); Ok(()) }); @@ -677,9 +674,9 @@ pub extern fn vcx_wallet_export(command_handle: u32, err: u32)>) -> u32 { info!("vcx_wallet_export >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(path, error::INVALID_OPTION.code_num); - check_useful_c_str!(backup_key, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(path, VcxErrorKind::InvalidOption); + check_useful_c_str!(backup_key, VcxErrorKind::InvalidOption); trace!("vcx_wallet_export(command_handle: {}, path: {}, backup_key: ****)", command_handle, path); @@ -728,8 +725,8 @@ pub extern fn vcx_wallet_import(command_handle: u32, err: u32)>) -> u32 { info!("vcx_wallet_import >>>"); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); - check_useful_c_str!(config, error::INVALID_OPTION.code_num); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); + check_useful_c_str!(config, VcxErrorKind::InvalidOption); trace!("vcx_wallet_import(command_handle: {}, config: ****)", command_handle); @@ -738,9 +735,8 @@ pub extern fn vcx_wallet_import(command_handle: u32, trace!("vcx_wallet_import(command_handle: {}, config: ****)", command_handle); match import(&config) { Ok(_) => { - let return_code = error::SUCCESS.code_num; - trace!("vcx_wallet_import(command_handle: {}, rc: {})", command_handle, return_code); - cb(command_handle, return_code); + trace!("vcx_wallet_import(command_handle: {}, rc: {})", command_handle, error::SUCCESS.message); + cb(command_handle, error::SUCCESS.code_num); } Err(e) => { warn!("vcx_wallet_import(command_handle: {}, rc: {})", command_handle, e); @@ -771,8 +767,8 @@ pub extern fn vcx_wallet_validate_payment_address(command_handle: i32, cb: Option) -> u32 { info!("vcx_wallet_validate_payment_address >>>"); - check_useful_c_str!(payment_address, error::INVALID_OPTION.code_num); - check_useful_c_callback!(cb, error::INVALID_OPTION.code_num); + check_useful_c_str!(payment_address, VcxErrorKind::InvalidOption); + check_useful_c_callback!(cb, VcxErrorKind::InvalidOption); trace!("vcx_wallet_validate_payment_address(command_handle: {}, payment_address: {})", command_handle, payment_address); diff --git a/vcx/libvcx/src/error/mod.rs b/vcx/libvcx/src/error/mod.rs index 342c4492f7..19228318ee 100644 --- a/vcx/libvcx/src/error/mod.rs +++ b/vcx/libvcx/src/error/mod.rs @@ -1,11 +1,16 @@ +use std::cell::RefCell; use std::fmt; +use std::ffi::CString; +use std::ptr; use failure::{Context, Backtrace, Fail}; +use libc::c_char; use utils::error; +use utils::cstring::CStringUtils; pub mod prelude { - pub use super::{err_msg, VcxError, VcxErrorExt, VcxErrorKind, VcxResult, VcxResultExt}; + pub use super::{err_msg, VcxError, VcxErrorExt, VcxErrorKind, VcxResult, VcxResultExt, get_current_error_c_json}; } #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)] @@ -35,6 +40,8 @@ pub enum VcxErrorKind { TimeoutLibindy, #[fail(display = "Parameter passed to libindy was invalid")] InvalidLibindyParam, + #[fail(display = "Library already initialized")] + AlreadyInitialized, // Connection #[fail(display = "Cannot create connection")] @@ -269,16 +276,15 @@ impl From> for VcxError { } } -pub type ErrorCode = u32; - -impl From for ErrorCode { - fn from(code: VcxError) -> ErrorCode { +impl From for u32 { + fn from(code: VcxError) -> u32 { + set_current_error(&code); code.kind().into() } } -impl From for ErrorCode { - fn from(code: VcxErrorKind) -> ErrorCode { +impl From for u32 { + fn from(code: VcxErrorKind) -> u32 { match code { VcxErrorKind::InvalidState => error::INVALID_STATE.code_num, VcxErrorKind::InvalidConfiguration => error::INVALID_CONFIGURATION.code_num, @@ -295,6 +301,7 @@ impl From for ErrorCode { VcxErrorKind::LibindyInvalidStructure => error::LIBINDY_INVALID_STRUCTURE.code_num, VcxErrorKind::TimeoutLibindy => error::TIMEOUT_LIBINDY_ERROR.code_num, VcxErrorKind::InvalidLibindyParam => error::INVALID_LIBINDY_PARAM.code_num, + VcxErrorKind::AlreadyInitialized => error::ALREADY_INITIALIZED.code_num, VcxErrorKind::CreateConnection => error::CREATE_CONNECTION_ERROR.code_num, VcxErrorKind::InvalidConnectionHandle => error::INVALID_CONNECTION_HANDLE.code_num, VcxErrorKind::InvalidInviteDetail => error::INVALID_INVITE_DETAILS.code_num, @@ -387,4 +394,28 @@ impl VcxErrorExt for E where E: Fail fn to_vcx(self, kind: VcxErrorKind, msg: D) -> VcxError where D: fmt::Display + Send + Sync + 'static { self.context(msg).context(kind).into() } +} + +thread_local! { + pub static CURRENT_ERROR_C_JSON: RefCell> = RefCell::new(None); +} + +pub fn set_current_error(err: &VcxError) { + CURRENT_ERROR_C_JSON.with(|error| { + let error_json = json!({ + "message": err.to_string(), + "backtrace": err.backtrace().map(|bt| bt.to_string()) + }).to_string(); + error.replace(Some(CStringUtils::string_to_cstring(error_json))); + }); +} + +pub fn get_current_error_c_json() -> *const c_char { + let mut value = ptr::null(); + + CURRENT_ERROR_C_JSON.with(|err| + err.borrow().as_ref().map(|err| value = err.as_ptr()) + ); + + value } \ No newline at end of file diff --git a/vcx/libvcx/src/lib.rs b/vcx/libvcx/src/lib.rs index beec8db679..4a760c34f2 100644 --- a/vcx/libvcx/src/lib.rs +++ b/vcx/libvcx/src/lib.rs @@ -16,6 +16,8 @@ extern crate futures; extern crate log; extern crate log4rs; +extern crate libc; + #[macro_use] extern crate serde_derive; diff --git a/vcx/libvcx/src/utils/ccallback.rs b/vcx/libvcx/src/utils/ccallback.rs index ba5cf3cf31..4d82dd0f57 100644 --- a/vcx/libvcx/src/utils/ccallback.rs +++ b/vcx/libvcx/src/utils/ccallback.rs @@ -2,7 +2,7 @@ macro_rules! check_useful_c_callback { ($x:ident, $e:expr) => { let $x = match $x { Some($x) => $x, - None => return $e + None => return VcxError::from_msg($e, "Invalid callback has been passed").into() }; } } \ No newline at end of file diff --git a/vcx/libvcx/src/utils/cstring.rs b/vcx/libvcx/src/utils/cstring.rs index 823a446a50..57666749fe 100644 --- a/vcx/libvcx/src/utils/cstring.rs +++ b/vcx/libvcx/src/utils/cstring.rs @@ -1,6 +1,4 @@ -extern crate libc; - -use self::libc::c_char; +use libc::c_char; use std::ffi::CStr; use std::str::Utf8Error; @@ -43,11 +41,11 @@ macro_rules! check_useful_c_str { ($x:ident, $e:expr) => { let $x = match CStringUtils::c_str_to_string($x) { Ok(Some(val)) => val, - _ => return $e, + _ => return VcxError::from_msg($e, "Invalid pointer has been passed").into() }; if $x.is_empty() { - return $e + return VcxError::from_msg($e, "Empty string has been passed").into() } } } @@ -56,7 +54,7 @@ macro_rules! check_useful_opt_c_str { ($x:ident, $e:expr) => { let $x = match CStringUtils::c_str_to_string($x) { Ok(opt_val) => opt_val, - Err(_) => return $e + Err(_) => return VcxError::from_msg($e, "Invalid pointer has been passed").into() }; } } @@ -65,11 +63,11 @@ macro_rules! check_useful_opt_c_str { macro_rules! check_useful_c_byte_array { ($ptr:ident, $len:expr, $err1:expr, $err2:expr) => { if $ptr.is_null() { - return $err1; + return VcxError::from_msg($err1, "Invalid pointer has been passed").into() } if $len <= 0 { - return $err2; + return VcxError::from_msg($err2, "Array length must be greater than 0").into() } let $ptr = unsafe { $crate::std::slice::from_raw_parts($ptr, $len as usize) }; diff --git a/vcx/libvcx/src/utils/libindy/callback_u32.rs b/vcx/libvcx/src/utils/libindy/callback_u32.rs index c50f16a1ea..a4c82e5c4b 100644 --- a/vcx/libvcx/src/utils/libindy/callback_u32.rs +++ b/vcx/libvcx/src/utils/libindy/callback_u32.rs @@ -1,6 +1,4 @@ -extern crate libc; - -use self::libc::c_char; +use libc::c_char; use std::collections::HashMap; use std::sync::Mutex; use std::ops::Deref; From 2901e9126164e66310f0771452648b6eff7b48e8 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Fri, 22 Feb 2019 08:55:58 +0300 Subject: [PATCH 07/28] Set thread as an optional Signed-off-by: artem.ivanov --- vcx/libvcx/src/credential.rs | 9 ++++--- vcx/libvcx/src/disclosed_proof.rs | 9 ++++--- vcx/libvcx/src/issuer_credential.rs | 34 +++++++----------------- vcx/libvcx/src/proof.rs | 41 +++++++---------------------- 4 files changed, 29 insertions(+), 64 deletions(-) diff --git a/vcx/libvcx/src/credential.rs b/vcx/libvcx/src/credential.rs index 5cc55363f4..07ee4c6f9a 100644 --- a/vcx/libvcx/src/credential.rs +++ b/vcx/libvcx/src/credential.rs @@ -52,7 +52,7 @@ impl Default for Credential { credential: None, payment_info: None, payment_txn: None, - thread: Thread::new(), + thread: Some(Thread::new()) } } } @@ -76,7 +76,7 @@ pub struct Credential { cred_id: Option, payment_info: Option, payment_txn: Option, - thread: Thread + thread: Option } impl Credential { @@ -160,7 +160,7 @@ impl Credential { .msg_type(&RemoteMessageType::CredReq)? .agent_did(local_agent_did)? .agent_vk(local_agent_vk)? - .edge_agent_payload(&local_my_vk, &local_their_vk, &cred_req_json, PayloadKinds::CredReq, Some(self.thread.clone()))? + .edge_agent_payload(&local_my_vk, &local_their_vk, &cred_req_json, PayloadKinds::CredReq, self.thread.clone())? .ref_msg_id(&offer_msg_id)? .send_secure() .map_err(|err| { @@ -188,7 +188,8 @@ impl Credential { let (credential, thread) = Payloads::decrypt(&my_vk, &payload)?; if let Some(_) = thread { - self.thread.increment_receiver(self.their_did.as_ref().map(String::as_str).unwrap_or("")); + let their_did = self.their_did.as_ref().map(String::as_str).unwrap_or(""); + self.thread.as_mut().map(|thread| thread.increment_receiver(&their_did)); } let credential_msg: CredentialMessage = serde_json::from_str(&credential) diff --git a/vcx/libvcx/src/disclosed_proof.rs b/vcx/libvcx/src/disclosed_proof.rs index 4e8e1903a8..d8c92b5132 100644 --- a/vcx/libvcx/src/disclosed_proof.rs +++ b/vcx/libvcx/src/disclosed_proof.rs @@ -45,7 +45,7 @@ impl Default for DisclosedProof { their_vk: None, agent_did: None, agent_vk: None, - thread: Thread::new() + thread: Some(Thread::new()) } } } @@ -63,7 +63,7 @@ pub struct DisclosedProof { their_vk: Option, agent_did: Option, agent_vk: Option, - thread: Thread + thread: Option } #[derive(Debug, Deserialize, Serialize)] @@ -414,7 +414,8 @@ impl DisclosedProof { true => DEFAULT_GENERATED_PROOF.to_string(), }; - self.thread.increment_receiver(self.their_did.as_ref().map(String::as_str).unwrap_or("")); + let their_did = self.their_did.as_ref().map(String::as_str).unwrap_or(""); + self.thread.as_mut().map(|thread| thread.increment_receiver(&their_did)); messages::send_message() .to(local_my_did)? @@ -422,7 +423,7 @@ impl DisclosedProof { .msg_type(&RemoteMessageType::Proof)? .agent_did(local_agent_did)? .agent_vk(local_agent_vk)? - .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof, Some(self.thread.clone())).or(Err(ProofError::ProofConnectionError()))? + .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof, self.thread.clone()).or(Err(ProofError::ProofConnectionError()))? .ref_msg_id(ref_msg_uid)? .send_secure() .map_err(|err| { diff --git a/vcx/libvcx/src/issuer_credential.rs b/vcx/libvcx/src/issuer_credential.rs index c77d36f6d1..d3ad449b2b 100644 --- a/vcx/libvcx/src/issuer_credential.rs +++ b/vcx/libvcx/src/issuer_credential.rs @@ -65,7 +65,7 @@ pub struct IssuerCredential { remote_did: String, //their_pw_did for this relationship remote_vk: String, - thread: Thread + thread: Option } #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] @@ -173,7 +173,7 @@ impl IssuerCredential { .to(&self.issued_did)? .to_vk(&self.issued_vk)? .msg_type(&RemoteMessageType::CredOffer)? - .edge_agent_payload(&self.issued_vk, &self.remote_vk, &payload, PayloadKinds::CredOffer, Some(self.thread.clone()))? + .edge_agent_payload(&self.issued_vk, &self.remote_vk, &payload, PayloadKinds::CredOffer, self.thread.clone())? .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? .set_title(&title)? @@ -221,14 +221,14 @@ impl IssuerCredential { let cred_req_msg_id = self.credential_request.as_ref().and_then(|cred_req| cred_req.msg_ref_id.as_ref()) .ok_or(IssuerCredError::InvalidCredRequest())?; - self.thread.sender_order += 1; + self.thread.as_mut().map(|thread| thread.sender_order += 1); let response = messages::send_message() .to(&self.issued_did)? .to_vk(&self.issued_vk)? .msg_type(&RemoteMessageType::Cred)? .status_code(&MessageStatusCode::Accepted)? - .edge_agent_payload(&self.issued_vk, &self.remote_vk, &data, PayloadKinds::Cred, Some(self.thread.clone()))? + .edge_agent_payload(&self.issued_vk, &self.remote_vk, &data, PayloadKinds::Cred, self.thread.clone())? .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? .ref_msg_id(cred_req_msg_id)? @@ -270,7 +270,8 @@ impl IssuerCredential { let cred_req = parse_credential_req_payload(offer_uid, payload)?; if let Some(tr) = thread { - self.thread.increment_receiver(self.remote_did.as_str()); + let remote_did = self.remote_did.as_str(); + self.thread.as_mut().map(|thread| thread.increment_receiver(&remote_did)); } self.credential_request = Some(cred_req); @@ -582,7 +583,7 @@ pub fn issuer_credential_create(cred_def_handle: u32, agent_vk: String::new(), cred_def_id, cred_def_handle, - thread: Thread::new(), + thread: Some(Thread::new()), }; new_issuer_credential.validate_credential_offer()?; @@ -787,12 +788,7 @@ pub mod tests { agent_vk: VERKEY.to_string(), cred_def_id: CRED_DEF_ID.to_string(), cred_def_handle: 0, - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }; issuer_credential } @@ -848,12 +844,7 @@ pub mod tests { agent_vk: String::new(), cred_def_id, cred_def_handle, - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }; let payment = issuer_credential.generate_payment_info().unwrap(); @@ -1023,12 +1014,7 @@ pub mod tests { remote_vk: VERKEY.to_string(), agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }; ::utils::httpclient::set_next_u8_response(CREDENTIAL_REQ_RESPONSE.to_vec()); diff --git a/vcx/libvcx/src/proof.rs b/vcx/libvcx/src/proof.rs index 9a0e90553f..18022a2083 100644 --- a/vcx/libvcx/src/proof.rs +++ b/vcx/libvcx/src/proof.rs @@ -55,7 +55,7 @@ pub struct Proof { agent_did: String, agent_vk: String, revocation_interval: RevocationInterval, - thread: Thread + thread: Option } impl Proof { @@ -288,7 +288,7 @@ impl Proof { .set_title(&title)? .set_detail(&title)? .agent_vk(&self.agent_vk)? - .edge_agent_payload(&self.prover_vk, &self.remote_vk, &proof_request, PayloadKinds::ProofRequest, Some(self.thread.clone())).or(Err(ProofError::ProofConnectionError()))? + .edge_agent_payload(&self.prover_vk, &self.remote_vk, &proof_request, PayloadKinds::ProofRequest, self.thread.clone()).or(Err(ProofError::ProofConnectionError()))? .send_secure() .map_err(|err| { warn!("{} could not send proofReq: {}", self.source_id, err); @@ -325,7 +325,8 @@ impl Proof { }; if let Some(tr) = thread { - self.thread.increment_receiver(self.remote_did.as_str()); + let remote_did = self.remote_did.as_str(); + self.thread.as_mut().map(|thread| thread.increment_receiver(&remote_did)); } self.state = VcxStateType::VcxStateAccepted; @@ -423,7 +424,7 @@ pub fn create_proof(source_id: String, agent_did: String::new(), agent_vk: String::new(), revocation_interval: revocation_details, - thread: Thread::new(), + thread: Some(Thread::new()), }; new_proof.validate_proof_request().map_err(|ec| ProofError::CommonError(ec))?; @@ -542,7 +543,6 @@ mod tests { use utils::httpclient; use connection::tests::build_test_connection; use utils::libindy::{pool, set_libindy_rc}; - use std::collections::HashMap; static PROOF_MSG: &str = r#"{"msg_type":"proof","version":"0.1","to_did":"BnRXf8yDMUwGyZVDkSENeq","from_did":"GxtnGN6ypZYgEqcftSQFnC","proof_request_id":"cCanHnpFAD","proofs":{"claim::e5fec91f-d03d-4513-813c-ab6db5715d55":{"proof":{"primary_proof":{"eq_proof":{"revealed_attrs":{"state":"96473275571522321025213415717206189191162"},"a_prime":"22605045280481376895214546474258256134055560453004805058368015338423404000586901936329279496160366852115900235316791489357953785379851822281248296428005020302405076144264617943389810572564188437603815231794326272302243703078443007359698858400857606408856314183672828086906560155576666631125808137726233827430076624897399072853872527464581329767287002222137559918765406079546649258389065217669558333867707240780369514832185660287640444094973804045885379406641474693993903268791773620198293469768106363470543892730424494655747935463337367735239405840517696064464669905860189004121807576749786474060694597244797343224031","e":"70192089123105616042684481760592174224585053817450673797400202710878562748001698340846985261463026529360990669802293480312441048965520897","v":"1148619141217957986496757711054111791862691178309410923416837802801708689012670430650138736456223586898110113348220116209094530854607083005898964558239710027534227973983322542548800291320747321452329327824406430787211689678096549398458892087551551587767498991043777397791000822007896620414888602588897806008609113730393639807814070738699614969916095861363383223421727858670289337712185089527052065958362840287749622133424503902085247641830693297082507827948006947829401008622239294382186995101394791468192083810475776455445579931271665980788474331866572497866962452476638881287668931141052552771328556458489781734943404258692308937784221642452132005267809852656378394530342203469943982066011466088478895643800295937901139711103301249691253510784029114718919483272055970725860849610885050165709968510696738864528287788491998027072378656038991754015693216663830793243584350961586874315757599094357535856429087122365865868729","m":{"address2":"11774234640096848605908744857306447015748098256395922562149769943967941106193320512788344020652220849708117081570187385467979956319507248530701654682748372348387275979419669108338","city":"4853213962270369118453000522408430296589146124488849630769837449684434138367659379663124155088827069418193027370932024893343033367076071757003149452226758383807126385017161888440","address1":"12970590675851114145396120869959510754345567924518524026685086869487243290925032320159287997675756075512889990901552679591155319959039145119122576164798225386578339739435869622811","zip":"8333721522340131864419931745588776943042067606218561135102011966361165456174036379901390244538991611895455576519950813910672825465382312504250936740379785802177629077591444977329"},"m1":"92853615502250003546205004470333326341901175168428906399291824325990659330595200000112546157141090642053863739870044907457400076448073272490169488870502566172795456430489790324815765612798273406119873266684053517977802902202155082987833343670942161987285661291655743810590661447300059024966135828466539810035","m2":"14442362430453309930284822850357071315613831915865367971974791350454381198894252834180803515368579729220423713315556807632571621646127926114010380486713602821529657583905131582938"},"ge_proofs":[]},"non_revoc_proof":null},"schema_seq_no":15,"issuer_did":"4fUDR9R7fjwELRvH9JT6HH"}},"aggregated_proof":{"c_hash":"68430476900085482958838239880418115228681348197588159723604944078288347793331","c_list":[[179,17,2,242,194,227,92,203,28,32,255,113,112,20,5,243,9,111,220,111,21,210,116,12,167,119,253,181,37,40,143,215,140,42,179,97,75,229,96,94,54,248,206,3,48,14,61,219,160,122,139,227,166,183,37,43,197,200,28,220,217,10,65,42,6,195,124,44,164,65,114,206,51,231,254,156,170,141,21,153,50,251,237,65,147,97,243,17,157,116,213,201,80,119,106,70,88,60,55,36,33,160,135,106,60,212,191,235,116,57,78,177,61,86,44,226,205,100,134,118,93,6,26,58,220,66,232,166,202,62,90,174,231,207,19,239,233,223,70,191,199,100,157,62,139,176,28,184,9,70,116,199,142,237,198,183,12,32,53,84,207,202,77,56,97,177,154,169,223,201,212,163,212,101,184,255,215,167,16,163,136,44,25,123,49,15,229,41,149,133,159,86,106,208,234,73,207,154,194,162,141,63,159,145,94,47,174,51,225,91,243,2,221,202,59,11,212,243,197,208,116,42,242,131,221,137,16,169,203,215,239,78,254,150,42,169,202,132,172,106,179,130,178,130,147,24,173,213,151,251,242,44,54,47,208,223]]},"requested_proof":{"revealed_attrs":{"sdf":["claim::e5fec91f-d03d-4513-813c-ab6db5715d55","UT","96473275571522321025213415717206189191162"]},"unrevealed_attrs":{},"self_attested_attrs":{},"predicates":{}}}"#; @@ -573,13 +573,7 @@ mod tests { agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), revocation_interval: RevocationInterval { from: None, to: None }, - - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }) } @@ -742,13 +736,7 @@ mod tests { agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), revocation_interval: RevocationInterval { from: None, to: None }, - - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }); httpclient::set_next_u8_response(PROOF_RESPONSE.to_vec()); @@ -784,13 +772,7 @@ mod tests { agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), revocation_interval: RevocationInterval { from: None, to: None }, - - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }); httpclient::set_next_u8_response(PROOF_RESPONSE.to_vec()); @@ -965,12 +947,7 @@ mod tests { agent_did: DID.to_string(), agent_vk: VERKEY.to_string(), revocation_interval: RevocationInterval { from: None, to: None }, - thread: Thread { - thid: None, - pthid: None, - sender_order: 0, - received_orders: HashMap::new(), - }, + thread: Some(Thread::new()), }; let rc = proof.proof_validation(); assert!(rc.is_ok()); From eb3863db68e7032a11a277866e4e8d95bac819fd Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Fri, 22 Feb 2019 10:08:41 +0300 Subject: [PATCH 08/28] Updated vcx python wrapper to fetch error details Signed-off-by: artem.ivanov --- vcx/libvcx/include/vcx.h | 20 ++++++++ vcx/libvcx/src/api/utils.rs | 59 ------------------------ vcx/libvcx/src/api/vcx.rs | 59 ++++++++++++++++++++++++ vcx/wrappers/python3/tests/test_error.py | 10 ++++ vcx/wrappers/python3/vcx/common.py | 11 +++-- vcx/wrappers/python3/vcx/error.py | 28 ++++++++++- 6 files changed, 121 insertions(+), 66 deletions(-) diff --git a/vcx/libvcx/include/vcx.h b/vcx/libvcx/include/vcx.h index 4b4680b116..3101bd7cff 100644 --- a/vcx/libvcx/include/vcx.h +++ b/vcx/libvcx/include/vcx.h @@ -1605,6 +1605,26 @@ vcx_error_t vcx_get_logger(const void* vcx_get_logger, vcx_u32_t line), void (**flushFn)(const void* context) ); +/// Get details for last occurred error. +/// +/// This function should be called in two places to handle both cases of error occurrence: +/// 1) synchronous - in the same application thread +/// 2) asynchronous - inside of function callback +/// +/// NOTE: Error is stored until the next one occurs in the same execution thread or until asynchronous callback finished. +/// Returning pointer has the same lifetime. +/// +/// #Params +/// * `error_json_p` - Reference that will contain error details (if any error has occurred before) +/// in the format: +/// { +/// "backtrace": Optional - error backtrace. +/// Collecting of backtrace can be enabled by setting environment variable `RUST_BACKTRACE=1` +/// "message": str - human-readable error description +/// } +/// +vcx_error_t vcx_current_error(const char ** error_json_p); + #ifdef __cplusplus } // extern "C" #endif diff --git a/vcx/libvcx/src/api/utils.rs b/vcx/libvcx/src/api/utils.rs index 64c32753fc..6f7349290c 100644 --- a/vcx/libvcx/src/api/utils.rs +++ b/vcx/libvcx/src/api/utils.rs @@ -343,34 +343,6 @@ pub extern fn vcx_messages_update_status(command_handle: u32, error::SUCCESS.code_num } -/// Get details for last occurred error. -/// -/// This function should be called in two places to handle both cases of error occurrence: -/// 1) synchronous - in the same application thread -/// 2) asynchronous - inside of function callback -/// -/// NOTE: Error is stored until the next one occurs in the same execution thread or until asynchronous callback finished. -/// Returning pointer has the same lifetime. -/// -/// #Params -/// * `error_json_p` - Reference that will contain error details (if any error has occurred before) -/// in the format: -/// { -/// "backtrace": Optional - error backtrace. -/// Collecting of backtrace can be enabled by setting environment variable `RUST_BACKTRACE=1` -/// "message": str - human-readable error description -/// } -/// -#[no_mangle] -pub extern fn vcx_get_current_error(error_json_p: *mut *const c_char) { - trace!("vcx_get_current_error >>> error_json_p: {:?}", error_json_p); - - let error = get_current_error_c_json(); - unsafe { *error_json_p = error }; - - trace!("vcx_get_current_error: <<<"); -} - #[cfg(test)] mod tests { use super::*; @@ -502,36 +474,5 @@ mod tests { error::SUCCESS.code_num); cb.receive(Some(Duration::from_secs(10))).unwrap(); } - - #[test] - fn get_current_error_works_for_no_error() { - let mut error_json_p: *const c_char = ptr::null(); - - vcx_get_current_error(&mut error_json_p); - assert_eq!(None, CStringUtils::c_str_to_string(error_json_p).unwrap()); - } - - #[test] - fn get_current_error_works_for_sync_error() { - vcx_provision_agent(ptr::null()); - - let mut error_json_p: *const c_char = ptr::null(); - vcx_get_current_error(&mut error_json_p); - assert!(CStringUtils::c_str_to_string(error_json_p).unwrap().is_some()); - } - - #[test] - fn get_current_error_works_for_async_error() { - extern fn cb(storage_handle: u32, - err: u32, - config: *const c_char) { - let mut error_json_p: *const c_char = ptr::null(); - vcx_get_current_error(&mut error_json_p); - assert!(CStringUtils::c_str_to_string(error_json_p).unwrap().is_some()); - } - - let config = CString::new("{}").unwrap(); - vcx_agent_provision_async(0, config.as_ptr(), Some(cb)); - } } diff --git a/vcx/libvcx/src/api/vcx.rs b/vcx/libvcx/src/api/vcx.rs index e4967febf1..22c9142e2e 100644 --- a/vcx/libvcx/src/api/vcx.rs +++ b/vcx/libvcx/src/api/vcx.rs @@ -269,6 +269,34 @@ pub extern fn vcx_mint_tokens(seed: *const c_char, fees: *const c_char) { ::utils::libindy::payments::mint_tokens_and_set_fees(None, None, fees, seed).unwrap_or_default(); } +/// Get details for last occurred error. +/// +/// This function should be called in two places to handle both cases of error occurrence: +/// 1) synchronous - in the same application thread +/// 2) asynchronous - inside of function callback +/// +/// NOTE: Error is stored until the next one occurs in the same execution thread or until asynchronous callback finished. +/// Returning pointer has the same lifetime. +/// +/// #Params +/// * `error_json_p` - Reference that will contain error details (if any error has occurred before) +/// in the format: +/// { +/// "backtrace": Optional - error backtrace. +/// Collecting of backtrace can be enabled by setting environment variable `RUST_BACKTRACE=1` +/// "message": str - human-readable error description +/// } +/// +#[no_mangle] +pub extern fn vcx_get_current_error(error_json_p: *mut *const c_char) { + trace!("vcx_get_current_error >>> error_json_p: {:?}", error_json_p); + + let error = get_current_error_c_json(); + unsafe { *error_json_p = error }; + + trace!("vcx_get_current_error: <<<"); +} + #[cfg(test)] mod tests { use super::*; @@ -773,4 +801,35 @@ mod tests { assert_ne!(get_pool_handle().unwrap(), 0); debug!("This statement should log"); } + + #[test] + fn get_current_error_works_for_no_error() { + let mut error_json_p: *const c_char = ptr::null(); + + vcx_get_current_error(&mut error_json_p); + assert_eq!(None, CStringUtils::c_str_to_string(error_json_p).unwrap()); + } + + #[test] + fn get_current_error_works_for_sync_error() { + ::api::utils::vcx_provision_agent(ptr::null()); + + let mut error_json_p: *const c_char = ptr::null(); + vcx_get_current_error(&mut error_json_p); + assert!(CStringUtils::c_str_to_string(error_json_p).unwrap().is_some()); + } + + #[test] + fn get_current_error_works_for_async_error() { + extern fn cb(storage_handle: u32, + err: u32, + config: *const c_char) { + let mut error_json_p: *const c_char = ptr::null(); + vcx_get_current_error(&mut error_json_p); + assert!(CStringUtils::c_str_to_string(error_json_p).unwrap().is_some()); + } + + let config = CString::new("{}").unwrap(); + ::api::utils::vcx_agent_provision_async(0, config.as_ptr(), Some(cb)); + } } diff --git a/vcx/wrappers/python3/tests/test_error.py b/vcx/wrappers/python3/tests/test_error.py index 8555920f5b..5883da0f58 100644 --- a/vcx/wrappers/python3/tests/test_error.py +++ b/vcx/wrappers/python3/tests/test_error.py @@ -1,4 +1,6 @@ import pytest + +from vcx.api.utils import vcx_agent_provision from vcx.error import ErrorCode, VcxError, error_message @@ -19,3 +21,11 @@ def test_all_error_codes(): assert(VcxError(max+1).error_msg == "Unknown Error") + +@pytest.mark.asyncio +@pytest.mark.usefixtures('vcx_init_test_mode') +async def test_error_details(): + with pytest.raises(VcxError) as e: + await vcx_agent_provision("") + assert ErrorCode.InvalidOption == e.value.error_code + assert e.value.vcx_error_msg diff --git a/vcx/wrappers/python3/vcx/common.py b/vcx/wrappers/python3/vcx/common.py index ac4375f1ea..c8ce839dd2 100644 --- a/vcx/wrappers/python3/vcx/common.py +++ b/vcx/wrappers/python3/vcx/common.py @@ -97,27 +97,28 @@ def create_cb(cb_type: CFUNCTYPE, transform_fn=None): def _cb(command_handle: int, err: int, *args): if transform_fn: args = transform_fn(*args) - _cxs_callback(command_handle, err, *args) + error = VcxError(ErrorCode(err)) + _cxs_callback(command_handle, error, *args) res = cb_type(_cb) return res -def _cxs_callback(command_handle: int, err: int, *args): +def _cxs_callback(command_handle: int, err: VcxError, *args): (event_loop, future) = _futures[command_handle] event_loop.call_soon_threadsafe(_cxs_loop_callback, command_handle, err, *args) -def _cxs_loop_callback(command_handle: int, err, *args): +def _cxs_loop_callback(command_handle: int, err: VcxError, *args): (event_loop, future) = _futures.pop(command_handle) if future.cancelled(): print("_indy_loop_callback: Future was cancelled earlier") else: - if err != ErrorCode.Success: - future.set_exception(VcxError(ErrorCode(err))) + if err.error_code != ErrorCode.Success: + future.set_exception(err) else: if len(args) == 0: res = None diff --git a/vcx/wrappers/python3/vcx/error.py b/vcx/wrappers/python3/vcx/error.py index 35b9d78d39..1307a1977f 100644 --- a/vcx/wrappers/python3/vcx/error.py +++ b/vcx/wrappers/python3/vcx/error.py @@ -1,8 +1,11 @@ +import json + LIBRARY = "libvcx.so" from vcx.cdll import _cdll from enum import IntEnum -from ctypes import c_char_p, cast, c_uint32 +from ctypes import c_char_p, byref, c_uint32 import logging +from typing import Optional class ErrorCode(IntEnum): @@ -55,7 +58,7 @@ class ErrorCode(IntEnum): InvalidMasterSecret = 1043, AlreadyInitialized = 1044, InvalidInviteDetails = 1045, - InvalidSelfAttestedVal = 1046, + InvalidSelfAttestedVal = 1046, InvalidPredicate = 1047, InvalidObjHandle = 1048, InvalidDisclosedProofHandle = 1049, @@ -109,10 +112,19 @@ class ErrorCode(IntEnum): class VcxError(Exception): # error_code: ErrorCode + # error_msg: Optional[str] - human-readable error description + # vcx_error_msg: Optional[str] - vcx error message. + # vcx_error_backtrace: Optional[str] - vcx error backtrace. + # Collecting of backtrace can be enabled by setting environment variable `RUST_BACKTRACE=1` def __init__(self, error_code: ErrorCode): self.error_code = error_code self.error_msg = error_message(error_code) + if error_code != ErrorCode.Success: + error_details = get_error_details() + if error_details: + self.vcx_error_msg = error_details['message'] + self.vcx_error_backtrace = error_details['backtrace'] def error_message(error_code: int) -> str: @@ -123,3 +135,15 @@ def error_message(error_code: int) -> str: err_msg = getattr(_cdll(), name)(c_error_code) logger.debug("error_message: Function %s[%s] returned error_message: %s", name, error_code, err_msg) return err_msg.decode() + + +def get_error_details() -> Optional[dict]: + logger = logging.getLogger(__name__) + logger.debug("get_error_details: >>>") + + error_c = c_char_p() + getattr(_cdll(), 'vcx_get_current_error')(byref(error_c)) + error_details = json.loads(error_c.value.decode()) if error_c.value else None + + logger.debug("get_error_details: <<< error_details: %s", error_details) + return error_details From 38eb03bfe7564d44faad0b98153a641ba0e8f926 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Fri, 22 Feb 2019 12:05:27 +0300 Subject: [PATCH 09/28] Updated vcx java wrapper to fetch error details Signed-off-by: artem.ivanov --- .../main/java/com/evernym/sdk/vcx/LibVcx.java | 3 +- .../com/evernym/sdk/vcx/VcxException.java | 33 +++++++++++++++++++ .../com/evernym/sdk/vcx/ErrorCodeTest.java | 14 ++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/LibVcx.java b/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/LibVcx.java index 0496c43a74..19b0f1873a 100644 --- a/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/LibVcx.java +++ b/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/LibVcx.java @@ -1,6 +1,7 @@ package com.evernym.sdk.vcx; import com.sun.jna.*; +import com.sun.jna.ptr.PointerByReference; import java.io.File; @@ -30,7 +31,7 @@ public int vcx_init_with_config(int command_handle, * Helper API for testing purposes. */ public void vcx_set_next_agency_response(int msg); - + public void vcx_get_current_error(PointerByReference error); /** * Schema object diff --git a/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/VcxException.java b/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/VcxException.java index d69829c703..618790604f 100644 --- a/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/VcxException.java +++ b/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/VcxException.java @@ -61,6 +61,8 @@ import com.evernym.sdk.vcx.wallet.WalletItemAlreadyExistsException; import com.evernym.sdk.vcx.wallet.WalletItemNotFoundException; +import com.sun.jna.ptr.PointerByReference; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,6 +74,8 @@ public class VcxException extends Exception { private static final Logger logger = LoggerFactory.getLogger("VcxException"); private static final long serialVersionUID = 2650355290834266234L; private int sdkErrorCode; + private String sdkMessage; + private String sdkBacktrace; /** * Initializes a new VcxException with the specified message. @@ -81,6 +85,21 @@ public class VcxException extends Exception { protected VcxException(String message, int sdkErrorCode) { super(message); this.sdkErrorCode = sdkErrorCode; + setSdkErrorDetails(); + } + + private void setSdkErrorDetails(){ + PointerByReference errorDetailsJson = new PointerByReference(); + + LibVcx.api.vcx_get_current_error(errorDetailsJson); + + try { + JSONObject errorDetails = new JSONObject(errorDetailsJson.getValue().getString(0)); + this.sdkMessage = errorDetails.optString("message"); + this.sdkBacktrace = errorDetails.optString("backtrace"); + } catch(Exception e) { + // TODO + } } /** @@ -92,6 +111,20 @@ public int getSdkErrorCode() { return sdkErrorCode; } + /** + * Gets the SDK error message for the exception. + * + * @return The SDK error message used to construct the exception. + */ + public String getSdkMessage() {return sdkMessage;} + + /** + * Gets the SDK error backtrace for the exception. + * + * @return The SDK error backtrace used to construct the exception. + */ + public String getSdkBacktrace() {return sdkBacktrace;} + /** * Initializes a new VcxException using the specified SDK error code. * diff --git a/vcx/wrappers/java/src/test/java/com/evernym/sdk/vcx/ErrorCodeTest.java b/vcx/wrappers/java/src/test/java/com/evernym/sdk/vcx/ErrorCodeTest.java index 6e46146527..636e238edc 100644 --- a/vcx/wrappers/java/src/test/java/com/evernym/sdk/vcx/ErrorCodeTest.java +++ b/vcx/wrappers/java/src/test/java/com/evernym/sdk/vcx/ErrorCodeTest.java @@ -1,6 +1,9 @@ package com.evernym.sdk.vcx; +import com.evernym.sdk.vcx.connection.ConnectionApi; +import java9.util.concurrent.CompletableFuture; +import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; import static com.evernym.sdk.vcx.ErrorCode.CONNECTION_ERROR; @@ -21,4 +24,15 @@ public void assertKnownErrorCodeisHandled(){ ErrorCode errorCode = ErrorCode.valueOf(1002); assertEquals(CONNECTION_ERROR,errorCode); } + + @Test + public void testGetErrorDetails(){ + try { + CompletableFuture future = ConnectionApi.connectionSerialize(0); + Awaitility.await().until(future::isDone); + } catch (VcxException e){ + assert(!e.getMessage().isEmpty()); + assert(!e.getSdkMessage().isEmpty()); + } + } } From 417cabede3618c8544d4f33be9e1a4cd9233bfd2 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Fri, 22 Feb 2019 12:54:20 +0300 Subject: [PATCH 10/28] Updated vcx ios wrapper to fetch error details (temporary commented) Signed-off-by: artem.ivanov --- vcx/wrappers/ios/vcx/utils/NSError+VcxError.m | 20 ++++++++++++++++++- .../ios/vcx/vcx.framework/Headers/libvcx.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/vcx/wrappers/ios/vcx/utils/NSError+VcxError.m b/vcx/wrappers/ios/vcx/utils/NSError+VcxError.m index abb8a9284d..04ec1452f8 100644 --- a/vcx/wrappers/ios/vcx/utils/NSError+VcxError.m +++ b/vcx/wrappers/ios/vcx/utils/NSError+VcxError.m @@ -11,7 +11,25 @@ @implementation NSError (VcxError) + (NSError*) errorFromVcxError:(vcx_error_t) error { - return [NSError errorWithDomain:VcxErrorDomain code: error userInfo:nil]; + NSMutableDictionary *userInfo = [NSMutableDictionary new]; + + // if (error != Success) { + // const char * error_json_p; + // indy_get_current_error(&error_json_p); + // + // NSString *errorDetailsJson = [NSString stringWithUTF8String:error_json_p]; + // + // NSError *error; + // NSDictionary *errorDetails = [NSJSONSerialization JSONObjectWithData:[NSData dataWithBytes:[errorDetailsJson UTF8String] + // length:[errorDetailsJson length]] + // options:kNilOptions + // error: &error]; + // + // [userInfo setValue:errorDetails[@"message"] forKey:@"sdk_message"]; + // [userInfo setValue:errorDetails[@"backtrace"] forKey:@"sdk_backtrace"]; + // } + + return [NSError errorWithDomain:VcxErrorDomain code: error userInfo:userInfo]; } @end diff --git a/vcx/wrappers/ios/vcx/vcx.framework/Headers/libvcx.h b/vcx/wrappers/ios/vcx/vcx.framework/Headers/libvcx.h index 7329146a8d..c4c44abc77 100644 --- a/vcx/wrappers/ios/vcx/vcx.framework/Headers/libvcx.h +++ b/vcx/wrappers/ios/vcx/vcx.framework/Headers/libvcx.h @@ -68,6 +68,8 @@ vcx_error_t vcx_update_agent_info(vcx_command_handle_t handle, const char *info, const char *vcx_error_c_message(int); const char *vcx_version(); +vcx_error_t vcx_current_error(const char ** error_json_p); + /** * Schema object * From 7f03d0bbd397503b7b19318cfddf31608c9fec48 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Fri, 22 Feb 2019 17:04:46 +0300 Subject: [PATCH 11/28] Code refactored Signed-off-by: artem.ivanov --- vcx/libvcx/src/api/vcx.rs | 1 + vcx/libvcx/src/credential_def.rs | 2 +- vcx/libvcx/src/disclosed_proof.rs | 20 +++++++++---------- vcx/libvcx/src/error/mod.rs | 4 +++- vcx/libvcx/src/issuer_credential.rs | 3 ++- vcx/libvcx/src/messages/agent_utils.rs | 12 +++++------ vcx/libvcx/src/messages/get_message.rs | 13 +++++------- vcx/libvcx/src/messages/invite.rs | 4 ++-- vcx/libvcx/src/messages/payload.rs | 2 +- .../src/messages/proofs/proof_message.rs | 2 +- vcx/libvcx/src/messages/update_connection.rs | 2 +- vcx/libvcx/src/messages/update_message.rs | 2 +- vcx/libvcx/src/messages/update_profile.rs | 2 +- vcx/libvcx/src/utils/libindy/anoncreds.rs | 2 +- vcx/libvcx/src/utils/libindy/payments.rs | 2 +- vcx/libvcx/src/utils/libindy/pool.rs | 6 +++--- vcx/libvcx/src/utils/libindy/wallet.rs | 2 +- vcx/libvcx/src/utils/openssl.rs | 8 ++++---- vcx/wrappers/ios/vcx/utils/NSError+VcxError.m | 4 +++- .../com/evernym/sdk/vcx/VcxException.java | 20 ++++++++++++++++++- .../com/evernym/sdk/vcx/ErrorCodeTest.java | 2 ++ vcx/wrappers/python3/tests/test_error.py | 4 +++- vcx/wrappers/python3/vcx/error.py | 11 ++++++---- 23 files changed, 79 insertions(+), 51 deletions(-) diff --git a/vcx/libvcx/src/api/vcx.rs b/vcx/libvcx/src/api/vcx.rs index 22c9142e2e..99185b9af3 100644 --- a/vcx/libvcx/src/api/vcx.rs +++ b/vcx/libvcx/src/api/vcx.rs @@ -831,5 +831,6 @@ mod tests { let config = CString::new("{}").unwrap(); ::api::utils::vcx_agent_provision_async(0, config.as_ptr(), Some(cb)); + ::std::thread::sleep(::std::time::Duration::from_secs(1)); } } diff --git a/vcx/libvcx/src/credential_def.rs b/vcx/libvcx/src/credential_def.rs index 9ee001cbc6..625b66b939 100644 --- a/vcx/libvcx/src/credential_def.rs +++ b/vcx/libvcx/src/credential_def.rs @@ -96,7 +96,7 @@ pub fn create_new_credentialdef(source_id: String, err } else { error!("{}", err); - VcxError::from(VcxErrorKind::CreateCredDef) + VcxError::from_msg(VcxErrorKind::CreateCredDef, err) } })?; diff --git a/vcx/libvcx/src/disclosed_proof.rs b/vcx/libvcx/src/disclosed_proof.rs index 1a19e3ac5f..00a2bc3ae3 100644 --- a/vcx/libvcx/src/disclosed_proof.rs +++ b/vcx/libvcx/src/disclosed_proof.rs @@ -119,7 +119,7 @@ fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) - tails_file, } ); - } else { return Err(VcxError::from(VcxErrorKind::InvalidProofCredentialData)); } + } else { return Err(VcxError::from_msg(VcxErrorKind::InvalidProofCredentialData, "Cannot get identifiers")); } } } @@ -128,7 +128,7 @@ fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) - fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) -> VcxResult> { let attr = proof_req.requested_attributes.get(attr_name) - .ok_or(VcxError::from(VcxErrorKind::InvalidProofCredentialData))?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidProofCredentialData, format!("Attribute not found for: {}", attr_name)))?; Ok(attr.non_revoked.clone().or(proof_req.non_revoked.clone().or(None))) @@ -258,7 +258,7 @@ impl DisclosedProof { let proof_req = self.proof_request .as_ref() - .ok_or(VcxError::from(VcxErrorKind::NotReady))?; + .ok_or(VcxError::from_msg(VcxErrorKind::NotReady, "Cannot get proot request"))?; let indy_proof_req = serde_json::to_string(&proof_req.proof_request_data) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize proof request: {}", err)))?; @@ -328,7 +328,7 @@ impl DisclosedProof { debug!("generating proof {}", self.source_id); if settings::test_indy_mode_enabled() { return Ok(error::SUCCESS.code_num); } - let proof_req = self.proof_request.as_ref().ok_or(VcxError::from(VcxErrorKind::CreateProof))?; + let proof_req = self.proof_request.as_ref().ok_or(VcxError::from_msg(VcxErrorKind::CreateProof, "Cannot get proof request"))?; let proof_req_data_json = serde_json::to_string(&proof_req.proof_request_data) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot serialize proof request: {}", err)))?; @@ -402,7 +402,7 @@ impl DisclosedProof { .agent_did(local_agent_did)? .agent_vk(local_agent_vk)? .edge_agent_payload(&local_my_vk, &local_their_vk, &proof, PayloadKinds::Proof, self.thread.clone()) - .or(Err(VcxError::from(VcxErrorKind::GeneralConnectionError)))? + .map_err(|err| VcxError::from_msg(VcxErrorKind::GeneralConnectionError, format!("Cannot encrypt payload: {}", err)))? .ref_msg_id(ref_msg_uid)? .send_secure() .map_err(|err| err.extend("Could not send proof"))?; @@ -536,9 +536,9 @@ pub fn get_proof_request(connection_handle: u32, msg_id: &str) -> VcxResult VcxResult { let payload = message.payload.as_ref() - .ok_or(VcxError::from(VcxErrorKind::InvalidHttpResponse))?; + .ok_or(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Cannot get payload"))?; let (request, thread) = Payloads::decrypt(&my_vk, payload)?; let mut request: ProofRequestMessage = serde_json::from_str(&request) - .or(Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, format!("Cannot deserialize proof request: {}", err)))?; request.thread_id = thread.and_then(|tr| tr.thid.clone()); request.msg_ref_id = Some(message.uid.to_owned()); diff --git a/vcx/libvcx/src/error/mod.rs b/vcx/libvcx/src/error/mod.rs index 19228318ee..665982f1ef 100644 --- a/vcx/libvcx/src/error/mod.rs +++ b/vcx/libvcx/src/error/mod.rs @@ -266,7 +266,7 @@ pub fn err_msg(kind: VcxErrorKind, msg: D) -> VcxError impl From for VcxError { fn from(kind: VcxErrorKind) -> VcxError { - VcxError::from_msg(kind, ::utils::error::error_string(kind.clone().into())) + VcxError::from_msg(kind, ::utils::error::error_message(&kind.clone().into())) } } @@ -403,7 +403,9 @@ thread_local! { pub fn set_current_error(err: &VcxError) { CURRENT_ERROR_C_JSON.with(|error| { let error_json = json!({ + "error": err.kind().to_string(), "message": err.to_string(), + "cause": Fail::find_root_cause(err).to_string(), "backtrace": err.backtrace().map(|bt| bt.to_string()) }).to_string(); error.replace(Some(CStringUtils::string_to_cstring(error_json))); diff --git a/vcx/libvcx/src/issuer_credential.rs b/vcx/libvcx/src/issuer_credential.rs index ed77dd2ef8..b238299de5 100644 --- a/vcx/libvcx/src/issuer_credential.rs +++ b/vcx/libvcx/src/issuer_credential.rs @@ -212,7 +212,8 @@ impl IssuerCredential { CRED_MSG.to_string() } else { let cred = self.generate_credential(&attrs_with_encodings, &to)?; - serde_json::to_string(&cred).or(Err(VcxError::from(VcxErrorKind::InvalidCredential)))? + serde_json::to_string(&cred) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidCredential, format!("Cannot serialize credential: {}", err)))? }; debug!("credential data: {}", data); diff --git a/vcx/libvcx/src/messages/agent_utils.rs b/vcx/libvcx/src/messages/agent_utils.rs index d0e998298f..c3a65af351 100644 --- a/vcx/libvcx/src/messages/agent_utils.rs +++ b/vcx/libvcx/src/messages/agent_utils.rs @@ -239,7 +239,7 @@ fn onboarding_v1(my_did: &str, my_vk: &str, agency_did: &str) -> VcxResult<(Stri let ConnectResponse { from_vk: agency_pw_vk, from_did: agency_pw_did, .. } = match response.remove(0) { A2AMessage::Version1(A2AMessageV1::ConnectResponse(resp)) => resp, - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of ConnectResponse")) }; settings::set_config_value(settings::CONFIG_REMOTE_TO_SDK_VERKEY, &agency_pw_vk); @@ -258,7 +258,7 @@ fn onboarding_v1(my_did: &str, my_vk: &str, agency_did: &str) -> VcxResult<(Stri let _response: SignUpResponse = match response.remove(0) { A2AMessage::Version1(A2AMessageV1::SignUpResponse(resp)) => resp, - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of SignUpResponse")) }; /* STEP 3 - CREATE AGENT */ @@ -275,7 +275,7 @@ fn onboarding_v1(my_did: &str, my_vk: &str, agency_did: &str) -> VcxResult<(Stri let response: CreateAgentResponse = match response.remove(0) { A2AMessage::Version1(A2AMessageV1::CreateAgentResponse(resp)) => resp, - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of CreateAgentResponse")) }; Ok((response.from_did, response.from_vk)) @@ -293,7 +293,7 @@ fn onboarding_v2(my_did: &str, my_vk: &str, agency_did: &str) -> VcxResult<(Stri let ConnectResponse { from_vk: agency_pw_vk, from_did: agency_pw_did, .. } = match response.remove(0) { A2AMessage::Version2(A2AMessageV2::ConnectResponse(resp)) => resp, - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of ConnectResponse")) }; settings::set_config_value(settings::CONFIG_REMOTE_TO_SDK_VERKEY, &agency_pw_vk); @@ -308,7 +308,7 @@ fn onboarding_v2(my_did: &str, my_vk: &str, agency_did: &str) -> VcxResult<(Stri let _response: SignUpResponse = match response.remove(0) { A2AMessage::Version2(A2AMessageV2::SignUpResponse(resp)) => resp, - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of SignUpResponse")) }; /* STEP 3 - CREATE AGENT */ @@ -321,7 +321,7 @@ fn onboarding_v2(my_did: &str, my_vk: &str, agency_did: &str) -> VcxResult<(Stri let response: CreateAgentResponse = match response.remove(0) { A2AMessage::Version2(A2AMessageV2::CreateAgentResponse(resp)) => resp, - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of CreateAgentResponse")) }; Ok((response.from_did, response.from_vk)) diff --git a/vcx/libvcx/src/messages/get_message.rs b/vcx/libvcx/src/messages/get_message.rs index e1d4021caa..1d0514c52d 100644 --- a/vcx/libvcx/src/messages/get_message.rs +++ b/vcx/libvcx/src/messages/get_message.rs @@ -132,7 +132,7 @@ impl GetMessagesBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::GetMessagesResponse(res)) => Ok(res.msgs), A2AMessage::Version2(A2AMessageV2::GetMessagesResponse(res)) => Ok(res.msgs), - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of GetMessagesResponse")) } } @@ -186,7 +186,7 @@ impl GetMessagesBuilder { let msgs = match response.remove(0) { A2AMessage::Version1(A2AMessageV1::GetMessagesByConnectionsResponse(res)) => res.msgs, A2AMessage::Version2(A2AMessageV2::GetMessagesByConnectionsResponse(res)) => res.msgs, - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of GetMessagesByConnectionsResponse")) }; msgs @@ -289,10 +289,7 @@ pub fn get_connection_messages(pw_did: &str, pw_vk: &str, agent_did: &str, agent .agent_vk(&agent_vk)? .uid(msg_uid)? .send_secure() - .map_err(|err| { - error!("could not post get_messages: {}", err); - VcxError::from(VcxErrorKind::PostMessageFailed) - })?; + .map_err(|err| err.extend("Cannot get messages"))?; trace!("message returned: {:?}", response); Ok(response) @@ -307,7 +304,7 @@ pub fn get_ref_msg(msg_id: &str, pw_did: &str, pw_vk: &str, agent_did: &str, age let msg_id = match message.get(0).as_ref().and_then(|message| message.ref_msg_id.as_ref()) { Some(ref ref_msg_id) if message[0].status_code == MessageStatusCode::Accepted => ref_msg_id.to_string(), - _ => return Err(VcxError::from(VcxErrorKind::NotReady)), + _ => return Err(VcxError::from_msg(VcxErrorKind::NotReady, "Cannot find referent message")), }; let message: Vec = get_connection_messages(pw_did, pw_vk, agent_did, agent_vk, Some(vec![msg_id]))?; @@ -320,7 +317,7 @@ pub fn get_ref_msg(msg_id: &str, pw_did: &str, pw_vk: &str, agent_did: &str, age // TODO: check returned verkey Ok((message[0].uid.clone(), payload.to_owned())) } - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)), + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Cannot find referent message")), } } diff --git a/vcx/libvcx/src/messages/invite.rs b/vcx/libvcx/src/messages/invite.rs index b7d7226fd8..71bbeed447 100644 --- a/vcx/libvcx/src/messages/invite.rs +++ b/vcx/libvcx/src/messages/invite.rs @@ -286,7 +286,7 @@ impl SendInviteBuilder { Ok((res.invite_detail, res.url_to_invite_detail)), A2AMessage::Version2(A2AMessageV2::ConnectionRequestResponse(res)) => Ok((res.invite_detail, res.url_to_invite_detail)), - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of ConnectionRequestResponse")) } } } @@ -383,7 +383,7 @@ impl AcceptInviteBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::MessageCreated(res)) => Ok(res.uid), A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswerResponse(res)) => Ok(res.id), - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of ConnectionAnswerResponse")) } } } diff --git a/vcx/libvcx/src/messages/payload.rs b/vcx/libvcx/src/messages/payload.rs index 4975351096..233455d686 100644 --- a/vcx/libvcx/src/messages/payload.rs +++ b/vcx/libvcx/src/messages/payload.rs @@ -55,7 +55,7 @@ impl Payloads { crypto::prep_msg(&my_vk, &their_vk, &bytes) } ProtocolTypes::V2 => { - let thread = thread.ok_or(VcxError::from(VcxErrorKind::InvalidState))?; + let thread = thread.ok_or(VcxError::from_msg(VcxErrorKind::InvalidState, "Cannot get thread"))?; let payload = PayloadV2 { type_: PayloadTypes::build_v2(msg_type), diff --git a/vcx/libvcx/src/messages/proofs/proof_message.rs b/vcx/libvcx/src/messages/proofs/proof_message.rs index 07e0707826..787eeebeb1 100644 --- a/vcx/libvcx/src/messages/proofs/proof_message.rs +++ b/vcx/libvcx/src/messages/proofs/proof_message.rs @@ -63,7 +63,7 @@ impl ProofMessage { timestamp, } ); - } else { return Err(VcxError::from(VcxErrorKind::InvalidProofCredentialData)); } + } else { return Err(VcxError::from_msg(VcxErrorKind::InvalidProofCredentialData, "Cannot get identifiers")); } } } diff --git a/vcx/libvcx/src/messages/update_connection.rs b/vcx/libvcx/src/messages/update_connection.rs index 831d0ee57d..29505a04b5 100644 --- a/vcx/libvcx/src/messages/update_connection.rs +++ b/vcx/libvcx/src/messages/update_connection.rs @@ -97,7 +97,7 @@ impl DeleteConnectionBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::UpdateConnectionResponse(res)) => Ok(()), A2AMessage::Version2(A2AMessageV2::UpdateConnectionResponse(res)) => Ok(()), - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of UpdateConnectionResponse")) } } diff --git a/vcx/libvcx/src/messages/update_message.rs b/vcx/libvcx/src/messages/update_message.rs index c87952b925..93542383eb 100644 --- a/vcx/libvcx/src/messages/update_message.rs +++ b/vcx/libvcx/src/messages/update_message.rs @@ -107,7 +107,7 @@ impl UpdateMessageStatusByConnectionsBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::UpdateMessageStatusByConnectionsResponse(res)) => Ok(()), A2AMessage::Version2(A2AMessageV2::UpdateMessageStatusByConnectionsResponse(res)) => Ok(()), - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of UpdateMessageStatusByConnectionsResponse")) } } } diff --git a/vcx/libvcx/src/messages/update_profile.rs b/vcx/libvcx/src/messages/update_profile.rs index 6d2d6aea55..d9adab3354 100644 --- a/vcx/libvcx/src/messages/update_profile.rs +++ b/vcx/libvcx/src/messages/update_profile.rs @@ -116,7 +116,7 @@ impl UpdateProfileDataBuilder { match response.remove(0) { A2AMessage::Version1(A2AMessageV1::UpdateConfigsResponse(res)) => Ok(()), A2AMessage::Version2(A2AMessageV2::UpdateConfigsResponse(res)) => Ok(()), - _ => return Err(VcxError::from(VcxErrorKind::InvalidHttpResponse)) + _ => return Err(VcxError::from_msg(VcxErrorKind::InvalidHttpResponse, "Message does not match any variant of UpdateConfigsResponse")) } } } diff --git a/vcx/libvcx/src/utils/libindy/anoncreds.rs b/vcx/libvcx/src/utils/libindy/anoncreds.rs index 1d72bfeeb4..6f1db1815a 100644 --- a/vcx/libvcx/src/utils/libindy/anoncreds.rs +++ b/vcx/libvcx/src/utils/libindy/anoncreds.rs @@ -170,7 +170,7 @@ pub fn libindy_prover_get_credentials_for_proof_req(proof_req: &str) -> VcxResul Ok(creds) } None => { - Err(VcxError::from(VcxErrorKind::InvalidAttributesStructure)) + Err(VcxError::from_msg(VcxErrorKind::InvalidAttributesStructure, "Invalid Json Parsing of Requested Attributes Retrieved From Libindy")) } } } diff --git a/vcx/libvcx/src/utils/libindy/payments.rs b/vcx/libvcx/src/utils/libindy/payments.rs index c2f8cccb90..2c4e906d68 100644 --- a/vcx/libvcx/src/utils/libindy/payments.rs +++ b/vcx/libvcx/src/utils/libindy/payments.rs @@ -266,7 +266,7 @@ fn _submit_fees_request(req: &str, inputs: &Vec, outputs: &Vec) let parsed_response = payments::parse_response_with_fees(&payment_method, &response) .wait() - .or(Err(VcxError::from(VcxErrorKind::InvalidLedgerResponse)))?; + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidLedgerResponse, format!("Cannot parse response: {}", err)))?; Ok((parsed_response, response)) } diff --git a/vcx/libvcx/src/utils/libindy/pool.rs b/vcx/libvcx/src/utils/libindy/pool.rs index 8b65400116..20d3506c94 100644 --- a/vcx/libvcx/src/utils/libindy/pool.rs +++ b/vcx/libvcx/src/utils/libindy/pool.rs @@ -29,7 +29,7 @@ pub fn create_pool_ledger_config(pool_name: &str, path: &str) -> VcxResult<()> { .wait() { Ok(x) => Ok(()), Err(x) => if x.error_code != ErrorCode::PoolLedgerConfigAlreadyExistsError { - Err(VcxError::from(VcxErrorKind::UnknownLiibndyError)) + Err(VcxError::from_msg(VcxErrorKind::UnknownLiibndyError, x)) } else { Ok(()) } @@ -72,8 +72,8 @@ pub fn delete(pool_name: &str) -> VcxResult<()> { pub fn get_pool_handle() -> VcxResult { POOL_HANDLE.read() - .or(Err(VcxError::from(VcxErrorKind::NoPoolOpen)))? - .ok_or(VcxError::from(VcxErrorKind::NoPoolOpen)) + .or(Err(VcxError::from_msg(VcxErrorKind::NoPoolOpen, "There is no pool opened")))? + .ok_or(VcxError::from_msg(VcxErrorKind::NoPoolOpen, "There is no pool opened")) } #[cfg(test)] diff --git a/vcx/libvcx/src/utils/libindy/wallet.rs b/vcx/libvcx/src/utils/libindy/wallet.rs index a148e09ab4..da578046c2 100644 --- a/vcx/libvcx/src/utils/libindy/wallet.rs +++ b/vcx/libvcx/src/utils/libindy/wallet.rs @@ -28,7 +28,7 @@ pub fn create_wallet(wallet_name: &str, wallet_type: Option<&str>, storage_confi Ok(x) => Ok(()), Err(x) => if x.error_code != ErrorCode::WalletAlreadyExistsError { warn!("could not create wallet {}: {:?}", wallet_name, x.message); - Err(VcxError::from(VcxErrorKind::WalletCreate)) + Err(VcxError::from_msg(VcxErrorKind::WalletCreate, format!("could not create wallet {}: {:?}", wallet_name, x.message))) } else { warn!("could not create wallet {}: {:?}", wallet_name, x.message); Ok(()) diff --git a/vcx/libvcx/src/utils/openssl.rs b/vcx/libvcx/src/utils/openssl.rs index b5dd290e0b..9ddda2f062 100644 --- a/vcx/libvcx/src/utils/openssl.rs +++ b/vcx/libvcx/src/utils/openssl.rs @@ -11,16 +11,16 @@ pub fn encode(s: &str ) -> VcxResult { let hash = sha256(s.as_bytes()); let bignum = match BigNum::from_slice(&hash) { Ok(b) => b, - Err(_) => { + Err(err) => { warn!("{}", BIG_NUMBER_ERROR.message); - return Err(VcxError::from(VcxErrorKind::EncodeError)) + return Err(VcxError::from_msg(VcxErrorKind::EncodeError, format!("Cannot encode string: {}", err))) } }; match bignum.to_dec_str() { Ok(s) => Ok(s.to_string()), - Err(_) => { + Err(err) => { warn!("{}", BIG_NUMBER_ERROR.message); - Err(VcxError::from(VcxErrorKind::EncodeError)) + return Err(VcxError::from_msg(VcxErrorKind::EncodeError, format!("Cannot encode string: {}", err))) } } } diff --git a/vcx/wrappers/ios/vcx/utils/NSError+VcxError.m b/vcx/wrappers/ios/vcx/utils/NSError+VcxError.m index 04ec1452f8..56095a76fb 100644 --- a/vcx/wrappers/ios/vcx/utils/NSError+VcxError.m +++ b/vcx/wrappers/ios/vcx/utils/NSError+VcxError.m @@ -25,7 +25,9 @@ + (NSError*) errorFromVcxError:(vcx_error_t) error // options:kNilOptions // error: &error]; // - // [userInfo setValue:errorDetails[@"message"] forKey:@"sdk_message"]; + // [userInfo setValue:errorDetails[@"error"] forKey:@"sdk_message"]; + // [userInfo setValue:errorDetails[@"message"] forKey:@"sdk_full_message"]; + // [userInfo setValue:errorDetails[@"cause"] forKey:@"sdk_cause"]; // [userInfo setValue:errorDetails[@"backtrace"] forKey:@"sdk_backtrace"]; // } diff --git a/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/VcxException.java b/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/VcxException.java index 618790604f..db373e393f 100644 --- a/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/VcxException.java +++ b/vcx/wrappers/java/src/main/java/com/evernym/sdk/vcx/VcxException.java @@ -75,6 +75,8 @@ public class VcxException extends Exception { private static final long serialVersionUID = 2650355290834266234L; private int sdkErrorCode; private String sdkMessage; + private String sdkFullMessage; + private String sdkCause; private String sdkBacktrace; /** @@ -95,7 +97,9 @@ private void setSdkErrorDetails(){ try { JSONObject errorDetails = new JSONObject(errorDetailsJson.getValue().getString(0)); - this.sdkMessage = errorDetails.optString("message"); + this.sdkMessage = errorDetails.optString("error"); + this.sdkFullMessage = errorDetails.optString("message"); + this.sdkCause = errorDetails.optString("cause"); this.sdkBacktrace = errorDetails.optString("backtrace"); } catch(Exception e) { // TODO @@ -118,6 +122,20 @@ public int getSdkErrorCode() { */ public String getSdkMessage() {return sdkMessage;} + /** + * Gets the SDK full error message for the exception. + * + * @return The SDK full error message used to construct the exception. + */ + public String getSdkFullMessage() {return sdkFullMessage;} + + /** + * Gets the SDK error cause for the exception. + * + * @return The SDK error cause used to construct the exception. + */ + public String getSdkCause() {return sdkCause;} + /** * Gets the SDK error backtrace for the exception. * diff --git a/vcx/wrappers/java/src/test/java/com/evernym/sdk/vcx/ErrorCodeTest.java b/vcx/wrappers/java/src/test/java/com/evernym/sdk/vcx/ErrorCodeTest.java index 636e238edc..c7a28bfdd7 100644 --- a/vcx/wrappers/java/src/test/java/com/evernym/sdk/vcx/ErrorCodeTest.java +++ b/vcx/wrappers/java/src/test/java/com/evernym/sdk/vcx/ErrorCodeTest.java @@ -33,6 +33,8 @@ public void testGetErrorDetails(){ } catch (VcxException e){ assert(!e.getMessage().isEmpty()); assert(!e.getSdkMessage().isEmpty()); + assert(!e.getSdkFullMessage().isEmpty()); + assert(!e.getSdkCause().isEmpty()); } } } diff --git a/vcx/wrappers/python3/tests/test_error.py b/vcx/wrappers/python3/tests/test_error.py index 5883da0f58..11d61ad531 100644 --- a/vcx/wrappers/python3/tests/test_error.py +++ b/vcx/wrappers/python3/tests/test_error.py @@ -28,4 +28,6 @@ async def test_error_details(): with pytest.raises(VcxError) as e: await vcx_agent_provision("") assert ErrorCode.InvalidOption == e.value.error_code - assert e.value.vcx_error_msg + assert e.value.error_msg + assert e.value.sdk_error_full_message + assert e.value.sdk_error_cause diff --git a/vcx/wrappers/python3/vcx/error.py b/vcx/wrappers/python3/vcx/error.py index 1307a1977f..127acd2756 100644 --- a/vcx/wrappers/python3/vcx/error.py +++ b/vcx/wrappers/python3/vcx/error.py @@ -113,8 +113,9 @@ class ErrorCode(IntEnum): class VcxError(Exception): # error_code: ErrorCode # error_msg: Optional[str] - human-readable error description - # vcx_error_msg: Optional[str] - vcx error message. - # vcx_error_backtrace: Optional[str] - vcx error backtrace. + # sdk_error_full_message: Optional[str] - vcx full error message. + # sdk_error_cause: Optional[str] - vcx error cause. + # sdk_error_backtrace: Optional[str] - vcx error backtrace. # Collecting of backtrace can be enabled by setting environment variable `RUST_BACKTRACE=1` def __init__(self, error_code: ErrorCode): @@ -123,8 +124,10 @@ def __init__(self, error_code: ErrorCode): if error_code != ErrorCode.Success: error_details = get_error_details() if error_details: - self.vcx_error_msg = error_details['message'] - self.vcx_error_backtrace = error_details['backtrace'] + self.error_msg = error_details['error'] + self.sdk_error_full_message = error_details['message'] + self.sdk_error_cause = error_details['cause'] + self.sdk_error_backtrace = error_details['backtrace'] def error_message(error_code: int) -> str: From f258b9df0479e71831b0013c5a0d44ba1e810576 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 26 Feb 2019 12:26:15 +0300 Subject: [PATCH 12/28] Fixed some mistakes to save backward compatibility Signed-off-by: artem.ivanov --- vcx/libvcx/include/vcx.h | 2 +- vcx/libvcx/src/error/mod.rs | 32 +++++++++++++------------- vcx/libvcx/src/messages/get_message.rs | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/vcx/libvcx/include/vcx.h b/vcx/libvcx/include/vcx.h index 3101bd7cff..889427048f 100644 --- a/vcx/libvcx/include/vcx.h +++ b/vcx/libvcx/include/vcx.h @@ -1623,7 +1623,7 @@ vcx_error_t vcx_get_logger(const void* vcx_get_logger, /// "message": str - human-readable error description /// } /// -vcx_error_t vcx_current_error(const char ** error_json_p); +vcx_error_t vcx_get_current_error(const char ** error_json_p); #ifdef __cplusplus } // extern "C" diff --git a/vcx/libvcx/src/error/mod.rs b/vcx/libvcx/src/error/mod.rs index 665982f1ef..b2d7954916 100644 --- a/vcx/libvcx/src/error/mod.rs +++ b/vcx/libvcx/src/error/mod.rs @@ -26,7 +26,7 @@ pub enum VcxErrorKind { InvalidJson, #[fail(display = "Invalid Option")] InvalidOption, - #[fail(display = "Invalid message pack")] + #[fail(display = "Invalid MessagePack")] InvalidMessagePack, #[fail(display = "Object cache error")] ObjectCacheError, @@ -44,19 +44,19 @@ pub enum VcxErrorKind { AlreadyInitialized, // Connection - #[fail(display = "Cannot create connection")] + #[fail(display = "Could not create connection")] CreateConnection, - #[fail(display = "Invalid connection handle")] + #[fail(display = "Invalid Connection Handle")] InvalidConnectionHandle, - #[fail(display = "Invalid invite detail")] + #[fail(display = "Invalid invite details structure")] InvalidInviteDetail, - #[fail(display = "Cannot delete connection")] + #[fail(display = "Cannot Delete Connection. Check status of connection is appropriate to be deleted from agency.")] DeleteConnection, #[fail(display = "Error with Connection")] GeneralConnectionError, // Payment - #[fail(display = "Payment information not found")] + #[fail(display = "No payment information associated with object")] NoPaymentInformation, #[fail(display = "Insufficient amount of tokens to process request")] InsufficientTokenAmount, @@ -64,19 +64,19 @@ pub enum VcxErrorKind { InvalidPaymentAddress, // Credential Definition error - #[fail(display = "Cannot create credential definition")] + #[fail(display = "Call to create Credential Definition failed")] CreateCredDef, - #[fail(display = "Credential definition already created")] + #[fail(display = "Can't create, Credential Def already on ledger")] CredDefAlreadyCreated, - #[fail(display = "Invalid credential definition handle")] + #[fail(display = "Invalid Credential Definition handle")] InvalidCredDefHandle, // Revocation - #[fail(display = "Cannot create revocation registry definition")] + #[fail(display = "Failed to create Revocation Registration Definition")] CreateRevRegDef, - #[fail(display = "Invalid revocation deltas")] + #[fail(display = "Invalid Revocation Details")] InvalidRevocationDetails, - #[fail(display = "Invalid revocation entry")] + #[fail(display = "Unable to Update Revocation Delta On Ledger")] InvalidRevocationEntry, #[fail(display = "Invalid Credential Revocation timestamp")] InvalidRevocationTimestamp, @@ -88,11 +88,11 @@ pub enum VcxErrorKind { CreateCredentialRequest, // Issuer Credential - #[fail(display = "Invalid issuer credential handle")] + #[fail(display = "Invalid Credential Issuer Handle")] InvalidIssuerCredentialHandle, #[fail(display = "Invalid Credential Request")] InvalidCredentialRequest, - #[fail(display = "Invalid Credential")] + #[fail(display = "Invalid credential json")] InvalidCredential, #[fail(display = "Attributes provided to Credential Offer are not correct, possibly malformed")] InvalidAttributesStructure, @@ -100,7 +100,7 @@ pub enum VcxErrorKind { // Proof #[fail(display = "Invalid proof handle")] InvalidProofHandle, - #[fail(display = "Invalid disclosed proof handle")] + #[fail(display = "Obj was not found with handle")] InvalidDisclosedProofHandle, #[fail(display = "Proof had invalid format")] InvalidProof, @@ -132,7 +132,7 @@ pub enum VcxErrorKind { InvalidLedgerResponse, #[fail(display = "No Pool open. Can't return handle.")] NoPoolOpen, - #[fail(display = "Message failed in post.")] + #[fail(display = "Message failed in post")] PostMessageFailed, // Wallet diff --git a/vcx/libvcx/src/messages/get_message.rs b/vcx/libvcx/src/messages/get_message.rs index 1d0514c52d..ae140db854 100644 --- a/vcx/libvcx/src/messages/get_message.rs +++ b/vcx/libvcx/src/messages/get_message.rs @@ -289,7 +289,7 @@ pub fn get_connection_messages(pw_did: &str, pw_vk: &str, agent_did: &str, agent .agent_vk(&agent_vk)? .uid(msg_uid)? .send_secure() - .map_err(|err| err.extend("Cannot get messages"))?; + .map_err(|err| err.map(VcxErrorKind::PostMessageFailed, "Cannot get messages"))?; trace!("message returned: {:?}", response); Ok(response) From a86fb3a315b829694e481ad4d12d2bbb0a6bb4f0 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 4 Mar 2019 09:17:21 +0300 Subject: [PATCH 13/28] Fixed mistakes Signed-off-by: artem.ivanov --- vcx/libvcx/src/api/vcx.rs | 4 ++-- vcx/wrappers/python3/vcx/error.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/vcx/libvcx/src/api/vcx.rs b/vcx/libvcx/src/api/vcx.rs index 99185b9af3..e517db788a 100644 --- a/vcx/libvcx/src/api/vcx.rs +++ b/vcx/libvcx/src/api/vcx.rs @@ -232,8 +232,8 @@ pub extern fn vcx_error_c_message(error_code: u32) -> *const c_char { pub extern fn vcx_update_institution_info(name: *const c_char, logo_url: *const c_char) -> u32 { info!("vcx_update_institution_info >>>"); - check_useful_c_str!(name, VcxErrorKind::InvalidOption); - check_useful_c_str!(logo_url, VcxErrorKind::InvalidOption); + check_useful_c_str!(name, VcxErrorKind::InvalidConfiguration); + check_useful_c_str!(logo_url, VcxErrorKind::InvalidConfiguration); trace!("vcx_update_institution_info(name: {}, logo_url: {})", name, logo_url); settings::set_config_value(::settings::CONFIG_INSTITUTION_NAME, &name); diff --git a/vcx/wrappers/python3/vcx/error.py b/vcx/wrappers/python3/vcx/error.py index 127acd2756..8cca30a9e3 100644 --- a/vcx/wrappers/python3/vcx/error.py +++ b/vcx/wrappers/python3/vcx/error.py @@ -124,7 +124,6 @@ def __init__(self, error_code: ErrorCode): if error_code != ErrorCode.Success: error_details = get_error_details() if error_details: - self.error_msg = error_details['error'] self.sdk_error_full_message = error_details['message'] self.sdk_error_cause = error_details['cause'] self.sdk_error_backtrace = error_details['backtrace'] From 20b6361a9eff2d7894a69219d9d415bba570be4e Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 4 Mar 2019 09:34:32 +0300 Subject: [PATCH 14/28] Fixed error creation for vcx python wrapper Signed-off-by: artem.ivanov --- vcx/wrappers/python3/vcx/common.py | 14 +++++++++----- vcx/wrappers/python3/vcx/error.py | 13 ++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/vcx/wrappers/python3/vcx/common.py b/vcx/wrappers/python3/vcx/common.py index c8ce839dd2..49c4eea0a3 100644 --- a/vcx/wrappers/python3/vcx/common.py +++ b/vcx/wrappers/python3/vcx/common.py @@ -3,7 +3,7 @@ import asyncio import itertools import logging -from .error import VcxError, ErrorCode +from .error import VcxError, ErrorCode, get_error_details from vcx.cdll import _cdll _futures = {} @@ -27,7 +27,8 @@ def do_call(name: str, *args): if err != ErrorCode.Success: logger.warning("_do_call: Function %s returned error %i", name, err) - future.set_exception(VcxError(ErrorCode(err))) + error_details = get_error_details() + future.set_exception(VcxError(ErrorCode(err), error_details)) logger.debug("do_call: <<< %s", future) return future @@ -52,7 +53,8 @@ def release(name, handle): if err != ErrorCode.Success: logger.warning("release: Function %s returned error %i", name, err) - raise VcxError(ErrorCode(err)) + error_details = get_error_details() + raise VcxError(ErrorCode(err), error_details) def get_version() -> str: @@ -84,7 +86,8 @@ def shutdown(delete_wallet: bool): err = do_call_sync(name, c_delete) if err != ErrorCode.Success: - raise VcxError(ErrorCode(err)) + error_details = get_error_details() + raise VcxError(ErrorCode(err), error_details) def mint_tokens(): @@ -97,7 +100,8 @@ def create_cb(cb_type: CFUNCTYPE, transform_fn=None): def _cb(command_handle: int, err: int, *args): if transform_fn: args = transform_fn(*args) - error = VcxError(ErrorCode(err)) + error_details = get_error_details() if err != ErrorCode.Success else None + error = VcxError(ErrorCode(err), error_details) _cxs_callback(command_handle, error, *args) res = cb_type(_cb) diff --git a/vcx/wrappers/python3/vcx/error.py b/vcx/wrappers/python3/vcx/error.py index 8cca30a9e3..494e9bf88c 100644 --- a/vcx/wrappers/python3/vcx/error.py +++ b/vcx/wrappers/python3/vcx/error.py @@ -118,15 +118,14 @@ class VcxError(Exception): # sdk_error_backtrace: Optional[str] - vcx error backtrace. # Collecting of backtrace can be enabled by setting environment variable `RUST_BACKTRACE=1` - def __init__(self, error_code: ErrorCode): + def __init__(self, error_code: ErrorCode, error_details: Optional[dict] = None): self.error_code = error_code self.error_msg = error_message(error_code) - if error_code != ErrorCode.Success: - error_details = get_error_details() - if error_details: - self.sdk_error_full_message = error_details['message'] - self.sdk_error_cause = error_details['cause'] - self.sdk_error_backtrace = error_details['backtrace'] + if error_details: + self.error_msg = error_details['error'] + self.sdk_error_full_message = error_details['message'] + self.sdk_error_cause = error_details['cause'] + self.sdk_error_backtrace = error_details['backtrace'] def error_message(error_code: int) -> str: From 4f5efb0b85d6f8f04058231caf9daddf066648ed Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 6 Mar 2019 09:26:43 +0300 Subject: [PATCH 15/28] Fixed compilation error in dummy-agent Signed-off-by: artem.ivanov --- vcx/dummy-cloud-agent/src/domain/payload.rs | 31 ++++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/vcx/dummy-cloud-agent/src/domain/payload.rs b/vcx/dummy-cloud-agent/src/domain/payload.rs index 794ef2d8cc..7e99c17fec 100644 --- a/vcx/dummy-cloud-agent/src/domain/payload.rs +++ b/vcx/dummy-cloud-agent/src/domain/payload.rs @@ -95,23 +95,20 @@ impl PayloadKinds { } impl PayloadTypes { - pub fn build(kind: PayloadKinds) -> PayloadTypes { - match ProtocolType::get() { - ProtocolTypes::V1 => { - PayloadTypes::PayloadTypeV1(PayloadTypeV1 { - name: kind.name().to_string(), - ver: MESSAGE_VERSION_V1.to_string(), - fmt: "json".to_string(), - }) - } - ProtocolTypes::V2 => { - PayloadTypes::PayloadTypeV2(PayloadTypeV2 { - did: DID.to_string(), - family: kind.family(), - version: kind.family().version().to_string(), - type_: kind.name().to_string(), - }) - } + pub fn build_v1(kind: PayloadKinds, fmt: &str) -> PayloadTypeV1 { + PayloadTypeV1 { + name: kind.name().to_string(), + ver: MESSAGE_VERSION_V1.to_string(), + fmt: fmt.to_string(), + } + } + + pub fn build_v2(kind: PayloadKinds) -> PayloadTypeV2 { + PayloadTypeV2 { + did: DID.to_string(), + family: kind.family(), + version: kind.family().version().to_string(), + type_: kind.name().to_string(), } } } From 2468102959ccd5d7e281c94cf2ce004169d2c13f Mon Sep 17 00:00:00 2001 From: Michael Boyd Date: Fri, 8 Mar 2019 13:59:31 +0800 Subject: [PATCH 16/28] added the chinese version of indy-walkthrough Signed-off-by: Michael Boyd --- docs/zh/indy-walkthrough-zh.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 docs/zh/indy-walkthrough-zh.md diff --git a/docs/zh/indy-walkthrough-zh.md b/docs/zh/indy-walkthrough-zh.md new file mode 100644 index 0000000000..4668acd50b --- /dev/null +++ b/docs/zh/indy-walkthrough-zh.md @@ -0,0 +1,24 @@ +## 什麼是 Indy 和 Libindy,還有為什麼它們那麼重要? + +Indy 提供一個私密、安全、身份的生態系統,而Libindy 為它提供客戶端。Indy 使人 -- 而不是傳統機構 -- 控制他們的個人資料以及如何公開。它令各種創新變得可能:授權、嶄新的支付流程、資產及文件管理、不同形式的委託、聲譽累積、與其他新技術整合等等。 + +Indy使用開源的分佈賬戶技術。這個賬戶是由一群參與者合作建立的一種數據庫,而非一個中央管理的大規模數據庫。數據冗餘地存在於多個地方,而由多部參與的電腦(機器)的交易所構成,透過大而有力的加密標準加以保護。它的設計充分使用密鑰管理和網絡安全的最佳實踐模式。所得的結果是一個可靠、公共的信任源頭,不受單一個體所控制,系統堅實而不受人侵駭入,足以抵禦其他個體敵意的破壞和顛覆。 + +如果你對加密學概念和區塊鏈技術還有疑惑,不用害怕,這指南會給你介紹Indy的主要概念,你來對地方了。 + +## 我们要讨论什么? +我们的目标是向你介绍很多关于 Indy 的概念,帮助你来理解让这一起工作起来的背后的原因。 + +我们会将整个过程编为一个故事。Alice,一个虚构的 Faber 大学的毕业生,想要应聘一家虚构的公司 Acme Corp 的一份工作。当她获得了这份工作后,她想要向 Thrift 银行申请一笔贷款,这样她就可以购买一辆汽车了。在工作申请表单上,她想用她的大学成绩单作为受过教育证明,并且一旦被录用后,Alice 想使用被雇佣的事实来作为申请贷款的信誉凭证。 + +在当今的世界里,身份信息以及信任交互非常混乱,它们很慢,与隐私性相违背,容易受到欺诈。我们将会展示给你 Indy 是如何让这些产生了巨大的进步。 + +作为 Faber 大学的毕业生,Alice 收到了一封毕业生的 newsletter,从中了解到她的母校可以提供数字成绩单(digital transcripts)。她登录了学校的毕业生网站,通过点击 获得成绩单 按钮,她申请了自己的成绩单。(其他的发起这个请求的方式还可能包括扫描一个 QR code,从一个公共的 URL 下载一份打包的成绩单,等等) + +## About Alice + +Alice 还没有意识到,想要使用这个数字的成绩单,她需要一个新的类型的身份信息 - 并不是 Faber 大学存储在在校(on-campus)数据库中为她创建的传统的身份信息,而是一个属于她自己的全新的便携的身份信息,独立于所有的过去和将来的关系,不经过她的允许,没有人能够废除(revoke)、指派(co-opt)或者关联(correlate)这个身份信息。这就是一个 自我主权的身份信息(self-sovereign identity),也是 Indy 的核心功能。 + +在常规的情况下,管理一个自我主权的身份信息会要求使用 一个工具,比如一个桌面的或者手机的应用程序。它可能是一个独立的应用,或者使用一个第三方的服务机构(代理商)提供的账本服务。Sovrin 基金会(Sovrin Foundation)发布了一个这种类型的工具。Faber 大学了解了这些需求,并会建议 Alice 安装一个 Indy app 如果她没有安装过的话。这个 app 会作为点击 获得成绩单 按钮之后的工作流中的一部分而被安装。 + +在常规的情况下,管理一个自我主权的身份信息会要求使用 一个工具,比如一个桌面的或者手机的应用程序。它可能是一个独立的应用,或者使用一个第三方的服务机构(代理商)提供的账本服务。Sovrin 基金会(Sovrin Foundation)发布了一个这种类型的工具。Faber 大学了解了这些需求,并会建议 Alice 安装一个 Indy app 如果她没有安装过的话。这个 app 会作为点击 获得成绩单 按钮之后的工作流中的一部分而被安装。 From b7b85bc7dcf6e43688658b6d29a260b499d28b9a Mon Sep 17 00:00:00 2001 From: Michael Boyd Date: Fri, 8 Mar 2019 14:09:26 +0800 Subject: [PATCH 17/28] added another paragraph Signed-off-by: Michael Boyd --- docs/zh/indy-walkthrough-zh.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/zh/indy-walkthrough-zh.md b/docs/zh/indy-walkthrough-zh.md index 4668acd50b..89469543dd 100644 --- a/docs/zh/indy-walkthrough-zh.md +++ b/docs/zh/indy-walkthrough-zh.md @@ -22,3 +22,6 @@ Alice 还没有意识到,想要使用这个数字的成绩单,她需要一 在常规的情况下,管理一个自我主权的身份信息会要求使用 一个工具,比如一个桌面的或者手机的应用程序。它可能是一个独立的应用,或者使用一个第三方的服务机构(代理商)提供的账本服务。Sovrin 基金会(Sovrin Foundation)发布了一个这种类型的工具。Faber 大学了解了这些需求,并会建议 Alice 安装一个 Indy app 如果她没有安装过的话。这个 app 会作为点击 获得成绩单 按钮之后的工作流中的一部分而被安装。 在常规的情况下,管理一个自我主权的身份信息会要求使用 一个工具,比如一个桌面的或者手机的应用程序。它可能是一个独立的应用,或者使用一个第三方的服务机构(代理商)提供的账本服务。Sovrin 基金会(Sovrin Foundation)发布了一个这种类型的工具。Faber 大学了解了这些需求,并会建议 Alice 安装一个 Indy app 如果她没有安装过的话。这个 app 会作为点击 获得成绩单 按钮之后的工作流中的一部分而被安装。 + + +当 Alice 点击了 获得成绩单 按钮后,她会下载一个带有一个 Indy 连接请求 的文件。这个连接请求文件的扩展名为 .indy,并且会和 Alice 的 Indy app 相关联,将会允许 Alice 创建跟另外一个在这个账本生态圈(ledger ecosystem)存在的一方(Faber 大学)的一个安全的信息沟通频道(channel)。 From 015e37142ae612f1f12fb278ccbeeadb191ee368 Mon Sep 17 00:00:00 2001 From: Atsushi Neki Date: Fri, 8 Mar 2019 14:15:41 +0800 Subject: [PATCH 18/28] Fix some broken links 'Indy Walkthrough' doc Signed-off-by: Atsushi Neki --- docs/getting-started/indy-walkthrough.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started/indy-walkthrough.md b/docs/getting-started/indy-walkthrough.md index c2d8396bb6..10c40df9e5 100644 --- a/docs/getting-started/indy-walkthrough.md +++ b/docs/getting-started/indy-walkthrough.md @@ -64,11 +64,11 @@ The ledger is intended to store **Identity Records** that describe a **Ledger En In this tutorial we will use two types of DIDs. The first one is a **Verinym**. A **Verinym** is associated with the **Legal Identity** of the **Identity Owner**. For example, all parties should be able to verify that some DID is used by a Government to publish schemas for some document type. The second type is a **Pseudonym** - a **Blinded Identifier** used to maintain privacy in the context of an ongoing digital relationship (**Connection**). If the Pseudonym is used to maintain only one digital relationship we will call it a Pairwise-Unique Identifier. We will use Pairwise-Unique Identifiers to maintain secure connections between actors in this tutorial. -The creation of a DID known to the Ledger is an **Identity Record** itself (NYM transaction). The NYM transaction can be used for creation of new DIDs that is known to that ledger, the setting and rotation of a verification key, and the setting and changing of roles. The most important fields of this transaction are `dest` (target DID), `role` (role of a user NYM record being created for) and the `verkey` (target verification key). See [Requests](https://github.com/hyperledger/indy-node/blob/master/docs/requests.md) to get more information about supported ledger transactions. +The creation of a DID known to the Ledger is an **Identity Record** itself (NYM transaction). The NYM transaction can be used for creation of new DIDs that is known to that ledger, the setting and rotation of a verification key, and the setting and changing of roles. The most important fields of this transaction are `dest` (target DID), `role` (role of a user NYM record being created for) and the `verkey` (target verification key). See [Requests](https://github.com/hyperledger/indy-node/blob/master/docs/source/requests.md) to get more information about supported ledger transactions. Publishing with a DID verification key allows a person, organization or thing, to verify that someone owns this DID as that person, organization or thing is the only one who knows the corresponding signing key and any DID-related operations requiring signing with this key. -Our ledger is public permissioned and anyone who wants to publish DIDs needs to get the role of **Trust Anchor** on the ledger. A **Trust Anchor** is a person or organization that the ledger already knows about, that is able to help bootstrap others. (It is *not* the same as what cybersecurity experts call a "trusted third party"; think of it more like a facilitator). See [Roles](https://github.com/hyperledger/indy-node/blob/master/docs/auth_rules.md) to get more information about roles. +Our ledger is public permissioned and anyone who wants to publish DIDs needs to get the role of **Trust Anchor** on the ledger. A **Trust Anchor** is a person or organization that the ledger already knows about, that is able to help bootstrap others. (It is *not* the same as what cybersecurity experts call a "trusted third party"; think of it more like a facilitator). See [Roles](https://github.com/hyperledger/indy-node/blob/master/docs/source/auth_rules.md) to get more information about roles. **The first step towards being able to place transactions on the ledger involves getting the role of Trust Anchor on the ledger. Faber College, Acme Corp and Thrift Bank will need to get the role of Trust Anchor on the ledger so they can create Verinyms and Pairwise-Unique Identifiers to provide the service to Alice.** From d2d58ebd786ecf3f8459b5d284278f192001fd97 Mon Sep 17 00:00:00 2001 From: Michael Boyd Date: Fri, 8 Mar 2019 14:31:14 +0800 Subject: [PATCH 19/28] added to index.rst Signed-off-by: Michael Boyd --- docs/index.rst | 2 ++ docs/zh/indy-walkthrough-zh.md | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index df201657e3..674a20d710 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,6 +31,8 @@ Find the other Indy docs at https://hyperledger-indy.readthedocs.io build-guides/index.rst migration-guides/index.rst architecture/index.rst + zh/indy-walkthrough-zh.md + .. toctree:: diff --git a/docs/zh/indy-walkthrough-zh.md b/docs/zh/indy-walkthrough-zh.md index 89469543dd..497dd638a9 100644 --- a/docs/zh/indy-walkthrough-zh.md +++ b/docs/zh/indy-walkthrough-zh.md @@ -1,4 +1,5 @@ -## 什麼是 Indy 和 Libindy,還有為什麼它們那麼重要? + +# 什麼是 Indy 和 Libindy,還有為什麼它們那麼重要? Indy 提供一個私密、安全、身份的生態系統,而Libindy 為它提供客戶端。Indy 使人 -- 而不是傳統機構 -- 控制他們的個人資料以及如何公開。它令各種創新變得可能:授權、嶄新的支付流程、資產及文件管理、不同形式的委託、聲譽累積、與其他新技術整合等等。 @@ -25,3 +26,4 @@ Alice 还没有意识到,想要使用这个数字的成绩单,她需要一 当 Alice 点击了 获得成绩单 按钮后,她会下载一个带有一个 Indy 连接请求 的文件。这个连接请求文件的扩展名为 .indy,并且会和 Alice 的 Indy app 相关联,将会允许 Alice 创建跟另外一个在这个账本生态圈(ledger ecosystem)存在的一方(Faber 大学)的一个安全的信息沟通频道(channel)。 + From 34e0bf8dfda5b19204514c6d81196ddf09bcd580 Mon Sep 17 00:00:00 2001 From: Douglas Wightman Date: Mon, 11 Mar 2019 09:54:37 -0600 Subject: [PATCH 20/28] VE-976 - fix Evernym agency compatibility Signed-off-by: Douglas Wightman --- vcx/libvcx/src/messages/get_message.rs | 1 - vcx/libvcx/src/messages/invite.rs | 27 +++++++++++++++++- vcx/libvcx/src/messages/mod.rs | 38 ++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/vcx/libvcx/src/messages/get_message.rs b/vcx/libvcx/src/messages/get_message.rs index 7d0c8fb1ea..ee81665874 100644 --- a/vcx/libvcx/src/messages/get_message.rs +++ b/vcx/libvcx/src/messages/get_message.rs @@ -436,7 +436,6 @@ mod tests { fn test_download_messages() { use std::thread; use std::time::Duration; - ::utils::logger::LibvcxDefaultLogger::init_testing_logger(); init!("agency"); let institution_did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); diff --git a/vcx/libvcx/src/messages/invite.rs b/vcx/libvcx/src/messages/invite.rs index 6ef6fcb62a..3cf1fcd9ee 100644 --- a/vcx/libvcx/src/messages/invite.rs +++ b/vcx/libvcx/src/messages/invite.rs @@ -13,10 +13,12 @@ pub struct SendInviteMessageDetails { #[serde(rename = "keyDlgProof")] key_dlg_proof: KeyDlgProof, #[serde(rename = "targetName")] + #[serde(skip_serializing_if = "Option::is_none")] target_name: Option, #[serde(rename = "phoneNo")] + #[serde(skip_serializing_if = "Option::is_none")] phone_no: Option, - #[serde(rename = "usePublicDID")] + #[serde(rename = "includePublicDID")] include_public_did: bool, } @@ -568,4 +570,27 @@ mod tests { let response = parse_invitation_acceptance_details(payload).unwrap(); println!("response: {:?}", response); } + + #[test] + fn test_send_invite_null_parameters() { + let details = SendInviteMessageDetails { + msg_type: MessageTypeV1 { + name: "Name".to_string(), + ver: "1.0".to_string() + }, + key_dlg_proof: KeyDlgProof { + agent_did: "did".to_string(), + agent_delegated_key: "key".to_string(), + signature: "sig".to_string(), + }, + target_name: None, + phone_no: None, + include_public_did: true + }; + + let string: String = serde_json::to_string(&details).unwrap(); + assert!(!string.contains("phoneNo")); + assert!(!string.contains("targetName")); + assert!(string.contains("includePublicDID")); + } } diff --git a/vcx/libvcx/src/messages/mod.rs b/vcx/libvcx/src/messages/mod.rs index 80edb55a30..3a0e355bea 100644 --- a/vcx/libvcx/src/messages/mod.rs +++ b/vcx/libvcx/src/messages/mod.rs @@ -447,6 +447,7 @@ pub struct CreateMessage { send_msg: bool, #[serde(skip_serializing_if = "Option::is_none")] uid: Option, + #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "replyToMsgId")] reply_to_msg_id: Option, } @@ -457,7 +458,9 @@ pub struct GeneralMessageDetail { msg_type: MessageTypeV1, #[serde(rename = "@msg")] msg: Vec, + #[serde(skip_serializing_if = "Option::is_none")] title: Option, + #[serde(skip_serializing_if = "Option::is_none")] detail: Option, } @@ -1033,4 +1036,39 @@ pub mod tests { let buf = to_i8(&vec); println!("new bundle: {:?}", buf); } + + #[test] + fn test_general_message_null_parameters() { + let details = GeneralMessageDetail { + msg_type: MessageTypeV1 { + name: "Name".to_string(), + ver: "1.0".to_string() + }, + msg: vec![1,2,3], + title: None, + detail: None + }; + + let string: String = serde_json::to_string(&details).unwrap(); + assert!(!string.contains("title")); + assert!(!string.contains("detail")); + } + + #[test] + fn test_create_message_null_parameters() { + let details = CreateMessage { + msg_type: MessageTypeV1 { + name: "Name".to_string(), + ver: "1.0".to_string() + }, + mtype: RemoteMessageType::ProofReq, + send_msg: true, + uid: None, + reply_to_msg_id: None + }; + + let string: String = serde_json::to_string(&details).unwrap(); + assert!(!string.contains("uid")); + assert!(!string.contains("replyToMsgId")); + } } From 14f5fe814aec707417b570c49450b8097f0f2e81 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 12 Mar 2019 08:35:40 +0300 Subject: [PATCH 21/28] Reverted Dummy-Agent changes Signed-off-by: artem.ivanov --- .../src/actors/agent_connection.rs | 27 +++++++--- vcx/dummy-cloud-agent/src/domain/a2a.rs | 11 +++- .../src/domain/internal_message.rs | 11 ++-- vcx/dummy-cloud-agent/src/domain/invite.rs | 4 +- vcx/dummy-cloud-agent/src/domain/payload.rs | 22 ++++++++ vcx/dummy-cloud-agent/src/utils/tests.rs | 52 ++++++++++--------- 6 files changed, 87 insertions(+), 40 deletions(-) diff --git a/vcx/dummy-cloud-agent/src/actors/agent_connection.rs b/vcx/dummy-cloud-agent/src/actors/agent_connection.rs index 474e39779e..97da837f4b 100644 --- a/vcx/dummy-cloud-agent/src/actors/agent_connection.rs +++ b/vcx/dummy-cloud-agent/src/actors/agent_connection.rs @@ -7,7 +7,7 @@ use domain::status::{ConnectionStatus, MessageStatusCode}; use domain::invite::{ForwardAgentDetail, InviteDetail, SenderDetail, AgentDetail}; use domain::internal_message::InternalMessage; use domain::key_deligation_proof::KeyDlgProof; -use domain::payload::{PayloadV1, PayloadV2, PayloadTypes, PayloadKinds}; +use domain::payload::{PayloadV1, PayloadV2, PayloadTypes, PayloadKinds, Thread}; use domain::protocol_type::{ProtocolType, ProtocolTypes}; use failure::{err_msg, Error, Fail}; use futures::*; @@ -349,7 +349,8 @@ impl AgentConnection { &sender_did, None, None, - Some(map! { "phone_no".to_string() => msg_detail.phone_no.clone() })); + Some(map! { "phone_no".to_string() => msg_detail.phone_no.clone() }), + None); (msg, msg_detail) }) @@ -460,7 +461,8 @@ impl AgentConnection { &sender_did, None, Some(msg_detail.msg), - Some(map! {"detail".to_string() => msg_detail.detail, "title".to_string()=> msg_detail.title})); + Some(map! {"detail".to_string() => msg_detail.detail, "title".to_string()=> msg_detail.title}), + None); if let Some(msg_id) = reply_to_msg_id.as_ref() { self.answer_message(msg_id, &msg.uid, &MessageStatusCode::Accepted).unwrap(); @@ -639,6 +641,7 @@ impl AgentConnection { &msg_detail.sender_detail.did, None, None, + None, None); let sender_did = slf.user_pairwise_did.clone(); @@ -648,7 +651,8 @@ impl AgentConnection { &sender_did, Some(conn_req_msg.uid.as_str()), None, - None); + None, + msg_detail.thread.clone()); slf.state.agent_key_dlg_proof = Some(key_dlg_proof); slf.state.remote_connection_detail = Some(RemoteConnectionDetail { @@ -709,7 +713,8 @@ impl AgentConnection { &msg_detail.sender_detail.did, None, None, - None); + None, + msg_detail.thread.clone()); slf.state.remote_connection_detail = Some(RemoteConnectionDetail { forward_agent_detail: msg_detail.sender_agency_detail.clone(), @@ -758,7 +763,8 @@ impl AgentConnection { sender_did: &str, ref_msg_id: Option<&str>, payload: Option>, - sending_data: Option>>) -> InternalMessage { + sending_data: Option>>, + thread: Option) -> InternalMessage { trace!("AgentConnection::create_and_store_internal_message >> {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}", uid, mtype, status_code, sender_did, ref_msg_id, payload, sending_data); @@ -768,7 +774,8 @@ impl AgentConnection { sender_did, ref_msg_id, payload, - sending_data); + sending_data, + thread); self.state.messages.insert(msg.uid.to_string(), msg.clone()); msg } @@ -1157,6 +1164,7 @@ impl AgentConnection { type_: PayloadTypes::build_v2(PayloadKinds::from(type_)), id: String::new(), msg, + thread: Thread::new(), }; let message = ftry!(serde_json::to_string(&payload_msg)); @@ -1199,6 +1207,7 @@ impl AgentConnection { }, status_code: msg.status_code.clone(), status_msg: msg.status_code.message().to_string(), + thread_id: msg_detail.thread_id.clone(), }; match ProtocolType::get() { @@ -1258,6 +1267,7 @@ impl AgentConnection { sender_detail, sender_agency_detail: self.forward_agent_detail.clone(), answer_status_code: MessageStatusCode::Accepted, + thread: None, }; vec![A2AMessage::Version1(A2AMessageV1::CreateMessage(msg_create)), @@ -1272,6 +1282,7 @@ impl AgentConnection { sender_detail, sender_agency_detail: self.forward_agent_detail.clone(), answer_status_code: MessageStatusCode::Accepted, + thread: message.thread.clone().unwrap_or(Thread::new()), }; vec![A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswer(msg))] } @@ -1603,4 +1614,4 @@ mod tests { }) }); } -} +} \ No newline at end of file diff --git a/vcx/dummy-cloud-agent/src/domain/a2a.rs b/vcx/dummy-cloud-agent/src/domain/a2a.rs index d70b70a7c7..ac66f22bdb 100644 --- a/vcx/dummy-cloud-agent/src/domain/a2a.rs +++ b/vcx/dummy-cloud-agent/src/domain/a2a.rs @@ -12,6 +12,7 @@ use domain::key_deligation_proof::KeyDlgProof; use domain::status::{MessageStatusCode, ConnectionStatus}; use domain::message_type::*; use domain::protocol_type::{ProtocolType, ProtocolTypes}; +use domain::payload::Thread; #[derive(Debug)] pub enum A2AMessageV1 { @@ -359,6 +360,7 @@ pub struct ConnectionRequestMessageDetail { pub phone_no: Option, #[serde(rename = "usePublicDID")] pub use_public_did: Option, + pub thread_id: Option, } impl From for ConnectionRequestMessageDetail { @@ -368,6 +370,7 @@ impl From for ConnectionRequestMessageDetail { target_name: con_req.target_name, phone_no: con_req.phone_no, use_public_did: Some(con_req.include_public_did), + thread_id: Some(con_req.id), } } } @@ -390,6 +393,8 @@ pub struct ConnectionRequestAnswerMessageDetail { pub sender_agency_detail: ForwardAgentDetail, #[serde(rename = "answerStatusCode")] pub answer_status_code: MessageStatusCode, + #[serde(skip_serializing_if = "Option::is_none")] + pub thread: Option } impl From for ConnectionRequestAnswerMessageDetail { @@ -399,6 +404,7 @@ impl From for ConnectionRequestAnswerMessageDetail { sender_detail: con_req_answer.sender_detail, sender_agency_detail: con_req_answer.sender_agency_detail, answer_status_code: con_req_answer.answer_status_code, + thread: Some(con_req_answer.thread), } } } @@ -479,6 +485,8 @@ pub struct ConnectionRequest { pub phone_no: Option, #[serde(rename = "usePublicDID")] pub include_public_did: bool, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Debug, Deserialize, Serialize)] @@ -508,6 +516,8 @@ pub struct ConnectionRequestAnswer { pub sender_agency_detail: ForwardAgentDetail, #[serde(rename = "answerStatusCode")] pub answer_status_code: MessageStatusCode, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Debug, Deserialize, Serialize)] @@ -1281,4 +1291,3 @@ struct UnpackMessage { message: String, sender_verkey: Option } - diff --git a/vcx/dummy-cloud-agent/src/domain/internal_message.rs b/vcx/dummy-cloud-agent/src/domain/internal_message.rs index 22037da71d..4bb83fd819 100644 --- a/vcx/dummy-cloud-agent/src/domain/internal_message.rs +++ b/vcx/dummy-cloud-agent/src/domain/internal_message.rs @@ -1,5 +1,6 @@ use domain::a2a::RemoteMessageType; use domain::status::MessageStatusCode; +use domain::payload::Thread; use utils::rand::rand_string; @@ -14,6 +15,7 @@ pub struct InternalMessage { pub ref_msg_id: Option, pub payload: Option>, pub sending_data: HashMap>, + pub thread: Option } impl InternalMessage { @@ -23,7 +25,8 @@ impl InternalMessage { sender_did: &str, ref_msg_id: Option<&str>, payload: Option>, - sending_data: Option>>) -> InternalMessage { + sending_data: Option>>, + thread: Option) -> InternalMessage { InternalMessage { uid: uid.map(String::from).unwrap_or(rand_string(10)), _type: mtype.clone(), @@ -32,9 +35,7 @@ impl InternalMessage { ref_msg_id: ref_msg_id.map(String::from), payload, sending_data: sending_data.unwrap_or(HashMap::new()), + thread, } } -} - - - +} \ No newline at end of file diff --git a/vcx/dummy-cloud-agent/src/domain/invite.rs b/vcx/dummy-cloud-agent/src/domain/invite.rs index 99af4f011c..1b70b3968c 100644 --- a/vcx/dummy-cloud-agent/src/domain/invite.rs +++ b/vcx/dummy-cloud-agent/src/domain/invite.rs @@ -15,6 +15,8 @@ pub struct InviteDetail { pub status_code: MessageStatusCode, #[serde(rename = "statusMsg")] pub status_msg: String, + #[serde(rename = "threadId")] + pub thread_id: Option } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -50,4 +52,4 @@ pub struct AgentDetail { pub did: String, // Agent Verkey pub verkey: String, -} +} \ No newline at end of file diff --git a/vcx/dummy-cloud-agent/src/domain/payload.rs b/vcx/dummy-cloud-agent/src/domain/payload.rs index 4ba4fe8cd0..7e99c17fec 100644 --- a/vcx/dummy-cloud-agent/src/domain/payload.rs +++ b/vcx/dummy-cloud-agent/src/domain/payload.rs @@ -1,6 +1,7 @@ use domain::message_type::{MessageTypeV2, MessageFamilies, MESSAGE_VERSION_V1, DID}; use domain::a2a::RemoteMessageType; use domain::protocol_type::{ProtocolType, ProtocolTypes}; +use std::collections::HashMap; #[derive(Deserialize, Serialize, Debug)] pub enum Payloads { @@ -24,6 +25,8 @@ pub struct PayloadV2 { pub id: String, #[serde(rename = "@msg")] pub msg: String, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Debug, Deserialize, Serialize)] @@ -123,4 +126,23 @@ impl From for PayloadKinds { RemoteMessageType::Other(other) => PayloadKinds::Other(other.to_string()), } } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Thread { + pub thid: Option, + pub pthid: Option, + pub sender_order: u32, + pub received_orders: HashMap, +} + +impl Thread { + pub fn new() -> Thread { + Thread { + thid: None, + pthid: None, + sender_order: 0, + received_orders: HashMap::new(), + } + } } \ No newline at end of file diff --git a/vcx/dummy-cloud-agent/src/utils/tests.rs b/vcx/dummy-cloud-agent/src/utils/tests.rs index 146214d808..7f5e384e30 100644 --- a/vcx/dummy-cloud-agent/src/utils/tests.rs +++ b/vcx/dummy-cloud-agent/src/utils/tests.rs @@ -237,9 +237,9 @@ pub fn compose_connect(wallet_handle: i32) -> BoxedFuture, Error> { }))]; let msg = A2AMessage::prepare_authcrypted(wallet_handle, - EDGE_AGENT_DID_VERKEY, - FORWARD_AGENT_DID_VERKEY, - &msgs).wait().unwrap(); + EDGE_AGENT_DID_VERKEY, + FORWARD_AGENT_DID_VERKEY, + &msgs).wait().unwrap(); compose_forward(wallet_handle, FORWARD_AGENT_DID, FORWARD_AGENT_DID_VERKEY, msg) } @@ -260,9 +260,9 @@ pub fn compose_signup(wallet_handle: i32, pairwise_did: &str, pairwise_verkey: & let msgs = [A2AMessage::Version1(A2AMessageV1::SignUp(SignUp {}))]; let msg = A2AMessage::prepare_authcrypted(wallet_handle, - EDGE_AGENT_DID_VERKEY, - pairwise_verkey, - &msgs).wait().unwrap(); + EDGE_AGENT_DID_VERKEY, + pairwise_verkey, + &msgs).wait().unwrap(); compose_forward(wallet_handle,&pairwise_did, FORWARD_AGENT_DID_VERKEY, msg) } @@ -282,9 +282,9 @@ pub fn compose_create_agent(wallet_handle: i32, pairwise_did: &str, pairwise_ver let msgs = vec![A2AMessage::Version1(A2AMessageV1::CreateAgent(CreateAgent {}))]; let msg = A2AMessage::prepare_authcrypted(wallet_handle, - EDGE_AGENT_DID_VERKEY, - pairwise_verkey, - &msgs).wait().unwrap(); + EDGE_AGENT_DID_VERKEY, + pairwise_verkey, + &msgs).wait().unwrap(); compose_forward(wallet_handle,pairwise_did, FORWARD_AGENT_DID_VERKEY, msg) } @@ -309,9 +309,9 @@ pub fn compose_create_key(wallet_handle: i32, agent_did: &str, agent_verkey: &st }))]; let msg = A2AMessage::prepare_authcrypted(wallet_handle, - EDGE_AGENT_DID_VERKEY, - agent_verkey, - &msgs).wait().unwrap(); + EDGE_AGENT_DID_VERKEY, + agent_verkey, + &msgs).wait().unwrap(); compose_forward(wallet_handle,agent_did, FORWARD_AGENT_DID_VERKEY, msg) } @@ -341,6 +341,7 @@ pub fn compose_create_connection_request(wallet_handle: i32, target_name: None, phone_no: Some(PHONE_NO.to_string()), use_public_did: Some(true), + thread_id: None, }))); let msgs = [create_msg, msg_details]; @@ -354,7 +355,7 @@ pub fn decompose_connection_request_created(wallet_handle: i32, msg: &[u8]) -> B assert_eq!(2, msgs.len()); match (msgs.remove(0), msgs.remove(0)) { (A2AMessage::Version1(A2AMessageV1::MessageCreated(msg_created)), - A2AMessage::Version1(A2AMessageV1::MessageDetail(MessageDetail::ConnectionRequestResp(msg_details)))) => + A2AMessage::Version1(A2AMessageV1::MessageDetail(MessageDetail::ConnectionRequestResp(msg_details)))) => Ok((sender_verkey, msg_created.uid, msg_details.invite_detail)), _ => Err(err_msg("Invalid message")) } @@ -391,6 +392,7 @@ pub fn compose_create_connection_request_answer(wallet_handle: i32, endpoint: FORWARD_AGENT_ENDPOINT.to_string(), }, answer_status_code: MessageStatusCode::Accepted, + thread: None, } ))); @@ -544,9 +546,9 @@ pub fn compose_get_messages_by_connection(wallet_handle: i32, pairwise_dids: Vec::new(), }))]; let msg = A2AMessage::prepare_authcrypted(wallet_handle, - EDGE_AGENT_DID_VERKEY, - agent_verkey, - &msgs).wait().unwrap(); + EDGE_AGENT_DID_VERKEY, + agent_verkey, + &msgs).wait().unwrap(); compose_forward(wallet_handle,agent_did, FORWARD_AGENT_DID_VERKEY, msg) } pub fn decompose_get_messages_by_connection(wallet_handle: i32, msg: &[u8]) -> BoxedFuture<(String, Vec), Error> { @@ -572,9 +574,9 @@ pub fn compose_update_configs(wallet_handle: i32, agent_did: &str, agent_verkey: }))]; let msg = A2AMessage::prepare_authcrypted(wallet_handle, - EDGE_AGENT_DID_VERKEY, - agent_verkey, - &msgs).wait().unwrap(); + EDGE_AGENT_DID_VERKEY, + agent_verkey, + &msgs).wait().unwrap(); compose_forward(wallet_handle, agent_did, FORWARD_AGENT_DID_VERKEY, msg) } @@ -586,9 +588,9 @@ pub fn compose_get_configs(wallet_handle: i32, agent_did: &str, agent_verkey: &s }))]; let msg = A2AMessage::prepare_authcrypted(wallet_handle, - EDGE_AGENT_DID_VERKEY, - agent_verkey, - &msgs).wait().unwrap(); + EDGE_AGENT_DID_VERKEY, + agent_verkey, + &msgs).wait().unwrap(); compose_forward(wallet_handle, agent_did, FORWARD_AGENT_DID_VERKEY, msg) } @@ -612,9 +614,9 @@ pub fn compose_remove_configs(wallet_handle: i32, agent_did: &str, agent_verkey: }))]; let msg = A2AMessage::prepare_authcrypted(wallet_handle, - EDGE_AGENT_DID_VERKEY, - agent_verkey, - &msgs).wait().unwrap(); + EDGE_AGENT_DID_VERKEY, + agent_verkey, + &msgs).wait().unwrap(); compose_forward(wallet_handle, agent_did, FORWARD_AGENT_DID_VERKEY, msg) } From dcd899088f43eb2dabd8d6be6c21cfd3ac0b5b11 Mon Sep 17 00:00:00 2001 From: Patrik Stas Date: Fri, 1 Mar 2019 15:58:42 +0100 Subject: [PATCH 22/28] Add demo for VCX Nodejs Wrapper Signed-off-by: Patrik Stas --- vcx/wrappers/node/.babelrc | 5 + vcx/wrappers/node/README.md | 18 + vcx/wrappers/node/demo/alice.js | 91 + vcx/wrappers/node/demo/common.js | 24 + vcx/wrappers/node/demo/faber.js | 167 ++ vcx/wrappers/node/package-lock.json | 3510 +++++++++++++++++++++++++-- vcx/wrappers/node/package.json | 8 + 7 files changed, 3655 insertions(+), 168 deletions(-) create mode 100644 vcx/wrappers/node/.babelrc create mode 100644 vcx/wrappers/node/demo/alice.js create mode 100644 vcx/wrappers/node/demo/common.js create mode 100644 vcx/wrappers/node/demo/faber.js diff --git a/vcx/wrappers/node/.babelrc b/vcx/wrappers/node/.babelrc new file mode 100644 index 0000000000..3c078e9f99 --- /dev/null +++ b/vcx/wrappers/node/.babelrc @@ -0,0 +1,5 @@ +{ + "presets": [ + "es2015" + ] +} diff --git a/vcx/wrappers/node/README.md b/vcx/wrappers/node/README.md index 7cfcb25063..0ccc28b761 100644 --- a/vcx/wrappers/node/README.md +++ b/vcx/wrappers/node/README.md @@ -33,3 +33,21 @@ npm run doc-gen ``` * A directory will be created locally `./docs` which contains an `index.html` file which can be used to navigate the generated documents. +## Run Demo +- Install dependencies +``` +npm install +``` +- Compile vcx wrapper +``` +npm compile +``` +- Start [Dummy Cloud Agent](../../dummy-cloud-agent) +- Run Faber agent, representing an institution +``` +npm run demo:faber +``` +- Give it a few seconds, then run Alice's agent which will connect with Faber's agent +``` +npm run demo:alice +``` diff --git a/vcx/wrappers/node/demo/alice.js b/vcx/wrappers/node/demo/alice.js new file mode 100644 index 0000000000..47766f832e --- /dev/null +++ b/vcx/wrappers/node/demo/alice.js @@ -0,0 +1,91 @@ +import {DisclosedProof} from "../dist/src/api/disclosed-proof"; +import {Connection} from "../dist/src/api/connection"; +import {Credential} from "../dist/src/api/credential"; +import {StateType} from "../dist/src"; +import readlineSync from 'readline-sync' +import sleepPromise from 'sleep-promise' +import * as demoCommon from './common' + +function getRandomInt(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min)) + min; +} + +const provisionConfig = { + 'agency_url': 'http://localhost:8080', + 'agency_did': 'VsKV7grR1BUE29mG2Fm2kX', + 'agency_verkey': 'Hezce2UWMZ3wUhVkh2LfKSs8nDzWwzs2Win7EzNN3YaR', + 'wallet_name': 'alice_wallet', + 'wallet_key': '123', + 'payment_method': 'null', + 'enterprise_seed': '000000000000000000000000Trustee1' +}; + + +async function run() { + await demoCommon.initLibNullPay(); + + console.log("#0 initialize rust API from NodeJS"); + await demoCommon.initRustApiAndLogger(); + + console.log("#1 Provision an agent and wallet, get back configuration details"); + let config = await demoCommon.provisionAgentInAgency(provisionConfig); + + console.log("#2 Initialize libvcx with new configuration"); + await demoCommon.initVcxWithProvisionedAgentConfig(config); + + console.log("#9 Input faber.py invitation details"); + const details = readlineSync.question('Enter your invite details: '); + const jdetails = JSON.parse(details); + + console.log("#10 Convert to valid json and string and create a connection to faber"); + const connection_to_faber = await Connection.createWithInvite({id: 'faber', invite: JSON.stringify(jdetails)}); + await connection_to_faber.connect({data: '{"use_public_did": true}'}); + await connection_to_faber.updateState(); + + console.log("#11 Wait for faber.py to issue a credential offer"); + await sleepPromise(5000); + const offers = await Credential.getOffers(connection_to_faber); + console.log(`Alice found following credentiaal offers: ${JSON.stringify(offers)}`); + + // Create a credential object from the credential offer + const credential = await Credential.create({sourceId: 'credential', offer: JSON.stringify(offers[0])}); + + console.log("#15 After receiving credential offer, send credential request"); + await credential.sendRequest({connection: connection_to_faber, payment : 0}); + + console.log("#16 Poll agency and accept credential offer from faber"); + let credential_state = await credential.getState(); + while (credential_state !== StateType.Accepted) { + sleepPromise(2000); + await credential.updateState(); + credential_state = await credential.getState(); + } + + console.log("#22 Poll agency for a proof request"); + const requests = await DisclosedProof.getRequests(connection_to_faber); + + console.log("#23 Create a Disclosed proof object from proof request"); + const proof = await DisclosedProof.create({sourceId: 'proof', request: JSON.stringify(requests[0])}); + + console.log("#24 Query for credentials in the wallet that satisfy the proof request"); + const credentials = await proof.getCredentials(); + + // Use the first available credentials to satisfy the proof request + for (let i = 0; i < Object.keys(credentials['attrs']).length; i++) { + const attr = Object.keys(credentials['attrs'])[i]; + credentials['attrs'][attr] = { + 'credential': credentials['attrs'][attr][0] + } + } + + console.log("#25 Generate the proof"); + await proof.generateProof({selectedCreds: credentials, selfAttestedAttrs: {}}); + + console.log("#26 Send the proof to faber"); + await proof.sendProof(connection_to_faber); +} + + +run(); \ No newline at end of file diff --git a/vcx/wrappers/node/demo/common.js b/vcx/wrappers/node/demo/common.js new file mode 100644 index 0000000000..235d9a26f1 --- /dev/null +++ b/vcx/wrappers/node/demo/common.js @@ -0,0 +1,24 @@ +import {initRustAPI, initVcxWithConfig, provisionAgent} from "./../dist/src"; +import * as ffi from "ffi"; + +export async function initLibNullPay() { + const myffi = ffi.Library('/usr/local/lib/libnullpay.dylib', {nullpay_init: ['void', []]}); + await myffi.nullpay_init(); +} + +export async function initRustApiAndLogger() { + let rustApi = initRustAPI(); + await rustApi.vcx_set_default_logger("info"); +} + +export async function provisionAgentInAgency(config) { + return JSON.parse(await provisionAgent(JSON.stringify(config))); +} + +export async function initVcxWithProvisionedAgentConfig(config) { + // Set some additional configuration options specific to Faber + config['institution_name'] = 'faber'; + config['institution_logo_url'] = 'http://robohash.org/234'; + config['genesis_path'] = 'docker.txn'; + await initVcxWithConfig(JSON.stringify(config)); +} \ No newline at end of file diff --git a/vcx/wrappers/node/demo/faber.js b/vcx/wrappers/node/demo/faber.js new file mode 100644 index 0000000000..5da2adcdcd --- /dev/null +++ b/vcx/wrappers/node/demo/faber.js @@ -0,0 +1,167 @@ +import {CredentialDef} from "../dist/src/api/credential-def"; +import {IssuerCredential} from "../dist/src/api/issuer-credential"; +import {Proof} from "../dist/src/api/proof"; +import {Connection} from "../dist/src/api/connection"; +import {Schema} from "./../dist/src/api/schema"; +import {StateType, ProofState} from "../dist/src"; +import sleepPromise from 'sleep-promise' +import * as demoCommon from "./common"; + +function getRandomInt(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min)) + min; +} + +const provisionConfig = { + 'agency_url': 'http://localhost:8080', + 'agency_did': 'VsKV7grR1BUE29mG2Fm2kX', + 'agency_verkey': 'Hezce2UWMZ3wUhVkh2LfKSs8nDzWwzs2Win7EzNN3YaR', + 'wallet_name': 'faber_wallet', + 'wallet_key': '123', + 'payment_method': 'null', + 'enterprise_seed': '000000000000000000000000Trustee1' +}; + +async function run() { + await demoCommon.initLibNullPay(); + + console.log("#0 initialize rust API from NodeJS"); + await demoCommon.initRustApiAndLogger(); + + console.log("#1 Provision an agent and wallet, get back configuration details"); + let config = await demoCommon.provisionAgentInAgency(provisionConfig); + + console.log("#2 Initialize libvcx with new configuration"); + await demoCommon.initVcxWithProvisionedAgentConfig(config); + + console.log("#3 Create a new schema on the ledger"); + const version = `${getRandomInt(1, 101)}.${getRandomInt(1, 101)}.${getRandomInt(1, 101)}`; + const schemaData = { + data: { + attrNames: ['name', 'date', 'degree'], + name: `Schema1`, + version + }, + paymentHandle: 0, + sourceId: 'testSchemaSourceId123' + }; + + const schema = await Schema.create(schemaData); + const schemaId = await schema.getSchemaId(); + console.log(`Created schema with id ${schemaId}`); + + console.log("#4 Create a new credential definition on the ledger"); + const data = { + name: 'DemoCredential123', + paymentHandle: 0, + revocation: false, + revocationDetails: { + tailsFile: 'tails.txt', + }, + schemaId: schemaId, + sourceId: 'testCredentialDefSourceId123' + }; + const cred_def = await CredentialDef.create(data); + const cred_def_id = await cred_def.getCredDefId(); + const credDefHandle = cred_def.handle; + console.log(`Created credential with id ${cred_def_id} and handle ${credDefHandle}`); + + console.log("#5 Create a connection to alice and print out the invite details"); + const connectionToAlice = await Connection.create({id: 'alice'}); + await connectionToAlice.connect('{"use_public_did": true}'); + await connectionToAlice.updateState(); + const details = await connectionToAlice.inviteDetails(false); + console.log("**invite details**"); + console.log(JSON.stringify(JSON.parse(details)), null, 0); + console.log("******************"); + + console.log("#6 Poll agency and wait for alice to accept the invitation (start alice.py now)"); + let connection_state = await connectionToAlice.getState(); + while (connection_state !== StateType.Accepted) { + await sleepPromise(2000); + await connectionToAlice.updateState(); + connection_state = await connectionToAlice.getState(); + console.log(`Connection to Alice is in state: ${connection_state}`); + } + console.log(`Connection to alice was Accepted!`); + + const schema_attrs = { + 'name': 'alice', + 'date': '05-2018', + 'degree': 'maths', + }; + + console.log("#12 Create an IssuerCredential object using the schema and credential definition") + + const credentialForAlice = await IssuerCredential.create({ + attr: schema_attrs, + sourceId: 'alice_degree', + credDefHandle, + credentialName: 'cred', + price: '0' + }); + + console.log("#13 Issue credential offer to alice"); + await credentialForAlice.sendOffer(connectionToAlice); + await credentialForAlice.updateState(); + + console.log("#14 Poll agency and wait for alice to send a credential request"); + let credential_state = await credentialForAlice.getState(); + while (credential_state !== StateType.RequestReceived) { + await sleepPromise(2000); + await credentialForAlice.updateState(); + credential_state = await credentialForAlice.getState(); + } + + console.log("#17 Issue credential to alice"); + await credentialForAlice.sendCredential(connectionToAlice); + + + console.log("#18 Wait for alice to accept credential"); + await credentialForAlice.updateState(); + credential_state = await credentialForAlice.getState(); + while (credential_state !== StateType.Accepted) { + sleepPromise(2000); + await credentialForAlice.updateState(); + credential_state = await credentialForAlice.getState(); + } + + const proofAttributes = [ + {'name': 'name', 'restrictions': [{'issuer_did': config['institution_did']}]}, + {'name': 'date', 'restrictions': [{'issuer_did': config['institution_did']}]}, + {'name': 'degree', 'restrictions': [{'issuer_did': config['institution_did']}]} + ]; + + console.log("#19 Create a Proof object"); + const proof = await Proof.create({ + sourceId: "213", + attrs: proofAttributes, + name: 'proofForAlice', + revocationInterval: {} + }); + + console.log("#20 Request proof of degree from alice"); + await proof.requestProof(connectionToAlice); + + console.log("#21 Poll agency and wait for alice to provide proof"); + let proofState = await proof.getState(); + while (proofState !== StateType.Accepted) { + sleepPromise(2000); + await proof.updateState(); + proofState = await proof.getState(); + } + + console.log("#27 Process the proof provided by alice"); + await proof.getProof(connectionToAlice); + + console.log("#28 Check if proof is valid"); + if (proof.proofState === ProofState.Verified) { + console.log("proof is verified!!") + } else { + console.log("could not verify proof :(") + } +} + + +run(); \ No newline at end of file diff --git a/vcx/wrappers/node/package-lock.json b/vcx/wrappers/node/package-lock.json index bd0963272f..0a89f5fd57 100644 --- a/vcx/wrappers/node/package-lock.json +++ b/vcx/wrappers/node/package-lock.json @@ -1,6 +1,6 @@ { "name": "node-vcx-wrapper", - "version": "0.1.543416+469b25d", + "version": "0.2.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -128,12 +128,64 @@ "@types/node": "8.0.47" } }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, "app-module-path": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", "dev": true }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true, + "optional": true + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -146,6 +198,12 @@ "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", @@ -163,215 +221,1827 @@ } } }, - "babylon": { - "version": "7.0.0-beta.19", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", - "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==", - "dev": true + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true, + "optional": true }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", - "dev": true + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.11.0", + "convert-source-map": "1.6.0", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.3", + "lodash": "4.17.11", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.7", + "v8flags": "2.1.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + } } }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.6.0", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.11", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } }, - "buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", - "dev": true + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.11", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } }, - "catharsis": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", - "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", "dev": true, "requires": { - "underscore-contrib": "0.3.0" + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.11" } }, - "chai": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", - "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", "dev": true, "requires": { - "assertion-error": "1.0.2", - "check-error": "1.0.2", - "deep-eql": "3.0.1", - "get-func-name": "2.0.0", - "pathval": "1.1.0", - "type-detect": "4.0.3" + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" } }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } }, - "color-convert": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", - "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", "dev": true, "requires": { - "color-name": "1.1.3" + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.11" + } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, "requires": { - "ms": "2.0.0" + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" } }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "babel-loader": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-6.2.4.tgz", + "integrity": "sha1-qnCv+N3CI6WVLoOaQ6bDpMi/oek=", "dev": true, "requires": { - "type-detect": "4.0.3" + "loader-utils": "0.2.17", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" } }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } }, - "doctrine": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", - "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", "dev": true, "requires": { - "esutils": "1.1.6", - "isarray": "0.0.1" + "babel-runtime": "6.26.0" } }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } }, - "esutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", - "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", - "dev": true + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } }, - "ffi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ffi/-/ffi-2.2.0.tgz", - "integrity": "sha1-vxiwRmain3EiftVoldVDCvRwQvo=", + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, "requires": { - "bindings": "1.2.1", - "debug": "2.6.9", - "nan": "2.7.0", - "ref": "1.3.5", - "ref-struct": "1.1.0" - }, - "dependencies": { - "bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", - "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=" + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.11" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.6.5", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-runtime": "6.26.0", + "core-js": "2.6.5", + "home-or-tmp": "2.0.0", + "lodash": "4.17.11", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.6.5", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.11" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + } + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.11" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" + }, + "dependencies": { + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + } + } + }, + "babylon": { + "version": "7.0.0-beta.19", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", + "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", + "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==", + "dev": true, + "optional": true + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "optional": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "catharsis": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", + "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "dev": true, + "requires": { + "underscore-contrib": "0.3.0" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "1.0.2", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.7", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.3" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "doctrine": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", + "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", + "dev": true, + "requires": { + "esutils": "1.1.6", + "isarray": "0.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", + "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "optional": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "optional": true, + "requires": { + "fill-range": "2.2.4" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "ffi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ffi/-/ffi-2.2.0.tgz", + "integrity": "sha1-vxiwRmain3EiftVoldVDCvRwQvo=", + "requires": { + "bindings": "1.2.1", + "debug": "2.6.9", + "nan": "2.7.0", + "ref": "1.3.5", + "ref-struct": "1.1.0" + }, + "dependencies": { + "bindings": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", + "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=" + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "optional": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.1", + "repeat-element": "1.1.3", + "repeat-string": "1.6.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "optional": true, + "requires": { + "for-in": "1.0.2" + } + }, + "formatio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", + "dev": true, + "requires": { + "samsam": "1.3.0" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + } + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.12.1", + "node-pre-gyp": "0.10.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.3.5" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.3" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.3.5" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.24", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.4", + "nopt": "4.0.1", + "npm-packlist": "1.2.0", + "npmlog": "4.1.2", + "rc": "1.2.8", + "rimraf": "2.6.3", + "semver": "5.6.0", + "tar": "4.4.8" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.5" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true }, - "nan": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", - "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" - } - } - }, - "formatio": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", - "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", - "dev": true, - "requires": { - "samsam": "1.3.0" - } - }, - "fs-extra": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", - "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.1" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "semver": { + "version": "5.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.1.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.5", + "minizlib": "1.2.1", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true } } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -386,6 +2056,32 @@ "path-is-absolute": "1.0.1" } }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "optional": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -410,12 +2106,81 @@ "uglify-js": "3.4.9" } }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -428,6 +2193,16 @@ "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", "dev": true }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -450,12 +2225,194 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "1.4.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "1.13.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true, + "optional": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "optional": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true, + "optional": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true, + "optional": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "optional": true + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "optional": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, "js2xmlparser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", @@ -485,6 +2442,18 @@ "underscore": "1.8.3" } }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -507,6 +2476,15 @@ "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", "dev": true }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, "klaw": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", @@ -516,6 +2494,18 @@ "graceful-fs": "4.1.11" } }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", @@ -533,18 +2523,71 @@ "integrity": "sha512-rPO6R1t8PjYL6xbsFUg7aByKkWAql907na6powPBORVs4DCm8aMBUkL4+6CXO0gEIV8vtu3mWV0FB8ZaCYPBmA==", "dev": true }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, "make-error": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", "dev": true }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, "marked": { "version": "0.3.19", "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz", "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", "dev": true }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true, + "optional": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -560,6 +2603,27 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -630,6 +2694,56 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "nan": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "optional": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true, + "optional": true + } + } + }, "nise": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/nise/-/nise-1.2.0.tgz", @@ -651,6 +2765,94 @@ } } }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "optional": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -670,6 +2872,48 @@ "wordwrap": "0.0.3" } }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "optional": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -691,16 +2935,414 @@ "isarray": "0.0.1" } }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true - }, - "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "optional": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true, + "optional": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true, + "optional": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "optional": true, + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.4" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "4.1.11", + "micromatch": "3.1.10", + "readable-stream": "2.3.6" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "optional": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "optional": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "optional": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "readline-sync": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.9.tgz", + "integrity": "sha1-PtqOZfI80qF+YTAbHwADOWr17No=", "dev": true }, "rechoir": { @@ -743,6 +3385,110 @@ "ref": "1.3.5" } }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "optional": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.4.0", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, "requizzle": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", @@ -769,6 +3515,33 @@ "path-parse": "1.0.6" } }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, "samsam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", @@ -781,6 +3554,29 @@ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, "shelljs": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", @@ -824,12 +3620,158 @@ } } }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "sleep-promise": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/sleep-promise/-/sleep-promise-8.0.1.tgz", + "integrity": "sha1-jXlaJ+ojlT32tSuRCB5eImZZk8U=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "optional": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, "source-map-support": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", @@ -840,6 +3782,61 @@ "source-map": "0.6.1" } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -867,6 +3864,62 @@ "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", "dev": true }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "optional": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, "ts-node": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-6.1.2.tgz", @@ -1307,11 +4360,132 @@ } } }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, "universalify": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, "weak": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/weak/-/weak-1.0.1.tgz", diff --git a/vcx/wrappers/node/package.json b/vcx/wrappers/node/package.json index a3dfa7942c..fb0375fc4a 100644 --- a/vcx/wrappers/node/package.json +++ b/vcx/wrappers/node/package.json @@ -34,6 +34,8 @@ "weak": "^1.0.1" }, "scripts": { + "demo:alice": "babel-node demo/alice.js", + "demo:faber": "babel-node demo/faber.js", "compile": "./node_modules/.bin/tsc -p ./tsconfig.json", "lint": "./node_modules/.bin/tslint --type-check -c ./tslint.json -p ./tsconfig.json && ./node_modules/.bin/tslint --type-check -c ./test/tslint.json -p ./test/tsconfig.json", "doc-gen": "./node_modules/.bin/typedoc --out doc --excludePrivate --excludeProtected --ignoreCompilerErrors src", @@ -41,6 +43,12 @@ "test-logging": "export TS_NODE_PROJECT=\"./test/tsconfig.json\" export NODE_ENV='test'&& find ./test/suite3 -name '*.test.ts' -exec ./node_modules/.bin/mocha --timeout 10000 -gc --expose-gc --exit --recursive --use_strict --require ts-node/register \\{} \\;" }, "devDependencies": { + "babel-cli": "^6.26.0", + "babel-core": "^6.26.3", + "babel-loader": "6.2.4", + "babel-preset-es2015": "^6.24.1", + "sleep-promise": "^8.0.1", + "readline-sync": "^1.4.9", "@types/chai": "^4.1.4", "@types/lodash": "^4.14.109", "@types/mocha": "^5.2.3", From 263eac2f675bc84d4a3bd4e59805be59ae1ad40c Mon Sep 17 00:00:00 2001 From: Patrik Stas Date: Thu, 7 Mar 2019 14:04:21 +0100 Subject: [PATCH 23/28] Add more node vcx demo documentation. Refactor node vcx demo. Signed-off-by: Patrik Stas --- vcx/wrappers/node/README.md | 34 +++++++++++++++++++++++++++++--- vcx/wrappers/node/demo/alice.js | 6 ------ vcx/wrappers/node/demo/common.js | 8 +++++++- vcx/wrappers/node/demo/faber.js | 6 +----- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/vcx/wrappers/node/README.md b/vcx/wrappers/node/README.md index 0ccc28b761..09319615de 100644 --- a/vcx/wrappers/node/README.md +++ b/vcx/wrappers/node/README.md @@ -31,14 +31,41 @@ npm install npm ci npm run doc-gen ``` -* A directory will be created locally `./docs` which contains an `index.html` file which can be used to navigate the generated documents. +* A directory will be created locally `./docs` which contains an `index.html` file which can be used to navigate the +generated documents. ## Run Demo -- Install dependencies +- The demo represents example how 2 actors, **Alice** and **Faber** institution, exchange credentials. +- They consult may consult Indy blockchain (pool of Indy nodes) to find out certain pieces of information. **Faber** +and **Alice** are represented by 2 scripts `faber.js` and `alice.js` but you could imagine that there's a webserver +running code alike what's inside `faber.js` and there's a perhaps smartphone or laptop running code +alike iin `alice.js`. +- **Faber** and **Alice** in the demo also don't exchange the credentials peer to peer. Instead, the exchange happens +through intermediary service represented by **Dummy Cloud Agent**. The data **Alice** and **Faber** are exchanging over +**Dummy Cloud Agent** are however encrypted and cannot be read by the **Dummy Cloud Agent**. The **Dummy Cloud Agent** +is something like illiterate postman. He'll take a letter from one party and delivers it to the other party. But he's +unable to read the messages he's handling. + + +### Pre-requirements +##### Libraries +Before you'll be able to run demo, you need to make sure you've compiled +[`libindy`](https://github.com/hyperledger/indy-sdk/tree/master/libindy), +[`libvcx`](https://github.com/hyperledger/indy-sdk/tree/master/vcx) and +[`libnullpay`](https://github.com/hyperledger/indy-sdk/tree/master/libnullpay) libraries and are available on your +system. +#### Indy pool +You'll also have to run pool of Indy nodes on your machine. You can achieve by simply running a docker container +which encapsulates multiple interconnected Indy nodes. +[Instructions here](https://github.com/hyperledger/indy-sdk#how-to-start-local-nodes-pool-with-docker). + +### Steps to run demo +- Install NodeJS dependencies ``` npm install ``` -- Compile vcx wrapper + +- Compile LibVCX Wrapper ``` npm compile ``` @@ -51,3 +78,4 @@ npm run demo:faber ``` npm run demo:alice ``` + diff --git a/vcx/wrappers/node/demo/alice.js b/vcx/wrappers/node/demo/alice.js index 47766f832e..a05cbea1e3 100644 --- a/vcx/wrappers/node/demo/alice.js +++ b/vcx/wrappers/node/demo/alice.js @@ -6,12 +6,6 @@ import readlineSync from 'readline-sync' import sleepPromise from 'sleep-promise' import * as demoCommon from './common' -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min)) + min; -} - const provisionConfig = { 'agency_url': 'http://localhost:8080', 'agency_did': 'VsKV7grR1BUE29mG2Fm2kX', diff --git a/vcx/wrappers/node/demo/common.js b/vcx/wrappers/node/demo/common.js index 235d9a26f1..6b16d8db30 100644 --- a/vcx/wrappers/node/demo/common.js +++ b/vcx/wrappers/node/demo/common.js @@ -21,4 +21,10 @@ export async function initVcxWithProvisionedAgentConfig(config) { config['institution_logo_url'] = 'http://robohash.org/234'; config['genesis_path'] = 'docker.txn'; await initVcxWithConfig(JSON.stringify(config)); -} \ No newline at end of file +} + +export async function getRandomInt(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min)) + min; +} diff --git a/vcx/wrappers/node/demo/faber.js b/vcx/wrappers/node/demo/faber.js index 5da2adcdcd..78b4bc251c 100644 --- a/vcx/wrappers/node/demo/faber.js +++ b/vcx/wrappers/node/demo/faber.js @@ -6,12 +6,8 @@ import {Schema} from "./../dist/src/api/schema"; import {StateType, ProofState} from "../dist/src"; import sleepPromise from 'sleep-promise' import * as demoCommon from "./common"; +import {getRandomInt} from "./common"; -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min)) + min; -} const provisionConfig = { 'agency_url': 'http://localhost:8080', From b305b4a14e6fc9d6d2b468e0ebcae705fee4d7b5 Mon Sep 17 00:00:00 2001 From: Patrik Stas Date: Thu, 7 Mar 2019 18:47:01 +0100 Subject: [PATCH 24/28] VCX Node wrapper: Add genesis transactions. Adjust logging. Signed-off-by: Patrik Stas --- vcx/wrappers/node/demo/alice.js | 3 ++- vcx/wrappers/node/demo/common.js | 10 +++++----- vcx/wrappers/node/demo/docker.txn | 4 ++++ vcx/wrappers/node/demo/faber.js | 19 ++++++++++++------- 4 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 vcx/wrappers/node/demo/docker.txn diff --git a/vcx/wrappers/node/demo/alice.js b/vcx/wrappers/node/demo/alice.js index a05cbea1e3..7e1a12f91d 100644 --- a/vcx/wrappers/node/demo/alice.js +++ b/vcx/wrappers/node/demo/alice.js @@ -16,12 +16,13 @@ const provisionConfig = { 'enterprise_seed': '000000000000000000000000Trustee1' }; +const logLevel = 'warn'; async function run() { await demoCommon.initLibNullPay(); console.log("#0 initialize rust API from NodeJS"); - await demoCommon.initRustApiAndLogger(); + await demoCommon.initRustApiAndLogger(logLevel); console.log("#1 Provision an agent and wallet, get back configuration details"); let config = await demoCommon.provisionAgentInAgency(provisionConfig); diff --git a/vcx/wrappers/node/demo/common.js b/vcx/wrappers/node/demo/common.js index 6b16d8db30..e7759ded90 100644 --- a/vcx/wrappers/node/demo/common.js +++ b/vcx/wrappers/node/demo/common.js @@ -1,14 +1,15 @@ import {initRustAPI, initVcxWithConfig, provisionAgent} from "./../dist/src"; import * as ffi from "ffi"; +import 'fs'; export async function initLibNullPay() { const myffi = ffi.Library('/usr/local/lib/libnullpay.dylib', {nullpay_init: ['void', []]}); await myffi.nullpay_init(); } -export async function initRustApiAndLogger() { +export async function initRustApiAndLogger(logLevel) { let rustApi = initRustAPI(); - await rustApi.vcx_set_default_logger("info"); + await rustApi.vcx_set_default_logger(logLevel); } export async function provisionAgentInAgency(config) { @@ -16,14 +17,13 @@ export async function provisionAgentInAgency(config) { } export async function initVcxWithProvisionedAgentConfig(config) { - // Set some additional configuration options specific to Faber config['institution_name'] = 'faber'; config['institution_logo_url'] = 'http://robohash.org/234'; - config['genesis_path'] = 'docker.txn'; + config['genesis_path'] = `${__dirname}/docker.txn` ; await initVcxWithConfig(JSON.stringify(config)); } -export async function getRandomInt(min, max) { +export function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min)) + min; diff --git a/vcx/wrappers/node/demo/docker.txn b/vcx/wrappers/node/demo/docker.txn new file mode 100644 index 0000000000..66fb071b90 --- /dev/null +++ b/vcx/wrappers/node/demo/docker.txn @@ -0,0 +1,4 @@ +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blskey":"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba","blskey_pop":"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1","client_ip":"127.0.0.1","client_port":9702,"node_ip":"127.0.0.1","node_port":9701,"services":["VALIDATOR"]},"dest":"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv"},"metadata":{"from":"Th7MpTaRZVRYnPiabds81Y"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node2","blskey":"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk","blskey_pop":"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5","client_ip":"127.0.0.1","client_port":9704,"node_ip":"127.0.0.1","node_port":9703,"services":["VALIDATOR"]},"dest":"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb"},"metadata":{"from":"EbP4aYNeTHL6q385GuVpRV"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node3","blskey":"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5","blskey_pop":"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh","client_ip":"127.0.0.1","client_port":9706,"node_ip":"127.0.0.1","node_port":9705,"services":["VALIDATOR"]},"dest":"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya"},"metadata":{"from":"4cU41vWW82ArfxJxHkzXPG"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"127.0.0.1","client_port":9708,"node_ip":"127.0.0.1","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"} \ No newline at end of file diff --git a/vcx/wrappers/node/demo/faber.js b/vcx/wrappers/node/demo/faber.js index 78b4bc251c..5cb4b0d9d3 100644 --- a/vcx/wrappers/node/demo/faber.js +++ b/vcx/wrappers/node/demo/faber.js @@ -19,11 +19,13 @@ const provisionConfig = { 'enterprise_seed': '000000000000000000000000Trustee1' }; +const logLevel = 'error'; + async function run() { await demoCommon.initLibNullPay(); console.log("#0 initialize rust API from NodeJS"); - await demoCommon.initRustApiAndLogger(); + await demoCommon.initRustApiAndLogger(logLevel); console.log("#1 Provision an agent and wallet, get back configuration details"); let config = await demoCommon.provisionAgentInAgency(provisionConfig); @@ -68,17 +70,20 @@ async function run() { await connectionToAlice.connect('{"use_public_did": true}'); await connectionToAlice.updateState(); const details = await connectionToAlice.inviteDetails(false); - console.log("**invite details**"); - console.log(JSON.stringify(JSON.parse(details)), null, 0); - console.log("******************"); - - console.log("#6 Poll agency and wait for alice to accept the invitation (start alice.py now)"); + console.log("\n\n**invite details**"); + console.log("**You'll ge queried to paste this data to alice side of the demo. This is invitation to connect.**"); + console.log("**It's assumed this is obtained by Alice from Faber by some existing secure channel.**"); + console.log("**Could be on website via HTTPS, QR code scanned at Faber institution, ...**"); + console.log("\n******************\n\n"); + console.log(JSON.stringify(JSON.parse(details))); + console.log("\n\n******************\n\n"); + + console.log("#6 Polling agency and waiting for alice to accept the invitation. (start alice.py now)"); let connection_state = await connectionToAlice.getState(); while (connection_state !== StateType.Accepted) { await sleepPromise(2000); await connectionToAlice.updateState(); connection_state = await connectionToAlice.getState(); - console.log(`Connection to Alice is in state: ${connection_state}`); } console.log(`Connection to alice was Accepted!`); From ca689e5a406a0afcc183e1fc779a1c4845942032 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 13 Mar 2019 12:24:09 +0300 Subject: [PATCH 25/28] Fixed merge errors Signed-off-by: artem.ivanov --- vcx/libvcx/src/connection.rs | 16 +++++++- vcx/libvcx/src/messages/invite.rs | 60 +++++++++++++++++++++++++++++- vcx/libvcx/src/messages/payload.rs | 6 ++- 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/vcx/libvcx/src/connection.rs b/vcx/libvcx/src/connection.rs index b2294fafdf..7a0f7eb3e2 100644 --- a/vcx/libvcx/src/connection.rs +++ b/vcx/libvcx/src/connection.rs @@ -7,7 +7,7 @@ use settings; use messages; use messages::{GeneralMessage, MessageStatusCode, RemoteMessageType, ObjectWithVersion}; use messages::invite::{InviteDetail, SenderDetail, Payload as ConnectionPayload, AcceptanceDetails}; -use messages::payload::Payloads; +use messages::payload::{Payloads, Thread}; use messages::get_message::Message; use object_cache::ObjectCache; use error::prelude::*; @@ -17,6 +17,7 @@ use utils::libindy::crypto; use utils::json::mapped_key_rewrite; use utils::constants::DEFAULT_SERIALIZE_VERSION; use utils::json::KeyMatch; +use std::collections::HashMap; lazy_static! { static ref CONNECTION_MAP: ObjectCache = Default::default(); @@ -74,6 +75,7 @@ impl Connection { .agent_did(&self.agent_did)? .agent_vk(&self.agent_vk)? .public_did(self.public_did.as_ref().map(String::as_str))? + .thread(&Thread::new())? .send_secure() .map_err(|err| err.extend("Cannot send invite"))?; @@ -115,6 +117,7 @@ impl Connection { .sender_agency_details(&details.sender_agency_detail)? .answer_status_code(&MessageStatusCode::Accepted)? .reply_to(&details.conn_req_id)? + .thread(&self._build_thread(&details))? .send_secure() .map_err(|err| err.extend("Cannot accept invite"))?; @@ -123,6 +126,17 @@ impl Connection { Ok(error::SUCCESS.code_num) } + fn _build_thread(&self, invite_detail: &InviteDetail) -> Thread { + let mut received_orders = HashMap::new(); + received_orders.insert(invite_detail.sender_detail.did.clone(), 0); + Thread { + thid: invite_detail.thread_id.clone(), + pthid: None, + sender_order: 0, + received_orders, + } + } + fn connect(&mut self, options: &ConnectionOptions) -> VcxResult { trace!("Connection::connect >>> options: {:?}", options); match self.state { diff --git a/vcx/libvcx/src/messages/invite.rs b/vcx/libvcx/src/messages/invite.rs index 56442aa8a2..af9e255c11 100644 --- a/vcx/libvcx/src/messages/invite.rs +++ b/vcx/libvcx/src/messages/invite.rs @@ -1,6 +1,7 @@ use settings; use messages::*; use messages::message_type::{MessageTypes, MessageTypeV1, MessageTypeV2}; +use messages::payload::Thread; use utils::httpclient; use utils::constants::*; use utils::uuid::uuid; @@ -38,6 +39,8 @@ pub struct ConnectionRequest { phone_no: Option, #[serde(rename = "usePublicDID")] include_public_did: bool, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] @@ -85,6 +88,8 @@ pub struct ConnectionRequestAnswer { sender_agency_detail: Option, #[serde(rename = "answerStatusCode")] answer_status_code: Option, + #[serde(rename = "~thread")] + pub thread: Thread, } #[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] @@ -154,6 +159,7 @@ pub struct SendInviteBuilder { agent_did: String, agent_vk: String, public_did: Option, + thread: Thread } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] @@ -211,6 +217,7 @@ impl SendInviteBuilder { agent_did: String::new(), agent_vk: String::new(), public_did: None, + thread: Thread::new(), } } @@ -236,6 +243,11 @@ impl SendInviteBuilder { Ok(self) } + pub fn thread(&mut self, thread: &Thread) -> VcxResult<&mut Self> { + self.thread = thread.clone(); + Ok(self) + } + pub fn generate_signature(&mut self) -> VcxResult<()> { let signature = format!("{}{}", self.payload.key_dlg_proof.agent_did, self.payload.key_dlg_proof.agent_delegated_key); let signature = ::utils::libindy::crypto::sign(&self.to_vk, signature.as_bytes())?; @@ -287,13 +299,13 @@ pub struct AcceptInviteBuilder { agent_did: String, agent_vk: String, reply_to_msg_id: Option, + thread: Thread } impl AcceptInviteBuilder { pub fn create() -> AcceptInviteBuilder { trace!("AcceptInvite::create_message >>>"); - AcceptInviteBuilder { to_did: String::new(), to_vk: String::new(), @@ -307,6 +319,7 @@ impl AcceptInviteBuilder { agent_did: String::new(), agent_vk: String::new(), reply_to_msg_id: None, + thread: Thread::new(), } } @@ -336,6 +349,11 @@ impl AcceptInviteBuilder { Ok(self) } + pub fn thread(&mut self, thread: &Thread) -> VcxResult<&mut Self> { + self.thread = thread.clone(); + Ok(self) + } + pub fn generate_signature(&mut self) -> VcxResult<()> { let signature = format!("{}{}", self.payload.key_dlg_proof.agent_did, self.payload.key_dlg_proof.agent_delegated_key); let signature = crypto::sign(&self.to_vk, signature.as_bytes())?; @@ -417,6 +435,7 @@ impl GeneralMessage for SendInviteBuilder { target_name: self.payload.target_name.clone(), phone_no: self.payload.phone_no.clone(), include_public_did: self.payload.include_public_did, + thread: self.thread.clone(), }; vec![A2AMessage::Version2(A2AMessageV2::ConnectionRequest(msg))] @@ -470,6 +489,7 @@ impl GeneralMessage for AcceptInviteBuilder { sender_detail: self.payload.sender_detail.clone(), sender_agency_detail: self.payload.sender_agency_detail.clone(), answer_status_code: self.payload.answer_status_code.clone(), + thread: self.thread.clone(), }; vec![A2AMessage::Version2(A2AMessageV2::ConnectionRequestAnswer(msg))] @@ -495,6 +515,13 @@ pub struct AcceptanceDetails { pub sender_detail: SenderDetail, } +pub fn parse_invitation_acceptance_details(payload: Vec) -> VcxResult { + debug!("parsing invitation acceptance details: {:?}", payload); + let response: AcceptanceDetails = rmp_serde::from_slice(&payload[..]) + .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidMessagePack, format!("Cannot decode acceptance details: {:?}", err)))?; + Ok(response.sender_detail) +} + #[cfg(test)] mod tests { use super::*; @@ -534,4 +561,35 @@ mod tests { assert_eq!(result, invite); assert_eq!(url, "http://localhost:9001/agency/invite/WRUzXXuFVTYkT8CjSZpFvT?uid=NjcwOWU"); } + + #[test] + fn test_parse_invitation_acceptance_details() { + let payload = vec![129, 172, 115, 101, 110, 100, 101, 114, 68, 101, 116, 97, 105, 108, 131, 163, 68, 73, 68, 182, 67, 113, 85, 88, 113, 53, 114, 76, 105, 117, 82, 111, 100, 55, 68, 67, 52, 97, 86, 84, 97, 115, 166, 118, 101, 114, 75, 101, 121, 217, 44, 67, 70, 86, 87, 122, 118, 97, 103, 113, 65, 99, 117, 50, 115, 114, 68, 106, 117, 106, 85, 113, 74, 102, 111, 72, 65, 80, 74, 66, 111, 65, 99, 70, 78, 117, 49, 55, 113, 117, 67, 66, 57, 118, 71, 176, 97, 103, 101, 110, 116, 75, 101, 121, 68, 108, 103, 80, 114, 111, 111, 102, 131, 168, 97, 103, 101, 110, 116, 68, 73, 68, 182, 57, 54, 106, 111, 119, 113, 111, 84, 68, 68, 104, 87, 102, 81, 100, 105, 72, 49, 117, 83, 109, 77, 177, 97, 103, 101, 110, 116, 68, 101, 108, 101, 103, 97, 116, 101, 100, 75, 101, 121, 217, 44, 66, 105, 118, 78, 52, 116, 114, 53, 78, 88, 107, 69, 103, 119, 66, 56, 81, 115, 66, 51, 109, 109, 109, 122, 118, 53, 102, 119, 122, 54, 85, 121, 53, 121, 112, 122, 90, 77, 102, 115, 74, 56, 68, 122, 169, 115, 105, 103, 110, 97, 116, 117, 114, 101, 217, 88, 77, 100, 115, 99, 66, 85, 47, 99, 89, 75, 72, 49, 113, 69, 82, 66, 56, 80, 74, 65, 43, 48, 51, 112, 121, 65, 80, 65, 102, 84, 113, 73, 80, 74, 102, 52, 84, 120, 102, 83, 98, 115, 110, 81, 86, 66, 68, 84, 115, 67, 100, 119, 122, 75, 114, 52, 54, 120, 87, 116, 80, 43, 78, 65, 68, 73, 57, 88, 68, 71, 55, 50, 50, 103, 113, 86, 80, 77, 104, 117, 76, 90, 103, 89, 67, 103, 61, 61]; + println!("payload: {:?}", payload); + let response = parse_invitation_acceptance_details(payload).unwrap(); + println!("response: {:?}", response); + } + + #[test] + fn test_send_invite_null_parameters() { + let details = SendInviteMessageDetails { + msg_type: MessageTypeV1 { + name: "Name".to_string(), + ver: "1.0".to_string() + }, + key_dlg_proof: KeyDlgProof { + agent_did: "did".to_string(), + agent_delegated_key: "key".to_string(), + signature: "sig".to_string(), + }, + target_name: None, + phone_no: None, + include_public_did: true + }; + + let string: String = serde_json::to_string(&details).unwrap(); + assert!(!string.contains("phoneNo")); + assert!(!string.contains("targetName")); + assert!(string.contains("includePublicDID")); + } } diff --git a/vcx/libvcx/src/messages/payload.rs b/vcx/libvcx/src/messages/payload.rs index 471cc8fa66..ad8f7db32b 100644 --- a/vcx/libvcx/src/messages/payload.rs +++ b/vcx/libvcx/src/messages/payload.rs @@ -103,12 +103,16 @@ impl Payloads { let message = message["message"].as_str() .ok_or(VcxError::from_msg(VcxErrorKind::InvalidJson, "Cannot find `message` field"))?.to_string(); - let my_payload: PayloadV2 = serde_json::from_str(&message) + let mut my_payload: PayloadV2 = serde_json::from_str(&message) .map_err(|err| { error!("could not deserialize bundle with i8 or u8: {}", err); VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize payload: {}", err)) })?; + if my_payload.thread.thid.is_none() { + my_payload.thread.thid = Some(my_payload.id); + } + Ok((my_payload.msg, Some(my_payload.thread))) } } From dab97f694715ad9362ec70d3d087f1b3944c9eec Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 13 Mar 2019 12:43:45 +0300 Subject: [PATCH 26/28] Disabled testing on amazon Signed-off-by: artem.ivanov --- Jenkinsfile.cd | 2 +- Jenkinsfile.ci | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile.cd b/Jenkinsfile.cd index 5f8604754a..bff30bf3c7 100644 --- a/Jenkinsfile.cd +++ b/Jenkinsfile.cd @@ -41,7 +41,7 @@ def testing() { stage('Testing') { parallel([ 'ubuntu-test' : { ubuntuTesting() }, - 'redhat-test' : { rhelTesting() }, + // FIXME 'redhat-test' : { rhelTesting() }, https://jira.hyperledger.org/browse/IS-1212 'android-test': { androidTesting() }, 'windows-test': { windowsTesting() }, 'ios-test' : { iosTesting() } diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 9ac39ce5f1..9cc2965793 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -16,7 +16,7 @@ def testing() { 'android-test': { androidTesting() }, 'macos-test' : { macosTesting() }, 'ios-test' : { iosTesting() }, - 'redhat-test' : { rhelTesting() }, + // FIXME 'redhat-test' : { rhelTesting() }, https://jira.hyperledger.org/browse/IS-1212 'windows-test': { windowsTesting() } ]) } From 2501ba27189b26bd5f97f2c6a67599e21a03001d Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 13 Mar 2019 13:02:47 +0300 Subject: [PATCH 27/28] Nodejs cd pipeline fix Signed-off-by: artem.ivanov --- Jenkinsfile.cd | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile.cd b/Jenkinsfile.cd index 5f8604754a..0d6f46d259 100644 --- a/Jenkinsfile.cd +++ b/Jenkinsfile.cd @@ -1140,22 +1140,23 @@ def nodejsWrapperPublishing(testEnv, isRelease, library) { def suffix = getSuffix(isRelease, "nodejs") - dir(paths[library]['dir']) { - testEnv.inside { - if (library == 'vcx') { // need addition step for VCX to create .js files - sh "npm run compile" - } + def directory = paths[library]['dir'] - npmPublish(version, suffix) + testEnv.inside { + if (library == 'vcx') { // need addition step for VCX to create .js files + sh "cd $directory && npm run compile" } + + npmPublish(version, suffix, directory) } } -def npmPublish(version, suffix) { +def npmPublish(version, suffix, directory) { withCredentials([file(credentialsId: 'npm_credentials', variable: 'credentialsFile')]) { sh 'cp $credentialsFile ~/.npmrc' - sh "npm version --no-git-tag-version --allow-same-version $version$suffix" - sh "npm publish" + sh "cd $directory && " + + "npm version --no-git-tag-version --allow-same-version $version$suffix &&" + + "npm publish" } } From bcb0e3778c8e45241c1d735a3adff390601a273f Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 13 Mar 2019 13:02:47 +0300 Subject: [PATCH 28/28] Nodejs cd pipeline fix Signed-off-by: artem.ivanov --- Jenkinsfile.cd | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile.cd b/Jenkinsfile.cd index 5f8604754a..8561ccefba 100644 --- a/Jenkinsfile.cd +++ b/Jenkinsfile.cd @@ -1140,22 +1140,23 @@ def nodejsWrapperPublishing(testEnv, isRelease, library) { def suffix = getSuffix(isRelease, "nodejs") - dir(paths[library]['dir']) { - testEnv.inside { - if (library == 'vcx') { // need addition step for VCX to create .js files - sh "npm run compile" - } + def directory = paths[library]['dir'] - npmPublish(version, suffix) + testEnv.inside { + if (library == 'vcx') { // need addition step for VCX to create .js files + sh "cd $directory && npm i && npm run compile" } + + npmPublish(version, suffix, directory) } } -def npmPublish(version, suffix) { +def npmPublish(version, suffix, directory) { withCredentials([file(credentialsId: 'npm_credentials', variable: 'credentialsFile')]) { sh 'cp $credentialsFile ~/.npmrc' - sh "npm version --no-git-tag-version --allow-same-version $version$suffix" - sh "npm publish" + sh "cd $directory && " + + "npm version --no-git-tag-version --allow-same-version $version$suffix &&" + + "npm publish" } }