@@ -3347,6 +3347,93 @@ mod tests {
33473347 } ) ;
33483348 }
33493349
3350+ #[ test_traced( "WARN" ) ]
3351+ fn test_standard_local_floor_jump_ignores_stale_application_ack ( ) {
3352+ let runner = deterministic:: Runner :: timed ( Duration :: from_secs ( 30 ) ) ;
3353+ runner. start ( |mut context| async move {
3354+ let Fixture { schemes, .. } =
3355+ bls12381_threshold_vrf:: fixture :: < V , _ > ( & mut context, NAMESPACE , NUM_VALIDATORS ) ;
3356+
3357+ let application = Application :: < B > :: manual_ack ( ) ;
3358+ let buffer = RecordingBuffer :: default ( ) ;
3359+ let ( mailbox, _buffer, resolver, _actor_handle) = start_standard_actor (
3360+ context. child ( "validator" ) ,
3361+ "local-floor-jump-ignores-stale-ack" ,
3362+ ConstantProvider :: new ( schemes[ 0 ] . clone ( ) ) ,
3363+ application. clone ( ) ,
3364+ Some ( buffer. clone ( ) ) ,
3365+ Start :: Genesis ( StandardHarness :: genesis_block ( NUM_VALIDATORS as u16 ) ) ,
3366+ )
3367+ . await ;
3368+ let mut mailbox = mailbox;
3369+
3370+ let block1_round = Round :: new ( Epoch :: zero ( ) , View :: new ( 1 ) ) ;
3371+ let block1 = make_raw_block ( Sha256 :: hash ( b"block1-parent" ) , Height :: new ( 1 ) , 100 ) ;
3372+ let block1_finalization = StandardHarness :: make_finalization (
3373+ Proposal :: new (
3374+ block1_round,
3375+ View :: zero ( ) ,
3376+ StandardHarness :: commitment ( & block1) ,
3377+ ) ,
3378+ & schemes,
3379+ QUORUM ,
3380+ ) ;
3381+ assert ! ( mailbox. verified( block1_round, block1) . await ) ;
3382+ StandardHarness :: report_finalization ( & mut mailbox, block1_finalization) . await ;
3383+ wait_until (
3384+ & context,
3385+ Duration :: from_secs ( 5 ) ,
3386+ "first block dispatch" ,
3387+ || application. pending_ack_heights ( ) == vec ! [ Height :: new( 1 ) ] ,
3388+ )
3389+ . await ;
3390+
3391+ let floor_round = Round :: new ( Epoch :: zero ( ) , View :: new ( 5 ) ) ;
3392+ let floor_block =
3393+ make_raw_block ( Sha256 :: hash ( b"local-floor-parent" ) , Height :: new ( 5 ) , 500 ) ;
3394+ let floor_finalization = StandardHarness :: make_finalization (
3395+ Proposal :: new (
3396+ floor_round,
3397+ View :: new ( 4 ) ,
3398+ StandardHarness :: commitment ( & floor_block) ,
3399+ ) ,
3400+ & schemes,
3401+ QUORUM ,
3402+ ) ;
3403+ buffer. insert ( floor_block. clone ( ) ) ;
3404+ mailbox. set_floor ( floor_finalization) ;
3405+ assert_eq ! (
3406+ mailbox
3407+ . get_block( Height :: new( 5 ) )
3408+ . await
3409+ . expect( "floor block missing" )
3410+ . digest( ) ,
3411+ floor_block. digest( )
3412+ ) ;
3413+ assert ! (
3414+ resolver. fetches( ) . is_empty( ) ,
3415+ "local floor anchor must not be fetched"
3416+ ) ;
3417+
3418+ let fetches_after_floor = resolver. fetches ( ) . len ( ) ;
3419+ assert_eq ! ( application. acknowledge_next( ) , Some ( Height :: new( 1 ) ) ) ;
3420+ context. sleep ( Duration :: from_millis ( 100 ) ) . await ;
3421+
3422+ let _subscription = mailbox. subscribe_by_commitment (
3423+ Sha256 :: hash ( b"below-local-floor-after-stale-ack" ) ,
3424+ CommitmentFallback :: FetchByCommitment {
3425+ height : Height :: new ( 2 ) ,
3426+ } ,
3427+ ) ;
3428+ let _ = mailbox. get_block ( Height :: new ( 5 ) ) . await ;
3429+ assert_eq ! (
3430+ resolver. fetches( ) . len( ) ,
3431+ fetches_after_floor,
3432+ "stale pre-floor ack must not lower a locally installed floor"
3433+ ) ;
3434+ } ) ;
3435+ }
3436+
33503437 #[ test_traced( "WARN" ) ]
33513438 fn test_standard_set_floor_repairs_gap_after_anchor_arrives ( ) {
33523439 let runner = deterministic:: Runner :: timed ( Duration :: from_secs ( 30 ) ) ;
0 commit comments