@@ -759,3 +759,74 @@ fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterpa
759
759
// commitment (still unrevoked) is the currently confirmed closing transaction.
760
760
assert_eq ! ( htlc_preimage_tx. input[ 0 ] . witness. second_to_last( ) . unwrap( ) , & payment_preimage. 0 [ ..] ) ;
761
761
}
762
+
763
+ #[ test]
764
+ fn test_retries_own_commitment_broadcast_after_reorg ( ) {
765
+ // Tests that a node will retry broadcasting its own commitment after seeing a confirmed
766
+ // counterparty commitment be reorged out.
767
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
768
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
769
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None , None ] ) ;
770
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
771
+
772
+ let ( _, _, chan_id, funding_tx) = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
773
+
774
+ // Route a payment so we have an HTLC to claim as well.
775
+ let _ = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 1_000_000 ) ;
776
+
777
+ // Connect blocks until the HTLC expiry is met, prompting a commitment broadcast by A.
778
+ connect_blocks ( & nodes[ 0 ] , TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1 ) ;
779
+ check_closed_broadcast ( & nodes[ 0 ] , 1 , true ) ;
780
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
781
+ check_closed_event ( & nodes[ 0 ] , 1 , ClosureReason :: HolderForceClosed , false , & [ nodes[ 1 ] . node . get_our_node_id ( ) ] , 100_000 ) ;
782
+
783
+ {
784
+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
785
+ assert_eq ! ( txn. len( ) , 2 ) ;
786
+ let htlc_tx_a = txn. pop ( ) . unwrap ( ) ;
787
+ let commitment_tx_a = txn. pop ( ) . unwrap ( ) ;
788
+ check_spends ! ( commitment_tx_a, funding_tx) ;
789
+ check_spends ! ( htlc_tx_a, commitment_tx_a) ;
790
+ } ;
791
+
792
+ // B will also broadcast its own commitment.
793
+ nodes[ 1 ] . node . force_close_broadcasting_latest_txn ( & chan_id, & nodes[ 0 ] . node . get_our_node_id ( ) ) . unwrap ( ) ;
794
+ check_closed_broadcast ( & nodes[ 1 ] , 1 , true ) ;
795
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
796
+ check_closed_event ( & nodes[ 1 ] , 1 , ClosureReason :: HolderForceClosed , false , & [ nodes[ 0 ] . node . get_our_node_id ( ) ] , 100_000 ) ;
797
+
798
+ let commitment_b = {
799
+ let mut txn = nodes[ 1 ] . tx_broadcaster . txn_broadcast ( ) ;
800
+ assert_eq ! ( txn. len( ) , 1 ) ;
801
+ let tx = txn. pop ( ) . unwrap ( ) ;
802
+ check_spends ! ( tx, funding_tx) ;
803
+ tx
804
+ } ;
805
+
806
+ // Confirm B's commitment, A should now broadcast an HTLC timeout for commitment B.
807
+ mine_transaction ( & nodes[ 0 ] , & commitment_b) ;
808
+ {
809
+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
810
+ if nodes[ 0 ] . connect_style . borrow ( ) . updates_best_block_first ( ) {
811
+ // `commitment_a` and `htlc_timeout_a` are rebroadcast because the best block was
812
+ // updated prior to seeing `commitment_b`.
813
+ assert_eq ! ( txn. len( ) , 3 ) ;
814
+ check_spends ! ( txn[ 2 ] , commitment_b) ;
815
+ } else {
816
+ assert_eq ! ( txn. len( ) , 1 ) ;
817
+ check_spends ! ( txn[ 0 ] , commitment_b) ;
818
+ }
819
+ }
820
+
821
+ // Disconnect the block, allowing A to retry its own commitment. Note that we connect two
822
+ // blocks, one to get us back to the original height, and another to retry our pending claims.
823
+ disconnect_blocks ( & nodes[ 0 ] , 1 ) ;
824
+ connect_blocks ( & nodes[ 0 ] , 2 ) ;
825
+ {
826
+ let mut txn = nodes[ 0 ] . tx_broadcaster . unique_txn_broadcast ( ) ;
827
+ assert_eq ! ( txn. len( ) , 2 ) ;
828
+ check_spends ! ( txn[ 0 ] , txn[ 1 ] ) ; // HTLC timeout A
829
+ check_spends ! ( txn[ 1 ] , funding_tx) ; // Commitment A
830
+ assert_ne ! ( txn[ 1 ] . txid( ) , commitment_b. txid( ) ) ;
831
+ }
832
+ }
0 commit comments