Skip to content

Commit

Permalink
Merge branch 'hyperledger-main' into gm/1306-cheqd-anoncreds-read
Browse files Browse the repository at this point in the history
Signed-off-by: George Mulhearn <gmulhearn@anonyome.com>
  • Loading branch information
gmulhearn-anonyome committed Dec 15, 2024
2 parents 7f69365 + cf43869 commit 08c557b
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 11 deletions.
18 changes: 16 additions & 2 deletions aries/aries_vcx/tests/test_primitives.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::error::Error;

use anoncreds_types::{
data_types::ledger::cred_def::CredentialDefinition, utils::validation::Validatable,
};
use aries_vcx::common::primitives::{
credential_definition::generate_cred_def, revocation_registry::generate_rev_reg,
};
Expand Down Expand Up @@ -46,13 +49,24 @@ async fn test_pool_create_cred_def_real() -> Result<(), Box<dyn Error>> {
.publish_cred_def(&setup.wallet, cred_def.try_clone()?, &setup.institution_did)
.await?;

std::thread::sleep(std::time::Duration::from_secs(2));
tokio::time::sleep(std::time::Duration::from_secs(2)).await;

let cred_def_json_ledger = ledger_read
.get_cred_def(&cred_def.id, Some(&setup.institution_did))
.await?;
cred_def_json_ledger.validate()?;

// same as the original generated cred def, but schema ID corrected to the qualified version
let cred_def_corrected_schema_id = CredentialDefinition {
schema_id: schema.schema_id,
..cred_def.try_clone().unwrap()
};

assert!(serde_json::to_string(&cred_def_json_ledger)?.contains(&cred_def.id.to_string()));
// check cred def matches originally, but with corected schema ID.
assert_eq!(
serde_json::to_value(cred_def_json_ledger)?,
serde_json::to_value(cred_def_corrected_schema_id)?
);
Ok(())
}

Expand Down
63 changes: 60 additions & 3 deletions aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,18 @@ pub use indy_ledger_response_parser::GetTxnAuthorAgreementData;
use indy_ledger_response_parser::{
ResponseParser, RevocationRegistryDeltaInfo, RevocationRegistryInfo,
};
use indy_vdr as vdr;
use indy_vdr::{
self as vdr,
ledger::{
identifiers::SchemaId as IndyVdrSchemaId,
requests::cred_def::CredentialDefinition as IndyVdrCredentialDefinition,
},
utils::{did::DidValue, Validatable},
};
use log::{debug, trace};
use public_key::Key;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_json::{json, Value};
use time::OffsetDateTime;
use vdr::{
config::PoolConfig,
Expand Down Expand Up @@ -169,6 +176,45 @@ where
trace!("submit_request << ledger response (is from cache: {is_from_cache}): {response}");
Ok(response)
}

async fn resolve_schema_id_from_seq_no(
&self,
seq_no: i32,
submitter_did: Option<&Did>,
) -> VcxLedgerResult<IndyVdrSchemaId> {
let response = self.get_ledger_txn(seq_no, submitter_did).await?;
let mut txn_response = self.response_parser.parse_get_txn_response(&response)?;
let txn = txn_response["txn"].take();

// mimic acapy & credo-ts behaviour - assumes node protocol >= 1.4

// check correct tx
let txn_type = &txn["type"];
if txn_type != &json!("101") {
return Err(VcxLedgerError::InvalidLedgerResponse(format!(
"Expected indy schema transaction type (101), found: {txn_type}"
)));
}

// pull schema identifier parts
let schema_did = &txn["metadata"]["from"];
let schema_name = &txn["data"]["data"]["name"];
let schema_version = &txn["data"]["data"]["version"];
let (Value::String(did), Value::String(name), Value::String(ver)) =
(schema_did, schema_name, schema_version)
else {
return Err(VcxLedgerError::InvalidLedgerResponse(
"Could not resolve schema DID, name & version from txn".into(),
));
};

// construct indy schema ID from parts
let did = DidValue::new(did, None);
did.validate()?;
let schema_id = IndyVdrSchemaId::new(&did, name, ver);
schema_id.validate()?;
Ok(schema_id)
}
}

impl<T> IndyVdrLedgerWrite<T>
Expand Down Expand Up @@ -503,7 +549,18 @@ where
let cred_def = self
.response_parser
.parse_get_cred_def_response(&response, None)?;
Ok(cred_def.convert(())?)

