1+ use crate :: bls_sig_utils:: BLSSignature ;
12use crate :: network:: message_sml:: MnListDiff ;
23use crate :: prelude:: CoreBlockHeight ;
34use crate :: sml:: error:: SmlError ;
5+ use crate :: sml:: llmq_entry_verification:: {
6+ LLMQEntryVerificationSkipStatus , LLMQEntryVerificationStatus ,
7+ } ;
48use crate :: sml:: masternode_list:: MasternodeList ;
9+ use crate :: sml:: quorum_entry:: qualified_quorum_entry:: {
10+ QualifiedQuorumEntry , VerifyingChainLockSignaturesType ,
11+ } ;
512
613impl MasternodeList {
714 /// Applies an `MnListDiff` to update the current masternode list.
@@ -32,7 +39,8 @@ impl MasternodeList {
3239 & self ,
3340 diff : MnListDiff ,
3441 diff_end_height : CoreBlockHeight ,
35- ) -> Result < MasternodeList , SmlError > {
42+ previous_chain_lock_sigs : Option < [ BLSSignature ; 3 ] > ,
43+ ) -> Result < ( MasternodeList , Option < BLSSignature > ) , SmlError > {
3644 // Ensure the base block hash matches
3745 if self . block_hash != diff. base_block_hash {
3846 return Err ( SmlError :: BaseBlockHashMismatch {
@@ -67,12 +75,73 @@ impl MasternodeList {
6775 }
6876 }
6977
78+ // Build a vector of optional signatures with slots matching new_quorums length
79+ let mut quorum_sig_lookup: Vec < Option < & BLSSignature > > = vec ! [ None ; diff. new_quorums. len( ) ] ;
80+
81+ // Fill each slot with the corresponding signature
82+ for quorum_sig_obj in & diff. quorums_chainlock_signatures {
83+ for & index in & quorum_sig_obj. index_set {
84+ if let Some ( slot) = quorum_sig_lookup. get_mut ( index as usize ) {
85+ * slot = Some ( & quorum_sig_obj. signature ) ;
86+ } else {
87+ return Err ( SmlError :: InvalidIndexInSignatureSet ( index) ) ;
88+ }
89+ }
90+ }
91+
92+ // Verify all slots have been filled
93+ if quorum_sig_lookup. iter ( ) . any ( Option :: is_none) {
94+ return Err ( SmlError :: IncompleteSignatureSet ) ;
95+ }
96+
97+ let mut rotating_sig = None ;
98+
7099 // Add or update new quorums
71- for new_quorum in diff. new_quorums {
72- updated_quorums
73- . entry ( new_quorum. llmq_type )
74- . or_default ( )
75- . insert ( new_quorum. quorum_hash , new_quorum. into ( ) ) ;
100+ for ( idx, new_quorum) in diff. new_quorums . into_iter ( ) . enumerate ( ) {
101+ updated_quorums. entry ( new_quorum. llmq_type ) . or_default ( ) . insert (
102+ new_quorum. quorum_hash ,
103+ {
104+ let commitment_hash = new_quorum. calculate_commitment_hash ( ) ;
105+ let entry_hash = new_quorum. calculate_entry_hash ( ) ;
106+ let verifying_chain_lock_signature =
107+ if new_quorum. llmq_type . is_rotating_quorum_type ( ) {
108+ if rotating_sig. is_none ( ) {
109+ if let Some ( sig) = quorum_sig_lookup[ idx] {
110+ rotating_sig = Some ( * sig)
111+ } else {
112+ return Err ( SmlError :: IncompleteSignatureSet ) ;
113+ }
114+ }
115+ if let Some ( previous_chain_lock_sigs) = previous_chain_lock_sigs {
116+ if let Some ( sig) = quorum_sig_lookup[ idx] {
117+ Some ( VerifyingChainLockSignaturesType :: Rotating ( [
118+ previous_chain_lock_sigs[ 0 ] ,
119+ previous_chain_lock_sigs[ 1 ] ,
120+ previous_chain_lock_sigs[ 2 ] ,
121+ * sig,
122+ ] ) )
123+ } else {
124+ return Err ( SmlError :: IncompleteSignatureSet ) ;
125+ }
126+ } else {
127+ None
128+ }
129+ } else {
130+ quorum_sig_lookup[ idx]
131+ . copied ( )
132+ . map ( VerifyingChainLockSignaturesType :: NonRotating )
133+ } ;
134+ QualifiedQuorumEntry {
135+ quorum_entry : new_quorum,
136+ verified : LLMQEntryVerificationStatus :: Skipped (
137+ LLMQEntryVerificationSkipStatus :: NotMarkedForVerification ,
138+ ) , // Default to unverified
139+ commitment_hash,
140+ entry_hash,
141+ verifying_chain_lock_signature,
142+ }
143+ } ,
144+ ) ;
76145 }
77146
78147 // Create and return the new MasternodeList
@@ -83,6 +152,6 @@ impl MasternodeList {
83152 diff_end_height,
84153 ) ;
85154
86- Ok ( builder. build ( ) )
155+ Ok ( ( builder. build ( ) , rotating_sig ) )
87156 }
88157}
0 commit comments