@@ -3464,7 +3464,16 @@ fn test_lost_preimage_monitor_events() {
3464
3464
do_test_lost_preimage_monitor_events ( false ) ;
3465
3465
}
3466
3466
3467
- fn do_test_lost_timeout_monitor_events ( on_counterparty_tx : bool , dust_htlcs : bool ) {
3467
+ #[ derive( PartialEq ) ]
3468
+ enum CommitmentType {
3469
+ RevokedCounterparty ,
3470
+ LatestCounterparty ,
3471
+ PreviousCounterparty ,
3472
+ LocalWithoutLastHTLC ,
3473
+ LocalWithLastHTLC ,
3474
+ }
3475
+
3476
+ fn do_test_lost_timeout_monitor_events ( confirm_tx : CommitmentType , dust_htlcs : bool ) {
3468
3477
// `MonitorEvent`s aren't delivered to the `ChannelManager` in a durable fasion - if the
3469
3478
// `ChannelManager` fetches the pending `MonitorEvent`s, then the `ChannelMonitor` gets
3470
3479
// persisted (i.e. due to a block update) then the node crashes, prior to persisting the
@@ -3511,9 +3520,37 @@ fn do_test_lost_timeout_monitor_events(on_counterparty_tx: bool, dust_htlcs: boo
3511
3520
3512
3521
send_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , 25_000_000 ) ;
3513
3522
3523
+ let cs_revoked_commit = get_local_commitment_txn ! ( nodes[ 2 ] , chan_b) ;
3524
+ assert_eq ! ( cs_revoked_commit. len( ) , 1 ) ;
3525
+
3514
3526
let amt = if dust_htlcs { 1_000 } else { 10_000_000 } ;
3515
3527
let ( _, hash_a, ..) = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , amt) ;
3516
- let ( _, hash_b, ..) = route_payment ( & nodes[ 1 ] , & [ & nodes[ 2 ] ] , amt) ;
3528
+
3529
+ let cs_previous_commit = get_local_commitment_txn ! ( nodes[ 2 ] , chan_b) ;
3530
+ assert_eq ! ( cs_previous_commit. len( ) , 1 ) ;
3531
+
3532
+ let ( route, hash_b, _, payment_secret_b) =
3533
+ get_route_and_payment_hash ! ( nodes[ 1 ] , nodes[ 2 ] , amt) ;
3534
+ let onion = RecipientOnionFields :: secret_only ( payment_secret_b) ;
3535
+ nodes[ 1 ] . node . send_payment_with_route ( route, hash_b, onion, PaymentId ( hash_b. 0 ) ) . unwrap ( ) ;
3536
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3537
+
3538
+ let updates = get_htlc_update_msgs ( & nodes[ 1 ] , & node_c_id) ;
3539
+ nodes[ 2 ] . node . handle_update_add_htlc ( node_b_id, & updates. update_add_htlcs [ 0 ] ) ;
3540
+ nodes[ 2 ] . node . handle_commitment_signed_batch_test ( node_b_id, & updates. commitment_signed ) ;
3541
+ check_added_monitors ( & nodes[ 2 ] , 1 ) ;
3542
+
3543
+ let ( cs_raa, cs_cs) = get_revoke_commit_msgs ! ( nodes[ 2 ] , node_b_id) ;
3544
+ if confirm_tx == CommitmentType :: LocalWithLastHTLC {
3545
+ // Only deliver the last RAA + CS if we need to update the local commitment with the third
3546
+ // HTLC.
3547
+ nodes[ 1 ] . node . handle_revoke_and_ack ( node_c_id, & cs_raa) ;
3548
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3549
+ nodes[ 1 ] . node . handle_commitment_signed_batch_test ( node_c_id, & cs_cs) ;
3550
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3551
+
3552
+ let _bs_raa = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendRevokeAndACK , node_c_id) ;
3553
+ }
3517
3554
3518
3555
nodes[ 1 ] . node . peer_disconnected ( nodes[ 2 ] . node . get_our_node_id ( ) ) ;
3519
3556
nodes[ 2 ] . node . peer_disconnected ( nodes[ 1 ] . node . get_our_node_id ( ) ) ;
@@ -3547,44 +3584,68 @@ fn do_test_lost_timeout_monitor_events(on_counterparty_tx: bool, dust_htlcs: boo
3547
3584
let bs_commit_tx = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
3548
3585
assert_eq ! ( bs_commit_tx. len( ) , 1 ) ;
3549
3586
3550
- let selected_commit_tx = if on_counterparty_tx {
3551
- & cs_commit_tx[ 0 ]
3552
- } else {
3553
- & bs_commit_tx[ 0 ]
3587
+ let selected_commit_tx = match confirm_tx {
3588
+ CommitmentType :: RevokedCounterparty => & cs_revoked_commit[ 0 ] ,
3589
+ CommitmentType :: PreviousCounterparty => & cs_previous_commit[ 0 ] ,
3590
+ CommitmentType :: LatestCounterparty => & cs_commit_tx[ 0 ] ,
3591
+ CommitmentType :: LocalWithoutLastHTLC |CommitmentType :: LocalWithLastHTLC => & bs_commit_tx[ 0 ] ,
3554
3592
} ;
3555
3593
3556
3594
mine_transaction ( & nodes[ 1 ] , selected_commit_tx) ;
3557
3595
// If the block gets connected first we may re-broadcast B's commitment transaction before
3558
- // seeing the C's confirm.
3559
- nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clear ( ) ;
3596
+ // seeing the C's confirm. In any case, if we confirmed the revoked counterparty commitment
3597
+ // transaction, we want to go ahead and confirm the spend of it.
3598
+ let bs_transactions = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
3599
+ if confirm_tx == CommitmentType :: RevokedCounterparty {
3600
+ assert ! ( bs_transactions. len( ) == 1 || bs_transactions. len( ) == 2 ) ;
3601
+ mine_transaction ( & nodes[ 1 ] , bs_transactions. last ( ) . unwrap ( ) ) ;
3602
+ } else {
3603
+ assert ! ( bs_transactions. len( ) == 1 || bs_transactions. len( ) == 0 ) ;
3604
+ }
3605
+
3560
3606
connect_blocks ( & nodes[ 1 ] , ANTI_REORG_DELAY - 1 ) ;
3561
3607
let mut events = nodes[ 1 ] . chain_monitor . chain_monitor . get_and_clear_pending_events ( ) ;
3562
- if on_counterparty_tx {
3563
- assert_eq ! ( events. len( ) , 1 , "{events:?}" ) ;
3564
- match events[ 0 ] {
3565
- Event :: SpendableOutputs { .. } => { } ,
3566
- _ => panic ! ( "Unexpected event {events:?}" ) ,
3567
- }
3568
- } else {
3569
- assert_eq ! ( events. len( ) , 0 ) ;
3608
+ match confirm_tx {
3609
+ CommitmentType :: LocalWithoutLastHTLC |CommitmentType :: LocalWithLastHTLC => {
3610
+ assert_eq ! ( events. len( ) , 0 , "{events:?}" ) ;
3611
+ } ,
3612
+ CommitmentType :: PreviousCounterparty |CommitmentType :: LatestCounterparty => {
3613
+ assert_eq ! ( events. len( ) , 1 , "{events:?}" ) ;
3614
+ match events[ 0 ] {
3615
+ Event :: SpendableOutputs { .. } => { } ,
3616
+ _ => panic ! ( "Unexpected event {events:?}" ) ,
3617
+ }
3618
+ } ,
3619
+ CommitmentType :: RevokedCounterparty => {
3620
+ assert_eq ! ( events. len( ) , 2 , "{events:?}" ) ;
3621
+ for event in events {
3622
+ match event {
3623
+ Event :: SpendableOutputs { .. } => { } ,
3624
+ _ => panic ! ( "Unexpected event {event:?}" ) ,
3625
+ }
3626
+ }
3627
+ } ,
3570
3628
}
3571
3629
3572
- connect_blocks ( & nodes[ 1 ] , TEST_FINAL_CLTV - ANTI_REORG_DELAY + 1 ) ;
3573
- if !on_counterparty_tx {
3574
- if !dust_htlcs {
3575
- handle_bump_events ( & nodes[ 1 ] , false , 1 ) ;
3630
+ if confirm_tx != CommitmentType :: RevokedCounterparty {
3631
+ connect_blocks ( & nodes[ 1 ] , TEST_FINAL_CLTV - ANTI_REORG_DELAY + 1 ) ;
3632
+ if confirm_tx == CommitmentType :: LocalWithoutLastHTLC || confirm_tx == CommitmentType :: LocalWithLastHTLC {
3633
+ if !dust_htlcs {
3634
+ handle_bump_events ( & nodes[ 1 ] , false , 1 ) ;
3635
+ }
3576
3636
}
3577
3637
}
3638
+
3578
3639
let bs_htlc_timeouts =
3579
3640
nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
3580
- if dust_htlcs {
3641
+ if dust_htlcs || confirm_tx == CommitmentType :: RevokedCounterparty {
3581
3642
assert_eq ! ( bs_htlc_timeouts. len( ) , 0 ) ;
3582
3643
} else {
3583
3644
assert_eq ! ( bs_htlc_timeouts. len( ) , 1 ) ;
3584
3645
3585
3646
// Now replay the timeouts on node B, which after 6 confirmations should fail the HTLCs via
3586
3647
// `MonitorUpdate`s
3587
- mine_transactions ( & nodes[ 1 ] , & bs_htlc_timeouts. iter ( ) . collect :: < Vec < _ > > ( ) ) ;
3648
+ mine_transaction ( & nodes[ 1 ] , & bs_htlc_timeouts[ 0 ] ) ;
3588
3649
connect_blocks ( & nodes[ 1 ] , ANTI_REORG_DELAY - 1 ) ;
3589
3650
}
3590
3651
@@ -3637,8 +3698,14 @@ fn do_test_lost_timeout_monitor_events(on_counterparty_tx: bool, dust_htlcs: boo
3637
3698
3638
3699
#[ test]
3639
3700
fn test_lost_timeout_monitor_events ( ) {
3640
- do_test_lost_timeout_monitor_events ( true , false ) ;
3641
- do_test_lost_timeout_monitor_events ( false , false ) ;
3642
- do_test_lost_timeout_monitor_events ( true , true ) ;
3643
- do_test_lost_timeout_monitor_events ( false , true ) ;
3701
+ do_test_lost_timeout_monitor_events ( CommitmentType :: RevokedCounterparty , false ) ;
3702
+ do_test_lost_timeout_monitor_events ( CommitmentType :: RevokedCounterparty , true ) ;
3703
+ do_test_lost_timeout_monitor_events ( CommitmentType :: PreviousCounterparty , false ) ;
3704
+ do_test_lost_timeout_monitor_events ( CommitmentType :: PreviousCounterparty , true ) ;
3705
+ do_test_lost_timeout_monitor_events ( CommitmentType :: LatestCounterparty , false ) ;
3706
+ do_test_lost_timeout_monitor_events ( CommitmentType :: LatestCounterparty , true ) ;
3707
+ do_test_lost_timeout_monitor_events ( CommitmentType :: LocalWithoutLastHTLC , false ) ;
3708
+ do_test_lost_timeout_monitor_events ( CommitmentType :: LocalWithoutLastHTLC , true ) ;
3709
+ do_test_lost_timeout_monitor_events ( CommitmentType :: LocalWithLastHTLC , false ) ;
3710
+ do_test_lost_timeout_monitor_events ( CommitmentType :: LocalWithLastHTLC , true ) ;
3644
3711
}
0 commit comments