// extract and map seqNo -> schemaId if required
let IndyVdrCredentialDefinition::CredentialDefinitionV1(mut cred_def) = cred_def;
if let Ok(seq_no) = cred_def.schema_id.0.parse::<i32>() {
cred_def.schema_id = self
.resolve_schema_id_from_seq_no(seq_no, submitter_did)
.await?;
}

let cred_def = IndyVdrCredentialDefinition::CredentialDefinitionV1(cred_def).convert(())?;

Ok(cred_def)
}

async fn get_rev_reg_def_json(
Expand Down
10 changes: 5 additions & 5 deletions aries/aries_vcx_ledger/src/ledger/type_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ impl Convert for IndyVdrCredentialDefinition {
fn convert(self, (): Self::Args) -> Result<Self::Target, Self::Error> {
match self {
IndyVdrCredentialDefinition::CredentialDefinitionV1(cred_def) => {
let Some((_method, issuer_id, _sig_type, _schema_id, _tag)) = cred_def.id.parts()
else {
return Err(format!("cred def ID is not valid: {}", cred_def.id).into());
let id = &cred_def.id;
let Some((_method, issuer_id, _sig_type, _schema_id, _tag)) = id.parts() else {
return Err(format!("cred def ID is malformed. cannot convert. {}", id).into());
};
Ok(OurCredentialDefinition {
id: OurCredentialDefinitionId::new(cred_def.id.to_string())?,
schema_id: OurSchemaId::new_unchecked(cred_def.schema_id.to_string()),
id: OurCredentialDefinitionId::new(id.to_string())?,
schema_id: OurSchemaId::new(cred_def.schema_id.to_string())?,
signature_type: OurSignatureType::CL,
tag: cred_def.tag,
value: OurCredentialDefinitionData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pub const GET_REVOC_REG_DEF: &str = "115";
pub const GET_REVOC_REG: &str = "116";
pub const GET_REVOC_REG_DELTA: &str = "117";
pub const GET_TXN_AUTHR_AGRMT: &str = "6";
pub const GET_TXN: &str = "3";
1 change: 1 addition & 0 deletions aries/misc/indy_ledger_response_parser/src/domain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ pub mod response;
pub mod rev_reg;
pub mod rev_reg_def;
pub mod schema;
pub mod txn;
19 changes: 19 additions & 0 deletions aries/misc/indy_ledger_response_parser/src/domain/txn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use serde_json::Value;

use super::{
constants::GET_TXN,
response::{GetReplyResultV0, GetReplyResultV1, ReplyType},
};

#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum GetTxnReplyResult {
GetTxnReplyResultV0(GetReplyResultV0<Value>),
GetTxnReplyResultV1(GetReplyResultV1<Value>),
}

impl ReplyType for GetTxnReplyResult {
fn get_type<'a>() -> &'a str {
GET_TXN
}
}
18 changes: 17 additions & 1 deletion aries/misc/indy_ledger_response_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub mod error;

use anoncreds_clsignatures::RevocationRegistryDelta as ClRevocationRegistryDelta;
pub use domain::author_agreement::GetTxnAuthorAgreementData;
use domain::author_agreement::GetTxnAuthorAgreementResult;
use domain::{author_agreement::GetTxnAuthorAgreementResult, txn::GetTxnReplyResult};
use error::LedgerResponseParserError;
use indy_vdr::{
ledger::{
Expand Down Expand Up @@ -236,6 +236,22 @@ impl ResponseParser {
})
}

// https://github.com/hyperledger/indy-node/blob/main/docs/source/requests.md#get_txn
pub fn parse_get_txn_response(
&self,
get_txn_response: &str,
) -> Result<serde_json::Value, LedgerResponseParserError> {
let reply: Reply<GetTxnReplyResult> = Self::parse_response(get_txn_response)?;

let data = match reply.result() {
GetTxnReplyResult::GetTxnReplyResultV0(res) => {
res.data.unwrap_or(serde_json::Value::Null)
}
GetTxnReplyResult::GetTxnReplyResultV1(res) => res.txn.data,
};
Ok(data)
}

pub fn parse_response<T>(response: &str) -> Result<Reply<T>, LedgerResponseParserError>
where
T: DeserializeOwned + ReplyType + ::std::fmt::Debug,
Expand Down

0 comments on commit 08c557b

Please sign in to comment.