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