Skip to content

Commit db92ffd

Browse files
fix(rust/rbac-registration): Fix some RBAC logging (#459)
* Fix some RBAC logging * Use map_err * Remove 'compare_key_hash' function * Fix some comments * Fix validate_stake_public_key formatting * Fix formatting inside convert_payment_key function * Fix tests * Use option instead of result for RegistrationChain::new and RegistrationChain::update * Remove debug formatting
1 parent b8b59d2 commit db92ffd

File tree

5 files changed

+96
-103
lines changed

5 files changed

+96
-103
lines changed

rust/rbac-registration/src/cardano/cip509/cip509.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ fn payment_history(
465465
report: &ProblemReport,
466466
) -> HashMap<ShelleyAddress, Vec<Payment>> {
467467
let hash = MultiEraTx::Conway(Box::new(Cow::Borrowed(txn))).hash();
468-
let context = format!("Populating payment history for Cip509, transaction hash = {hash:?}");
468+
let context = format!("Populating payment history for Cip509, transaction = {hash}");
469469

470470
let mut result: HashMap<_, _> = track_payment_addresses
471471
.iter()

rust/rbac-registration/src/cardano/cip509/types/role_data.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ use pallas::ledger::{
1111
};
1212

1313
use crate::cardano::cip509::{
14-
rbac::role_data::CborRoleData,
15-
utils::cip19::{compare_key_hash, extract_key_hash},
16-
KeyLocalRef,
14+
rbac::role_data::CborRoleData, utils::cip19::extract_key_hash, KeyLocalRef,
1715
};
1816

1917
/// A role data.
@@ -132,20 +130,31 @@ fn convert_payment_key(
132130
return None;
133131
},
134132
};
135-
validate_payment_output(address, &witness, context, report);
136133

137-
match Address::from_bytes(address) {
138-
Ok(Address::Shelley(a)) => Some(a),
139-
Ok(a) => {
134+
let address = match Address::from_bytes(address) {
135+
Ok(a) => a,
136+
Err(e) => {
140137
report.other(
141-
&format!("Unsupported address type ({a:?}) in payment key index ({index})"),
138+
&format!("Invalid address in payment key index ({index}): {e}"),
139+
context,
140+
);
141+
return None;
142+
},
143+
};
144+
validate_payment_output(&address, &witness, context, report);
145+
146+
match address {
147+
Address::Shelley(a) => Some(a),
148+
Address::Byron(_) => {
149+
report.other(
150+
&format!("Unsupported Byron address type in payment key index ({index})"),
142151
context,
143152
);
144153
None
145154
},
146-
Err(e) => {
155+
Address::Stake(_) => {
147156
report.other(
148-
&format!("Invalid address in payment key index ({index}): {e:?}"),
157+
&format!("Unsupported Stake address type in payment key index ({index})"),
149158
context,
150159
);
151160
None
@@ -155,23 +164,24 @@ fn convert_payment_key(
155164

156165
/// Helper function for validating payment output key.
157166
fn validate_payment_output(
158-
output_address: &[u8],
167+
address: &Address,
159168
witness: &TxnWitness,
160169
context: &str,
161170
report: &ProblemReport,
162171
) {
163-
let Some(key) = extract_key_hash(output_address) else {
172+
let bytes = address.to_vec();
173+
let Some(key) = extract_key_hash(&bytes) else {
164174
report.other("Failed to extract payment key hash from address", context);
165175
return;
166176
};
167177

168178
// Set transaction index to 0 because the list of transaction is manually constructed
169179
// for TxWitness -> &[txn.clone()], so we can assume that the witness contains only
170180
// the witness within this transaction.
171-
if let Err(e) = compare_key_hash(&[key], witness, 0.into()) {
181+
if !witness.check_witness_in_tx(&key, 0.into()) {
172182
report.other(
173183
&format!(
174-
"Unable to find payment output key ({key:?}) in the transaction witness set: {e:?}"
184+
"Payment Key {address} (0x{key}) is not present in the transaction witness set, and can not be verified as owned and spendable."
175185
),
176186
context,
177187
);
Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,9 @@
11
//! Utility functions for CIP-19 address.
22
3-
use anyhow::bail;
4-
use cardano_blockchain_types::{TxnIndex, TxnWitness, VKeyHash};
3+
use cardano_blockchain_types::VKeyHash;
54

65
/// Extract the first 28 bytes from the given key
76
/// Refer to <https://cips.cardano.org/cip/CIP-19> for more information.
87
pub(crate) fn extract_key_hash(key: &[u8]) -> Option<VKeyHash> {
98
key.get(1..29).and_then(|v| v.try_into().ok())
109
}
11-
12-
/// Compare the given public key bytes with the transaction witness set.
13-
pub(crate) fn compare_key_hash(
14-
pk_addrs: &[VKeyHash],
15-
witness: &TxnWitness,
16-
txn_idx: TxnIndex,
17-
) -> anyhow::Result<()> {
18-
if pk_addrs.is_empty() {
19-
bail!("No public key addresses provided");
20-
}
21-
22-
pk_addrs.iter().try_for_each(|pk_addr| {
23-
// Key hash not found in the transaction witness set
24-
if !witness.check_witness_in_tx(pk_addr, txn_idx) {
25-
bail!(
26-
"Public key hash not found in transaction witness set given {:?}",
27-
pk_addr
28-
);
29-
}
30-
31-
Ok(())
32-
})
33-
}

rust/rbac-registration/src/cardano/cip509/validation.rs

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ use pallas::{
2323
};
2424
use x509_cert::{der::Encode as X509Encode, Certificate as X509};
2525

26-
use super::{
27-
extract_key::{c509_key, x509_key},
28-
utils::cip19::compare_key_hash,
29-
};
3026
use crate::cardano::cip509::{
31-
rbac::Cip509RbacMetadata, types::TxInputHash, C509Cert, Cip0134UriSet, LocalRefInt, RoleData,
32-
SimplePublicKeyType, X509DerCert,
27+
rbac::Cip509RbacMetadata,
28+
types::TxInputHash,
29+
utils::extract_key::{c509_key, x509_key},
30+
C509Cert, Cip0134UriSet, LocalRefInt, RoleData, SimplePublicKeyType, X509DerCert,
3331
};
3432

3533
/// Context-specific primitive type with tag number 6 (`raw_tag` 134) for
@@ -109,7 +107,9 @@ pub fn validate_aux(
109107
let hash = Blake2b256Hash::new(raw_aux_data);
110108
if hash != auxiliary_data_hash {
111109
report.other(
112-
&format!("Incorrect transaction auxiliary data hash = '{hash:?}', expected = '{auxiliary_data_hash:?}'"),
110+
&format!("Incorrect transaction auxiliary data hash = '0x{hash}', expected = '0x{auxiliary_data_hash}'. \
111+
This metadata does not belong with this transaction. \
112+
Catalyst metadata may not be transcribed to any other transaction body, and is therefore invalid."),
113113
context,
114114
);
115115
}
@@ -142,17 +142,22 @@ pub fn validate_stake_public_key(
142142
return;
143143
}
144144

145-
if let Err(e) = compare_key_hash(&pk_addrs, &witness, 0.into()) {
146-
report.other(
147-
&format!("Failed to compare public keys with witnesses: {e:?}"),
148-
context,
149-
);
145+
for (hash, address) in pk_addrs {
146+
if !witness.check_witness_in_tx(&hash, 0.into()) {
147+
report.other(
148+
&format!(
149+
"Payment Key '{address}' (0x{hash}) is not present in the transaction witness set, and can not be verified as owned and spendable."
150+
),
151+
context,
152+
);
153+
}
150154
}
151155
}
152156

153157
/// Extracts all stake addresses from both X509 and C509 certificates containing in the
154-
/// given `Cip509` and converts their hashes to bytes.
155-
fn extract_stake_addresses(uris: Option<&Cip0134UriSet>) -> Vec<VKeyHash> {
158+
/// given `Cip509`. Returns a list of pairs containing verifying public key hash and
159+
/// `bech32` string representation of address.
160+
fn extract_stake_addresses(uris: Option<&Cip0134UriSet>) -> Vec<(VKeyHash, String)> {
156161
let Some(uris) = uris else {
157162
return Vec::new();
158163
};
@@ -163,7 +168,13 @@ fn extract_stake_addresses(uris: Option<&Cip0134UriSet>) -> Vec<VKeyHash> {
163168
.flat_map(|(_index, uris)| uris.iter())
164169
.filter_map(|uri| {
165170
if let Address::Stake(a) = uri.address() {
166-
a.payload().as_hash().as_slice().try_into().ok()
171+
let bech32 = uri.address().to_string();
172+
a.payload()
173+
.as_hash()
174+
.as_slice()
175+
.try_into()
176+
.ok()
177+
.map(|hash| (hash, bech32))
167178
} else {
168179
None
169180
}
@@ -547,7 +558,7 @@ mod tests {
547558
let report = registration.consume().unwrap_err();
548559
assert!(report.is_problematic());
549560
let report = format!("{report:?}");
550-
assert!(report.contains("Public key hash not found in transaction witness set"));
561+
assert!(report.contains("is not present in the transaction witness set, and can not be verified as owned and spendable"));
551562
}
552563

553564
#[test]
@@ -617,7 +628,7 @@ mod tests {
617628

618629
let addresses = extract_stake_addresses(cip509.certificate_uris());
619630
assert_eq!(1, addresses.len());
620-
assert_eq!(addresses.first().unwrap(), &hash);
631+
assert_eq!(addresses.first().unwrap().0, hash);
621632
}
622633

623634
// Verify that we are able to parse `Cip509` with legacy transaction output type.

0 commit comments

Comments
 (0)