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