@@ -834,3 +834,95 @@ fn test_closing_signed_reinit_timeout() {
834834 do_test_closing_signed_reinit_timeout ( TimeoutStep :: AfterClosingSigned ) ;
835835 do_test_closing_signed_reinit_timeout ( TimeoutStep :: NoTimeout ) ;
836836}
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