@@ -248,12 +248,14 @@ fn validate_partial_sig_messages_by_duty_logic(
248248 }
249249 }
250250 }
251- Role :: SyncCommittee if message_count > MAX_SIGNATURES_IN_SYNC_COMMITTEE => {
252- // Rule: Number of signatures must be <= MAX_SIGNATURES_IN_SYNC_COMMITTEE
253- return Err ( ValidationFailure :: TooManyPartialSignatureMessages {
254- got : message_count,
255- limit : MAX_SIGNATURES_IN_SYNC_COMMITTEE ,
256- } ) ;
251+ Role :: SyncCommittee => {
252+ if message_count > MAX_SIGNATURES_IN_SYNC_COMMITTEE {
253+ // Rule: Number of signatures must be <= MAX_SIGNATURES_IN_SYNC_COMMITTEE
254+ return Err ( ValidationFailure :: TooManyPartialSignatureMessages {
255+ got : message_count,
256+ limit : MAX_SIGNATURES_IN_SYNC_COMMITTEE ,
257+ } ) ;
258+ }
257259 }
258260 _ if message_count > 1 => {
259261 // Rule: For other duties, only one signature is allowed
@@ -715,9 +717,9 @@ mod tests {
715717 ) ;
716718 }
717719
718- fn create_partial_signature_messages ( ) -> Vec < PartialSignatureMessage > {
720+ fn create_partial_signature_messages_with_count ( count : usize ) -> Vec < PartialSignatureMessage > {
719721 let mut messages = vec ! [ ] ;
720- for _ in 0 ..3 {
722+ for _ in 0 ..count {
721723 messages. push ( PartialSignatureMessage {
722724 partial_signature : Signature :: empty ( ) ,
723725 signing_root : Hash256 :: from ( [ 0u8 ; 32 ] ) ,
@@ -728,12 +730,62 @@ mod tests {
728730 messages
729731 }
730732
733+ /// Helper function to validate sync committee partial signatures with a given message count.
734+ /// Returns the validation result for assertion in individual tests.
735+ fn validate_sync_committee_signature_count (
736+ message_count : usize ,
737+ ) -> Result < ValidatedSSVMessage , ValidationFailure > {
738+ let committee_info = create_committee_info ( FOUR_NODE_COMMITTEE ) ;
739+
740+ let messages = create_partial_signature_messages_with_count ( message_count) ;
741+
742+ let partial_sig_messages = PartialSignatureMessages {
743+ kind : PartialSignatureKind :: PostConsensus ,
744+ slot : Slot :: new ( 0 ) ,
745+ messages : messages. into ( ) ,
746+ } ;
747+
748+ let msg_id = create_message_id_for_test ( Role :: SyncCommittee ) ;
749+ let ssv_msg_data = partial_sig_messages. as_ssz_bytes ( ) ;
750+ let ssv_msg = SSVMessage :: new ( MsgType :: SSVPartialSignatureMsgType , msg_id, ssv_msg_data)
751+ . expect ( "SSVMessage should be created" ) ;
752+
753+ let ( private_key, public_key) = generate_test_key_pair ( ) ;
754+ let p_key = PKey :: from_rsa ( private_key) . unwrap ( ) ;
755+ let mut signer = Signer :: new ( MessageDigest :: sha256 ( ) , & p_key) . unwrap ( ) ;
756+ signer. update ( & ssv_msg. as_ssz_bytes ( ) ) . unwrap ( ) ;
757+ let signature = vec ! [
758+ signer
759+ . sign_to_vec( )
760+ . expect( "Failed to sign message" )
761+ . try_into( )
762+ . expect( "Signature should be 256 bytes" ) ,
763+ ] ;
764+
765+ let signed_msg = SignedSSVMessage :: new ( signature, vec ! [ OperatorId ( 1 ) ] , ssv_msg, vec ! [ ] )
766+ . expect ( "SignedSSVMessage should be created" ) ;
767+
768+ let map =
769+ create_operator_pub_keys ( committee_info. committee_members . clone ( ) , vec ! [ public_key] ) ;
770+
771+ let validation_context =
772+ create_test_validation_context ( & signed_msg, & committee_info, Role :: SyncCommittee , & map) ;
773+
774+ validate_partial_signature_message (
775+ validation_context,
776+ & mut DutyState :: new ( 2 ) ,
777+ Arc :: new ( MockDutiesProvider {
778+ voluntary_exit_duty_count : 0 ,
779+ } ) ,
780+ )
781+ }
782+
731783 #[ test]
732784 fn test_too_many_partial_signature_messages ( ) {
733785 let committee_info = create_committee_info ( FOUR_NODE_COMMITTEE ) ;
734786
735787 // Create messages with more than allowed count
736- let messages = create_partial_signature_messages ( ) ;
788+ let messages = create_partial_signature_messages_with_count ( 3 ) ;
737789
738790 let partial_sig_messages = PartialSignatureMessages {
739791 kind : PartialSignatureKind :: PostConsensus ,
@@ -780,12 +832,65 @@ mod tests {
780832 ) ;
781833 }
782834
835+ #[ test]
836+ fn test_sync_committee_accepts_multiple_signatures_within_limit ( ) {
837+ // Test 3 signatures (well within the limit)
838+ let result = validate_sync_committee_signature_count ( 3 ) ;
839+
840+ assert ! (
841+ result. is_ok( ) ,
842+ "{}" ,
843+ format!( "Expected successful validation but got: {result:?}" )
844+ ) ;
845+ }
846+
847+ #[ test]
848+ fn test_sync_committee_accepts_max_signatures ( ) {
849+ // Test exactly 13 signatures (at the limit)
850+ let result = validate_sync_committee_signature_count ( 13 ) ;
851+
852+ assert ! (
853+ result. is_ok( ) ,
854+ "{}" ,
855+ format!( "Expected successful validation for 13 signatures but got: {result:?}" )
856+ ) ;
857+ }
858+
859+ #[ test]
860+ fn test_sync_committee_rejects_too_many_signatures ( ) {
861+ // Test 14 signatures (one over the limit)
862+ let result = validate_sync_committee_signature_count ( 14 ) ;
863+
864+ assert_validation_error (
865+ result,
866+ |failure| {
867+ matches ! (
868+ failure,
869+ ValidationFailure :: TooManyPartialSignatureMessages { got: 14 , limit: 13 }
870+ )
871+ } ,
872+ "TooManyPartialSignatureMessages with got=14, limit=13" ,
873+ ) ;
874+ }
875+
876+ #[ test]
877+ fn test_sync_committee_accepts_single_signature ( ) {
878+ // Test 1 signature (minimal case)
879+ let result = validate_sync_committee_signature_count ( 1 ) ;
880+
881+ assert ! (
882+ result. is_ok( ) ,
883+ "{}" ,
884+ format!( "Expected successful validation for single signature but got: {result:?}" )
885+ ) ;
886+ }
887+
783888 #[ test]
784889 fn test_triple_validator_index_fails ( ) {
785890 let committee_info = create_committee_info ( FOUR_NODE_COMMITTEE ) ;
786891
787892 // Create messages with a validator index that appears 3 times
788- let messages = create_partial_signature_messages ( ) ;
893+ let messages = create_partial_signature_messages_with_count ( 3 ) ;
789894
790895 let partial_sig_messages = PartialSignatureMessages {
791896 kind : PartialSignatureKind :: PostConsensus ,
0 commit comments