@@ -834,3 +834,95 @@ fn test_closing_signed_reinit_timeout() {
834
834
do_test_closing_signed_reinit_timeout ( TimeoutStep :: AfterClosingSigned ) ;
835
835
do_test_closing_signed_reinit_timeout ( TimeoutStep :: NoTimeout ) ;
836
836
}
837
+
838
+ fn do_simple_legacy_shutdown_test ( high_initiator_fee : bool ) {
839
+ // A simpe test of the legacy shutdown fee negotiation logic.
840
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
841
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
842
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
843
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
844
+
845
+ let chan = create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
846
+
847
+ if high_initiator_fee {
848
+ // If high_initiator_fee is set, set nodes[0]'s feerate significantly higher. This
849
+ // shouldn't impact the flow at all given nodes[1] will happily accept the higher fee.
850
+ let mut feerate_lock = chanmon_cfgs[ 0 ] . fee_estimator . sat_per_kw . lock ( ) . unwrap ( ) ;
851
+ * feerate_lock *= 10 ;
852
+ }
853
+
854
+ nodes[ 0 ] . node . close_channel ( & OutPoint { txid : chan. 3 . txid ( ) , index : 0 } . to_channel_id ( ) ) . unwrap ( ) ;
855
+ let node_0_shutdown = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendShutdown , nodes[ 1 ] . node. get_our_node_id( ) ) ;
856
+ nodes[ 1 ] . node . handle_shutdown ( & nodes[ 0 ] . node . get_our_node_id ( ) , & InitFeatures :: known ( ) , & node_0_shutdown) ;
857
+ let node_1_shutdown = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendShutdown , nodes[ 0 ] . node. get_our_node_id( ) ) ;
858
+ nodes[ 0 ] . node . handle_shutdown ( & nodes[ 1 ] . node . get_our_node_id ( ) , & InitFeatures :: known ( ) , & node_1_shutdown) ;
859
+
860
+ let mut node_0_closing_signed = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendClosingSigned , nodes[ 1 ] . node. get_our_node_id( ) ) ;
861
+ node_0_closing_signed. fee_range = None ;
862
+ if high_initiator_fee {
863
+ assert ! ( node_0_closing_signed. fee_satoshis > 500 ) ;
864
+ } else {
865
+ assert ! ( node_0_closing_signed. fee_satoshis < 500 ) ;
866
+ }
867
+
868
+ nodes[ 1 ] . node . handle_closing_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & node_0_closing_signed) ;
869
+ let ( _, mut node_1_closing_signed) = get_closing_signed_broadcast ! ( nodes[ 1 ] . node, nodes[ 0 ] . node. get_our_node_id( ) ) ;
870
+ node_1_closing_signed. as_mut ( ) . unwrap ( ) . fee_range = None ;
871
+
872
+ nodes[ 0 ] . node . handle_closing_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & node_1_closing_signed. unwrap ( ) ) ;
873
+ let ( _, node_0_none) = get_closing_signed_broadcast ! ( nodes[ 0 ] . node, nodes[ 1 ] . node. get_our_node_id( ) ) ;
874
+ assert ! ( node_0_none. is_none( ) ) ;
875
+ }
876
+
877
+ #[ test]
878
+ fn simple_legacy_shutdown_test ( ) {
879
+ do_simple_legacy_shutdown_test ( false ) ;
880
+ do_simple_legacy_shutdown_test ( true ) ;
881
+ }
882
+
883
+ #[ test]
884
+ fn simple_target_feerate_shutdown ( ) {
885
+ // Simple test of target in `close_channel_with_target_feerate`.
886
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
887
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
888
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
889
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
890
+
891
+ let chan = create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
892
+ let chan_id = OutPoint { txid : chan. 3 . txid ( ) , index : 0 } . to_channel_id ( ) ;
893
+
894
+ nodes[ 0 ] . node . close_channel_with_target_feerate ( & chan_id, 253 * 10 ) . unwrap ( ) ;
895
+ let node_0_shutdown = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendShutdown , nodes[ 1 ] . node. get_our_node_id( ) ) ;
896
+ nodes[ 1 ] . node . close_channel_with_target_feerate ( & chan_id, 253 * 5 ) . unwrap ( ) ;
897
+ let node_1_shutdown = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendShutdown , nodes[ 0 ] . node. get_our_node_id( ) ) ;
898
+
899
+ nodes[ 1 ] . node . handle_shutdown ( & nodes[ 0 ] . node . get_our_node_id ( ) , & InitFeatures :: known ( ) , & node_0_shutdown) ;
900
+ nodes[ 0 ] . node . handle_shutdown ( & nodes[ 1 ] . node . get_our_node_id ( ) , & InitFeatures :: known ( ) , & node_1_shutdown) ;
901
+
902
+ let node_0_closing_signed = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendClosingSigned , nodes[ 1 ] . node. get_our_node_id( ) ) ;
903
+ nodes[ 1 ] . node . handle_closing_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & node_0_closing_signed) ;
904
+ let ( _, node_1_closing_signed_opt) = get_closing_signed_broadcast ! ( nodes[ 1 ] . node, nodes[ 0 ] . node. get_our_node_id( ) ) ;
905
+ let node_1_closing_signed = node_1_closing_signed_opt. unwrap ( ) ;
906
+
907
+ // nodes[1] was passed a target which was larger than the current channel feerate, which it
908
+ // should ignore in favor of the channel fee, as there is no use demanding a minimum higher
909
+ // than what will be paid on a force-close transaction. Note that we have to consider rounding,
910
+ // so only check that we're within 10 sats.
911
+ assert ! ( node_0_closing_signed. fee_range. as_ref( ) . unwrap( ) . min_fee_satoshis >=
912
+ node_1_closing_signed. fee_range. as_ref( ) . unwrap( ) . min_fee_satoshis * 10 - 5 ) ;
913
+ assert ! ( node_0_closing_signed. fee_range. as_ref( ) . unwrap( ) . min_fee_satoshis <=
914
+ node_1_closing_signed. fee_range. as_ref( ) . unwrap( ) . min_fee_satoshis * 10 + 5 ) ;
915
+
916
+ // Further, because nodes[0]'s target fee is larger than the `Normal` fee estimation plus our
917
+ // force-closure-avoidance buffer, min should equal max, and the nodes[1]-selected fee should
918
+ // be the nodes[0] only available fee.
919
+ assert_eq ! ( node_0_closing_signed. fee_range. as_ref( ) . unwrap( ) . min_fee_satoshis,
920
+ node_0_closing_signed. fee_range. as_ref( ) . unwrap( ) . max_fee_satoshis) ;
921
+ assert_eq ! ( node_0_closing_signed. fee_range. as_ref( ) . unwrap( ) . min_fee_satoshis,
922
+ node_0_closing_signed. fee_satoshis) ;
923
+ assert_eq ! ( node_0_closing_signed. fee_satoshis, node_1_closing_signed. fee_satoshis) ;
924
+
925
+ nodes[ 0 ] . node . handle_closing_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & node_1_closing_signed) ;
926
+ let ( _, node_0_none) = get_closing_signed_broadcast ! ( nodes[ 0 ] . node, nodes[ 1 ] . node. get_our_node_id( ) ) ;
927
+ assert ! ( node_0_none. is_none( ) ) ;
928
+ }
0 commit comments