diff --git a/rust/catalyst-types/src/hash_wrapper.rs b/rust/catalyst-types/src/hash_wrapper.rs new file mode 100644 index 0000000000..b3112ccd5a --- /dev/null +++ b/rust/catalyst-types/src/hash_wrapper.rs @@ -0,0 +1,127 @@ +//! A macro for defining a new type wrappers for the given hash types. + +/// Defines a new type wrapper for the given hash types. +/// +/// # Examples +/// +/// ``` +/// use catalyst_types::{define_hashes, hashes::Blake2b128Hash}; +/// +/// define_hashes!( +/// /// You can document the declared types... +/// (SomeHash, Blake2b128Hash), +/// // ...or not. +/// (AnotherHash, Blake2b128Hash), +/// ); +/// +/// let hash = SomeHash::new(&[1, 2, 3]); +/// println!("{hash:?}"); +/// ``` +#[macro_export] +macro_rules! define_hashes { + ($($(#[$docs:meta])* ($name:ident, $inner:ty)),+ $(,)?) => { + $( + $(#[$docs])* + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct $name($inner); + + impl $name { + /// Creates a new instance from the given bytes by hashing them. + #[must_use] + pub fn new(input_bytes: &[u8]) -> Self { + Self(<$inner>::new(input_bytes)) + } + } + + impl From<$name> for Vec { + fn from(value: $name) -> Self { + value.0.into() + } + } + + impl From<$inner> for $name { + fn from(value: $inner) -> Self { + Self(value) + } + } + + impl TryFrom<&[u8]> for $name { + type Error = $crate::hashes::Blake2bHashError; + + fn try_from(value: &[u8]) -> Result { + Ok(Self(<$inner>::try_from(value)?)) + } + } + + impl TryFrom> for $name { + type Error = $crate::hashes::Blake2bHashError; + + fn try_from(value: Vec) -> Result { + value.as_slice().try_into() + } + } + + impl std::str::FromStr for $name { + type Err = $crate::hashes::Blake2bHashError; + + fn from_str(s: &str) -> Result { + let hash: $inner = s.parse().map_err($crate::hashes::Blake2bHashError::from)?; + Ok(Self(hash)) + } + } + + impl minicbor::Encode for $name { + fn encode( + &self, e: &mut minicbor::Encoder, ctx: &mut C, + ) -> Result<(), minicbor::encode::Error> { + self.0.encode(e, ctx) + } + } + + impl<'a, C> minicbor::Decode<'a, C> for $name { + fn decode( + d: &mut minicbor::Decoder<'a>, ctx: &mut C, + ) -> Result { + let hash = <$inner>::decode(d, ctx)?; + Ok(Self(hash)) + } + } + )+ + }; +} + +#[cfg(test)] +mod tests { + use crate::hashes::Blake2b128Hash; + + // Define one type without a trailing comma. + define_hashes!((H1, Blake2b128Hash)); + // Define one type with a trailing comma and a doc-comment. + define_hashes!( + /// Some documentation. + (H2, Blake2b128Hash), + ); + // Define multiple types at once. + define_hashes!( + /// Documentation. + (H3, Blake2b128Hash), + // No documentation. + (H4, Blake2b128Hash), + /// More documentation. + (H5, Blake2b128Hash), + ); + + // There is little reason to check the conversion itself, it is mostly a demonstration + // that the methods defined by the macro are working. + #[test] + fn hash_wrapper() { + let hash = H1::new(&[1, 2, 3, 4, 5]); + + let v = Vec::from(hash); + let from_slice = H1::try_from(v.as_slice()).unwrap(); + assert_eq!(hash, from_slice); + + let from_vec = H1::try_from(v).unwrap(); + assert_eq!(hash, from_vec); + } +} diff --git a/rust/catalyst-types/src/lib.rs b/rust/catalyst-types/src/lib.rs index e3862bfd62..85f3231235 100644 --- a/rust/catalyst-types/src/lib.rs +++ b/rust/catalyst-types/src/lib.rs @@ -2,6 +2,7 @@ pub mod cbor_utils; pub mod conversion; +pub mod hash_wrapper; pub mod hashes; pub mod id_uri; pub mod mmap_file; diff --git a/rust/catalyst-types/src/uuid/uuid_v7.rs b/rust/catalyst-types/src/uuid/uuid_v7.rs index 5cf3a6a05b..98fbd8cda6 100644 --- a/rust/catalyst-types/src/uuid/uuid_v7.rs +++ b/rust/catalyst-types/src/uuid/uuid_v7.rs @@ -2,12 +2,13 @@ use std::fmt::{Display, Formatter}; use minicbor::{Decode, Decoder, Encode}; +use uuid::Uuid; use super::{decode_cbor_uuid, encode_cbor_uuid, CborContext, UuidError, INVALID_UUID}; /// Type representing a `UUIDv7`. #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, serde::Serialize)] -pub struct UuidV7(uuid::Uuid); +pub struct UuidV7(Uuid); impl UuidV7 { /// Version for `UUIDv7`. @@ -17,7 +18,7 @@ impl UuidV7 { #[must_use] #[allow(clippy::new_without_default)] pub fn new() -> Self { - Self(uuid::Uuid::now_v7()) + Self(Uuid::now_v7()) } /// Generates a zeroed out `UUIDv7` that can never be valid. @@ -34,13 +35,13 @@ impl UuidV7 { /// Returns the `uuid::Uuid` type. #[must_use] - pub fn uuid(&self) -> uuid::Uuid { + pub fn uuid(&self) -> Uuid { self.0 } } /// Check if this is a valid `UUIDv7`. -fn is_valid(uuid: &uuid::Uuid) -> bool { +fn is_valid(uuid: &Uuid) -> bool { uuid != &INVALID_UUID && uuid.get_version_num() == UuidV7::UUID_VERSION_NUMBER } @@ -72,10 +73,10 @@ impl Encode for UuidV7 { } /// Returns a `UUIDv7` from `uuid::Uuid`. -impl TryFrom for UuidV7 { +impl TryFrom for UuidV7 { type Error = UuidError; - fn try_from(uuid: uuid::Uuid) -> Result { + fn try_from(uuid: Uuid) -> Result { if is_valid(&uuid) { Ok(Self(uuid)) } else { @@ -87,7 +88,7 @@ impl TryFrom for UuidV7 { /// Returns a `uuid::Uuid` from `UUIDv7`. /// /// NOTE: This does not guarantee that the `UUID` is valid. -impl From for uuid::Uuid { +impl From for Uuid { fn from(value: UuidV7) -> Self { value.0 } @@ -96,7 +97,7 @@ impl From for uuid::Uuid { impl<'de> serde::Deserialize<'de> for UuidV7 { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { - let uuid = uuid::Uuid::deserialize(deserializer)?; + let uuid = Uuid::deserialize(deserializer)?; if is_valid(&uuid) { Ok(Self(uuid)) } else { diff --git a/rust/rbac-registration/src/cardano/cip509/cip509.rs b/rust/rbac-registration/src/cardano/cip509/cip509.rs index 3dd41cf09c..086ca39ea3 100644 --- a/rust/rbac-registration/src/cardano/cip509/cip509.rs +++ b/rust/rbac-registration/src/cardano/cip509/cip509.rs @@ -202,6 +202,12 @@ impl Cip509 { self.metadata.as_ref().and_then(|m| m.role_data.get(&role)) } + /// Returns a purpose of this registration. + #[must_use] + pub fn purpose(&self) -> Option { + self.purpose + } + /// Returns a hash of the previous transaction. #[must_use] pub fn previous_transaction(&self) -> Option { diff --git a/rust/rbac-registration/src/cardano/cip509/mod.rs b/rust/rbac-registration/src/cardano/cip509/mod.rs index b100233bf8..d6f296df21 100644 --- a/rust/rbac-registration/src/cardano/cip509/mod.rs +++ b/rust/rbac-registration/src/cardano/cip509/mod.rs @@ -3,7 +3,8 @@ //! CDDL Reference: pub use cip509::Cip509; -pub use rbac::{C509Cert, SimplePublicKeyType, X509DerCert}; +#[allow(clippy::module_name_repetitions)] +pub use rbac::{C509Cert, Cip509RbacMetadata, SimplePublicKeyType, X509DerCert}; pub use types::{ CertKeyHash, KeyLocalRef, LocalRefInt, Payment, PaymentHistory, PointTxnIdx, RoleData, RoleNumber, TxInputHash, ValidationSignature,