@@ -73,6 +73,8 @@ impl RegistrationChain {
7373 ) ;
7474 }
7575
76+ // Checks that a new registration doesn't contain a signing key that was used by any
77+ // other chain. Returns a list of public keys in the registration.
7678 for role in reg. all_roles ( ) {
7779 if let Some ( key) = reg. signing_pk_for_role ( role) {
7880 if let Some ( previous) = provider. catalyst_id_from_public_key ( & key) . await ? {
@@ -97,66 +99,68 @@ impl RegistrationChain {
9799 } ) )
98100 }
99101
100- // /// Attempts to update an existing RBAC registration chain
101- // /// with a new CIP-509 registration, validating address and key usage consistency.
102- // ///
103- // /// # Errors
104- // /// - Propagates any I/O or provider-level errors encountered while checking key
105- // /// ownership (e.g., database lookup failures).
106- // pub async fn update<Provider>(
107- // &self,
108- // reg: Cip509,
109- // provider: &Provider,
110- // ) -> anyhow::Result<Option<Self>>
111- // where
112- // Provider: RbacRegistrationProvider,
113- // {
114- // // Check that addresses from the new registration aren't used in other chains.
115- // let previous_addresses = self.stake_addresses();
116- // let reg_addresses = reg.stake_addresses();
117- // let new_addresses: Vec<_> =
118- // reg_addresses.difference(&previous_addresses).collect(); for address in
119- // &new_addresses { match provider.chain_from_stake_address(address).await? {
120- // None => {
121- // // All good: the address wasn't used before.
122- // },
123- // Some(_) => {
124- // reg.report().functional_validation(
125- // &format!("{address} stake addresses is already used"),
126- // "It isn't allowed to use same stake address in multiple
127- // registration chains", );
128- // },
129- // }
130- // }
131-
132- // let latest_signing_pk = self.get_latest_signing_pk_for_role(RoleId::Role0);
133- // let new_inner = if let Some((signing_pk, _)) = latest_signing_pk {
134- // self.inner.update_stateless(reg, signing_pk)?
135- // } else {
136- // reg.report().missing_field(
137- // "latest signing key for role 0",
138- // "cannot perform signature validation during Registration Chain update",
139- // );
140- // return None;
141- // };
142-
143- // // Try to add a new registration to the chain.
144- // let (signing_pk, _) = self.get_latest_signing_pk_for_role(RoleId::Role0)?;
145- // let new_chain = chain.inner.update_stateless(reg.clone(), signing_pk)?;
146-
147- // // Check that new public keys aren't used by other chains.
148- // new_chain
149- // .validate_public_keys(&report, provider)
150- // .await
151- // .ok()?;
152-
153- // // Return an error if any issues were recorded in the report.
154- // if report.is_problematic() {
155- // return None;
156- // }
157-
158- // Some(new_chain)
159- // }
102+ /// Attempts to update an existing RBAC registration chain
103+ /// with a new CIP-509 registration, validating address and key usage consistency.
104+ ///
105+ /// # Errors
106+ /// - Propagates any I/O or provider-level errors encountered while checking key
107+ /// ownership (e.g., database lookup failures).
108+ pub async fn update < Provider > (
109+ & self ,
110+ reg : Cip509 ,
111+ provider : & Provider ,
112+ ) -> anyhow:: Result < Option < Self > >
113+ where
114+ Provider : RbacRegistrationProvider ,
115+ {
116+ // Check that addresses from the new registration aren't used in other chains.
117+ let previous_addresses = self . stake_addresses ( ) ;
118+ let reg_addresses = reg. stake_addresses ( ) ;
119+ let new_addresses: Vec < _ > = reg_addresses. difference ( & previous_addresses) . collect ( ) ;
120+ for address in & new_addresses {
121+ if provider. chain_from_stake_address ( address) . await ?. is_some ( ) {
122+ reg. report ( ) . functional_validation (
123+ & format ! ( "{address} stake addresses is already used" ) ,
124+ "It isn't allowed to use same stake address in multiple registration chains, if its not a new chain" ,
125+ ) ;
126+ }
127+ }
128+
129+ // Checks that a new registration doesn't contain a signing key that was used by any
130+ // other chain. Returns a list of public keys in the registration.
131+ {
132+ let cat_id = self . catalyst_id ( ) ;
133+ for role in reg. all_roles ( ) {
134+ if let Some ( key) = reg. signing_pk_for_role ( role) {
135+ if let Some ( previous) = provider. catalyst_id_from_public_key ( & key) . await ? {
136+ if & previous != cat_id {
137+ reg. report ( ) . functional_validation (
138+ & format ! ( "An update to {cat_id} registration chain uses the same public key ({key:?}) as {previous} chain" ) ,
139+ "It isn't allowed to use role 0 signing (certificate subject public) key in different chains" ,
140+ ) ;
141+ }
142+ }
143+ }
144+ }
145+ }
146+
147+ let Some ( ( latest_signing_pk, _) ) = self . get_latest_signing_pk_for_role ( RoleId :: Role0 )
148+ else {
149+ reg. report ( ) . missing_field (
150+ "latest signing key for role 0" ,
151+ "cannot perform signature validation during Registration Chain update" ,
152+ ) ;
153+ return Ok ( None ) ;
154+ } ;
155+
156+ let Some ( new_inner) = self . inner . update ( reg, latest_signing_pk) else {
157+ return Ok ( None ) ;
158+ } ;
159+
160+ Ok ( Some ( Self {
161+ inner : new_inner. into ( ) ,
162+ } ) )
163+ }
160164
161165 /// Update the registration chain.
162166 ///
@@ -169,7 +173,7 @@ impl RegistrationChain {
169173 ) -> Option < Self > {
170174 let latest_signing_pk = self . get_latest_signing_pk_for_role ( RoleId :: Role0 ) ;
171175 let new_inner = if let Some ( ( signing_pk, _) ) = latest_signing_pk {
172- self . inner . update_stateless ( cip509, signing_pk) ?
176+ self . inner . update ( cip509, signing_pk) ?
173177 } else {
174178 cip509. report ( ) . missing_field (
175179 "latest signing key for role 0" ,
@@ -488,7 +492,7 @@ impl RegistrationChainInner {
488492 /// # Arguments
489493 /// - `cip509` - The CIP509.
490494 #[ must_use]
491- fn update_stateless (
495+ fn update (
492496 & self ,
493497 cip509 : Cip509 ,
494498 signing_pk : VerifyingKey ,
@@ -594,7 +598,7 @@ impl RegistrationChainInner {
594598 role : RoleId ,
595599 ) -> Option < ( VerifyingKey , KeyRotation ) > {
596600 self . role_data_record . get ( & role) . and_then ( |rdr| {
597- rdr. encryption_keys ( ) . last ( ) . and_then ( |key| {
601+ rdr. encryption_keys ( ) . last ( ) . and_then ( |key| {
598602 let rotation = KeyRotation :: from_latest_rotation ( rdr. encryption_keys ( ) ) ;
599603
600604 key. data ( ) . extract_pk ( ) . map ( |pk| ( pk, rotation) )
0 commit comments