Skip to content

Commit fa137db

Browse files
committed
Merge branch 'rbac-registration-improvements' into test/rbac
Signed-off-by: bkioshn <[email protected]>
2 parents 232363e + 3371497 commit fa137db

File tree

32 files changed

+926
-722
lines changed

32 files changed

+926
-722
lines changed

rust/cardano-blockchain-types/src/cip134_uri.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::fmt::{Display, Formatter};
88
use anyhow::{anyhow, Context, Error, Result};
99
use pallas::ledger::addresses::Address;
1010

11-
/// An URI in the CIP-0134 format.
11+
/// A URI in the CIP-0134 format.
1212
///
1313
/// See the [proposal] for more details.
1414
///

rust/cardano-blockchain-types/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Catalyst Enhanced `MultiEraBlock` Structures
22
33
mod auxdata;
4+
mod cip134_uri;
45
mod fork;
56
mod metadata;
67
mod multi_era_block_data;
@@ -27,5 +28,3 @@ pub use point::Point;
2728
pub use slot::Slot;
2829
pub use txn_index::TxnIndex;
2930
pub use txn_witness::{TxnWitness, VKeyHash};
30-
31-
mod cip134_uri;

rust/cardano-blockchain-types/src/slot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use serde::Serialize;
1111

1212
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default, Serialize)]
1313

14-
/// Slot on the blockchain, typically one slot equals one second. However chain
14+
/// Slot on the blockchain, typically one slot equals one second. However chain
1515
/// parameters can alter how long a slot is.
1616
pub struct Slot(u64);
1717

rust/catalyst-types/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ fluent-uri = "0.3.2"
2323
hex = "0.4.3"
2424
minicbor = { version = "0.25.1", features = ["std"] }
2525
num-traits = "0.2.19"
26-
orx-concurrent-vec = "3.1.0"
26+
orx-concurrent-vec = { version = "3.2.0", features = ["serde"] }
2727
pallas-crypto = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
28-
serde = { version = "1.0.217", features = ["derive"] }
28+
serde = { version = "1.0.217", features = ["derive", "rc"] }
2929
thiserror = "2.0.9"
3030
base64-url = "3.0.0"
3131
uuid = { version = "1.11.0", features = ["v4", "v7", "serde"] }
@@ -36,3 +36,4 @@ tracing = "0.1.41"
3636
[dev-dependencies]
3737
ed25519-dalek = { version = "2.1.1", features = ["rand_core"] }
3838
rand = "0.8.5"
39+
serde_json = "1"

rust/catalyst-types/src/problem_report.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use std::sync::Arc;
88

99
use orx_concurrent_vec::ConcurrentVec;
10-
use serde::{ser::SerializeSeq, Serialize};
10+
use serde::Serialize;
1111

1212
/// The kind of problem being reported
1313
#[derive(Debug, Serialize, Clone)]
@@ -82,20 +82,9 @@ struct Entry {
8282
}
8383

8484
/// The Problem Report list
85-
#[derive(Debug, Clone)]
85+
#[derive(Debug, Clone, Serialize)]
8686
struct Report(ConcurrentVec<Entry>);
8787

88-
impl Serialize for Report {
89-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
90-
where S: serde::Serializer {
91-
let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
92-
for e in self.0.iter_cloned() {
93-
seq.serialize_element(&e)?;
94-
}
95-
seq.end()
96-
}
97-
}
98-
9988
/// An inner state of the report.
10089
#[derive(Debug, Serialize)]
10190
struct State {
@@ -469,4 +458,14 @@ mod tests {
469458
// The original report must have the same (problematic) state.
470459
assert!(original.is_problematic());
471460
}
461+
462+
#[test]
463+
fn serialize() {
464+
let report = ProblemReport::new("top level context");
465+
report.invalid_value("field name", "found", "constraint", "context");
466+
467+
let serialized = serde_json::to_string(&report).unwrap();
468+
let expected = r#"{"context":"top level context","report":[{"kind":{"type":"InvalidValue","field":"field name","value":"found","constraint":"constraint"},"context":"context"}]}"#;
469+
assert_eq!(serialized, expected);
470+
}
472471
}

rust/catalyst-types/src/uuid/mod.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
//! `UUID` types.
22
3+
#[allow(clippy::module_name_repetitions)]
4+
pub use uuid_v4::UuidV4;
5+
#[allow(clippy::module_name_repetitions)]
6+
pub use uuid_v7::UuidV7;
7+
38
mod uuid_v4;
49
mod uuid_v7;
510

611
use minicbor::data::Tag;
7-
pub use uuid_v4::UuidV4 as V4;
8-
pub use uuid_v7::UuidV7 as V7;
912

1013
/// Invalid Doc Type UUID
1114
pub const INVALID_UUID: uuid::Uuid = uuid::Uuid::from_bytes([0x00; 16]);
@@ -14,6 +17,19 @@ pub const INVALID_UUID: uuid::Uuid = uuid::Uuid::from_bytes([0x00; 16]);
1417
#[allow(dead_code)]
1518
const UUID_CBOR_TAG: u64 = 37;
1619

