@@ -459,6 +459,86 @@ mod tests {
459459 update. next_sync_committee = None ;
460460 contract. submit_beacon_chain_light_client_update ( update) ;
461461 }
462+
463+ #[ test]
464+ #[ should_panic( expected = "BLS12381InvalidInput" ) ]
465+ pub fn test_panic_on_invalid_bls_signature ( ) {
466+ let TestContext {
467+ mut contract,
468+ headers : _,
469+ updates,
470+ } = get_test_context ( None ) ;
471+ set_env ! ( prepaid_gas: Gas :: from_tgas( 1_000_000 ) , predecessor_account_id: accounts( 0 ) ) ;
472+ let mut update = updates[ 1 ] . clone ( ) ;
473+
474+ // Corrupt the BLS signature by modifying the last byte
475+ let mut signature_bytes = update. sync_aggregate . sync_committee_signature . 0 . to_vec ( ) ;
476+ let last_idx = signature_bytes. len ( ) - 1 ;
477+ signature_bytes[ last_idx] = signature_bytes[ last_idx] . wrapping_add ( 1 ) ;
478+ update. sync_aggregate . sync_committee_signature = signature_bytes. into ( ) ;
479+
480+ contract. submit_beacon_chain_light_client_update ( update) ;
481+ }
482+
483+ #[ test]
484+ #[ should_panic( expected = "Failed to verify the bls signature" ) ]
485+ pub fn test_panic_on_mismatched_sync_committee_bits ( ) {
486+ let TestContext {
487+ mut contract,
488+ headers : _,
489+ updates,
490+ } = get_test_context ( None ) ;
491+ set_env ! ( prepaid_gas: Gas :: from_tgas( 1_000_000 ) , predecessor_account_id: accounts( 0 ) ) ;
492+ let mut update = updates[ 1 ] . clone ( ) ;
493+
494+ // Create a sync committee bits pattern that doesn't match the signature
495+ // but still meets the minimum participation threshold
496+ let mut sync_committee_bits = bitarr ! [ u8 , Lsb0 ; 0 ; 512 ] ;
497+ // Set exactly 342 bits (minimum required) but in different positions
498+ // than the original signature was created for
499+ for i in 0 ..342 {
500+ sync_committee_bits. set ( i, true ) ;
501+ }
502+ update. sync_aggregate . sync_committee_bits = sync_committee_bits. as_raw_mut_slice ( ) . to_vec ( ) . into ( ) ;
503+
504+ contract. submit_beacon_chain_light_client_update ( update) ;
505+ }
506+
507+ #[ test]
508+ #[ should_panic( expected = "BLS12381InvalidInput" ) ]
509+ pub fn test_panic_on_zero_bls_signature ( ) {
510+ let TestContext {
511+ mut contract,
512+ headers : _,
513+ updates,
514+ } = get_test_context ( None ) ;
515+ set_env ! ( prepaid_gas: Gas :: from_tgas( 1_000_000 ) , predecessor_account_id: accounts( 0 ) ) ;
516+ let mut update = updates[ 1 ] . clone ( ) ;
517+
518+ // Set signature to all zeros
519+ let signature_bytes = vec ! [ 0u8 ; 96 ] ;
520+ update. sync_aggregate . sync_committee_signature = signature_bytes. into ( ) ;
521+
522+ contract. submit_beacon_chain_light_client_update ( update) ;
523+ }
524+
525+ #[ test]
526+ #[ should_panic( expected = "Failed to verify the bls signature" ) ]
527+ pub fn test_panic_on_wrong_attested_header ( ) {
528+ let TestContext {
529+ mut contract,
530+ headers : _,
531+ updates,
532+ } = get_test_context ( None ) ;
533+ set_env ! ( prepaid_gas: Gas :: from_tgas( 1_000_000 ) , predecessor_account_id: accounts( 0 ) ) ;
534+ let mut update = updates[ 1 ] . clone ( ) ;
535+
536+ // Modify the attested header to make signature verification fail
537+ // but keep the signature and bits valid (so it passes format checks)
538+ update. attested_beacon_header . slot = update. attested_beacon_header . slot + 1 ;
539+
540+ contract. submit_beacon_chain_light_client_update ( update) ;
541+ }
462542 }
463543
464544 #[ cfg( feature = "mainnet" ) ]
0 commit comments