@@ -9,7 +9,9 @@ use std::{
99
1010use anyhow:: Context ;
1111use c509_certificate:: c509:: C509 ;
12- use cardano_blockchain_types:: { hashes:: TransactionId , Point , StakeAddress , TxnIndex } ;
12+ use cardano_blockchain_types:: {
13+ hashes:: TransactionId , pallas_addresses:: Address , Cip0134Uri , Point , StakeAddress , TxnIndex ,
14+ } ;
1315use catalyst_types:: {
1416 catalyst_id:: { key_rotation:: KeyRotation , role_index:: RoleId , CatalystId } ,
1517 conversion:: zero_out_last_n_bytes,
@@ -344,10 +346,29 @@ impl RegistrationChain {
344346 . and_then ( |rdr| rdr. encryption_key_from_rotation ( rotation) )
345347 }
346348
347- /// Returns all stake addresses associated to this registration .
349+ /// Returns all stake addresses associated to this chain .
348350 #[ must_use]
349351 pub fn stake_addresses ( & self ) -> HashSet < StakeAddress > {
350- self . inner . certificate_uris . stake_addresses ( )
352+ let stolen_stake_addresses = self
353+ . inner
354+ . stolen_uris
355+ . iter ( )
356+ . flat_map ( |v| {
357+ v. data ( ) . iter ( ) . filter_map ( |uri| {
358+ match uri. address ( ) {
359+ Address :: Stake ( a) => Some ( a. clone ( ) . into ( ) ) ,
360+ _ => None ,
361+ }
362+ } )
363+ } )
364+ . collect ( ) ;
365+
366+ self . inner
367+ . certificate_uris
368+ . stake_addresses ( )
369+ . difference ( & stolen_stake_addresses)
370+ . cloned ( )
371+ . collect ( )
351372 }
352373}
353374
@@ -376,6 +397,9 @@ struct RegistrationChainInner {
376397 /// List of point + transaction index, and certificate key hash.
377398 revocations : Vec < PointData < CertKeyHash > > ,
378399
400+ /// URIs which are stolen by another registration chains.
401+ stolen_uris : Vec < PointData < Box < [ Cip0134Uri ] > > > ,
402+
379403 // Role
380404 /// Map of role number to list point + transaction index, and role data.
381405 /// Record history of the whole role data in point in time.
@@ -494,6 +518,7 @@ impl RegistrationChainInner {
494518 certificate_uris,
495519 simple_keys,
496520 revocations,
521+ stolen_uris : vec ! [ ] ,
497522 role_data_history,
498523 role_data_record,
499524 payment_history,
@@ -514,10 +539,25 @@ impl RegistrationChainInner {
514539 let mut new_inner = self . clone ( ) ;
515540
516541 let Some ( prv_tx_id) = cip509. previous_transaction ( ) else {
517- cip509
518- . report ( )
519- . missing_field ( "previous transaction ID" , context) ;
520- return None ;
542+ if let Some ( cat_id) = cip509. catalyst_id ( ) {
543+ if cat_id == & self . catalyst_id {
544+ cip509. report ( ) . functional_validation (
545+ & format ! (
546+ "Trying to apply the first registration to the assosiated {} again" ,
547+ cat_id. as_short_id( )
548+ ) ,
549+ "It isn't allowed to submit first registration twice" ,
550+ ) ;
551+ return None ;
552+ }
553+
554+ return new_inner. update_cause_another_chain ( cip509) ;
555+ } else {
556+ cip509
557+ . report ( )
558+ . missing_field ( "previous transaction ID" , context) ;
559+ return None ;
560+ }
521561 } ;
522562
523563 // Previous transaction ID in the CIP509 should equal to the current transaction ID
@@ -603,6 +643,32 @@ impl RegistrationChainInner {
603643 Some ( new_inner)
604644 }
605645
646+ /// Update the registration chain with the `cip509` assosiated to another chain.
647+ /// This is the case when registration for different chain affecting the current one,
648+ /// by invalidating some data for the current registration chain (stoling stake
649+ /// addresses etc.).
650+ ///
651+ /// The provided `cip509` should be fully validated by another chain before trying to
652+ /// submit to the current one.
653+ #[ must_use]
654+ fn update_cause_another_chain (
655+ mut self ,
656+ cip509 : & Cip509 ,
657+ ) -> Option < Self > {
658+ if let Some ( uri_set) = cip509. certificate_uris ( ) {
659+ let origin = cip509. origin ( ) . clone ( ) ;
660+ self . stolen_uris . push ( PointData :: new (
661+ origin,
662+ uri_set
663+ . values ( )
664+ . cloned ( )
665+ . collect :: < Vec < _ > > ( )
666+ . into_boxed_slice ( ) ,
667+ ) ) ;
668+ }
669+ Some ( self )
670+ }
671+
606672 /// Get the latest signing public key for a role.
607673 /// Returns the public key and the rotation,`None` if not found.
608674 #[ must_use]
0 commit comments