@@ -759,3 +759,122 @@ 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
+ fn do_test_retries_own_commitment_broadcast_after_reorg ( anchors : bool , revoked_counterparty_commitment : bool ) {
764
+ // Tests that a node will retry broadcasting its own commitment after seeing a confirmed
765
+ // counterparty commitment be reorged out.
766
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
767
+ if revoked_counterparty_commitment {
768
+ chanmon_cfgs[ 1 ] . keys_manager . disable_revocation_policy_check = true ;
769
+ }
770
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
771
+ let mut config = test_default_channel_config ( ) ;
772
+ if anchors {
773
+ config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
774
+ config. manually_accept_inbound_channels = true ;
775
+ }
776
+ let persister;
777
+ let new_chain_monitor;
778
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( config) , Some ( config) ] ) ;
779
+ let nodes_1_deserialized;
780
+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
781
+
782
+ let ( _, _, chan_id, funding_tx) = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
783
+
784
+ // Route a payment so we have an HTLC to claim as well.
785
+ let _ = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 1_000_000 ) ;
786
+
787
+ if revoked_counterparty_commitment {
788
+ // Trigger a fee update such that we advance the state. We will have B broadcast its state
789
+ // without the fee update.
790
+ let serialized_node = nodes[ 1 ] . node . encode ( ) ;
791
+ let serialized_monitor = get_monitor ! ( nodes[ 1 ] , chan_id) . encode ( ) ;
792
+
793
+ * chanmon_cfgs[ 0 ] . fee_estimator . sat_per_kw . lock ( ) . unwrap ( ) += 1 ;
794
+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
795
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
796
+
797
+ let fee_update = get_htlc_update_msgs ! ( nodes[ 0 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
798
+ nodes[ 1 ] . node . handle_update_fee ( & nodes[ 0 ] . node . get_our_node_id ( ) , & fee_update. update_fee . unwrap ( ) ) ;
799
+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , fee_update. commitment_signed, false ) ;
800
+
801
+ reload_node ! (
802
+ nodes[ 1 ] , config, & serialized_node, & [ & serialized_monitor] , persister, new_chain_monitor, nodes_1_deserialized
803
+ ) ;
804
+ }
805
+
806
+ // Connect blocks until the HTLC expiry is met, prompting a commitment broadcast by A.
807
+ connect_blocks ( & nodes[ 0 ] , TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1 ) ;
808
+ check_closed_broadcast ( & nodes[ 0 ] , 1 , true ) ;
809
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
810
+ check_closed_event ( & nodes[ 0 ] , 1 , ClosureReason :: HolderForceClosed , false , & [ nodes[ 1 ] . node . get_our_node_id ( ) ] , 100_000 ) ;
811
+
812
+ {
813
+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
814
+ if anchors {
815
+ assert_eq ! ( txn. len( ) , 1 ) ;
816
+ let commitment_tx_a = txn. pop ( ) . unwrap ( ) ;
817
+ check_spends ! ( commitment_tx_a, funding_tx) ;
818
+ } else {
819
+ assert_eq ! ( txn. len( ) , 2 ) ;
820
+ let htlc_tx_a = txn. pop ( ) . unwrap ( ) ;
821
+ let commitment_tx_a = txn. pop ( ) . unwrap ( ) ;
822
+ check_spends ! ( commitment_tx_a, funding_tx) ;
823
+ check_spends ! ( htlc_tx_a, commitment_tx_a) ;
824
+ }
825
+ } ;
826
+
827
+ // B will also broadcast its own commitment.
828
+ nodes[ 1 ] . node . force_close_broadcasting_latest_txn ( & chan_id, & nodes[ 0 ] . node . get_our_node_id ( ) ) . unwrap ( ) ;
829
+ check_closed_broadcast ( & nodes[ 1 ] , 1 , true ) ;
830
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
831
+ check_closed_event ( & nodes[ 1 ] , 1 , ClosureReason :: HolderForceClosed , false , & [ nodes[ 0 ] . node . get_our_node_id ( ) ] , 100_000 ) ;
832
+
833
+ let commitment_b = {
834
+ let mut txn = nodes[ 1 ] . tx_broadcaster . txn_broadcast ( ) ;
835
+ assert_eq ! ( txn. len( ) , 1 ) ;
836
+ let tx = txn. pop ( ) . unwrap ( ) ;
837
+ check_spends ! ( tx, funding_tx) ;
838
+ tx
839
+ } ;
840
+
841
+ // Confirm B's commitment, A should now broadcast an HTLC timeout for commitment B.
842
+ mine_transaction ( & nodes[ 0 ] , & commitment_b) ;
843
+ {
844
+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
845
+ if nodes[ 0 ] . connect_style . borrow ( ) . updates_best_block_first ( ) {
846
+ // `commitment_a` and `htlc_timeout_a` are rebroadcast because the best block was
847
+ // updated prior to seeing `commitment_b`.
848
+ assert_eq ! ( txn. len( ) , if anchors { 2 } else { 3 } ) ;
849
+ check_spends ! ( txn. last( ) . unwrap( ) , commitment_b) ;
850
+ } else {
851
+ assert_eq ! ( txn. len( ) , 1 ) ;
852
+ check_spends ! ( txn[ 0 ] , commitment_b) ;
853
+ }
854
+ }
855
+
856
+ // Disconnect the block, allowing A to retry its own commitment. Note that we connect two
857
+ // blocks, one to get us back to the original height, and another to retry our pending claims.
858
+ disconnect_blocks ( & nodes[ 0 ] , 1 ) ;
859
+ connect_blocks ( & nodes[ 0 ] , 2 ) ;
860
+ {
861
+ let mut txn = nodes[ 0 ] . tx_broadcaster . unique_txn_broadcast ( ) ;
862
+ if anchors {
863
+ assert_eq ! ( txn. len( ) , 1 ) ;
864
+ check_spends ! ( txn[ 0 ] , funding_tx) ;
865
+ } else {
866
+ assert_eq ! ( txn. len( ) , 2 ) ;
867
+ check_spends ! ( txn[ 0 ] , txn[ 1 ] ) ; // HTLC timeout A
868
+ check_spends ! ( txn[ 1 ] , funding_tx) ; // Commitment A
869
+ assert_ne ! ( txn[ 1 ] . txid( ) , commitment_b. txid( ) ) ;
870
+ }
871
+ }
872
+ }
873
+
874
+ #[ test]
875
+ fn test_retries_own_commitment_broadcast_after_reorg ( ) {
876
+ do_test_retries_own_commitment_broadcast_after_reorg ( false , false ) ;
877
+ do_test_retries_own_commitment_broadcast_after_reorg ( false , true ) ;
878
+ do_test_retries_own_commitment_broadcast_after_reorg ( true , false ) ;
879
+ do_test_retries_own_commitment_broadcast_after_reorg ( true , true ) ;
880
+ }
0 commit comments