Skip to content

Commit d591cb2

Browse files
vlopes11Mr-Leshiy
andauthored
feat(rust/rbac-registration): use KeyRotation (#297)
* feat(rust/rbac-registration): use KeyRotation Refactors the implementation of key rotation values associated with IdUri and RBAC registrations. Update all occurrences within the `rbac-registration` crate that employ the `usize` type for rotation values (e.g., `get_encryption_pk_for_role_at_rotation`, `get_singing_key_cert_or_key_for_role_at_rotation`) to utilize the newly introduced `KeyRotation` type instead. * apply fmt * update comments & rename function * fmt --------- Co-authored-by: Alex Pozhylenkov <[email protected]>
1 parent 3b932f6 commit d591cb2

File tree

3 files changed

+45
-20
lines changed

3 files changed

+45
-20
lines changed

rust/catalyst-types/src/id_uri/key_rotation.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,24 @@ impl KeyRotation {
3030
pub fn is_default(self) -> bool {
3131
self == Self::DEFAULT
3232
}
33+
34+
/// Get the key by the rotation value from the provided keys slice, if present.
35+
pub fn get_key<'a, T>(&self, keys: &'a [T]) -> Option<&'a T> {
36+
keys.get(self.0 as usize)
37+
}
38+
39+
/// Get the latest rotation value calculated from the provided keys slice
40+
/// (`keys.len() - 1`).
41+
///
42+
/// An empty slice will be saturated to `0` rotation value.
43+
pub fn from_latest_rotation<T>(keys: &[T]) -> Self {
44+
// we allow the cast here as per spec we cannot overflow `u16` with a keys count.
45+
#[allow(clippy::cast_possible_truncation)]
46+
let rotation = keys.len() as u16;
47+
let rotation = rotation.saturating_sub(1);
48+
49+
Self(rotation)
50+
}
3351
}
3452

