Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Eliminate dependence of indy-ledger-response-parser on indy-api-types #934

Merged
merged 4 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions aries_vcx_core/src/errors/mapping_ledger_response_parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use indy_ledger_response_parser::error::LedgerResponseParserError;

use super::error::{AriesVcxCoreError, AriesVcxCoreErrorKind};

impl From<LedgerResponseParserError> for AriesVcxCoreError {
fn from(err: LedgerResponseParserError) -> Self {
match &err {
LedgerResponseParserError::JsonError(err) => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidJson, err.to_string())
}
LedgerResponseParserError::LedgerItemNotFound(item) => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::LedgerItemNotFound, err.to_string())
}
LedgerResponseParserError::InvalidTransaction(message) => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidLedgerResponse, err.to_string())
}
}
}
}
1 change: 1 addition & 0 deletions aries_vcx_core/src/errors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ mod mapping_indy_api_types;
mod mapping_indyvdr;
#[cfg(feature = "vdr_proxy_ledger")]
mod mapping_indyvdr_proxy;
mod mapping_ledger_response_parser;
mod mapping_others;
4 changes: 2 additions & 2 deletions indy_ledger_response_parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ edition = "2021"
serde = { version = "1.0.163", features = ["derive"] }
serde_json = "1.0.96"
time = "=0.3.20"
ursa = { version = "0.3.7" }
indy-api-types = { path = "../libvdrtools/indy-api-types" }
indy-vdr = { git = "https://github.com/Patrik-Stas/indy-vdr.git", rev = "3cd499ad75", default-features = false, features = ["log"] }
thiserror = "1.0.44"
anoncreds-clsignatures = "0.2.0"
25 changes: 14 additions & 11 deletions indy_ledger_response_parser/src/domain/response.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use indy_api_types::{
errors::{err_msg, IndyErrorKind},
IndyError,
};
use crate::error::LedgerResponseParserError;