20+
/// Uuid validation errors, which could occur during decoding or converting to
21+
/// `UuidV4` or `UuidV7` types.
22+
#[derive(Debug, Clone, thiserror::Error)]
23+
#[allow(clippy::module_name_repetitions)]
24+
pub enum UuidError {
25+
/// `UUIDv4` invalid error
26+
#[error("'{0}' is not a valid UUIDv4")]
27+
InvalidUuidV4(uuid::Uuid),
28+
/// `UUIDv7` invalid error
29+
#[error("'{0}' is not a valid UUIDv7")]
30+
InvalidUuidV7(uuid::Uuid),
31+
}
32+
1733
/// Context for `CBOR` encoding and decoding
1834
pub enum CborContext {
1935
/// Untagged bytes
@@ -77,30 +93,52 @@ fn encode_cbor_uuid<W: minicbor::encode::Write>(
7793
#[cfg(test)]
7894
mod tests {
7995

80-
use super::{V4, V7};
96+
use super::*;
8197
use crate::uuid::CborContext;
8298

8399
#[test]
84100
fn test_cbor_uuid_v4_roundtrip() {
85-
let uuid: V4 = uuid::Uuid::new_v4().into();
101+
let uuid = UuidV4::new();
86102
let mut bytes = Vec::new();
87103
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Untagged).unwrap();
88104
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Untagged).unwrap();
89105
assert_eq!(uuid, decoded);
90106
}
91107

108+
#[test]
109+
fn test_cbor_uuid_v4_invalid_decoding() {
110+
let uuid_v7 = UuidV7::new();
111+
let mut bytes = Vec::new();
112+
minicbor::encode_with(uuid_v7, &mut bytes, &mut CborContext::Untagged).unwrap();
113+
assert!(
114+
minicbor::decode_with::<_, UuidV4>(bytes.as_slice(), &mut CborContext::Untagged)
115+
.is_err()
116+
);
117+
}
118+
92119
#[test]
93120
fn test_cbor_uuid_v7_roundtrip() {
94-
let uuid: V7 = uuid::Uuid::now_v7().into();
121+
let uuid = UuidV7::new();
95122
let mut bytes = Vec::new();
96123
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Untagged).unwrap();
97124
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Untagged).unwrap();
98125
assert_eq!(uuid, decoded);
99126
}
100127

128+
#[test]
129+
fn test_cbor_uuid_v7_invalid_decoding() {
130+
let uuid_v4 = UuidV4::new();
131+
let mut bytes = Vec::new();
132+
minicbor::encode_with(uuid_v4, &mut bytes, &mut CborContext::Untagged).unwrap();
133+
assert!(
134+
minicbor::decode_with::<_, UuidV7>(bytes.as_slice(), &mut CborContext::Untagged)
135+
.is_err()
136+
);
137+
}
138+
101139
#[test]
102140
fn test_tagged_cbor_uuid_v4_roundtrip() {
103-
let uuid: V4 = uuid::Uuid::new_v4().into();
141+
let uuid = UuidV4::new();
104142
let mut bytes = Vec::new();
105143
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Tagged).unwrap();
106144
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Tagged).unwrap();
@@ -109,7 +147,7 @@ mod tests {
109147

110148
#[test]
111149
fn test_tagged_cbor_uuid_v7_roundtrip() {
112-
let uuid: V7 = uuid::Uuid::now_v7().into();
150+
let uuid = UuidV7::new();
113151
let mut bytes = Vec::new();
114152
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Tagged).unwrap();
115153
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Tagged).unwrap();
@@ -118,7 +156,7 @@ mod tests {
118156

119157
#[test]
120158
fn test_optional_cbor_uuid_v4_roundtrip() {
121-
let uuid: V4 = uuid::Uuid::new_v4().into();
159+
let uuid = UuidV4::new();
122160

123161
let mut bytes = Vec::new();
124162
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Untagged).unwrap();
@@ -133,7 +171,7 @@ mod tests {
133171

134172
#[test]
135173
fn test_optional_cbor_uuid_v7_roundtrip() {
136-
let uuid: V7 = uuid::Uuid::now_v7().into();
174+
let uuid = UuidV7::new();
137175

138176
let mut bytes = Vec::new();
139177
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Untagged).unwrap();

rust/catalyst-types/src/uuid/uuid_v4.rs

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,65 @@
22
use std::fmt::{Display, Formatter};
33

44
use minicbor::{Decode, Decoder, Encode};
5+
use uuid::Uuid;
56

6-
use super::{decode_cbor_uuid, encode_cbor_uuid, CborContext, INVALID_UUID};
7+
use super::{decode_cbor_uuid, encode_cbor_uuid, CborContext, UuidError, INVALID_UUID};
78

89
/// Type representing a `UUIDv4`.
9-
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
10-
#[serde(from = "uuid::Uuid")]
11-
#[serde(into = "uuid::Uuid")]
12-
pub struct UuidV4 {
13-
/// UUID
14-
uuid: uuid::Uuid,
15-
}
10+
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, serde::Serialize)]
11+
pub struct UuidV4(Uuid);
1612