3553
impl Default for KeyRotation {

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use std::collections::HashMap;
44

5+
use catalyst_types::id_uri::key_rotation::KeyRotation;
56
use pallas::ledger::addresses::ShelleyAddress;
67

78
use super::{CertOrPk, PointData, PointTxnIdx};
@@ -86,15 +87,15 @@ impl RoleDataRecord {
8687
/// The first signing key is at rotation 0, the second at rotation 1, and so on.
8788
/// Returns `None` if the given key rotation does not exist.
8889
#[must_use]
89-
pub fn signing_key_from_rotation(&self, rotation: usize) -> Option<&CertOrPk> {
90-
self.signing_keys.get(rotation).map(PointData::data)
90+
pub fn signing_key_from_rotation(&self, rotation: &KeyRotation) -> Option<&CertOrPk> {
91+
rotation.get_key(&self.signing_keys).map(PointData::data)
9192
}
9293

9394
/// Get the encryption key data associated with this role and the given key rotation.
9495
/// The first encryption key is at rotation 0, the second at rotation 1, and so on.
9596
/// Returns `None` if the given key rotation does not exist.
9697
#[must_use]
97-
pub fn encryption_key_from_rotation(&self, rotation: usize) -> Option<&CertOrPk> {
98-
self.encryption_keys.get(rotation).map(PointData::data)
98+
pub fn encryption_key_from_rotation(&self, rotation: &KeyRotation) -> Option<&CertOrPk> {
99+
rotation.get_key(&self.encryption_keys).map(PointData::data)
99100
}
100101
}

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use std::{collections::HashMap, sync::Arc};
77
use anyhow::bail;
88
use c509_certificate::c509::C509;
99
use cardano_blockchain_types::{Cip0134Uri, StakeAddress, TransactionId};
10-
use catalyst_types::{id_uri::IdUri, uuid::UuidV4};
10+
use catalyst_types::{
11+
id_uri::{key_rotation::KeyRotation, IdUri},
12+
uuid::UuidV4,
13+
};
1114
use ed25519_dalek::VerifyingKey;
1215
use pallas::ledger::addresses::Address;
1316
use tracing::error;
@@ -133,12 +136,12 @@ impl RegistrationChain {
133136
#[must_use]
134137
pub fn get_latest_signing_pk_for_role(
135138
&self, role: &RoleNumber,
136-
) -> Option<(VerifyingKey, usize)> {
139+
) -> Option<(VerifyingKey, KeyRotation)> {
137140
self.inner.role_data_record.get(role).and_then(|rdr| {
138141
rdr.signing_keys().last().and_then(|key| {
139-
key.data()
140-
.extract_pk()
141-
.map(|pk| (pk, rdr.signing_keys().len().saturating_sub(1)))
142+
let rotation = KeyRotation::from_latest_rotation(rdr.signing_keys());
143+
144+
key.data().extract_pk().map(|pk| (pk, rotation))
142145
})
143146
})
144147
}
@@ -148,12 +151,12 @@ impl RegistrationChain {
148151
#[must_use]
149152
pub fn get_latest_encryption_pk_for_role(
150153
&self, role: &RoleNumber,
151-
) -> Option<(VerifyingKey, usize)> {
154+
) -> Option<(VerifyingKey, KeyRotation)> {
152155
self.inner.role_data_record.get(role).and_then(|rdr| {
153156
rdr.encryption_keys().last().and_then(|key| {
154-
key.data()
155-
.extract_pk()
156-
.map(|pk| (pk, rdr.encryption_keys().len().saturating_sub(1)))
157+
let rotation = KeyRotation::from_latest_rotation(rdr.encryption_keys());
158+
159+
key.data().extract_pk().map(|pk| (pk, rotation))
157160
})
158161
})
159162
}
@@ -162,7 +165,7 @@ impl RegistrationChain {
162165
/// Returns the public key, `None` if not found.
163166
#[must_use]
164167
pub fn get_signing_pk_for_role_at_rotation(
165-
&self, role: &RoleNumber, rotation: usize,
168+
&self, role: &RoleNumber, rotation: &KeyRotation,
166169
) -> Option<VerifyingKey> {
167170
self.inner.role_data_record.get(role).and_then(|rdr| {
168171
rdr.signing_key_from_rotation(rotation)
@@ -174,7 +177,7 @@ impl RegistrationChain {
174177
/// Returns the public key, `None` if not found.
175178
#[must_use]
176179
pub fn get_encryption_pk_for_role_at_rotation(
177-
&self, role: &RoleNumber, rotation: usize,
180+
&self, role: &RoleNumber, rotation: &KeyRotation,
178181
) -> Option<VerifyingKey> {
179182
self.inner.role_data_record.get(role).and_then(|rdr| {
180183
rdr.encryption_key_from_rotation(rotation)
@@ -186,7 +189,7 @@ impl RegistrationChain {
186189
/// given rotation.
187190
#[must_use]
188191
pub fn get_singing_key_cert_or_key_for_role_at_rotation(
189-
&self, role: &RoleNumber, rotation: usize,
192+
&self, role: &RoleNumber, rotation: &KeyRotation,
190193
) -> Option<&CertOrPk> {
191194
self.inner
192195
.role_data_record
@@ -198,7 +201,7 @@ impl RegistrationChain {
198201
/// with given rotation.
199202
#[must_use]
200203
pub fn get_encryption_key_cert_or_key_for_role_at_rotation(
201-
&self, role: &RoleNumber, rotation: usize,
204+
&self, role: &RoleNumber, rotation: &KeyRotation,
202205
) -> Option<&CertOrPk> {
203206
self.inner
204207
.role_data_record
@@ -487,12 +490,15 @@ mod test {
487490
let (_k, r) = update
488491
.get_latest_signing_pk_for_role(&RoleNumber::ROLE_0)
489492
.unwrap();
490-
assert_eq!(r, 1);
493+
assert_eq!(r, KeyRotation::from(1));
491494
assert!(update
492-
.get_signing_pk_for_role_at_rotation(&RoleNumber::ROLE_0, 2)
495+
.get_signing_pk_for_role_at_rotation(&RoleNumber::ROLE_0, &KeyRotation::from(2))
493496
.is_none());
494497
assert!(update
495-
.get_singing_key_cert_or_key_for_role_at_rotation(&RoleNumber::ROLE_0, 0)
498+
.get_singing_key_cert_or_key_for_role_at_rotation(
499+
&RoleNumber::ROLE_0,
500+
&KeyRotation::from(0)
501+
)
496502
.is_some());
497503
}
498504
}

0 commit comments

Comments
 (0)