#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -107,10 +104,16 @@ impl<'a, T> TryFrom<ReplyV0<TypedReply<'a, T>>> for ReplyV0<T>
where
T: ReplyType,
{
type Error = IndyError;
type Error = LedgerResponseParserError;

fn try_from(value: ReplyV0<TypedReply<'a, T>>) -> Result<Self, Self::Error> {
if value.result.type_ != T::get_type() {
Err(err_msg(IndyErrorKind::InvalidTransaction, "Invalid response type"))
let expected_type = T::get_type();
let actual_type = value.result.type_;
if expected_type != actual_type {
Err(LedgerResponseParserError::InvalidTransaction(format!(
"Unexpected response type:\nExpected: {}\nActual: {}",
expected_type, actual_type
)))
} else {
Ok(ReplyV0 {
result: value.result.reply,
Expand All @@ -123,15 +126,15 @@ impl<'a, T> TryFrom<ReplyV1<TypedReply<'a, T>>> for ReplyV1<T>
where
T: ReplyType,
{
type Error = IndyError;
type Error = LedgerResponseParserError;

fn try_from(value: ReplyV1<TypedReply<'a, T>>) -> Result<Self, Self::Error> {
let value = value
.data
.result
.into_iter()
.next()
.ok_or_else(|| err_msg(IndyErrorKind::InvalidTransaction, "Invalid response type"))?;
.ok_or_else(|| LedgerResponseParserError::InvalidTransaction("Result field is empty".to_string()))?;
let data = ReplyDataV1 {
result: [value.try_into()?],
};
Expand All @@ -143,7 +146,7 @@ impl<'a, T> TryFrom<Reply<TypedReply<'a, T>>> for Reply<T>
where
T: ReplyType,
{
type Error = IndyError;
type Error = LedgerResponseParserError;

fn try_from(value: Reply<TypedReply<'a, T>>) -> Result<Self, Self::Error> {
let reply = match value {
Expand All @@ -158,7 +161,7 @@ impl<'a, T> TryFrom<MessageWithTypedReply<'a, T>> for Message<T>
where
T: ReplyType,
{
type Error = IndyError;
type Error = LedgerResponseParserError;

fn try_from(value: MessageWithTypedReply<'a, T>) -> Result<Self, Self::Error> {
match value {
Expand Down
2 changes: 1 addition & 1 deletion indy_ledger_response_parser/src/domain/rev_reg.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::constants::{GET_REVOC_REG, GET_REVOC_REG_DELTA};

use anoncreds_clsignatures::RevocationRegistry;
use indy_vdr::ledger::{identifiers::RevocationRegistryId, requests::rev_reg::RevocationRegistryV1};
use ursa::cl::RevocationRegistry;

use super::response::{GetReplyResultV1, ReplyType};

Expand Down
11 changes: 11 additions & 0 deletions indy_ledger_response_parser/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use thiserror::Error;

#[derive(Debug, Error)]
pub enum LedgerResponseParserError {
#[error("JSON error: {0}")]
JsonError(#[from] serde_json::error::Error),
#[error("Ledger item not found: {0}")]
LedgerItemNotFound(&'static str),
#[error("Invalid transaction: {0}")]
InvalidTransaction(String),
}
70 changes: 31 additions & 39 deletions indy_ledger_response_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ extern crate serde;
extern crate serde_json;

mod domain;
pub mod error;

use anoncreds_clsignatures::RevocationRegistryDelta as ClRevocationRegistryDelta;
pub use domain::author_agreement::GetTxnAuthorAgreementData;
use domain::author_agreement::GetTxnAuthorAgreementResult;
pub use indy_api_types::{errors, ErrorCode};
use indy_api_types::{
errors::{err_msg, IndyErrorKind, IndyResult, IndyResultExt},
IndyError,
};
use error::LedgerResponseParserError;
use indy_vdr::{
ledger::{
identifiers::{CredentialDefinitionId, RevocationRegistryId, SchemaId},
Expand All @@ -25,8 +23,6 @@ use indy_vdr::{
utils::did::DidValue,
};
use serde::de::DeserializeOwned;
// TODO: Can we replace this to get rid of dependency on Ursa
use ursa::cl::RevocationRegistryDelta as UrsaRevocationDelta;

use crate::domain::{
cred_def::GetCredDefReplyResult,
Expand Down Expand Up @@ -56,22 +52,15 @@ impl ResponseParser {
Self {}
}

pub fn parse_get_nym_response(&self, get_nym_response: &str) -> IndyResult<NymData> {
pub fn parse_get_nym_response(&self, get_nym_response: &str) -> Result<NymData, LedgerResponseParserError> {
let reply: Reply<GetNymReplyResult> = Self::parse_response(get_nym_response)?;

let nym_data = match reply.result() {
GetNymReplyResult::GetNymReplyResultV0(res) => {
let data: GetNymResultDataV0 = res
.data
.ok_or_else(|| IndyError::from_msg(IndyErrorKind::LedgerItemNotFound, format!("Nym not found")))
.and_then(|data| {
serde_json::from_str(&data).map_err(|err| {
IndyError::from_msg(
IndyErrorKind::InvalidState,
format!("Cannot parse GET_NYM response: {}", err),
)
})
})?;
.ok_or_else(|| LedgerResponseParserError::LedgerItemNotFound("NYM"))
.and_then(|data| serde_json::from_str(&data).map_err(Into::into))?;

NymData {
did: data.dest,
Expand All @@ -93,7 +82,7 @@ impl ResponseParser {
&self,
get_schema_response: &str,
method_name: Option<&str>,
) -> IndyResult<Schema> {
) -> Result<Schema, LedgerResponseParserError> {
let reply: Reply<GetSchemaReplyResult> = Self::parse_response(get_schema_response)?;

let schema = match reply.result() {
Expand Down Expand Up @@ -128,7 +117,7 @@ impl ResponseParser {
&self,
get_cred_def_response: &str,
method_name: Option<&str>,
) -> IndyResult<CredentialDefinition> {
) -> Result<CredentialDefinition, LedgerResponseParserError> {
let reply: Reply<GetCredDefReplyResult> = Self::parse_response(get_cred_def_response)?;

let cred_def = match reply.result() {
Expand Down Expand Up @@ -159,7 +148,7 @@ impl ResponseParser {
pub fn parse_get_revoc_reg_def_response(
&self,
get_revoc_reg_def_response: &str,
) -> IndyResult<RevocationRegistryDefinition> {
) -> Result<RevocationRegistryDefinition, LedgerResponseParserError> {
let reply: Reply<GetRevocRegDefReplyResult> = Self::parse_response(get_revoc_reg_def_response)?;

let revoc_reg_def = match reply.result() {
Expand All @@ -172,7 +161,10 @@ impl ResponseParser {
))
}

pub fn parse_get_revoc_reg_response(&self, get_revoc_reg_response: &str) -> IndyResult<RevocationRegistryInfo> {
pub fn parse_get_revoc_reg_response(
&self,
get_revoc_reg_response: &str,
) -> Result<RevocationRegistryInfo, LedgerResponseParserError> {
let reply: Reply<GetRevocRegReplyResult> = Self::parse_response(get_revoc_reg_response)?;

let (revoc_reg_def_id, revoc_reg, timestamp) = match reply.result() {
Expand All @@ -191,13 +183,16 @@ impl ResponseParser {
})
}

pub fn parse_get_txn_author_agreement_response(&self, taa_response: &str) -> IndyResult<GetTxnAuthorAgreementData> {
pub fn parse_get_txn_author_agreement_response(
&self,
taa_response: &str,
) -> Result<GetTxnAuthorAgreementData, LedgerResponseParserError> {
let reply: Reply<GetTxnAuthorAgreementResult> = Self::parse_response(taa_response)?;

let data = match reply.result() {
GetTxnAuthorAgreementResult::GetTxnAuthorAgreementResultV1(res) => res
.data
.ok_or_else(|| IndyError::from_msg(IndyErrorKind::LedgerItemNotFound, "TAA not found"))?,
.ok_or_else(|| LedgerResponseParserError::LedgerItemNotFound("TAA"))?,
};

Ok(GetTxnAuthorAgreementData {
Expand All @@ -212,7 +207,7 @@ impl ResponseParser {
pub fn parse_get_revoc_reg_delta_response(
&self,
get_revoc_reg_delta_response: &str,
) -> IndyResult<RevocationRegistryDeltaInfo> {
) -> Result<RevocationRegistryDeltaInfo, LedgerResponseParserError> {
let reply: Reply<GetRevocRegDeltaReplyResult> = Self::parse_response(get_revoc_reg_delta_response)?;

let (revoc_reg_def_id, revoc_reg) = match reply.result() {
Expand All @@ -223,16 +218,12 @@ impl ResponseParser {
};

let revoc_reg_delta = RevocationRegistryDeltaV1 {
value: serde_json::to_value(UrsaRevocationDelta::from_parts(
value: serde_json::to_value(ClRevocationRegistryDelta::from_parts(
revoc_reg.value.accum_from.map(|accum| accum.value).as_ref(),
&revoc_reg.value.accum_to.value,
&revoc_reg.value.issued,
&revoc_reg.value.revoked,
))
.to_indy(
IndyErrorKind::InvalidStructure,
"Cannot convert RevocationRegistryDelta to Value",
)?,
))?,
};

Ok(RevocationRegistryDeltaInfo {
Expand All @@ -242,20 +233,21 @@ impl ResponseParser {
})
}

pub fn parse_response<T>(response: &str) -> IndyResult<Reply<T>>
pub fn parse_response<T>(response: &str) -> Result<Reply<T>, LedgerResponseParserError>
where
T: DeserializeOwned + ReplyType + ::std::fmt::Debug,
{
let message: Message<T> = serde_json::from_str(response).to_indy(
IndyErrorKind::LedgerItemNotFound,
"Structure doesn't correspond to type. Most probably not found",
)?; // FIXME: Review how we handle not found
// TODO: Distinguish between not found and unexpected response format
let message: Message<T> = serde_json::from_str(response).map_err(|_| {
LedgerResponseParserError::LedgerItemNotFound(
"Structure doesn't correspond to type. Most probably not found",
)
})?;

match message {
Message::Reject(response) | Message::ReqNACK(response) => Err(err_msg(
IndyErrorKind::InvalidTransaction,
format!("Transaction has been failed: {:?}", response.reason),
)),
Message::Reject(response) | Message::ReqNACK(response) => {
Err(LedgerResponseParserError::InvalidTransaction(response.reason))
}
Message::Reply(reply) => Ok(reply),
}
}
Expand Down