@@ -726,3 +726,103 @@ fn test_invalid_shutdown_script() {
726
726
}
727
727
check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
728
728
}
729
+
730
+ fn do_test_closing_signed_reinit_timeout ( timeout_step : u8 ) {
731
+ // The range-based closing signed negotiation allows the funder to restart the process with a
732
+ // new range if the previous range did not overlap. This allows implementations to request user
733
+ // intervention allowing users to enter a new fee range. We do not implement the sending side
734
+ // of this, instead opting to allow users to enter an explicit "willing to pay up to X to avoid
735
+ // force-closing" value and relying on that instead.
736
+ //
737
+ // Here we run test the fundee side of that restart mechanism, implementing the funder side of
738
+ // it manually.
739
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
740
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
741
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
742
+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
743
+ let chan_id = create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) . 2 ;
744
+
745
+ send_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 8_000_000 ) ;
746
+
747
+ nodes[ 0 ] . node . close_channel ( & chan_id, None ) . unwrap ( ) ;
748
+ let node_0_shutdown = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendShutdown , nodes[ 1 ] . node. get_our_node_id( ) ) ;
749
+ nodes[ 1 ] . node . handle_shutdown ( & nodes[ 0 ] . node . get_our_node_id ( ) , & InitFeatures :: known ( ) , & node_0_shutdown) ;
750
+ let node_1_shutdown = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendShutdown , nodes[ 0 ] . node. get_our_node_id( ) ) ;
751
+ nodes[ 0 ] . node . handle_shutdown ( & nodes[ 1 ] . node . get_our_node_id ( ) , & InitFeatures :: known ( ) , & node_1_shutdown) ;
752
+
753
+ {
754
+ // Now we set nodes[1] to require a relatively high feerate for closing. This should result
755
+ // in it rejecting nodes[0]'s initial closing_signed, giving nodes[0] a chance to try
756
+ // again.
757
+ let mut feerate_lock = chanmon_cfgs[ 1 ] . fee_estimator . sat_per_kw . lock ( ) . unwrap ( ) ;
758
+ * feerate_lock *= 10 ;
759
+ }
760
+
761
+ let mut node_0_closing_signed = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendClosingSigned , nodes[ 1 ] . node. get_our_node_id( ) ) ;
762
+ assert ! ( node_0_closing_signed. fee_satoshis <= 500 ) ;
763
+
764
+ if timeout_step != 0 {
765
+ nodes[ 1 ] . node . handle_closing_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & node_0_closing_signed) ;
766
+ // At this point nodes[1] should send back a warning message indicating it disagrees with the
767
+ // given channel-closing fee. Currently we do not implement warning messages so instead we
768
+ // remain silent here.
769
+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
770
+
771
+ // Now deliver a mutated closing_signed indicating a higher acceptable fee range, which
772
+ // nodes[1] should happily accept and respond to.
773
+ node_0_closing_signed. fee_range . as_mut ( ) . unwrap ( ) . max_fee_satoshis *= 10 ;
774
+ {
775
+ let mut lock;
776
+ get_channel_ref ! ( nodes[ 0 ] , lock, chan_id) . closing_fee_limits . as_mut ( ) . unwrap ( ) . 1 *= 10 ;
777
+ }
778
+ nodes[ 1 ] . node . handle_closing_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & node_0_closing_signed) ;
779
+ let node_1_closing_signed = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendClosingSigned , nodes[ 0 ] . node. get_our_node_id( ) ) ;
780
+ nodes[ 0 ] . node . handle_closing_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & node_1_closing_signed) ;
781
+ let node_0_2nd_closing_signed = get_closing_signed_broadcast ! ( nodes[ 0 ] . node, nodes[ 1 ] . node. get_our_node_id( ) ) ;
782
+ if timeout_step > 1 {
783
+ nodes[ 1 ] . node . handle_closing_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & node_0_2nd_closing_signed. 1 . unwrap ( ) ) ;
784
+ }
785
+ }
786
+
787
+ if timeout_step <= 1 {
788
+ assert ! ( nodes[ 1 ] . tx_broadcaster. txn_broadcasted. lock( ) . unwrap( ) . is_empty( ) ) ;
789
+ } else {
790
+ assert_eq ! ( nodes[ 1 ] . tx_broadcaster. txn_broadcasted. lock( ) . unwrap( ) . len( ) , 1 ) ;
791
+ }
792
+
793
+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
794
+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
795
+
796
+ let txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
797
+ assert_eq ! ( txn. len( ) , 1 ) ;
798
+ assert_eq ! ( txn[ 0 ] . output. len( ) , 2 ) ;
799
+
800
+ // If we timed out we should have a P2WPKH and P2WSH output, otherwise both should be P2WPKH.
801
+ if timeout_step <= 1 {
802
+ assert ! ( ( txn[ 0 ] . output[ 0 ] . script_pubkey. len( ) == 20 +1 +1 &&
803
+ txn[ 0 ] . output[ 1 ] . script_pubkey. len( ) == 32 +1 +1 ) ||
804
+ ( txn[ 0 ] . output[ 1 ] . script_pubkey. len( ) == 20 +1 +1 &&
805
+ txn[ 0 ] . output[ 0 ] . script_pubkey. len( ) == 32 +1 +1 ) ) ;
806
+ check_closed_broadcast ! ( nodes[ 1 ] , true ) ;
807
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
808
+ } else {
809
+ assert_eq ! ( txn[ 0 ] . output[ 0 ] . script_pubkey. len( ) , 20 +1 +1 ) ;
810
+ assert_eq ! ( txn[ 0 ] . output[ 1 ] . script_pubkey. len( ) , 20 +1 +1 ) ;
811
+
812
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
813
+ assert_eq ! ( events. len( ) , 1 ) ;
814
+ match events[ 0 ] {
815
+ MessageSendEvent :: BroadcastChannelUpdate { ref msg } => {
816
+ assert_eq ! ( msg. contents. flags & 2 , 2 ) ;
817
+ } ,
818
+ _ => panic ! ( "Unexpected event" ) ,
819
+ }
820
+ }
821
+ }
822
+
823
+ #[ test]
824
+ fn test_closing_signed_reinit_timeout ( ) {
825
+ do_test_closing_signed_reinit_timeout ( 0 ) ;
826
+ do_test_closing_signed_reinit_timeout ( 1 ) ;
827
+ do_test_closing_signed_reinit_timeout ( 2 ) ;
828
+ }
0 commit comments