@@ -619,3 +619,103 @@ fn test_shutdown_script_segwit_but_not_anysegwit() {
619619 }
620620 check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
621621}
622+
623+ fn do_test_closing_signed_reinit_timeout ( timeout_step : u8 ) {
624+ // The range-based closing signed negotiation allows the funder to restart the process with a
625+ // new range if the previous range did not overlap. This allows implementations to request user
626+ // intervention allowing users to enter a new fee range. We do not implement the sending side
627+ // of this, instead opting to allow users to enter an explicit "willing to pay up to X to avoid
628+ // force-closing" value and relying on that instead.
629+ //
630+ // Here we run test the fundee side of that restart mechanism, implementing the funder side of
631+ // it manually.
632+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
633+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
634+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
635+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
636+ let chan_id = create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) . 2 ;
637+
638+ send_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 8_000_000 ) ;
639+
640+ nodes[ 0 ] . node . close_channel ( & chan_id, None ) . unwrap ( ) ;
641+ let node_0_shutdown = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendShutdown , nodes[ 1 ] . node. get_our_node_id( ) ) ;
642+ nodes[ 1 ] . node . handle_shutdown ( & nodes[ 0 ] . node . get_our_node_id ( ) , & InitFeatures :: known ( ) , & node_0_shutdown) ;
643+ let node_1_shutdown = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendShutdown , nodes[ 0 ] . node. get_our_node_id( ) ) ;
644+ nodes[ 0 ] . node . handle_shutdown ( & nodes[ 1 ] . node . get_our_node_id ( ) , & InitFeatures :: known ( ) , & node_1_shutdown) ;
645+
646+ {
647+ // Now we set nodes[1] to require a relatively high feerate for closing. This should result
648+ // in it rejecting nodes[0]'s initial closing_signed, giving nodes[0] a chance to try
649+ // again.
650+ let mut feerate_lock = chanmon_cfgs[ 1 ] . fee_estimator . sat_per_kw . lock ( ) . unwrap ( ) ;
651+ * feerate_lock *= 10 ;
652+ }
653+
654+ let mut node_0_closing_signed = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendClosingSigned , nodes[ 1 ] . node. get_our_node_id( ) ) ;
655+ assert ! ( node_0_closing_signed. fee_satoshis <= 500 ) ;
656+
657+ if timeout_step != 0 {
658+ nodes[ 1 ] . node . handle_closing_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & node_0_closing_signed) ;
659+ // At this point nodes[1] should send back a warning message indicating it disagrees with the
660+ // given channel-closing fee. Currently we do not implement warning messages so instead we
661+ // remain silent here.
662+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
663+
664+ // Now deliver a mutated closing_signed indicating a higher acceptable fee range, which
665+ // nodes[1] should happily accept and respond to.
666+ node_0_closing_signed. fee_range . as_mut ( ) . unwrap ( ) . max_fee_satoshis *= 10 ;
667+ {
668+ let mut lock;
669+ get_channel_ref ! ( nodes[ 0 ] , lock, chan_id) . closing_fee_limits . as_mut ( ) . unwrap ( ) . 1 *= 10 ;
670+ }
671+ nodes[ 1 ] . node . handle_closing_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & node_0_closing_signed) ;
672+ let node_1_closing_signed = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendClosingSigned , nodes[ 0 ] . node. get_our_node_id( ) ) ;
673+ nodes[ 0 ] . node . handle_closing_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & node_1_closing_signed) ;
674+ let node_0_2nd_closing_signed = get_closing_signed_broadcast ! ( nodes[ 0 ] . node, nodes[ 1 ] . node. get_our_node_id( ) ) ;
675+ if timeout_step > 1 {
676+ nodes[ 1 ] . node . handle_closing_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & node_0_2nd_closing_signed. 1 . unwrap ( ) ) ;
677+ }
678+ }
679+
680+ if timeout_step <= 1 {
681+ assert ! ( nodes[ 1 ] . tx_broadcaster. txn_broadcasted. lock( ) . unwrap( ) . is_empty( ) ) ;
682+ } else {
683+ assert_eq ! ( nodes[ 1 ] . tx_broadcaster. txn_broadcasted. lock( ) . unwrap( ) . len( ) , 1 ) ;
684+ }
685+
686+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
687+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
688+
689+ let txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
690+ assert_eq ! ( txn. len( ) , 1 ) ;
691+ assert_eq ! ( txn[ 0 ] . output. len( ) , 2 ) ;
692+
693+ // If we timed out we should have a P2WPKH and P2WSH output, otherwise both should be P2WPKH.
694+ if timeout_step <= 1 {
695+ assert ! ( ( txn[ 0 ] . output[ 0 ] . script_pubkey. len( ) == 20 +1 +1 &&
696+ txn[ 0 ] . output[ 1 ] . script_pubkey. len( ) == 32 +1 +1 ) ||
697+ ( txn[ 0 ] . output[ 1 ] . script_pubkey. len( ) == 20 +1 +1 &&
698+ txn[ 0 ] . output[ 0 ] . script_pubkey. len( ) == 32 +1 +1 ) ) ;
699+ check_closed_broadcast ! ( nodes[ 1 ] , true ) ;
700+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
701+ } else {
702+ assert_eq ! ( txn[ 0 ] . output[ 0 ] . script_pubkey. len( ) , 20 +1 +1 ) ;
703+ assert_eq ! ( txn[ 0 ] . output[ 1 ] . script_pubkey. len( ) , 20 +1 +1 ) ;
704+
705+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
706+ assert_eq ! ( events. len( ) , 1 ) ;
707+ match events[ 0 ] {
708+ MessageSendEvent :: BroadcastChannelUpdate { ref msg } => {
709+ assert_eq ! ( msg. contents. flags & 2 , 2 ) ;
710+ } ,
711+ _ => panic ! ( "Unexpected event" ) ,
712+ }
713+ }
714+ }
715+
716+ #[ test]
717+ fn test_closing_signed_reinit_timeout ( ) {
718+ do_test_closing_signed_reinit_timeout ( 0 ) ;
719+ do_test_closing_signed_reinit_timeout ( 1 ) ;
720+ do_test_closing_signed_reinit_timeout ( 2 ) ;
721+ }
0 commit comments