From bca6b405eea000dc151dae16aa81e7f0037930f5 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Tue, 26 Nov 2024 20:11:53 +0700 Subject: [PATCH 1/7] feat: add cardano registration chain Signed-off-by: bkioshn --- rust/rbac-registration/src/lib.rs | 1 + .../src/registration/cardano.rs | 520 ++++++++++++++++++ .../rbac-registration/src/registration/mod.rs | 3 + 3 files changed, 524 insertions(+) create mode 100644 rust/rbac-registration/src/registration/cardano.rs create mode 100644 rust/rbac-registration/src/registration/mod.rs diff --git a/rust/rbac-registration/src/lib.rs b/rust/rbac-registration/src/lib.rs index 72fecd94b77..ab9cfd1e493 100644 --- a/rust/rbac-registration/src/lib.rs +++ b/rust/rbac-registration/src/lib.rs @@ -1,4 +1,5 @@ //! This crate provides functionalities for RBAC registration. pub mod cardano; +pub mod registration; pub(crate) mod utils; diff --git a/rust/rbac-registration/src/registration/cardano.rs b/rust/rbac-registration/src/registration/cardano.rs new file mode 100644 index 00000000000..da6ab4f435c --- /dev/null +++ b/rust/rbac-registration/src/registration/cardano.rs @@ -0,0 +1,520 @@ +//! Chain of Cardano registration data + +use std::{collections::HashMap, sync::Arc}; + +use anyhow::bail; +use c509_certificate::c509::C509; +use pallas::{ + codec::utils::Bytes, + crypto::hash::Hash, + ledger::{primitives::conway::Value, traverse::MultiEraTx}, + network::miniprotocols::Point, +}; +use tracing::error; + +use crate::{ + cardano::cip509::{ + self, + rbac::{ + certs::{C509Cert, X509DerCert}, + pub_key::{Ed25519PublicKey, SimplePublicKeyType}, + role_data::KeyLocalRef, + CertKeyHash, + }, + Cip509, UuidV4, + }, + utils::general::decremented_index, +}; + +/// Registration chain type. +pub type RegistrationChain = Arc; + +/// Inner structure of registration chain. +#[derive(Clone)] +pub struct RegistrationChainInner { + /// The current transaction ID hash (32 bytes) + current_tx_id_hash: Hash<32>, + /// List of purpose for this registration chain + purpose: Vec, + + // RBAC + /// Map of index in array to point, transaction index, and x509 certificate. + x509_certs: HashMap)>, + /// Map of index in array to point, transaction index, and c509 certificate. + c509_certs: HashMap, + /// Map of index in array to point, transaction index, and public key. + simple_keys: HashMap, + /// List of point, transaction index, and certificate key hash. + revocations: Vec<(PointTxIdx, CertKeyHash)>, + + // Role + /// Map of role number to point, transaction index, and role data. + role_data: HashMap, + /// List of payment keys to track. + tracking_payment_keys: Arc>, + /// Map of payment key to its history. + payment_history: HashMap>, +} + +/// Point (slot) and transaction index. +#[allow(dead_code)] +#[derive(Clone)] +pub(crate) struct PointTxIdx((Point, usize)); + +impl PointTxIdx { + /// Create an instance of point and transaction index. + pub(crate) fn new(point: Point, tx_idx: usize) -> Self { + PointTxIdx((point, tx_idx)) + } +} + +/// Payment history of the public key in tracking payment keys. +#[allow(dead_code)] +#[derive(Clone)] +pub struct PaymentHistory { + /// The point and transaction index. + point_tx_idx: PointTxIdx, + /// Transaction hash that this payment come from. + tx_hash: Hash<32>, + /// The transaction output index that this payment come from. + output_index: u16, + /// The value of the payment. + value: Value, +} + +/// Role data +#[allow(dead_code)] +#[derive(Clone)] +pub struct RoleData { + /// List of reference of signing keys to the data within registration. + signing_key_ref: Vec, + /// List of reference of encryption keys to the data within registration. + encryption_ref: Vec, + /// A payment key where reward will be distributed to. + payment_key: Ed25519PublicKey, + /// Map of role extended data (10-99) to its data + role_extended_data: HashMap>, +} + +impl RegistrationChainInner { + /// Create a new instance of registration chain. + /// The first new value should be the chain root. + /// + /// # Arguments + /// - `cip509` - The CIP509. + /// - `tracking_payment_keys` - The list of payment keys to track. + /// - `point` - The point (slot) of the transaction. + /// - `tx_idx` - The transaction index. + /// - `txn` - The transaction. + /// + /// # Errors + /// + /// Returns an error if data is invalid + #[allow(dead_code)] + pub fn new( + cip509: Cip509, tracking_payment_keys: Vec, point: Point, tx_idx: usize, + txn: &MultiEraTx, + ) -> anyhow::Result { + // Should be chain root, return immediately if not + if cip509.prv_tx_id.is_some() { + bail!("Invalid chain root, previous transaction ID should be None."); + } + + let mut validation_report = Vec::new(); + // Do the CIP509 validation, ensuring the basic validation pass. + if !cip509.validate(txn, tx_idx, &mut validation_report) { + // Log out the error if any + error!("CIP509 validation failed: {:?}", validation_report); + bail!("CIP509 validation failed, {:?}", validation_report); + } + + // Add purpose to the list + let purpose = vec![cip509.purpose]; + + let registration = cip509.x509_chunks.0; + let point_tx_idx = PointTxIdx::new(point, tx_idx); + + let x509_cert_map = chain_root_x509_certs(registration.x509_certs, &point_tx_idx); + let c509_cert_map = chain_root_c509_certs(registration.c509_certs, &point_tx_idx); + let public_key_map = chain_root_public_keys(registration.pub_keys, &point_tx_idx); + let revocations = revocations_list(registration.revocation_list, &point_tx_idx); + let role_data_map = chain_root_role_data(registration.role_set, txn, &point_tx_idx)?; + + let mut payment_history = HashMap::new(); + for tracking_key in &tracking_payment_keys { + // Keep record of payment history, the payment key that we want to track + let histories = update_payment_history(tracking_key, txn, &point_tx_idx)?; + payment_history.insert(tracking_key.clone(), histories); + } + + Ok(Self { + purpose, + current_tx_id_hash: txn.hash(), + x509_certs: x509_cert_map, + c509_certs: c509_cert_map, + simple_keys: public_key_map, + revocations, + role_data: role_data_map, + tracking_payment_keys: Arc::new(tracking_payment_keys), + payment_history, + }) + } + + /// Update the registration chain. + /// + /// # Arguments + /// - `point` - The point (slot) of the transaction. + /// - `tx_idx` - The transaction index. + /// - `txn` - The transaction. + /// - `cip509` - The CIP509. + /// + /// # Errors + /// + /// Returns an error if data is invalid + #[allow(dead_code)] + pub fn update( + &self, point: Point, tx_idx: usize, txn: &MultiEraTx, cip509: Cip509, + ) -> anyhow::Result { + let mut new_inner = self.clone(); + + let mut validation_report = Vec::new(); + // Do the CIP509 validation, ensuring the basic validation pass. + if !cip509.validate(txn, tx_idx, &mut validation_report) { + error!("CIP509 validation failed: {:?}", validation_report); + bail!("CIP509 validation failed, {:?}", validation_report); + } + + // Check and update the current transaction ID hash + if let Some(prv_tx_id) = cip509.prv_tx_id { + // Previous transaction ID in the CIP509 should equal to the current transaction ID + // or else it is not a part of the chain + if prv_tx_id == self.current_tx_id_hash { + new_inner.current_tx_id_hash = prv_tx_id; + } else { + bail!("Invalid previous transaction ID, not a part of this registration chain"); + } + } + + // Add purpose to the chain, if not already exist + let purpose = cip509.purpose; + if !self.purpose.contains(&purpose) { + new_inner.purpose.push(purpose); + } + + let registration = cip509.x509_chunks.0; + let point_tx_idx = PointTxIdx::new(point, tx_idx); + + update_x509_certs(&mut new_inner, registration.x509_certs, &point_tx_idx); + update_c509_certs(&mut new_inner, registration.c509_certs, &point_tx_idx)?; + update_public_keys(&mut new_inner, registration.pub_keys, &point_tx_idx); + + let revocations = revocations_list(registration.revocation_list, &point_tx_idx); + // Revocation list should be appended + new_inner.revocations.extend(revocations); + + update_role_data(&mut new_inner, registration.role_set, txn, &point_tx_idx)?; + + for tracking_key in self.tracking_payment_keys.iter() { + let histories = update_payment_history(tracking_key, txn, &point_tx_idx)?; + // If tracking payment key doesn't exist, insert an empty vector, + // then add the histories to the history vector + new_inner + .payment_history + .entry(tracking_key.clone()) + .or_default() + .extend(histories); + } + + Ok(new_inner) + } +} + +/// Process x509 certificate for chain root. +#[allow(dead_code)] +fn chain_root_x509_certs( + x509_certs: Option>, point_tx_idx: &PointTxIdx, +) -> HashMap)> { + let mut map = HashMap::new(); + if let Some(cert_list) = x509_certs { + for (idx, cert) in cert_list.iter().enumerate() { + // Chain root, expect only the certificate not undefined or delete + if let cip509::rbac::certs::X509DerCert::X509Cert(cert) = cert { + map.insert(idx, (point_tx_idx.clone(), cert.clone())); + } + } + } + map +} + +/// Update x509 certificates in the registration chain. +#[allow(dead_code)] +fn update_x509_certs( + new_inner: &mut RegistrationChainInner, x509_certs: Option>, + point_tx_idx: &PointTxIdx, +) { + if let Some(cert_list) = x509_certs { + for (idx, cert) in cert_list.iter().enumerate() { + match cert { + // Unchanged to that index, so continue + cip509::rbac::certs::X509DerCert::Undefined => continue, + // Delete the certificate + cip509::rbac::certs::X509DerCert::Deleted => { + new_inner.x509_certs.remove(&idx); + }, + // Add the new certificate + cip509::rbac::certs::X509DerCert::X509Cert(cert) => { + new_inner + .x509_certs + .insert(idx, (point_tx_idx.clone(), cert.clone())); + }, + } + } + } +} + +/// Process c509 certificates for chain root. +#[allow(dead_code)] +fn chain_root_c509_certs( + c509_certs: Option>, point_tx_idx: &PointTxIdx, +) -> HashMap { + let mut map = HashMap::new(); + if let Some(cert_list) = c509_certs { + for (idx, cert) in cert_list.iter().enumerate() { + if let cip509::rbac::certs::C509Cert::C509Certificate(cert) = cert { + // Chain root, expect only the certificate not undefined or delete + map.insert(idx, (point_tx_idx.clone(), *cert.clone())); + } + } + } + map +} + +/// Update c509 certificates in the registration chain. +#[allow(dead_code)] +fn update_c509_certs( + new_inner: &mut RegistrationChainInner, c509_certs: Option>, + point_tx_idx: &PointTxIdx, +) -> anyhow::Result<()> { + if let Some(cert_list) = c509_certs { + for (idx, cert) in cert_list.iter().enumerate() { + match cert { + // Unchanged to that index, so continue + cip509::rbac::certs::C509Cert::Undefined => continue, + // Delete the certificate + cip509::rbac::certs::C509Cert::Deleted => { + new_inner.c509_certs.remove(&idx); + }, + // Certificate reference + cip509::rbac::certs::C509Cert::C509CertInMetadatumReference(_) => { + bail!("Unsupported c509 certificate in metadatum reference") + }, + // Add the new certificate + cip509::rbac::certs::C509Cert::C509Certificate(c509) => { + new_inner + .c509_certs + .insert(idx, (point_tx_idx.clone(), *c509.clone())); + }, + } + } + } + Ok(()) +} + +/// Process public keys for chain root. +#[allow(dead_code)] +fn chain_root_public_keys( + pub_keys: Option>, point_tx_idx: &PointTxIdx, +) -> HashMap { + let mut map = HashMap::new(); + if let Some(key_list) = pub_keys { + for (idx, key) in key_list.iter().enumerate() { + // Chain root, expect only the public key not undefined or delete + if let cip509::rbac::pub_key::SimplePublicKeyType::Ed25519(key) = key { + map.insert(idx, (point_tx_idx.clone(), key.clone())); + } + } + } + map +} + +/// Update public keys in the registration chain. +#[allow(dead_code)] +fn update_public_keys( + new_inner: &mut RegistrationChainInner, pub_keys: Option>, + point_tx_idx: &PointTxIdx, +) { + if let Some(key_list) = pub_keys { + for (idx, cert) in key_list.iter().enumerate() { + match cert { + // Unchanged to that index, so continue + cip509::rbac::pub_key::SimplePublicKeyType::Undefined => continue, + // Delete the public key + cip509::rbac::pub_key::SimplePublicKeyType::Deleted => { + new_inner.simple_keys.remove(&idx); + }, + // Add the new public key + cip509::rbac::pub_key::SimplePublicKeyType::Ed25519(key) => { + new_inner + .simple_keys + .insert(idx, (point_tx_idx.clone(), key.clone())); + }, + } + } + } +} + +/// Process the revocation list. +#[allow(dead_code)] +fn revocations_list( + revocation_list: Option>, point_tx_idx: &PointTxIdx, +) -> Vec<(PointTxIdx, CertKeyHash)> { + let mut revocations = Vec::new(); + if let Some(revocations_data) = revocation_list { + for item in revocations_data { + revocations.push((point_tx_idx.clone(), item.clone())); + } + } + revocations +} + +/// Process the role data for chain root. +#[allow(dead_code)] +fn chain_root_role_data( + role_set: Option>, txn: &MultiEraTx, + point_tx_idx: &PointTxIdx, +) -> anyhow::Result> { + let mut role_data_map = HashMap::new(); + if let Some(role_set_data) = role_set { + for role_data in role_set_data { + let signing_key = role_data.role_signing_key.clone().unwrap_or_default(); + let encryption_key = role_data.role_encryption_key.clone().unwrap_or_default(); + + // Get the payment key + let payment_key = get_payment_key_from_tx(txn, role_data.payment_key)?; + + // Map of role number to point and role data + role_data_map.insert( + role_data.role_number, + (point_tx_idx.clone(), RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }), + ); + } + } + Ok(role_data_map) +} + +/// Update the role data in the registration chain. +#[allow(dead_code)] +fn update_role_data( + inner: &mut RegistrationChainInner, role_set: Option>, + txn: &MultiEraTx, point_tx_idx: &PointTxIdx, +) -> anyhow::Result<()> { + if let Some(role_set_data) = role_set { + for role_data in role_set_data { + // If there is new role singing key, use it, else use the old one + let signing_key = role_data.role_signing_key.unwrap_or_else(|| { + match inner.role_data.get(&role_data.role_number) { + Some((_, role_data)) => role_data.signing_key_ref.clone(), + None => Vec::new(), + } + }); + + // If there is new role encryption key, use it, else use the old one + let encryption_key = role_data.role_encryption_key.unwrap_or_else(|| { + match inner.role_data.get(&role_data.role_number) { + Some((_, role_data)) => role_data.encryption_ref.clone(), + None => Vec::new(), + } + }); + let payment_key = get_payment_key_from_tx(txn, role_data.payment_key)?; + + // Map of role number to point and role data + // Note that new role data will overwrite the old one + inner.role_data.insert( + role_data.role_number, + (point_tx_idx.clone(), RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }), + ); + } + } + Ok(()) +} + +/// Helper function for retrieving the payment key from the transaction. +fn get_payment_key_from_tx( + txn: &MultiEraTx, payment_key_ref: Option, +) -> anyhow::Result { + // The index should exist since it pass the basic validation + if let Some(key_ref) = payment_key_ref { + if let MultiEraTx::Conway(tx) = txn { + // Transaction output + if key_ref < 0 { + let index = decremented_index(key_ref.abs())?; + if let Some(output) = tx.transaction_body.outputs.get(index) { + // Conway era -> Post alonzo tx output + match output { + pallas::ledger::primitives::conway::PseudoTransactionOutput::PostAlonzo( + o, + ) => { + let payment_key: Ed25519PublicKey = + o.address.clone().try_into().map_err(|_| { + anyhow::anyhow!("Failed to convert Vec to Ed25519PublicKey in payment key reference") + })?; + return Ok(payment_key); + }, + // Not support legacy form of transaction output + pallas::ledger::primitives::conway::PseudoTransactionOutput::Legacy(_) => { + bail!("Unsupported transaction output type in payment key reference"); + }, + } + } + // Index doesn't exist + bail!("Payment key not found in transaction output"); + } + // Transaction input, currently unsupported because of the reference to transaction hash + bail!("Unsupported payment key reference to transaction input"); + } + } + Ok(Ed25519PublicKey::default()) +} + +/// Update the payment history given the tracking payment keys. +fn update_payment_history( + tracking_key: &Ed25519PublicKey, txn: &MultiEraTx, point_tx_idx: &PointTxIdx, +) -> anyhow::Result> { + let mut payment_history = Vec::new(); + if let MultiEraTx::Conway(tx) = txn { + // Conway era -> Post alonzo tx output + for (index, output) in tx.transaction_body.outputs.iter().enumerate() { + match output { + pallas::ledger::primitives::conway::PseudoTransactionOutput::PostAlonzo(o) => { + let address_bytes: Bytes = tracking_key.clone().into(); + if address_bytes == o.address { + let output_index: u16 = index.try_into().map_err(|_| { + anyhow::anyhow!("Cannot convert usize to u16 in update payment history") + })?; + + payment_history.push(PaymentHistory { + point_tx_idx: point_tx_idx.clone(), + tx_hash: txn.hash(), + output_index, + value: o.value.clone(), + }); + } + }, + pallas::ledger::primitives::conway::PseudoTransactionOutput::Legacy(_) => { + bail!("Unsupported transaction output type in update payment history"); + }, + } + } + } + Ok(payment_history) +} diff --git a/rust/rbac-registration/src/registration/mod.rs b/rust/rbac-registration/src/registration/mod.rs new file mode 100644 index 00000000000..a6a5c3c002d --- /dev/null +++ b/rust/rbac-registration/src/registration/mod.rs @@ -0,0 +1,3 @@ +//! Registration module + +pub mod cardano; From 969df75fb0ee343aac99f713c9daeb1f2e995693 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 27 Nov 2024 12:03:33 +0700 Subject: [PATCH 2/7] feat: add wrapper to registration chain inner Signed-off-by: bkioshn --- .../src/registration/cardano.rs | 168 ++++++++++++++---- 1 file changed, 136 insertions(+), 32 deletions(-) diff --git a/rust/rbac-registration/src/registration/cardano.rs b/rust/rbac-registration/src/registration/cardano.rs index da6ab4f435c..38e82730f43 100644 --- a/rust/rbac-registration/src/registration/cardano.rs +++ b/rust/rbac-registration/src/registration/cardano.rs @@ -26,12 +26,44 @@ use crate::{ utils::general::decremented_index, }; -/// Registration chain type. -pub type RegistrationChain = Arc; +/// Registration chains. +pub struct RegistrationChain { + inner: Arc, +} + +impl RegistrationChain { + /// Create a new instance of registration chain. + pub fn new( + &self, point: Point, tracking_payment_keys: Vec, tx_idx: usize, + txn: &MultiEraTx, cip509: Cip509, + ) -> anyhow::Result { + let inner = RegistrationChainInner::new(cip509, tracking_payment_keys, point, tx_idx, txn)?; + + Ok(Self { + inner: Arc::new(inner), + }) + } + + /// Update the registration chain. + pub fn update( + &self, point: Point, tx_idx: usize, txn: &MultiEraTx, cip509: Cip509, + ) -> anyhow::Result { + let new_inner = self.inner.update(point, tx_idx, txn, cip509)?; + + Ok(Self { + inner: Arc::new(new_inner), + }) + } + + /// Get the registration chain inner. + pub fn registration_chain(&self) -> &RegistrationChainInner { + self.inner.as_ref() + } +} /// Inner structure of registration chain. #[derive(Clone)] -pub struct RegistrationChainInner { +struct RegistrationChainInner { /// The current transaction ID hash (32 bytes) current_tx_id_hash: Hash<32>, /// List of purpose for this registration chain @@ -57,7 +89,6 @@ pub struct RegistrationChainInner { } /// Point (slot) and transaction index. -#[allow(dead_code)] #[derive(Clone)] pub(crate) struct PointTxIdx((Point, usize)); @@ -69,9 +100,8 @@ impl PointTxIdx { } /// Payment history of the public key in tracking payment keys. -#[allow(dead_code)] #[derive(Clone)] -pub struct PaymentHistory { +struct PaymentHistory { /// The point and transaction index. point_tx_idx: PointTxIdx, /// Transaction hash that this payment come from. @@ -82,10 +112,31 @@ pub struct PaymentHistory { value: Value, } +impl PaymentHistory { + /// Get the point and transaction index. + pub fn point_tx_idx(&self) -> &PointTxIdx { + &self.point_tx_idx + } + + /// Get the transaction hash. + pub fn tx_hash(&self) -> Hash<32> { + self.tx_hash + } + + /// Get the transaction output index. + pub fn output_index(&self) -> u16 { + self.output_index + } + + /// Get the value of the payment. + pub fn value(&self) -> &Value { + &self.value + } +} + /// Role data -#[allow(dead_code)] #[derive(Clone)] -pub struct RoleData { +struct RoleData { /// List of reference of signing keys to the data within registration. signing_key_ref: Vec, /// List of reference of encryption keys to the data within registration. @@ -96,6 +147,28 @@ pub struct RoleData { role_extended_data: HashMap>, } +impl RoleData { + /// Get the reference of signing keys. + pub fn signing_key_ref(&self) -> &[KeyLocalRef] { + &self.signing_key_ref + } + + /// Get the reference of encryption keys. + pub fn encryption_ref(&self) -> &[KeyLocalRef] { + &self.encryption_ref + } + + /// Get the payment key. + pub fn payment_key(&self) -> &Ed25519PublicKey { + &self.payment_key + } + + /// Get the role extended data. + pub fn role_extended_data(&self) -> &HashMap> { + &self.role_extended_data + } +} + impl RegistrationChainInner { /// Create a new instance of registration chain. /// The first new value should be the chain root. @@ -110,8 +183,7 @@ impl RegistrationChainInner { /// # Errors /// /// Returns an error if data is invalid - #[allow(dead_code)] - pub fn new( + fn new( cip509: Cip509, tracking_payment_keys: Vec, point: Point, tx_idx: usize, txn: &MultiEraTx, ) -> anyhow::Result { @@ -171,7 +243,6 @@ impl RegistrationChainInner { /// # Errors /// /// Returns an error if data is invalid - #[allow(dead_code)] pub fn update( &self, point: Point, tx_idx: usize, txn: &MultiEraTx, cip509: Cip509, ) -> anyhow::Result { @@ -227,10 +298,45 @@ impl RegistrationChainInner { Ok(new_inner) } + + pub fn current_tx_id_hash(&self) -> Hash<32> { + self.current_tx_id_hash + } + + pub fn purpose(&self) -> &[UuidV4] { + &self.purpose + } + + pub fn x509_certs(&self) -> &HashMap)> { + &self.x509_certs + } + + pub fn c509_certs(&self) -> &HashMap { + &self.c509_certs + } + + pub fn simple_keys(&self) -> &HashMap { + &self.simple_keys + } + + pub fn revocations(&self) -> &[(PointTxIdx, CertKeyHash)] { + &self.revocations + } + + pub fn role_data(&self) -> &HashMap { + &self.role_data + } + + pub fn tracking_payment_keys(&self) -> &Vec { + &self.tracking_payment_keys + } + + pub fn payment_history(&self) -> &HashMap> { + &self.payment_history + } } /// Process x509 certificate for chain root. -#[allow(dead_code)] fn chain_root_x509_certs( x509_certs: Option>, point_tx_idx: &PointTxIdx, ) -> HashMap)> { @@ -247,7 +353,6 @@ fn chain_root_x509_certs( } /// Update x509 certificates in the registration chain. -#[allow(dead_code)] fn update_x509_certs( new_inner: &mut RegistrationChainInner, x509_certs: Option>, point_tx_idx: &PointTxIdx, @@ -273,7 +378,6 @@ fn update_x509_certs( } /// Process c509 certificates for chain root. -#[allow(dead_code)] fn chain_root_c509_certs( c509_certs: Option>, point_tx_idx: &PointTxIdx, ) -> HashMap { @@ -290,7 +394,6 @@ fn chain_root_c509_certs( } /// Update c509 certificates in the registration chain. -#[allow(dead_code)] fn update_c509_certs( new_inner: &mut RegistrationChainInner, c509_certs: Option>, point_tx_idx: &PointTxIdx, @@ -321,7 +424,6 @@ fn update_c509_certs( } /// Process public keys for chain root. -#[allow(dead_code)] fn chain_root_public_keys( pub_keys: Option>, point_tx_idx: &PointTxIdx, ) -> HashMap { @@ -338,7 +440,6 @@ fn chain_root_public_keys( } /// Update public keys in the registration chain. -#[allow(dead_code)] fn update_public_keys( new_inner: &mut RegistrationChainInner, pub_keys: Option>, point_tx_idx: &PointTxIdx, @@ -364,7 +465,6 @@ fn update_public_keys( } /// Process the revocation list. -#[allow(dead_code)] fn revocations_list( revocation_list: Option>, point_tx_idx: &PointTxIdx, ) -> Vec<(PointTxIdx, CertKeyHash)> { @@ -378,7 +478,6 @@ fn revocations_list( } /// Process the role data for chain root. -#[allow(dead_code)] fn chain_root_role_data( role_set: Option>, txn: &MultiEraTx, point_tx_idx: &PointTxIdx, @@ -395,12 +494,15 @@ fn chain_root_role_data( // Map of role number to point and role data role_data_map.insert( role_data.role_number, - (point_tx_idx.clone(), RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }), + ( + point_tx_idx.clone(), + RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }, + ), ); } } @@ -408,7 +510,6 @@ fn chain_root_role_data( } /// Update the role data in the registration chain. -#[allow(dead_code)] fn update_role_data( inner: &mut RegistrationChainInner, role_set: Option>, txn: &MultiEraTx, point_tx_idx: &PointTxIdx, @@ -436,12 +537,15 @@ fn update_role_data( // Note that new role data will overwrite the old one inner.role_data.insert( role_data.role_number, - (point_tx_idx.clone(), RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }), + ( + point_tx_idx.clone(), + RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }, + ), ); } } From 3e569027afad86c7921a3cb1d8b2f5f6154defe1 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 27 Nov 2024 12:24:13 +0700 Subject: [PATCH 3/7] fix: format Signed-off-by: bkioshn --- .../src/registration/cardano.rs | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/rust/rbac-registration/src/registration/cardano.rs b/rust/rbac-registration/src/registration/cardano.rs index 38e82730f43..05fed353e6e 100644 --- a/rust/rbac-registration/src/registration/cardano.rs +++ b/rust/rbac-registration/src/registration/cardano.rs @@ -494,15 +494,12 @@ fn chain_root_role_data( // Map of role number to point and role data role_data_map.insert( role_data.role_number, - ( - point_tx_idx.clone(), - RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }, - ), + (point_tx_idx.clone(), RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }), ); } } @@ -537,15 +534,12 @@ fn update_role_data( // Note that new role data will overwrite the old one inner.role_data.insert( role_data.role_number, - ( - point_tx_idx.clone(), - RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }, - ), + (point_tx_idx.clone(), RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }), ); } } From b8b3882b3071a9168957b28b13600d2f28d128fd Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 27 Nov 2024 14:59:38 +0700 Subject: [PATCH 4/7] fix: comment Signed-off-by: bkioshn --- .../src/registration/cardano.rs | 70 +++++++++++++++++-- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/rust/rbac-registration/src/registration/cardano.rs b/rust/rbac-registration/src/registration/cardano.rs index 05fed353e6e..9a200d73d67 100644 --- a/rust/rbac-registration/src/registration/cardano.rs +++ b/rust/rbac-registration/src/registration/cardano.rs @@ -28,11 +28,24 @@ use crate::{ /// Registration chains. pub struct RegistrationChain { + /// Inner part of the registration chain. inner: Arc, } impl RegistrationChain { /// Create a new instance of registration chain. + /// The first new value should be the chain root. + /// + /// # Arguments + /// - `cip509` - The CIP509. + /// - `tracking_payment_keys` - The list of payment keys to track. + /// - `point` - The point (slot) of the transaction. + /// - `tx_idx` - The transaction index. + /// - `txn` - The transaction. + /// + /// # Errors + /// + /// Returns an error if data is invalid pub fn new( &self, point: Point, tracking_payment_keys: Vec, tx_idx: usize, txn: &MultiEraTx, cip509: Cip509, @@ -45,6 +58,16 @@ impl RegistrationChain { } /// Update the registration chain. + /// + /// # Arguments + /// - `point` - The point (slot) of the transaction. + /// - `tx_idx` - The transaction index. + /// - `txn` - The transaction. + /// - `cip509` - The CIP509. + /// + /// # Errors + /// + /// Returns an error if data is invalid pub fn update( &self, point: Point, tx_idx: usize, txn: &MultiEraTx, cip509: Cip509, ) -> anyhow::Result { @@ -56,6 +79,7 @@ impl RegistrationChain { } /// Get the registration chain inner. + #[must_use] pub fn registration_chain(&self) -> &RegistrationChainInner { self.inner.as_ref() } @@ -63,7 +87,7 @@ impl RegistrationChain { /// Inner structure of registration chain. #[derive(Clone)] -struct RegistrationChainInner { +pub struct RegistrationChainInner { /// The current transaction ID hash (32 bytes) current_tx_id_hash: Hash<32>, /// List of purpose for this registration chain @@ -90,18 +114,30 @@ struct RegistrationChainInner { /// Point (slot) and transaction index. #[derive(Clone)] -pub(crate) struct PointTxIdx((Point, usize)); +pub struct PointTxIdx((Point, usize)); impl PointTxIdx { /// Create an instance of point and transaction index. pub(crate) fn new(point: Point, tx_idx: usize) -> Self { PointTxIdx((point, tx_idx)) } + + /// Get the point. + #[must_use] + pub fn point(&self) -> &Point { + &self.0 .0 + } + + /// Get the transaction index. + #[must_use] + pub fn tx_idx(&self) -> usize { + self.0 .1 + } } /// Payment history of the public key in tracking payment keys. #[derive(Clone)] -struct PaymentHistory { +pub struct PaymentHistory { /// The point and transaction index. point_tx_idx: PointTxIdx, /// Transaction hash that this payment come from. @@ -114,21 +150,25 @@ struct PaymentHistory { impl PaymentHistory { /// Get the point and transaction index. + #[must_use] pub fn point_tx_idx(&self) -> &PointTxIdx { &self.point_tx_idx } /// Get the transaction hash. + #[must_use] pub fn tx_hash(&self) -> Hash<32> { self.tx_hash } /// Get the transaction output index. + #[must_use] pub fn output_index(&self) -> u16 { self.output_index } /// Get the value of the payment. + #[must_use] pub fn value(&self) -> &Value { &self.value } @@ -136,7 +176,7 @@ impl PaymentHistory { /// Role data #[derive(Clone)] -struct RoleData { +pub struct RoleData { /// List of reference of signing keys to the data within registration. signing_key_ref: Vec, /// List of reference of encryption keys to the data within registration. @@ -149,21 +189,25 @@ struct RoleData { impl RoleData { /// Get the reference of signing keys. + #[must_use] pub fn signing_key_ref(&self) -> &[KeyLocalRef] { &self.signing_key_ref } /// Get the reference of encryption keys. + #[must_use] pub fn encryption_ref(&self) -> &[KeyLocalRef] { &self.encryption_ref } /// Get the payment key. + #[must_use] pub fn payment_key(&self) -> &Ed25519PublicKey { &self.payment_key } /// Get the role extended data. + #[must_use] pub fn role_extended_data(&self) -> &HashMap> { &self.role_extended_data } @@ -299,38 +343,56 @@ impl RegistrationChainInner { Ok(new_inner) } + /// Get the current transaction ID hash. + #[must_use] pub fn current_tx_id_hash(&self) -> Hash<32> { self.current_tx_id_hash } + /// Get a list of purpose for this registration chain. + #[must_use] pub fn purpose(&self) -> &[UuidV4] { &self.purpose } + /// Get the map of index in array to point, transaction index, and x509 certificate. + #[must_use] pub fn x509_certs(&self) -> &HashMap)> { &self.x509_certs } + /// Get the map of index in array to point, transaction index, and c509 certificate. + #[must_use] pub fn c509_certs(&self) -> &HashMap { &self.c509_certs } + /// Get the map of index in array to point, transaction index, and public key. + #[must_use] pub fn simple_keys(&self) -> &HashMap { &self.simple_keys } + /// Get a list of revocations. + #[must_use] pub fn revocations(&self) -> &[(PointTxIdx, CertKeyHash)] { &self.revocations } + /// Get the map of role number to point, transaction index, and role data. + #[must_use] pub fn role_data(&self) -> &HashMap { &self.role_data } + /// Get the list of payment keys to track. + #[must_use] pub fn tracking_payment_keys(&self) -> &Vec { &self.tracking_payment_keys } + /// Get the map of payment key to its history. + #[must_use] pub fn payment_history(&self) -> &HashMap> { &self.payment_history } From 672a1d6f63ebbeb27d276990cde8af72f9b2a6c8 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Fri, 29 Nov 2024 11:43:38 +0700 Subject: [PATCH 5/7] fix: signing and encryption key Signed-off-by: bkioshn --- .../src/registration/cardano.rs | 68 +++++++++++-------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/rust/rbac-registration/src/registration/cardano.rs b/rust/rbac-registration/src/registration/cardano.rs index 9a200d73d67..e164ca738ae 100644 --- a/rust/rbac-registration/src/registration/cardano.rs +++ b/rust/rbac-registration/src/registration/cardano.rs @@ -177,10 +177,10 @@ impl PaymentHistory { /// Role data #[derive(Clone)] pub struct RoleData { - /// List of reference of signing keys to the data within registration. - signing_key_ref: Vec, - /// List of reference of encryption keys to the data within registration. - encryption_ref: Vec, + /// A signing keys to the data within registration. + signing_key_ref: Option, + /// An encryption keys to the data within registration. + encryption_ref: Option, /// A payment key where reward will be distributed to. payment_key: Ed25519PublicKey, /// Map of role extended data (10-99) to its data @@ -190,13 +190,13 @@ pub struct RoleData { impl RoleData { /// Get the reference of signing keys. #[must_use] - pub fn signing_key_ref(&self) -> &[KeyLocalRef] { + pub fn signing_key_ref(&self) -> &Option { &self.signing_key_ref } /// Get the reference of encryption keys. #[must_use] - pub fn encryption_ref(&self) -> &[KeyLocalRef] { + pub fn encryption_ref(&self) -> &Option { &self.encryption_ref } @@ -547,8 +547,8 @@ fn chain_root_role_data( let mut role_data_map = HashMap::new(); if let Some(role_set_data) = role_set { for role_data in role_set_data { - let signing_key = role_data.role_signing_key.clone().unwrap_or_default(); - let encryption_key = role_data.role_encryption_key.clone().unwrap_or_default(); + let signing_key = role_data.role_signing_key.clone(); + let encryption_key = role_data.role_encryption_key.clone(); // Get the payment key let payment_key = get_payment_key_from_tx(txn, role_data.payment_key)?; @@ -556,12 +556,15 @@ fn chain_root_role_data( // Map of role number to point and role data role_data_map.insert( role_data.role_number, - (point_tx_idx.clone(), RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }), + ( + point_tx_idx.clone(), + RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }, + ), ); } } @@ -576,32 +579,37 @@ fn update_role_data( if let Some(role_set_data) = role_set { for role_data in role_set_data { // If there is new role singing key, use it, else use the old one - let signing_key = role_data.role_signing_key.unwrap_or_else(|| { - match inner.role_data.get(&role_data.role_number) { + let signing_key = match role_data.role_signing_key { + Some(key) => Some(key), + None => match inner.role_data.get(&role_data.role_number) { Some((_, role_data)) => role_data.signing_key_ref.clone(), - None => Vec::new(), - } - }); + None => None, + }, + }; // If there is new role encryption key, use it, else use the old one - let encryption_key = role_data.role_encryption_key.unwrap_or_else(|| { - match inner.role_data.get(&role_data.role_number) { + let encryption_key = match role_data.role_encryption_key { + Some(key) => Some(key), + None => match inner.role_data.get(&role_data.role_number) { Some((_, role_data)) => role_data.encryption_ref.clone(), - None => Vec::new(), - } - }); + None => None, + }, + }; let payment_key = get_payment_key_from_tx(txn, role_data.payment_key)?; // Map of role number to point and role data // Note that new role data will overwrite the old one inner.role_data.insert( role_data.role_number, - (point_tx_idx.clone(), RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }), + ( + point_tx_idx.clone(), + RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }, + ), ); } } From 7aa17548d9d2b5d63e310c2b0552dc724a0eb2c5 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Fri, 29 Nov 2024 14:38:02 +0700 Subject: [PATCH 6/7] chore: fix format Signed-off-by: bkioshn --- .../src/registration/cardano.rs | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/rust/rbac-registration/src/registration/cardano.rs b/rust/rbac-registration/src/registration/cardano.rs index e164ca738ae..d73518cfeca 100644 --- a/rust/rbac-registration/src/registration/cardano.rs +++ b/rust/rbac-registration/src/registration/cardano.rs @@ -556,15 +556,12 @@ fn chain_root_role_data( // Map of role number to point and role data role_data_map.insert( role_data.role_number, - ( - point_tx_idx.clone(), - RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }, - ), + (point_tx_idx.clone(), RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }), ); } } @@ -581,18 +578,22 @@ fn update_role_data( // If there is new role singing key, use it, else use the old one let signing_key = match role_data.role_signing_key { Some(key) => Some(key), - None => match inner.role_data.get(&role_data.role_number) { - Some((_, role_data)) => role_data.signing_key_ref.clone(), - None => None, + None => { + match inner.role_data.get(&role_data.role_number) { + Some((_, role_data)) => role_data.signing_key_ref.clone(), + None => None, + } }, }; // If there is new role encryption key, use it, else use the old one let encryption_key = match role_data.role_encryption_key { Some(key) => Some(key), - None => match inner.role_data.get(&role_data.role_number) { - Some((_, role_data)) => role_data.encryption_ref.clone(), - None => None, + None => { + match inner.role_data.get(&role_data.role_number) { + Some((_, role_data)) => role_data.encryption_ref.clone(), + None => None, + } }, }; let payment_key = get_payment_key_from_tx(txn, role_data.payment_key)?; @@ -601,15 +602,12 @@ fn update_role_data( // Note that new role data will overwrite the old one inner.role_data.insert( role_data.role_number, - ( - point_tx_idx.clone(), - RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }, - ), + (point_tx_idx.clone(), RoleData { + signing_key_ref: signing_key, + encryption_ref: encryption_key, + payment_key, + role_extended_data: role_data.role_extended_data_keys.clone(), + }), ); } } From 4050ab9e6b32730f0936ea5dfb89d2002b8dc30a Mon Sep 17 00:00:00 2001 From: bkioshn Date: Fri, 29 Nov 2024 16:47:10 +0700 Subject: [PATCH 7/7] fix: move struct to its own file and private the inner regis Signed-off-by: bkioshn --- .../{cardano.rs => cardano/mod.rs} | 269 ++++++------------ .../registration/cardano/payment_history.rs | 56 ++++ .../src/registration/cardano/point_tx_idx.rs | 26 ++ .../src/registration/cardano/role_data.rs | 57 ++++ 4 files changed, 225 insertions(+), 183 deletions(-) rename rust/rbac-registration/src/registration/{cardano.rs => cardano/mod.rs} (83%) create mode 100644 rust/rbac-registration/src/registration/cardano/payment_history.rs create mode 100644 rust/rbac-registration/src/registration/cardano/point_tx_idx.rs create mode 100644 rust/rbac-registration/src/registration/cardano/role_data.rs diff --git a/rust/rbac-registration/src/registration/cardano.rs b/rust/rbac-registration/src/registration/cardano/mod.rs similarity index 83% rename from rust/rbac-registration/src/registration/cardano.rs rename to rust/rbac-registration/src/registration/cardano/mod.rs index d73518cfeca..318772903a2 100644 --- a/rust/rbac-registration/src/registration/cardano.rs +++ b/rust/rbac-registration/src/registration/cardano/mod.rs @@ -1,15 +1,20 @@ //! Chain of Cardano registration data +pub mod payment_history; +pub mod point_tx_idx; +pub mod role_data; + use std::{collections::HashMap, sync::Arc}; use anyhow::bail; use c509_certificate::c509::C509; use pallas::{ - codec::utils::Bytes, - crypto::hash::Hash, - ledger::{primitives::conway::Value, traverse::MultiEraTx}, + codec::utils::Bytes, crypto::hash::Hash, ledger::traverse::MultiEraTx, network::miniprotocols::Point, }; +use payment_history::PaymentHistory; +use point_tx_idx::PointTxIdx; +use role_data::RoleData; use tracing::error; use crate::{ @@ -18,7 +23,6 @@ use crate::{ rbac::{ certs::{C509Cert, X509DerCert}, pub_key::{Ed25519PublicKey, SimplePublicKeyType}, - role_data::KeyLocalRef, CertKeyHash, }, Cip509, UuidV4, @@ -78,139 +82,86 @@ impl RegistrationChain { }) } - /// Get the registration chain inner. + /// Get the current transaction ID hash. #[must_use] - pub fn registration_chain(&self) -> &RegistrationChainInner { - self.inner.as_ref() - } -} - -/// Inner structure of registration chain. -#[derive(Clone)] -pub struct RegistrationChainInner { - /// The current transaction ID hash (32 bytes) - current_tx_id_hash: Hash<32>, - /// List of purpose for this registration chain - purpose: Vec, - - // RBAC - /// Map of index in array to point, transaction index, and x509 certificate. - x509_certs: HashMap)>, - /// Map of index in array to point, transaction index, and c509 certificate. - c509_certs: HashMap, - /// Map of index in array to point, transaction index, and public key. - simple_keys: HashMap, - /// List of point, transaction index, and certificate key hash. - revocations: Vec<(PointTxIdx, CertKeyHash)>, - - // Role - /// Map of role number to point, transaction index, and role data. - role_data: HashMap, - /// List of payment keys to track. - tracking_payment_keys: Arc>, - /// Map of payment key to its history. - payment_history: HashMap>, -} - -/// Point (slot) and transaction index. -#[derive(Clone)] -pub struct PointTxIdx((Point, usize)); - -impl PointTxIdx { - /// Create an instance of point and transaction index. - pub(crate) fn new(point: Point, tx_idx: usize) -> Self { - PointTxIdx((point, tx_idx)) + pub fn current_tx_id_hash(&self) -> Hash<32> { + self.inner.current_tx_id_hash } - /// Get the point. + /// Get a list of purpose for this registration chain. #[must_use] - pub fn point(&self) -> &Point { - &self.0 .0 + pub fn purpose(&self) -> &[UuidV4] { + &self.inner.purpose } - /// Get the transaction index. + /// Get the map of index in array to point, transaction index, and x509 certificate. #[must_use] - pub fn tx_idx(&self) -> usize { - self.0 .1 + pub fn x509_certs(&self) -> &HashMap)> { + &self.inner.x509_certs } -} - -/// Payment history of the public key in tracking payment keys. -#[derive(Clone)] -pub struct PaymentHistory { - /// The point and transaction index. - point_tx_idx: PointTxIdx, - /// Transaction hash that this payment come from. - tx_hash: Hash<32>, - /// The transaction output index that this payment come from. - output_index: u16, - /// The value of the payment. - value: Value, -} -impl PaymentHistory { - /// Get the point and transaction index. + /// Get the map of index in array to point, transaction index, and c509 certificate. #[must_use] - pub fn point_tx_idx(&self) -> &PointTxIdx { - &self.point_tx_idx + pub fn c509_certs(&self) -> &HashMap { + &self.inner.c509_certs } - /// Get the transaction hash. + /// Get the map of index in array to point, transaction index, and public key. #[must_use] - pub fn tx_hash(&self) -> Hash<32> { - self.tx_hash + pub fn simple_keys(&self) -> &HashMap { + &self.inner.simple_keys } - /// Get the transaction output index. + /// Get a list of revocations. #[must_use] - pub fn output_index(&self) -> u16 { - self.output_index + pub fn revocations(&self) -> &[(PointTxIdx, CertKeyHash)] { + &self.inner.revocations } - /// Get the value of the payment. + /// Get the map of role number to point, transaction index, and role data. #[must_use] - pub fn value(&self) -> &Value { - &self.value + pub fn role_data(&self) -> &HashMap { + &self.inner.role_data } -} - -/// Role data -#[derive(Clone)] -pub struct RoleData { - /// A signing keys to the data within registration. - signing_key_ref: Option, - /// An encryption keys to the data within registration. - encryption_ref: Option, - /// A payment key where reward will be distributed to. - payment_key: Ed25519PublicKey, - /// Map of role extended data (10-99) to its data - role_extended_data: HashMap>, -} -impl RoleData { - /// Get the reference of signing keys. + /// Get the list of payment keys to track. #[must_use] - pub fn signing_key_ref(&self) -> &Option { - &self.signing_key_ref + pub fn tracking_payment_keys(&self) -> &Vec { + &self.inner.tracking_payment_keys } - /// Get the reference of encryption keys. + /// Get the map of payment key to its history. #[must_use] - pub fn encryption_ref(&self) -> &Option { - &self.encryption_ref + pub fn payment_history(&self) -> &HashMap> { + &self.inner.payment_history } +} - /// Get the payment key. - #[must_use] - pub fn payment_key(&self) -> &Ed25519PublicKey { - &self.payment_key - } +/// Inner structure of registration chain. +#[derive(Clone)] +struct RegistrationChainInner { + /// The current transaction ID hash (32 bytes) + current_tx_id_hash: Hash<32>, + /// List of purpose for this registration chain + purpose: Vec, - /// Get the role extended data. - #[must_use] - pub fn role_extended_data(&self) -> &HashMap> { - &self.role_extended_data - } + // RBAC + /// Map of index in array to point, transaction index, and x509 certificate. + x509_certs: HashMap)>, + /// Map of index in array to point, transaction index, and c509 certificate. + c509_certs: HashMap, + /// Map of index in array to point, transaction index, and public key. + simple_keys: HashMap, + /// List of point, transaction index, and certificate key hash. + revocations: Vec<(PointTxIdx, CertKeyHash)>, + + // Role + /// Map of role number to point, transaction index, and role data. + role_data: HashMap, + /// List of payment keys to track. + tracking_payment_keys: Arc>, + /// Map of payment key to its history. + payment_history: HashMap>, } impl RegistrationChainInner { @@ -287,7 +238,7 @@ impl RegistrationChainInner { /// # Errors /// /// Returns an error if data is invalid - pub fn update( + fn update( &self, point: Point, tx_idx: usize, txn: &MultiEraTx, cip509: Cip509, ) -> anyhow::Result { let mut new_inner = self.clone(); @@ -342,60 +293,6 @@ impl RegistrationChainInner { Ok(new_inner) } - - /// Get the current transaction ID hash. - #[must_use] - pub fn current_tx_id_hash(&self) -> Hash<32> { - self.current_tx_id_hash - } - - /// Get a list of purpose for this registration chain. - #[must_use] - pub fn purpose(&self) -> &[UuidV4] { - &self.purpose - } - - /// Get the map of index in array to point, transaction index, and x509 certificate. - #[must_use] - pub fn x509_certs(&self) -> &HashMap)> { - &self.x509_certs - } - - /// Get the map of index in array to point, transaction index, and c509 certificate. - #[must_use] - pub fn c509_certs(&self) -> &HashMap { - &self.c509_certs - } - - /// Get the map of index in array to point, transaction index, and public key. - #[must_use] - pub fn simple_keys(&self) -> &HashMap { - &self.simple_keys - } - - /// Get a list of revocations. - #[must_use] - pub fn revocations(&self) -> &[(PointTxIdx, CertKeyHash)] { - &self.revocations - } - - /// Get the map of role number to point, transaction index, and role data. - #[must_use] - pub fn role_data(&self) -> &HashMap { - &self.role_data - } - - /// Get the list of payment keys to track. - #[must_use] - pub fn tracking_payment_keys(&self) -> &Vec { - &self.tracking_payment_keys - } - - /// Get the map of payment key to its history. - #[must_use] - pub fn payment_history(&self) -> &HashMap> { - &self.payment_history - } } /// Process x509 certificate for chain root. @@ -556,12 +453,15 @@ fn chain_root_role_data( // Map of role number to point and role data role_data_map.insert( role_data.role_number, - (point_tx_idx.clone(), RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }), + ( + point_tx_idx.clone(), + RoleData::new( + signing_key, + encryption_key, + payment_key, + role_data.role_extended_data_keys.clone(), + ), + ), ); } } @@ -580,7 +480,7 @@ fn update_role_data( Some(key) => Some(key), None => { match inner.role_data.get(&role_data.role_number) { - Some((_, role_data)) => role_data.signing_key_ref.clone(), + Some((_, role_data)) => role_data.signing_key_ref().clone(), None => None, } }, @@ -591,7 +491,7 @@ fn update_role_data( Some(key) => Some(key), None => { match inner.role_data.get(&role_data.role_number) { - Some((_, role_data)) => role_data.encryption_ref.clone(), + Some((_, role_data)) => role_data.encryption_ref().clone(), None => None, } }, @@ -602,12 +502,15 @@ fn update_role_data( // Note that new role data will overwrite the old one inner.role_data.insert( role_data.role_number, - (point_tx_idx.clone(), RoleData { - signing_key_ref: signing_key, - encryption_ref: encryption_key, - payment_key, - role_extended_data: role_data.role_extended_data_keys.clone(), - }), + ( + point_tx_idx.clone(), + RoleData::new( + signing_key, + encryption_key, + payment_key, + role_data.role_extended_data_keys.clone(), + ), + ), ); } } @@ -668,12 +571,12 @@ fn update_payment_history( anyhow::anyhow!("Cannot convert usize to u16 in update payment history") })?; - payment_history.push(PaymentHistory { - point_tx_idx: point_tx_idx.clone(), - tx_hash: txn.hash(), + payment_history.push(PaymentHistory::new( + point_tx_idx.clone(), + txn.hash(), output_index, - value: o.value.clone(), - }); + o.value.clone(), + )); } }, pallas::ledger::primitives::conway::PseudoTransactionOutput::Legacy(_) => { diff --git a/rust/rbac-registration/src/registration/cardano/payment_history.rs b/rust/rbac-registration/src/registration/cardano/payment_history.rs new file mode 100644 index 00000000000..13e4aabc5d5 --- /dev/null +++ b/rust/rbac-registration/src/registration/cardano/payment_history.rs @@ -0,0 +1,56 @@ +//! Payment history of the public key in tracking payment keys. + +use pallas::{crypto::hash::Hash, ledger::primitives::conway::Value}; + +use super::point_tx_idx::PointTxIdx; + +/// Payment history of the public key in tracking payment keys. +#[derive(Clone)] +pub struct PaymentHistory { + /// The point and transaction index. + point_tx_idx: PointTxIdx, + /// Transaction hash that this payment come from. + tx_hash: Hash<32>, + /// The transaction output index that this payment come from. + output_index: u16, + /// The value of the payment. + value: Value, +} + +impl PaymentHistory { + /// Create an instance of payment history. + pub(crate) fn new( + point_tx_idx: PointTxIdx, tx_hash: Hash<32>, output_index: u16, value: Value, + ) -> Self { + PaymentHistory { + point_tx_idx, + tx_hash, + output_index, + value, + } + } + + /// Get the point and transaction index. + #[must_use] + pub fn point_tx_idx(&self) -> &PointTxIdx { + &self.point_tx_idx + } + + /// Get the transaction hash. + #[must_use] + pub fn tx_hash(&self) -> Hash<32> { + self.tx_hash + } + + /// Get the transaction output index. + #[must_use] + pub fn output_index(&self) -> u16 { + self.output_index + } + + /// Get the value of the payment. + #[must_use] + pub fn value(&self) -> &Value { + &self.value + } +} diff --git a/rust/rbac-registration/src/registration/cardano/point_tx_idx.rs b/rust/rbac-registration/src/registration/cardano/point_tx_idx.rs new file mode 100644 index 00000000000..27247dd5c2f --- /dev/null +++ b/rust/rbac-registration/src/registration/cardano/point_tx_idx.rs @@ -0,0 +1,26 @@ +//! Point or absolute slot and transaction index. + +use pallas::network::miniprotocols::Point; + +/// Point (slot) and transaction index. +#[derive(Clone)] +pub struct PointTxIdx((Point, usize)); + +impl PointTxIdx { + /// Create an instance of point and transaction index. + pub(crate) fn new(point: Point, tx_idx: usize) -> Self { + PointTxIdx((point, tx_idx)) + } + + /// Get the point. + #[must_use] + pub fn point(&self) -> &Point { + &self.0 .0 + } + + /// Get the transaction index. + #[must_use] + pub fn tx_idx(&self) -> usize { + self.0 .1 + } +} diff --git a/rust/rbac-registration/src/registration/cardano/role_data.rs b/rust/rbac-registration/src/registration/cardano/role_data.rs new file mode 100644 index 00000000000..684671415e7 --- /dev/null +++ b/rust/rbac-registration/src/registration/cardano/role_data.rs @@ -0,0 +1,57 @@ +//! RBAC role data + +use std::collections::HashMap; + +use crate::cardano::cip509::rbac::{pub_key::Ed25519PublicKey, role_data::KeyLocalRef}; + +/// Role data +#[derive(Clone)] +pub struct RoleData { + /// A signing keys to the data within registration. + signing_key_ref: Option, + /// An encryption keys to the data within registration. + encryption_ref: Option, + /// A payment key where reward will be distributed to. + payment_key: Ed25519PublicKey, + /// Map of role extended data (10-99) to its data + role_extended_data: HashMap>, +} + +impl RoleData { + /// Create an instance of role data. + pub(crate) fn new( + signing_key_ref: Option, encryption_ref: Option, + payment_key: Ed25519PublicKey, role_extended_data: HashMap>, + ) -> Self { + RoleData { + signing_key_ref, + encryption_ref, + payment_key, + role_extended_data, + } + } + + /// Get the reference of signing keys. + #[must_use] + pub fn signing_key_ref(&self) -> &Option { + &self.signing_key_ref + } + + /// Get the reference of encryption keys. + #[must_use] + pub fn encryption_ref(&self) -> &Option { + &self.encryption_ref + } + + /// Get the payment key. + #[must_use] + pub fn payment_key(&self) -> &Ed25519PublicKey { + &self.payment_key + } + + /// Get the role extended data. + #[must_use] + pub fn role_extended_data(&self) -> &HashMap> { + &self.role_extended_data + } +}