From 2256f8696bbaafc187b7e02b8a83f78f1e1ceb40 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Mon, 4 Aug 2025 20:21:35 +0200 Subject: [PATCH 1/9] Fix some RBAC logging --- .../src/cardano/cip509/cip509.rs | 2 +- .../src/cardano/cip509/types/role_data.rs | 2 +- .../src/cardano/cip509/utils/cip19.rs | 5 +---- .../src/cardano/cip509/validation.rs | 2 +- .../src/registration/cardano/mod.rs | 19 ++++--------------- 5 files changed, 8 insertions(+), 22 deletions(-) diff --git a/rust/rbac-registration/src/cardano/cip509/cip509.rs b/rust/rbac-registration/src/cardano/cip509/cip509.rs index a7d497e1a8f..ff4dbe314ce 100644 --- a/rust/rbac-registration/src/cardano/cip509/cip509.rs +++ b/rust/rbac-registration/src/cardano/cip509/cip509.rs @@ -454,7 +454,7 @@ fn payment_history( report: &ProblemReport, ) -> HashMap> { let hash = MultiEraTx::Conway(Box::new(Cow::Borrowed(txn))).hash(); - let context = format!("Populating payment history for Cip509, transaction hash = {hash:?}"); + let context = format!("Populating payment history for Cip509, transaction hash = {hash}"); let mut result: HashMap<_, _> = track_payment_addresses .iter() diff --git a/rust/rbac-registration/src/cardano/cip509/types/role_data.rs b/rust/rbac-registration/src/cardano/cip509/types/role_data.rs index 57816a0efcf..4a355701920 100644 --- a/rust/rbac-registration/src/cardano/cip509/types/role_data.rs +++ b/rust/rbac-registration/src/cardano/cip509/types/role_data.rs @@ -155,7 +155,7 @@ fn validate_payment_output( if let Err(e) = compare_key_hash(&[key], witness, 0.into()) { report.other( &format!( - "Unable to find payment output key ({key:?}) in the transaction witness set: {e:?}" + "Unable to find payment output key ({key}) in the transaction witness set: {e:?}" ), context, ); diff --git a/rust/rbac-registration/src/cardano/cip509/utils/cip19.rs b/rust/rbac-registration/src/cardano/cip509/utils/cip19.rs index b238f5d094d..04d770b6d7d 100644 --- a/rust/rbac-registration/src/cardano/cip509/utils/cip19.rs +++ b/rust/rbac-registration/src/cardano/cip509/utils/cip19.rs @@ -20,10 +20,7 @@ pub(crate) fn compare_key_hash( pk_addrs.iter().try_for_each(|pk_addr| { // Key hash not found in the transaction witness set if !witness.check_witness_in_tx(pk_addr, txn_idx) { - bail!( - "Public key hash not found in transaction witness set given {:?}", - pk_addr - ); + bail!("Public key hash not found in transaction witness set given {pk_addr}",); } Ok(()) diff --git a/rust/rbac-registration/src/cardano/cip509/validation.rs b/rust/rbac-registration/src/cardano/cip509/validation.rs index b7dba58eb95..3693a0824e8 100644 --- a/rust/rbac-registration/src/cardano/cip509/validation.rs +++ b/rust/rbac-registration/src/cardano/cip509/validation.rs @@ -105,7 +105,7 @@ pub fn validate_aux( let hash = Blake2b256Hash::new(raw_aux_data); if hash != auxiliary_data_hash { report.other( - &format!("Incorrect transaction auxiliary data hash = '{hash:?}', expected = '{auxiliary_data_hash:?}'"), + &format!("Incorrect transaction auxiliary data hash = '{hash}', expected = '{auxiliary_data_hash}'"), context, ); } diff --git a/rust/rbac-registration/src/registration/cardano/mod.rs b/rust/rbac-registration/src/registration/cardano/mod.rs index b968bf89fe3..fcbccbf2dea 100644 --- a/rust/rbac-registration/src/registration/cardano/mod.rs +++ b/rust/rbac-registration/src/registration/cardano/mod.rs @@ -17,7 +17,6 @@ use catalyst_types::{ uuid::UuidV4, }; use ed25519_dalek::{Signature, VerifyingKey}; -use tracing::error; use update_rbac::{ revocations_list, update_c509_certs, update_public_keys, update_role_data, update_x509_certs, }; @@ -345,13 +344,8 @@ impl RegistrationChainInner { context, )?; - let (purpose, registration, payment_history) = match cip509.consume() { - Ok(v) => v, - Err(e) => { - let error = format!("Invalid Cip509: {e:?}"); - error!(error); - bail!(error); - }, + let Ok((purpose, registration, payment_history)) = cip509.consume() else { + bail!("Unable to start a chain: invalid Cip509"); }; let purpose = vec![purpose]; @@ -436,13 +430,8 @@ impl RegistrationChainInner { } let point_tx_idx = cip509.origin().clone(); - let (purpose, registration, payment_history) = match cip509.consume() { - Ok(v) => v, - Err(e) => { - let error = format!("Invalid Cip509: {e:?}"); - error!(error); - bail!(error); - }, + let Ok((purpose, registration, payment_history)) = cip509.consume() else { + bail!("Unable to update a chain: invalid Cip509"); }; // Add purpose to the chain, if not already exist From 47d76fa1464c5505eaf0e3c58cca6f7cef2e4289 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 5 Aug 2025 13:04:48 +0200 Subject: [PATCH 2/9] Use map_err --- .../src/registration/cardano/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rust/rbac-registration/src/registration/cardano/mod.rs b/rust/rbac-registration/src/registration/cardano/mod.rs index fcbccbf2dea..b5c3f3f97ce 100644 --- a/rust/rbac-registration/src/registration/cardano/mod.rs +++ b/rust/rbac-registration/src/registration/cardano/mod.rs @@ -7,7 +7,7 @@ use std::{ sync::Arc, }; -use anyhow::{bail, Context}; +use anyhow::{anyhow, bail, Context}; use c509_certificate::c509::C509; use cardano_blockchain_types::{Point, StakeAddress, TransactionId, TxnIndex}; use catalyst_types::{ @@ -344,9 +344,9 @@ impl RegistrationChainInner { context, )?; - let Ok((purpose, registration, payment_history)) = cip509.consume() else { - bail!("Unable to start a chain: invalid Cip509"); - }; + let (purpose, registration, payment_history) = cip509 + .consume() + .map_err(|_| anyhow!("Unable to start a chain: invalid Cip509"))?; let purpose = vec![purpose]; let certificate_uris = registration.certificate_uris.clone(); @@ -430,9 +430,9 @@ impl RegistrationChainInner { } let point_tx_idx = cip509.origin().clone(); - let Ok((purpose, registration, payment_history)) = cip509.consume() else { - bail!("Unable to update a chain: invalid Cip509"); - }; + let (purpose, registration, payment_history) = cip509 + .consume() + .map_err(|_| anyhow!("Unable to update a chain: invalid Cip509"))?; // Add purpose to the chain, if not already exist if !self.purpose.contains(&purpose) { From fbdca264c01fbc77a60c8febe0aedebaf8123577 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 5 Aug 2025 20:08:06 +0200 Subject: [PATCH 3/9] Remove 'compare_key_hash' function --- .../src/cardano/cip509/types/role_data.rs | 9 +++---- .../src/cardano/cip509/utils/cip19.rs | 21 +--------------- .../src/cardano/cip509/validation.rs | 25 +++++++++++-------- 3 files changed, 19 insertions(+), 36 deletions(-) diff --git a/rust/rbac-registration/src/cardano/cip509/types/role_data.rs b/rust/rbac-registration/src/cardano/cip509/types/role_data.rs index 4a355701920..a5bb30be009 100644 --- a/rust/rbac-registration/src/cardano/cip509/types/role_data.rs +++ b/rust/rbac-registration/src/cardano/cip509/types/role_data.rs @@ -11,9 +11,7 @@ use pallas::ledger::{ }; use crate::cardano::cip509::{ - rbac::role_data::CborRoleData, - utils::cip19::{compare_key_hash, extract_key_hash}, - KeyLocalRef, + rbac::role_data::CborRoleData, utils::cip19::extract_key_hash, KeyLocalRef, }; /// A role data. @@ -152,10 +150,11 @@ fn validate_payment_output( // Set transaction index to 0 because the list of transaction is manually constructed // for TxWitness -> &[txn.clone()], so we can assume that the witness contains only // the witness within this transaction. - if let Err(e) = compare_key_hash(&[key], witness, 0.into()) { + if !witness.check_witness_in_tx(&key, 0.into()) { + // TODO: FIXME: Fix payment key format. report.other( &format!( - "Unable to find payment output key ({key}) in the transaction witness set: {e:?}" + "Payment Key FIXME (0x{key}) is not present in the transaction witness set, and can not be verified as owned and spendable." ), context, ); diff --git a/rust/rbac-registration/src/cardano/cip509/utils/cip19.rs b/rust/rbac-registration/src/cardano/cip509/utils/cip19.rs index 04d770b6d7d..a7bb80007c1 100644 --- a/rust/rbac-registration/src/cardano/cip509/utils/cip19.rs +++ b/rust/rbac-registration/src/cardano/cip509/utils/cip19.rs @@ -1,28 +1,9 @@ //! Utility functions for CIP-19 address. -use anyhow::bail; -use cardano_blockchain_types::{TxnIndex, TxnWitness, VKeyHash}; +use cardano_blockchain_types::VKeyHash; /// Extract the first 28 bytes from the given key /// Refer to for more information. pub(crate) fn extract_key_hash(key: &[u8]) -> Option { key.get(1..29).and_then(|v| v.try_into().ok()) } - -/// Compare the given public key bytes with the transaction witness set. -pub(crate) fn compare_key_hash( - pk_addrs: &[VKeyHash], witness: &TxnWitness, txn_idx: TxnIndex, -) -> anyhow::Result<()> { - if pk_addrs.is_empty() { - bail!("No public key addresses provided"); - } - - pk_addrs.iter().try_for_each(|pk_addr| { - // Key hash not found in the transaction witness set - if !witness.check_witness_in_tx(pk_addr, txn_idx) { - bail!("Public key hash not found in transaction witness set given {pk_addr}",); - } - - Ok(()) - }) -} diff --git a/rust/rbac-registration/src/cardano/cip509/validation.rs b/rust/rbac-registration/src/cardano/cip509/validation.rs index 3693a0824e8..cb33c606e93 100644 --- a/rust/rbac-registration/src/cardano/cip509/validation.rs +++ b/rust/rbac-registration/src/cardano/cip509/validation.rs @@ -23,13 +23,11 @@ use pallas::{ }; use x509_cert::{der::Encode as X509Encode, Certificate as X509}; -use super::{ - extract_key::{c509_key, x509_key}, - utils::cip19::compare_key_hash, -}; use crate::cardano::cip509::{ - rbac::Cip509RbacMetadata, types::TxInputHash, C509Cert, Cip0134UriSet, LocalRefInt, RoleData, - SimplePublicKeyType, X509DerCert, + rbac::Cip509RbacMetadata, + types::TxInputHash, + utils::extract_key::{c509_key, x509_key}, + C509Cert, Cip0134UriSet, LocalRefInt, RoleData, SimplePublicKeyType, X509DerCert, }; /// Context-specific primitive type with tag number 6 (`raw_tag` 134) for @@ -136,11 +134,16 @@ pub fn validate_stake_public_key( return; } - if let Err(e) = compare_key_hash(&pk_addrs, &witness, 0.into()) { - report.other( - &format!("Failed to compare public keys with witnesses: {e:?}"), - context, - ); + for address in pk_addrs { + if witness.check_witness_in_tx(&address, 0.into()) { + // TODO: FIXME: Fix payment key format. + report.other( + &format!( + "Payment Key FIXME (0x{address}) is not present in the transaction witness set, and can not be verified as owned and spendable." + ), + context, + ); + } } } From b205c881ab25afb6b9c06a68956cb6b4d0faef9e Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 5 Aug 2025 20:14:40 +0200 Subject: [PATCH 4/9] Fix some comments --- rust/rbac-registration/src/cardano/cip509/cip509.rs | 2 +- rust/rbac-registration/src/cardano/cip509/validation.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/rust/rbac-registration/src/cardano/cip509/cip509.rs b/rust/rbac-registration/src/cardano/cip509/cip509.rs index ff4dbe314ce..ae707e33e17 100644 --- a/rust/rbac-registration/src/cardano/cip509/cip509.rs +++ b/rust/rbac-registration/src/cardano/cip509/cip509.rs @@ -454,7 +454,7 @@ fn payment_history( report: &ProblemReport, ) -> HashMap> { let hash = MultiEraTx::Conway(Box::new(Cow::Borrowed(txn))).hash(); - let context = format!("Populating payment history for Cip509, transaction hash = {hash}"); + let context = format!("Populating payment history for Cip509, transaction = {hash}"); let mut result: HashMap<_, _> = track_payment_addresses .iter() diff --git a/rust/rbac-registration/src/cardano/cip509/validation.rs b/rust/rbac-registration/src/cardano/cip509/validation.rs index cb33c606e93..4ce27e1629d 100644 --- a/rust/rbac-registration/src/cardano/cip509/validation.rs +++ b/rust/rbac-registration/src/cardano/cip509/validation.rs @@ -103,7 +103,9 @@ pub fn validate_aux( let hash = Blake2b256Hash::new(raw_aux_data); if hash != auxiliary_data_hash { report.other( - &format!("Incorrect transaction auxiliary data hash = '{hash}', expected = '{auxiliary_data_hash}'"), + &format!("Incorrect transaction auxiliary data hash = '0x{hash}', expected = '0x{auxiliary_data_hash}'. \ + This metadata does not belong with this transaction. \ + Catalyst metadata may not be transcribed to any other transaction body, and is therefore invalid."), context, ); } From 6838c2d75e2edb9048634a7d67da28d7b1e4d58e Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 5 Aug 2025 21:25:17 +0200 Subject: [PATCH 5/9] Fix validate_stake_public_key formatting --- .../src/cardano/cip509/validation.rs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/rust/rbac-registration/src/cardano/cip509/validation.rs b/rust/rbac-registration/src/cardano/cip509/validation.rs index 4ce27e1629d..8008c8d1f6f 100644 --- a/rust/rbac-registration/src/cardano/cip509/validation.rs +++ b/rust/rbac-registration/src/cardano/cip509/validation.rs @@ -136,12 +136,11 @@ pub fn validate_stake_public_key( return; } - for address in pk_addrs { - if witness.check_witness_in_tx(&address, 0.into()) { - // TODO: FIXME: Fix payment key format. + for (hash, address) in pk_addrs { + if witness.check_witness_in_tx(&hash, 0.into()) { report.other( &format!( - "Payment Key FIXME (0x{address}) is not present in the transaction witness set, and can not be verified as owned and spendable." + "Payment Key '{address}' (0x{hash}) is not present in the transaction witness set, and can not be verified as owned and spendable." ), context, ); @@ -150,8 +149,9 @@ pub fn validate_stake_public_key( } /// Extracts all stake addresses from both X509 and C509 certificates containing in the -/// given `Cip509` and converts their hashes to bytes. -fn extract_stake_addresses(uris: Option<&Cip0134UriSet>) -> Vec { +/// given `Cip509`. Returns a list of pairs containing verifying public key hash and +/// `bech32` string representation of address. +fn extract_stake_addresses(uris: Option<&Cip0134UriSet>) -> Vec<(VKeyHash, String)> { let Some(uris) = uris else { return Vec::new(); }; @@ -162,7 +162,13 @@ fn extract_stake_addresses(uris: Option<&Cip0134UriSet>) -> Vec { .flat_map(|(_index, uris)| uris.iter()) .filter_map(|uri| { if let Address::Stake(a) = uri.address() { - a.payload().as_hash().as_slice().try_into().ok() + let bech32 = uri.address().to_string(); + a.payload() + .as_hash() + .as_slice() + .try_into() + .ok() + .map(|hash| (hash, bech32)) } else { None } @@ -590,7 +596,7 @@ mod tests { let addresses = extract_stake_addresses(cip509.certificate_uris()); assert_eq!(1, addresses.len()); - assert_eq!(addresses.first().unwrap(), &hash); + assert_eq!(addresses.first().unwrap().0, hash); } // Verify that we are able to parse `Cip509` with legacy transaction output type. From ae64c192456487130d1ff54057f0b59c470d38a3 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 5 Aug 2025 21:58:30 +0200 Subject: [PATCH 6/9] Fix formatting inside convert_payment_key function --- .../src/cardano/cip509/types/role_data.rs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/rust/rbac-registration/src/cardano/cip509/types/role_data.rs b/rust/rbac-registration/src/cardano/cip509/types/role_data.rs index 897d995801d..5083dcb460d 100644 --- a/rust/rbac-registration/src/cardano/cip509/types/role_data.rs +++ b/rust/rbac-registration/src/cardano/cip509/types/role_data.rs @@ -130,20 +130,24 @@ fn convert_payment_key( return None; }, }; - validate_payment_output(address, &witness, context, report); - match Address::from_bytes(address) { - Ok(Address::Shelley(a)) => Some(a), - Ok(a) => { + let address = match Address::from_bytes(address) { + Ok(a) => a, + Err(e) => { report.other( - &format!("Unsupported address type ({a:?}) in payment key index ({index})"), + &format!("Invalid address in payment key index ({index}): {e:?}"), context, ); - None + return None; }, - Err(e) => { + }; + validate_payment_output(&address, &witness, context, report); + + match address { + Address::Shelley(a) => Some(a), + a => { report.other( - &format!("Invalid address in payment key index ({index}): {e:?}"), + &format!("Unsupported address type ({a:?}) in payment key index ({index})"), context, ); None @@ -153,12 +157,13 @@ fn convert_payment_key( /// Helper function for validating payment output key. fn validate_payment_output( - output_address: &[u8], + address: &Address, witness: &TxnWitness, context: &str, report: &ProblemReport, ) { - let Some(key) = extract_key_hash(output_address) else { + let bytes = address.to_vec(); + let Some(key) = extract_key_hash(&bytes) else { report.other("Failed to extract payment key hash from address", context); return; }; @@ -167,10 +172,9 @@ fn validate_payment_output( // for TxWitness -> &[txn.clone()], so we can assume that the witness contains only // the witness within this transaction. if !witness.check_witness_in_tx(&key, 0.into()) { - // TODO: FIXME: Fix payment key format. report.other( &format!( - "Payment Key FIXME (0x{key}) is not present in the transaction witness set, and can not be verified as owned and spendable." + "Payment Key {address} (0x{key}) is not present in the transaction witness set, and can not be verified as owned and spendable." ), context, ); From 0cff5892e5df208a210aebfbbed8e627a79d6ed8 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 5 Aug 2025 22:09:37 +0200 Subject: [PATCH 7/9] Fix tests --- rust/rbac-registration/src/cardano/cip509/validation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/rbac-registration/src/cardano/cip509/validation.rs b/rust/rbac-registration/src/cardano/cip509/validation.rs index 798e26d37ee..f20ca4d5ae8 100644 --- a/rust/rbac-registration/src/cardano/cip509/validation.rs +++ b/rust/rbac-registration/src/cardano/cip509/validation.rs @@ -143,7 +143,7 @@ pub fn validate_stake_public_key( } for (hash, address) in pk_addrs { - if witness.check_witness_in_tx(&hash, 0.into()) { + if !witness.check_witness_in_tx(&hash, 0.into()) { report.other( &format!( "Payment Key '{address}' (0x{hash}) is not present in the transaction witness set, and can not be verified as owned and spendable." @@ -558,7 +558,7 @@ mod tests { let report = registration.consume().unwrap_err(); assert!(report.is_problematic()); let report = format!("{report:?}"); - assert!(report.contains("Public key hash not found in transaction witness set")); + assert!(report.contains("is not present in the transaction witness set, and can not be verified as owned and spendable")); } #[test] From b16a019d3d2a4cc502dca78daa5b6a19e4d1e753 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 6 Aug 2025 17:03:36 +0200 Subject: [PATCH 8/9] Use option instead of result for RegistrationChain::new and RegistrationChain::update --- .../src/registration/cardano/mod.rs | 75 ++++++++++--------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/rust/rbac-registration/src/registration/cardano/mod.rs b/rust/rbac-registration/src/registration/cardano/mod.rs index 18dd8a79260..3345fb64de4 100644 --- a/rust/rbac-registration/src/registration/cardano/mod.rs +++ b/rust/rbac-registration/src/registration/cardano/mod.rs @@ -7,7 +7,7 @@ use std::{ sync::Arc, }; -use anyhow::{anyhow, bail, Context}; +use anyhow::Context; use c509_certificate::c509::C509; use cardano_blockchain_types::{Point, StakeAddress, TransactionId, TxnIndex}; use catalyst_types::{ @@ -46,10 +46,10 @@ impl RegistrationChain { /// # Errors /// /// Returns an error if data is invalid - pub fn new(cip509: Cip509) -> anyhow::Result { + pub fn new(cip509: Cip509) -> Option { let inner = RegistrationChainInner::new(cip509)?; - Ok(Self { + Some(Self { inner: Arc::new(inner), }) } @@ -65,7 +65,7 @@ impl RegistrationChain { pub fn update( &self, cip509: Cip509, - ) -> anyhow::Result { + ) -> Option { let latest_signing_pk = self.get_latest_signing_pk_for_role(&RoleId::Role0); let new_inner = if let Some((signing_pk, _)) = latest_signing_pk { self.inner.update(cip509, signing_pk)? @@ -74,9 +74,9 @@ impl RegistrationChain { "latest signing key for role 0", "cannot perform signature validation during Registration Chain update", ); - bail!("No latest signing key found for role 0, cannot perform signature validation") + return None; }; - Ok(Self { + Some(Self { inner: Arc::new(new_inner), }) } @@ -300,18 +300,17 @@ impl RegistrationChainInner { /// # Errors /// /// Returns an error if data is invalid - fn new(cip509: Cip509) -> anyhow::Result { + fn new(cip509: Cip509) -> Option { let context = "Registration Chain new"; // Should be chain root, return immediately if not if cip509.previous_transaction().is_some() { cip509 .report() .invalid_value("previous transaction ID", "None", "Some", context); - bail!("Invalid chain root, previous transaction ID should be None."); } let Some(catalyst_id) = cip509.catalyst_id().cloned() else { cip509.report().missing_field("catalyst id", context); - bail!("Invalid chain root, catalyst id should be present."); + return None; }; let point_tx_idx = cip509.origin().clone(); @@ -336,7 +335,7 @@ impl RegistrationChainInner { // must contain role 0 let Some(role0_data) = role_data_record.get(&RoleId::Role0) else { cip509.report().missing_field("Role 0", context); - bail!("Role 0 not found"); + return None; }; let Some(signing_pk) = role0_data .signing_keys() @@ -346,7 +345,7 @@ impl RegistrationChainInner { cip509 .report() .missing_field("Signing pk for role 0 not found", context); - bail!("No valid signing key found for role 0"); + return None; }; check_validation_signature( @@ -355,11 +354,11 @@ impl RegistrationChainInner { signing_pk, cip509.report(), context, - )?; + ); - let (purpose, registration, payment_history) = cip509 - .consume() - .map_err(|_| anyhow!("Unable to start a chain: invalid Cip509"))?; + let Ok((purpose, registration, payment_history)) = cip509.consume() else { + return None; + }; let purpose = vec![purpose]; let certificate_uris = registration.certificate_uris.clone(); @@ -383,7 +382,7 @@ impl RegistrationChainInner { ); let revocations = revocations_list(registration.revocation_list.clone(), &point_tx_idx); - Ok(Self { + Some(Self { catalyst_id, current_tx_id_hash, purpose, @@ -410,7 +409,7 @@ impl RegistrationChainInner { &self, cip509: Cip509, signing_pk: VerifyingKey, - ) -> anyhow::Result { + ) -> Option { let context = "Registration Chain update"; let mut new_inner = self.clone(); @@ -418,7 +417,7 @@ impl RegistrationChainInner { cip509 .report() .missing_field("previous transaction ID", context); - bail!("Missing previous transaction ID"); + return None; }; // Previous transaction ID in the CIP509 should equal to the current transaction ID @@ -431,7 +430,7 @@ impl RegistrationChainInner { signing_pk, cip509.report(), context, - )?; + ); // If successful, update the chain current transaction ID hash new_inner.current_tx_id_hash = @@ -443,13 +442,13 @@ impl RegistrationChainInner { &format!("{:?}", self.current_tx_id_hash), context, ); - bail!("Invalid previous transaction ID, not a part of this registration chain"); + return None; } let point_tx_idx = cip509.origin().clone(); - let (purpose, registration, payment_history) = cip509 - .consume() - .map_err(|_| anyhow!("Unable to update a chain: invalid Cip509"))?; + let Ok((purpose, registration, payment_history)) = cip509.consume() else { + return None; + }; // Add purpose to the chain, if not already exist if !self.purpose.contains(&purpose) { @@ -485,7 +484,7 @@ impl RegistrationChainInner { &point_tx_idx, ); - Ok(new_inner) + Some(new_inner) } } @@ -497,34 +496,37 @@ fn check_validation_signature( signing_pk: VerifyingKey, report: &ProblemReport, context: &str, -) -> anyhow::Result<()> { +) { let context = &format!("Check Validation Signature in {context}"); // Note that the validation signature can be in the range of 1 - 64 bytes // But since we allow only Ed25519, it should be 64 bytes let unsigned_aux = zero_out_last_n_bytes(raw_aux_data, Signature::BYTE_SIZE); - let validation_sig = validation_signature.with_context(|| { + let Some(validation_sig) = validation_signature else { report.missing_field("validation signature", context); - "Missing validation signature" - })?; + return; + }; - let sig: Signature = validation_sig.clone().try_into().with_context(|| { + let Ok(sig) = validation_sig.clone().try_into() else { report.conversion_error( "validation signature", &format!("{validation_sig:?}"), "Ed25519 signature", context, ); - "Failed to convert validation signature to Ed25519 Signature" - })?; + return; + }; // Verify the signature using the latest signing public key - signing_pk + if let Err(e) = signing_pk .verify_strict(&unsigned_aux, &sig) .with_context(|| { report.other("Signature validation failed", context); "Signature verification failed" }) + { + report.functional_validation(&format!("Signature validation failed: {e}"), context); + } } #[cfg(test)] @@ -569,12 +571,13 @@ mod test { .unwrap(); assert!(registration.report().is_problematic()); - let error = chain.update(registration).unwrap_err(); - let error = format!("{error:?}"); + let report = registration.report().to_owned(); + assert!(chain.update(registration).is_none()); + let report = format!("{report:?}"); assert!( - error.contains("Invalid previous transaction ID"), + report.contains("kind: InvalidValue { field: \"previous transaction ID\""), "{}", - error + report ); // Add the second registration. From 9186eba5e50abbc8380a2b092832b936d363875c Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 6 Aug 2025 17:08:27 +0200 Subject: [PATCH 9/9] Remove debug formatting --- .../src/cardano/cip509/types/role_data.rs | 13 ++++++++++--- .../src/registration/cardano/mod.rs | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/rust/rbac-registration/src/cardano/cip509/types/role_data.rs b/rust/rbac-registration/src/cardano/cip509/types/role_data.rs index 5083dcb460d..2f788da9d50 100644 --- a/rust/rbac-registration/src/cardano/cip509/types/role_data.rs +++ b/rust/rbac-registration/src/cardano/cip509/types/role_data.rs @@ -135,7 +135,7 @@ fn convert_payment_key( Ok(a) => a, Err(e) => { report.other( - &format!("Invalid address in payment key index ({index}): {e:?}"), + &format!("Invalid address in payment key index ({index}): {e}"), context, ); return None; @@ -145,9 +145,16 @@ fn convert_payment_key( match address { Address::Shelley(a) => Some(a), - a => { + Address::Byron(_) => { report.other( - &format!("Unsupported address type ({a:?}) in payment key index ({index})"), + &format!("Unsupported Byron address type in payment key index ({index})"), + context, + ); + None + }, + Address::Stake(_) => { + report.other( + &format!("Unsupported Stake address type in payment key index ({index})"), context, ); None diff --git a/rust/rbac-registration/src/registration/cardano/mod.rs b/rust/rbac-registration/src/registration/cardano/mod.rs index 3345fb64de4..ff959890b7b 100644 --- a/rust/rbac-registration/src/registration/cardano/mod.rs +++ b/rust/rbac-registration/src/registration/cardano/mod.rs @@ -46,6 +46,7 @@ impl RegistrationChain { /// # Errors /// /// Returns an error if data is invalid + #[must_use] pub fn new(cip509: Cip509) -> Option { let inner = RegistrationChainInner::new(cip509)?; @@ -62,6 +63,7 @@ impl RegistrationChain { /// # Errors /// /// Returns an error if data is invalid + #[must_use] pub fn update( &self, cip509: Cip509, @@ -300,6 +302,7 @@ impl RegistrationChainInner { /// # Errors /// /// Returns an error if data is invalid + #[must_use] fn new(cip509: Cip509) -> Option { let context = "Registration Chain new"; // Should be chain root, return immediately if not @@ -405,6 +408,7 @@ impl RegistrationChainInner { /// # Errors /// /// Returns an error if data is invalid + #[must_use] fn update( &self, cip509: Cip509,