Skip to content

Commit 1ce2bf0

Browse files
Registration chain
1 parent 20e731e commit 1ce2bf0

File tree

6 files changed

+66
-94
lines changed

6 files changed

+66
-94
lines changed

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl Cip509 {
157157
.as_ref(),
158158
&cip509.report,
159159
);
160-
if let Some(role_data) = cip509.role_data(RoleNumber::Role0) {
160+
if let Some(role_data) = cip509.role_data(RoleNumber::ROLE_0) {
161161
validate_stake_public_key(transaction, cip509.certificate_uris(), &cip509.report);
162162
validate_payment_key(transaction, conway_transaction, role_data, &cip509.report);
163163
validate_role_signing_key(role_data, &cip509.report);
@@ -242,26 +242,23 @@ impl Cip509 {
242242
self.metadata.as_ref().map(|m| &m.certificate_uris)
243243
}
244244

245+
/// Returns a transaction inputs hash.
245246
pub fn txn_inputs_hash(&self) -> Option<&TxInputHash> {
246247
self.txn_inputs_hash.as_ref()
247248
}
248249

249250
/// Returns `Cip509` fields consuming the structure if it was successfully decoded and
250251
/// validated otherwise return the problem report that contains all the encountered
251252
/// issues.
252-
pub fn try_consume(
253-
self,
254-
) -> Result<(Uuid, TxInputHash, Cip509RbacMetadata, ValidationSignature), ProblemReport> {
253+
pub fn try_consume(self) -> Result<(Uuid, Cip509RbacMetadata), ProblemReport> {
255254
match (
256255
self.purpose,
257256
self.txn_inputs_hash,
258257
self.metadata,
259258
self.validation_signature,
260259
) {
261-
(Some(purpose), Some(txn_inputs_hash), Some(metadata), Some(validation_signature))
262-
if !self.report.is_problematic() =>
263-
{
264-
Ok((purpose, txn_inputs_hash, metadata, validation_signature))
260+
(Some(purpose), Some(_), Some(metadata), Some(_)) if !self.report.is_problematic() => {
261+
Ok((purpose, metadata))
265262
},
266263

267264
_ => Err(self.report),

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
//! CDDL Reference: <https://github.com/input-output-hk/catalyst-CIPs/blob/x509-envelope-metadata/CIP-XXXX/x509-envelope.cddl>
44
55
pub use cip509::Cip509;
6-
pub use rbac::{role_data, C509Cert, SimplePublicKeyType, X509DerCert};
6+
pub use rbac::{
7+
role_data::{self, RoleData},
8+
C509Cert, RoleNumber, SimplePublicKeyType, X509DerCert,
9+
};
710
pub use types::CertKeyHash;
811
pub use utils::Cip0134UriSet;
912

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub struct RoleNumber(u8);
66

77
impl RoleNumber {
88
/// A number of the `Role0` role.
9-
pub const Role0: Self = RoleNumber(0);
9+
pub const ROLE_0: Self = RoleNumber(0);
1010
}
1111

1212
impl From<u8> for RoleNumber {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ mod tests {
492492
panic!("Unexpected transaction era");
493493
};
494494
let role_data = cip509
495-
.role_data(RoleNumber::Role0)
495+
.role_data(RoleNumber::ROLE_0)
496496
.expect("There must be role0");
497497
validate_payment_key(tx, conway_tx, role_data, &report);
498498
if report.is_problematic() {
@@ -525,7 +525,7 @@ mod tests {
525525
panic!("Unexpected transaction era");
526526
};
527527
let role_data = cip509
528-
.role_data(RoleNumber::Role0)
528+
.role_data(RoleNumber::ROLE_0)
529529
.expect("There must be role0");
530530
validate_payment_key(tx, conway_tx, role_data, &report);
531531
if report.is_problematic() {
@@ -555,7 +555,7 @@ mod tests {
555555
}
556556

557557
let role_data = cip509
558-
.role_data(RoleNumber::Role0)
558+
.role_data(RoleNumber::ROLE_0)
559559
.expect("There must be role0");
560560
validate_role_signing_key(role_data, &report);
561561
if report.is_problematic() {

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

Lines changed: 53 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@ use pallas::{
1919
};
2020
use payment_history::PaymentHistory;
2121
use point_tx_idx::PointTxIdx;
22-
use role_data::RoleData;
23-
use tracing::error;
22+
use tracing::{error, warn};
2423
use uuid::Uuid;
2524
use x509_cert::certificate::Certificate as X509Certificate;
2625

2726
use crate::{
2827
cardano::cip509::{
29-
C509Cert, CertKeyHash, Cip0134UriSet, Cip509, SimplePublicKeyType, X509DerCert,
28+
C509Cert, CertKeyHash, Cip0134UriSet, Cip509, RoleData as Cip509RoleData, RoleNumber,
29+
SimplePublicKeyType, X509DerCert,
3030
},
31+
registration::cardano::role_data::RoleData,
3132
utils::general::decremented_index,
3233
};
3334

@@ -121,7 +122,7 @@ impl RegistrationChain {
121122

122123
/// Get the map of role number to point, transaction index, and role data.
123124
#[must_use]
124-
pub fn role_data(&self) -> &HashMap<u8, (PointTxIdx, RoleData)> {
125+
pub fn role_data(&self) -> &HashMap<RoleNumber, (PointTxIdx, RoleData)> {
125126
&self.inner.role_data
126127
}
127128

@@ -154,7 +155,7 @@ struct RegistrationChainInner {
154155

155156
// Role
156157
/// Map of role number to point, transaction index, and role data.
157-
role_data: HashMap<u8, (PointTxIdx, RoleData)>,
158+
role_data: HashMap<RoleNumber, (PointTxIdx, RoleData)>,
158159
/// Map of tracked payment key to its history.
159160
tracking_payment_history: HashMap<ShelleyAddress, Vec<PaymentHistory>>,
160161
}
@@ -182,28 +183,26 @@ impl RegistrationChainInner {
182183
bail!("Invalid chain root, previous transaction ID should be None.");
183184
}
184185

185-
let mut validation_report = Vec::new();
186-
let validation_data = cip509.validate(txn, &mut validation_report);
187-
188-
// Do the CIP509 validation, ensuring the basic validation pass.
189-
if !is_valid_cip509(&validation_data) {
190-
// Log out the error if any
191-
error!("CIP509 validation failed: {:?}", validation_report);
192-
bail!("CIP509 validation failed, {:?}", validation_report);
193-
}
186+
// TODO: FIXME: Remove txn_inputs_hash?
187+
let (purpose, registration) = match cip509.try_consume() {
188+
Ok(v) => v,
189+
Err(e) => {
190+
let error = format!("Invalid Cip509: {e:?}");
191+
error!(error);
192+
bail!(error);
193+
},
194+
};
194195

195-
// Add purpose to the list
196-
let purpose = cip509.purpose().into_iter().collect();
196+
let purpose = vec![purpose];
197197

198-
let registration = cip509.metadata().clone();
199198
let point_tx_idx = PointTxIdx::new(point, tx_idx);
200199

201200
let certificate_uris = registration.certificate_uris;
202201
let x509_cert_map = chain_root_x509_certs(registration.x509_certs, &point_tx_idx);
203202
let c509_cert_map = chain_root_c509_certs(registration.c509_certs, &point_tx_idx);
204203
let public_key_map = chain_root_public_keys(registration.pub_keys, &point_tx_idx);
205204
let revocations = revocations_list(registration.revocation_list, &point_tx_idx);
206-
let role_data_map = chain_root_role_data(registration.role_set, txn, &point_tx_idx)?;
205+
let role_data_map = chain_root_role_data(registration.role_data, txn, &point_tx_idx)?;
207206

208207
let mut tracking_payment_history = HashMap::new();
209208
// Create a payment history for each tracking payment key
@@ -242,45 +241,42 @@ impl RegistrationChainInner {
242241
) -> anyhow::Result<Self> {
243242
let mut new_inner = self.clone();
244243

245-
let mut validation_report = Vec::new();
246-
let validation_data = cip509.validate(txn, &mut validation_report);
247-
248-
// Do the CIP509 validation, ensuring the basic validation pass.
249-
if !is_valid_cip509(&validation_data) {
250-
error!("CIP509 validation failed: {:?}", validation_report);
251-
bail!("CIP509 validation failed, {:?}", validation_report);
244+
let Some(prv_tx_id) = cip509.previous_transaction() else {
245+
bail!("Empty previous transaction ID");
246+
};
247+
// Previous transaction ID in the CIP509 should equal to the current transaction ID
248+
// or else it is not a part of the chain
249+
if prv_tx_id == self.current_tx_id_hash {
250+
new_inner.current_tx_id_hash = prv_tx_id;
251+
} else {
252+
bail!("Invalid previous transaction ID, not a part of this registration chain");
252253
}
253254

254-
// Check and update the current transaction ID hash
255-
if let Some(prv_tx_id) = cip509.previous_transaction() {
256-
// Previous transaction ID in the CIP509 should equal to the current transaction ID
257-
// or else it is not a part of the chain
258-
if prv_tx_id == &self.current_tx_id_hash {
259-
new_inner.current_tx_id_hash = *prv_tx_id;
260-
} else {
261-
bail!("Invalid previous transaction ID, not a part of this registration chain");
262-
}
263-
}
255+
let (purpose, registration) = match cip509.try_consume() {
256+
Ok(v) => v,
257+
Err(e) => {
258+
let error = format!("Invalid Cip509: {e:?}");
259+
error!(error);
260+
bail!(error);
261+
},
262+
};
264263

265264
// Add purpose to the chain, if not already exist
266-
if let Some(purpose) = cip509.purpose() {
267-
if !self.purpose.contains(&purpose) {
268-
new_inner.purpose.push(purpose);
269-
}
265+
if !self.purpose.contains(&purpose) {
266+
new_inner.purpose.push(purpose);
270267
}
271268

272-
let registration = cip509.metadata().clone();
273269
let point_tx_idx = PointTxIdx::new(point, tx_idx);
274270
new_inner.certificate_uris = new_inner.certificate_uris.update(&registration);
275271
update_x509_certs(&mut new_inner, registration.x509_certs, &point_tx_idx);
276-
update_c509_certs(&mut new_inner, registration.c509_certs, &point_tx_idx)?;
272+
update_c509_certs(&mut new_inner, registration.c509_certs, &point_tx_idx);
277273
update_public_keys(&mut new_inner, registration.pub_keys, &point_tx_idx);
278274

279275
let revocations = revocations_list(registration.revocation_list, &point_tx_idx);
280276
// Revocation list should be appended
281277
new_inner.revocations.extend(revocations);
282278

283-
update_role_data(&mut new_inner, registration.role_set, txn, &point_tx_idx)?;
279+
update_role_data(&mut new_inner, registration.role_data, txn, &point_tx_idx)?;
284280

285281
update_tracking_payment_history(
286282
&mut new_inner.tracking_payment_history,
@@ -348,7 +344,7 @@ fn chain_root_c509_certs(
348344
/// Update c509 certificates in the registration chain.
349345
fn update_c509_certs(
350346
new_inner: &mut RegistrationChainInner, c509_certs: Vec<C509Cert>, point_tx_idx: &PointTxIdx,
351-
) -> anyhow::Result<()> {
347+
) {
352348
for (idx, cert) in c509_certs.into_iter().enumerate() {
353349
match cert {
354350
// Unchanged to that index, so continue
@@ -359,7 +355,7 @@ fn update_c509_certs(
359355
},
360356
// Certificate reference
361357
C509Cert::C509CertInMetadatumReference(_) => {
362-
bail!("Unsupported c509 certificate in metadatum reference")
358+
warn!("Unsupported C509CertInMetadatumReference");
363359
},
364360
// Add the new certificate
365361
C509Cert::C509Certificate(c509) => {
@@ -369,7 +365,6 @@ fn update_c509_certs(
369365
},
370366
}
371367
}
372-
Ok(())
373368
}
374369

375370
/// Process public keys for chain root.
@@ -422,26 +417,23 @@ fn revocations_list(
422417

423418
/// Process the role data for chain root.
424419
fn chain_root_role_data(
425-
role_set: Vec<role_data::RoleData>, txn: &MultiEraTx, point_tx_idx: &PointTxIdx,
426-
) -> anyhow::Result<HashMap<u8, (PointTxIdx, RoleData)>> {
420+
role_set: HashMap<RoleNumber, Cip509RoleData>, txn: &MultiEraTx, point_tx_idx: &PointTxIdx,
421+
) -> anyhow::Result<HashMap<RoleNumber, (PointTxIdx, RoleData)>> {
427422
let mut role_data_map = HashMap::new();
428-
for role_data in role_set {
429-
let signing_key = role_data.role_signing_key.clone();
430-
let encryption_key = role_data.role_encryption_key.clone();
431-
423+
for (role_number, role_data) in role_set {
432424
// Get the payment key
433425
let payment_key = get_payment_addr_from_tx(txn, role_data.payment_key)?;
434426

435427
// Map of role number to point and role data
436428
role_data_map.insert(
437-
role_data.role_number,
429+
role_number,
438430
(
439431
point_tx_idx.clone(),
440432
RoleData::new(
441-
signing_key,
442-
encryption_key,
433+
role_data.role_signing_key,
434+
role_data.role_encryption_key,
443435
payment_key,
444-
role_data.role_extended_data_keys.clone(),
436+
role_data.role_extended_data_keys,
445437
),
446438
),
447439
);
@@ -451,15 +443,15 @@ fn chain_root_role_data(
451443

452444
/// Update the role data in the registration chain.
453445
fn update_role_data(
454-
inner: &mut RegistrationChainInner, role_set: Vec<RoleData>, txn: &MultiEraTx,
455-
point_tx_idx: &PointTxIdx,
446+
inner: &mut RegistrationChainInner, role_set: HashMap<RoleNumber, Cip509RoleData>,
447+
txn: &MultiEraTx, point_tx_idx: &PointTxIdx,
456448
) -> anyhow::Result<()> {
457-
for role_data in role_set {
449+
for (role_number, role_data) in role_set {
458450
// If there is new role singing key, use it, else use the old one
459451
let signing_key = match role_data.role_signing_key {
460452
Some(key) => Some(key),
461453
None => {
462-
match inner.role_data.get(&role_data.role_number) {
454+
match inner.role_data.get(&role_number) {
463455
Some((_, role_data)) => role_data.signing_key_ref().clone(),
464456
None => None,
465457
}
@@ -470,7 +462,7 @@ fn update_role_data(
470462
let encryption_key = match role_data.role_encryption_key {
471463
Some(key) => Some(key),
472464
None => {
473-
match inner.role_data.get(&role_data.role_number) {
465+
match inner.role_data.get(&role_number) {
474466
Some((_, role_data)) => role_data.encryption_ref().clone(),
475467
None => None,
476468
}
@@ -481,7 +473,7 @@ fn update_role_data(
481473
// Map of role number to point and role data
482474
// Note that new role data will overwrite the old one
483475
inner.role_data.insert(
484-
role_data.role_number,
476+
role_number,
485477
(
486478
point_tx_idx.clone(),
487479
RoleData::new(

rust/rbac-registration/src/utils/general.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,3 @@ pub(crate) fn decremented_index(int: i16) -> anyhow::Result<usize> {
1212
},
1313
}
1414
}
15-
16-
/// Decode the given UTF-8 content.
17-
pub(crate) fn decode_utf8(content: &[u8]) -> anyhow::Result<String> {
18-
// Decode the UTF-8 string
19-
std::str::from_utf8(content)
20-
.map(std::string::ToString::to_string)
21-
.map_err(|_| {
22-
anyhow::anyhow!(
23-
"Invalid UTF-8 string, expected valid UTF-8 string but got {:?}",
24-
content
25-
)
26-
})
27-
}
28-
29-
/// Zero out the last n bytes
30-
pub(crate) fn zero_out_last_n_bytes(vec: &mut [u8], n: usize) {
31-
if let Some(slice) = vec.get_mut(vec.len().saturating_sub(n)..) {
32-
slice.fill(0);
33-
}
34-
}

0 commit comments

Comments
 (0)