Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rust/rbac-registration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ thiserror = "2.0.11"

c509-certificate = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "c509-certificate-v0.0.3" }
cbork-utils = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cbork-utils-v0.0.2" }
cardano-blockchain-types = { version = "0.0.8", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cardano-blockchain-types/v0.0.8" }
cardano-blockchain-types = { version = "0.0.9", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cardano-blockchain-types/v0.0.9" }
catalyst-types = { version = "0.0.10", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.10" }
102 changes: 67 additions & 35 deletions rust/rbac-registration/src/cardano/cip509/cip509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{

use anyhow::{Context, anyhow};
use cardano_blockchain_types::{
MetadatumLabel, MultiEraBlock, TxnIndex,
MetadatumLabel, MultiEraBlock, StakeAddress, TxnIndex,
hashes::{BLAKE_2B256_SIZE, Blake2b256Hash, TransactionId},
pallas_addresses::{Address, ShelleyAddress},
pallas_primitives::{Nullable, conway},
Expand All @@ -22,6 +22,7 @@ use catalyst_types::{
uuid::UuidV4,
};
use cbork_utils::decode_helper::{decode_bytes, decode_helper, decode_map_len};
use ed25519_dalek::VerifyingKey;
use minicbor::{
Decode, Decoder,
decode::{self},
Expand All @@ -31,8 +32,9 @@ use tracing::warn;
use uuid::Uuid;

use crate::cardano::cip509::{
Payment, PointTxnIdx, RoleData,
C509Cert, LocalRefInt, Payment, PointTxnIdx, RoleData, SimplePublicKeyType, X509DerCert,
decode_context::DecodeContext,
extract_key,
rbac::Cip509RbacMetadata,
types::{PaymentHistory, TxInputHash, ValidationSignature},
utils::Cip0134UriSet,
Expand Down Expand Up @@ -80,7 +82,8 @@ pub struct Cip509 {
origin: PointTxnIdx,
/// A catalyst ID.
///
/// This field is only present in role 0 registrations.
/// This field is only present in role 0 registrations and only for the first
/// registration, which defines a `CatalystId` for the chain.
catalyst_id: Option<CatalystId>,
/// Raw aux data associated with the transaction that CIP509 is attached to,
raw_aux_data: Vec<u8>,
Expand Down Expand Up @@ -180,6 +183,12 @@ impl Cip509 {
validate_self_sign_cert(metadata, &report);
}

// We want to keep `catalyst_id` field only for the first registration,
// which starts a new chain
if cip509.prv_tx_id.is_some() {
cip509.catalyst_id = None;
}

Ok(Some(cip509))
}

Expand Down Expand Up @@ -227,6 +236,48 @@ impl Cip509 {
self.metadata.as_ref().and_then(|m| m.role_data.get(&role))
}

/// Returns signing public key for a role.
/// Would return only signing public keys for the present certificates,
/// if certificate marked as deleted or undefined it would be skipped.
#[must_use]
pub fn signing_public_key_for_role(
&self,
role: RoleId,
) -> Option<VerifyingKey> {
self.metadata.as_ref().and_then(|m| {
let key_ref = m.role_data.get(&role).and_then(|d| d.signing_key())?;
match key_ref.local_ref {
LocalRefInt::X509Certs => {
m.x509_certs.get(key_ref.key_offset).and_then(|c| {
if let X509DerCert::X509Cert(c) = c {
extract_key::x509_key(c).ok()
} else {
None
}
})
},
LocalRefInt::C509Certs => {
m.c509_certs.get(key_ref.key_offset).and_then(|c| {
if let C509Cert::C509Certificate(c) = c {
extract_key::c509_key(c).ok()
} else {
None
}
})
},
LocalRefInt::PubKeys => {
m.pub_keys.get(key_ref.key_offset).and_then(|c| {
if let SimplePublicKeyType::Ed25519(c) = c {
Some(*c)
} else {
None
}
})
},
}
})
}

/// Returns a purpose of this registration.
#[must_use]
pub fn purpose(&self) -> Option<UuidV4> {
Expand Down Expand Up @@ -269,24 +320,13 @@ impl Cip509 {
self.txn_inputs_hash.as_ref()
}

/// Returns a Catalyst ID of this registration if role 0 is present.
/// Returns a Catalyst ID of this registration if role 0 is present and if its a first
/// registration, which defines a `CatalystId` for the chain.
#[must_use]
pub fn catalyst_id(&self) -> Option<&CatalystId> {
self.catalyst_id.as_ref()
}

/// Returns a list of addresses extracted from certificate URIs of a specific role.
#[must_use]
pub fn certificate_addresses(
&self,
role: usize,
) -> HashSet<Address> {
self.metadata
.as_ref()
.map(|m| m.certificate_uris.role_addresses(role))
.unwrap_or_default()
}

/// Return validation signature.
#[must_use]
pub fn validation_signature(&self) -> Option<&ValidationSignature> {
Expand All @@ -305,26 +345,18 @@ impl Cip509 {
self.metadata.as_ref()
}

/// Returns `Cip509` fields consuming the structure if it was successfully decoded and
/// validated otherwise return the problem report that contains all the encountered
/// issues.
///
/// # Errors
///
/// - `Err(ProblemReport)`
pub fn consume(self) -> Result<(UuidV4, Cip509RbacMetadata, PaymentHistory), ProblemReport> {
match (
self.purpose,
self.txn_inputs_hash,
self.metadata,
self.validation_signature,
) {
(Some(purpose), Some(_), Some(metadata), Some(_)) if !self.report.is_problematic() => {
Ok((purpose, metadata, self.payment_history))
},
/// Returns a set of stake addresses.
#[must_use]
pub fn stake_addresses(&self) -> HashSet<StakeAddress> {
self.certificate_uris()
.map(Cip0134UriSet::stake_addresses)
.unwrap_or_default()
}

_ => Err(self.report),
}
/// Returns a payment history map.
#[must_use]
pub fn payment_history(&self) -> &PaymentHistory {
&self.payment_history
}
}

Expand Down
14 changes: 7 additions & 7 deletions rust/rbac-registration/src/cardano/cip509/rbac/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,31 @@ use crate::cardano::cip509::{
#[allow(clippy::module_name_repetitions)]
pub struct Cip509RbacMetadata {
/// A potentially empty list of x509 certificates.
pub x509_certs: Vec<X509DerCert>,
pub(crate) x509_certs: Vec<X509DerCert>,
/// A potentially empty list of c509 certificates.
pub c509_certs: Vec<C509Cert>,
pub(crate) c509_certs: Vec<C509Cert>,
/// A set of URIs contained in both x509 and c509 certificates.
///
/// URIs from different certificate types are stored separately and certificate
/// indexes are preserved too.
///
/// This field isn't present in the encoded format and is populated by processing both
/// `x509_certs` and `c509_certs` fields.
pub certificate_uris: Cip0134UriSet,
pub(crate) certificate_uris: Cip0134UriSet,
/// A list of public keys that can be used instead of storing full certificates.
///
/// Check [this section] to understand how certificates and the public keys list are
/// related.
///
/// [this section]: https://github.com/input-output-hk/catalyst-CIPs/tree/x509-role-registration-metadata/CIP-XXXX#storing-certificates-and-public-key
pub pub_keys: Vec<SimplePublicKeyType>,
pub(crate) pub_keys: Vec<SimplePublicKeyType>,
/// A potentially empty list of revoked certificates.
pub revocation_list: Vec<CertKeyHash>,
pub(crate) revocation_list: Vec<CertKeyHash>,
/// A potentially empty role data.
pub role_data: HashMap<RoleId, RoleData>,
pub(crate) role_data: HashMap<RoleId, RoleData>,
/// Optional map of purpose key data.
/// Empty map if no purpose key data is present.
pub purpose_key_data: HashMap<u16, Vec<u8>>,
pub(crate) purpose_key_data: HashMap<u16, Vec<u8>>,
}

/// The first valid purpose key.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub enum CertOrPk {

impl CertOrPk {
/// Extract public key from the given certificate or public key.
pub(crate) fn extract_pk(&self) -> Option<VerifyingKey> {
pub(crate) fn extract_public_key(&self) -> Option<VerifyingKey> {
match self {
CertOrPk::X509(Some(x509)) => extract_key::x509_key(x509).ok(),
CertOrPk::C509(Some(c509)) => extract_key::c509_key(c509).ok(),
Expand Down
Loading