@@ -539,6 +539,59 @@ mod tests {
539539 }
540540 self
541541 }
542+
543+ /// Assert that a slashable attestation fails to be signed locally (empty result) and is
544+ /// either signed or not by the web3signer rig depending on the value of
545+ /// `web3signer_should_sign`.
546+ ///
547+ /// The batch attestation signing API returns an empty result instead of an error for
548+ /// slashable attestations.
549+ pub async fn assert_slashable_attestation_should_sign < F , R > (
550+ self ,
551+ case_name : & str ,
552+ generate_sig : F ,
553+ web3signer_should_sign : bool ,
554+ ) -> Self
555+ where
556+ F : Fn (
557+ PublicKeyBytes ,
558+ Arc < LighthouseValidatorStore < TestingSlotClock , E > > ,
559+ ) -> R ,
560+ R : Future < Output = Result < Vec < Attestation < E > > , lighthouse_validator_store:: Error > > ,
561+ {
562+ for validator_rig in & self . validator_rigs {
563+ let result =
564+ generate_sig ( self . validator_pubkey , validator_rig. validator_store . clone ( ) )
565+ . await ;
566+
567+ if !validator_rig. using_web3signer || !web3signer_should_sign {
568+ // For local validators, slashable attestations should return an empty result
569+ // or an error.
570+ match result {
571+ Ok ( attestations) => {
572+ assert ! (
573+ attestations. is_empty( ) ,
574+ "should not sign slashable {case_name}: expected empty result"
575+ ) ;
576+ }
577+ Err ( ValidatorStoreError :: Slashable ( _) ) => {
578+ // Also acceptable - error indicates slashable
579+ }
580+ Err ( e) => {
581+ panic ! ( "unexpected error for slashable {case_name}: {e:?}" ) ;
582+ }
583+ }
584+ } else {
585+ // Web3signer should sign (has its own slashing protection)
586+ let attestations = result. expect ( "should sign slashable {case_name}" ) ;
587+ assert ! (
588+ !attestations. is_empty( ) ,
589+ "web3signer should sign slashable {case_name}"
590+ ) ;
591+ }
592+ }
593+ self
594+ }
542595 }
543596
544597 /// Get a generic, arbitrary attestation for signing.
@@ -838,38 +891,35 @@ mod tests {
838891 . unwrap ( )
839892 } )
840893 . await
841- . assert_slashable_message_should_sign (
894+ . assert_slashable_attestation_should_sign (
842895 "double_vote_attestation" ,
843896 move |pubkey, validator_store| async move {
844897 let attestation = double_vote_attestation ( ) ;
845898 validator_store
846899 . sign_attestations ( vec ! [ ( pubkey, 0 , attestation) ] )
847900 . await
848- . map ( |_| ( ) )
849901 } ,
850902 slashable_message_should_sign,
851903 )
852904 . await
853- . assert_slashable_message_should_sign (
905+ . assert_slashable_attestation_should_sign (
854906 "surrounding_attestation" ,
855907 move |pubkey, validator_store| async move {
856908 let attestation = surrounding_attestation ( ) ;
857909 validator_store
858910 . sign_attestations ( vec ! [ ( pubkey, 0 , attestation) ] )
859911 . await
860- . map ( |_| ( ) )
861912 } ,
862913 slashable_message_should_sign,
863914 )
864915 . await
865- . assert_slashable_message_should_sign (
916+ . assert_slashable_attestation_should_sign (
866917 "surrounded_attestation" ,
867918 move |pubkey, validator_store| async move {
868919 let attestation = surrounded_attestation ( ) ;
869920 validator_store
870921 . sign_attestations ( vec ! [ ( pubkey, 0 , attestation) ] )
871922 . await
872- . map ( |_| ( ) )
873923 } ,
874924 slashable_message_should_sign,
875925 )
0 commit comments