1713
impl UuidV4 {
1814
/// Version for `UUIDv4`.
1915
const UUID_VERSION_NUMBER: usize = 4;
2016

17+
/// Generates a random `UUIDv4`.
18+
#[must_use]
19+
#[allow(clippy::new_without_default)]
20+
pub fn new() -> Self {
21+
Self(Uuid::new_v4())
22+
}
23+
2124
/// Generates a zeroed out `UUIDv4` that can never be valid.
2225
#[must_use]
2326
pub fn invalid() -> Self {
24-
Self { uuid: INVALID_UUID }
27+
Self(INVALID_UUID)
2528
}
2629

2730
/// Check if this is a valid `UUIDv4`.
2831
#[must_use]
2932
pub fn is_valid(&self) -> bool {
30-
self.uuid != INVALID_UUID && self.uuid.get_version_num() == Self::UUID_VERSION_NUMBER
33+
is_valid(&self.uuid())
3134
}
3235

3336
/// Returns the `uuid::Uuid` type.
3437
#[must_use]
35-
pub fn uuid(&self) -> uuid::Uuid {
36-
self.uuid
38+
pub fn uuid(&self) -> Uuid {
39+
self.0
3740
}
3841
}
3942

43+
/// Check if this is a valid `UUIDv4`.
44+
fn is_valid(uuid: &Uuid) -> bool {
45+
uuid != &INVALID_UUID && uuid.get_version_num() == UuidV4::UUID_VERSION_NUMBER
46+
}
47+
4048
impl Display for UuidV4 {
4149
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
42-
write!(f, "{}", self.uuid)
50+
write!(f, "{}", self.0)
4351
}
4452
}
4553

4654
impl Decode<'_, CborContext> for UuidV4 {
4755
fn decode(d: &mut Decoder<'_>, ctx: &mut CborContext) -> Result<Self, minicbor::decode::Error> {
4856
let uuid = decode_cbor_uuid(d, ctx)?;
49-
Ok(Self { uuid })
57+
if is_valid(&uuid) {
58+
Ok(Self(uuid))
59+
} else {
60+
Err(minicbor::decode::Error::message(UuidError::InvalidUuidV4(
61+
uuid,
62+
)))
63+
}
5064
}
5165
}
5266

@@ -59,27 +73,41 @@ impl Encode<CborContext> for UuidV4 {
5973
}
6074

6175
/// Returns a `UUIDv4` from `uuid::Uuid`.
62-
///
63-
/// NOTE: This does not guarantee that the `UUID` is valid.
64-
impl From<uuid::Uuid> for UuidV4 {
65-
fn from(uuid: uuid::Uuid) -> Self {
66-
Self { uuid }
76+
impl TryFrom<Uuid> for UuidV4 {
77+
type Error = UuidError;
78+
79+
fn try_from(uuid: Uuid) -> Result<Self, Self::Error> {
80+
if is_valid(&uuid) {
81+
Ok(Self(uuid))
82+
} else {
83+
Err(UuidError::InvalidUuidV4(uuid))
84+
}
6785
}
6886
}
6987

7088
/// Returns a `uuid::Uuid` from `UUIDv4`.
7189
///
7290
/// NOTE: This does not guarantee that the `UUID` is valid.
73-
impl From<UuidV4> for uuid::Uuid {
91+
impl From<UuidV4> for Uuid {
7492
fn from(value: UuidV4) -> Self {
75-
value.uuid
93+
value.0
94+
}
95+
}
96+
97+
impl<'de> serde::Deserialize<'de> for UuidV4 {
98+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99+
where D: serde::Deserializer<'de> {
100+
let uuid = Uuid::deserialize(deserializer)?;
101+
if is_valid(&uuid) {
102+
Ok(Self(uuid))
103+
} else {
104+
Err(serde::de::Error::custom(UuidError::InvalidUuidV4(uuid)))
105+
}
76106
}
77107
}
78108

79109
#[cfg(test)]
80110
mod tests {
81-
use uuid::Uuid;
82-
83111
use super::*;
84112

85113
#[test]
@@ -95,15 +123,17 @@ mod tests {
95123

96124
#[test]
97125
fn test_valid_uuid() {
98-
let valid_uuid = UuidV4::from(Uuid::new_v4());
126+
let valid_uuid = UuidV4::try_from(Uuid::new_v4()).unwrap();
127+
assert!(valid_uuid.is_valid(), "Valid UUID should be valid");
128+
129+
let valid_uuid = UuidV4::new();
99130
assert!(valid_uuid.is_valid(), "Valid UUID should be valid");
100131
}
101132

102133
#[test]
103134
fn test_invalid_version_uuid() {
104-
let invalid_version_uuid = UuidV4::from(Uuid::from_u128(0));
105135
assert!(
106-
!invalid_version_uuid.is_valid(),
136+
UuidV4::try_from(INVALID_UUID).is_err(),
107137
"Zero UUID should not be valid"
108138
);
109139
}

0 commit comments

Comments
 (0)