Move `Channel::get_*_pending_htlc_stats` to `ChannelContext` impl
[rust-lightning] / lightning / src / ln / functional_tests.rs
index ec0068f3194f126843c918763b78a8fbde53312c..d64060be79607cf84f0247c9574317285c8ddb0d 100644 (file)
@@ -20,9 +20,9 @@ use crate::chain::transaction::OutPoint;
 use crate::sign::{ChannelSigner, EcdsaChannelSigner, EntropySource};
 use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason};
 use crate::ln::{PaymentPreimage, PaymentSecret, PaymentHash};
-use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT};
+use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT, get_holder_selected_channel_reserve_satoshis};
 use crate::ln::channelmanager::{self, PaymentId, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, BREAKDOWN_TIMEOUT, ENABLE_GOSSIP_TICKS, DISABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA};
-use crate::ln::channel::{Channel, ChannelError};
+use crate::ln::channel::{DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, Channel, ChannelError};
 use crate::ln::{chan_utils, onion_utils};
 use crate::ln::chan_utils::{OFFERED_HTLC_SCRIPT_WEIGHT, htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
 use crate::routing::gossip::{NetworkGraph, NetworkUpdate};
@@ -75,7 +75,7 @@ fn test_insane_channel_opens() {
        // Instantiate channel parameters where we push the maximum msats given our
        // funding satoshis
        let channel_value_sat = 31337; // same as funding satoshis
-       let channel_reserve_satoshis = Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(channel_value_sat, &cfg);
+       let channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_sat, &cfg);
        let push_msat = (channel_value_sat - channel_reserve_satoshis) * 1000;
 
        // Have node0 initiate a channel to node1 with aforementioned parameters
@@ -157,7 +157,7 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) {
        let feerate_per_kw = 253;
        let opt_anchors = false;
        push_amt -= feerate_per_kw as u64 * (commitment_tx_base_weight(opt_anchors) + 4 * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 * 1000;
-       push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
+       push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
 
        let temp_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, if send_from_initiator { 0 } else { push_amt }, 42, None).unwrap();
        let mut open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
@@ -180,8 +180,8 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) {
                let mut sender_node_per_peer_lock;
                let mut sender_node_peer_state_lock;
                let mut chan = get_channel_ref!(sender_node, counterparty_node, sender_node_per_peer_lock, sender_node_peer_state_lock, temp_channel_id);
-               chan.holder_selected_channel_reserve_satoshis = 0;
-               chan.holder_max_htlc_value_in_flight_msat = 100_000_000;
+               chan.context.holder_selected_channel_reserve_satoshis = 0;
+               chan.context.holder_max_htlc_value_in_flight_msat = 100_000_000;
        }
 
        let funding_tx = sign_funding_transaction(&nodes[0], &nodes[1], 100_000, temp_channel_id);
@@ -643,7 +643,7 @@ fn test_update_fee_that_funder_cannot_afford() {
        let channel_id = chan.2;
        let secp_ctx = Secp256k1::new();
        let default_config = UserConfig::default();
-       let bs_channel_reserve_sats = Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(channel_value, &default_config);
+       let bs_channel_reserve_sats = get_holder_selected_channel_reserve_satoshis(channel_value, &default_config);
 
        let opt_anchors = false;
 
@@ -728,7 +728,7 @@ fn test_update_fee_that_funder_cannot_afford() {
                        commit_tx_keys.clone(),
                        non_buffer_feerate + 4,
                        &mut htlcs,
-                       &local_chan.channel_transaction_parameters.as_counterparty_broadcastable()
+                       &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable()
                );
                local_chan_signer.sign_counterparty_commitment(&commitment_tx, Vec::new(), &secp_ctx).unwrap()
        };
@@ -1453,11 +1453,11 @@ fn test_fee_spike_violation_fails_htlc() {
                        commitment_number,
                        95000,
                        local_chan_balance,
-                       local_chan.opt_anchors(), local_funding, remote_funding,
+                       local_chan.context.opt_anchors(), local_funding, remote_funding,
                        commit_tx_keys.clone(),
                        feerate_per_kw,
                        &mut vec![(accepted_htlc_info, ())],
-                       &local_chan.channel_transaction_parameters.as_counterparty_broadcastable()
+                       &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable()
                );
                local_chan_signer.sign_counterparty_commitment(&commitment_tx, Vec::new(), &secp_ctx).unwrap()
        };
@@ -1517,7 +1517,7 @@ fn test_chan_reserve_violation_outbound_htlc_inbound_chan() {
        let mut push_amt = 100_000_000;
        push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, opt_anchors);
 
-       push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
+       push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
 
        let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt);
 
@@ -1550,7 +1550,7 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() {
        // transaction fee with 0 HTLCs (183 sats)).
        let mut push_amt = 100_000_000;
        push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, opt_anchors);
-       push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
+       push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt);
 
        // Send four HTLCs to cover the initial push_msat buffer we're required to include
@@ -1606,7 +1606,7 @@ fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() {
        // transaction fee with 0 HTLCs (183 sats)).
        let mut push_amt = 100_000_000;
        push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, opt_anchors);
-       push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
+       push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
        create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, push_amt);
 
        let dust_amt = crate::ln::channel::MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000
@@ -1651,7 +1651,7 @@ fn test_chan_init_feerate_unaffordability() {
 
        // During open, we don't have a "counterparty channel reserve" to check against, so that
        // requirement only comes into play on the open_channel handling side.
-       push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
+       push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000;
        nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, push_amt, 42, None).unwrap();
        let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
        open_channel_msg.push_msat += 1;
@@ -1777,7 +1777,7 @@ fn test_inbound_outbound_capacity_is_not_zero() {
        assert_eq!(channels0.len(), 1);
        assert_eq!(channels1.len(), 1);
 
-       let reserve = Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000, &default_config);
+       let reserve = get_holder_selected_channel_reserve_satoshis(100_000, &default_config);
        assert_eq!(channels0[0].inbound_capacity_msat, 95000000 - reserve*1000);
        assert_eq!(channels1[0].outbound_capacity_msat, 95000000 - reserve*1000);
 
@@ -3122,7 +3122,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
                // The dust limit applied to HTLC outputs considers the fee of the HTLC transaction as
                // well, so HTLCs at exactly the dust limit will not be included in commitment txn.
                nodes[2].node.per_peer_state.read().unwrap().get(&nodes[1].node.get_our_node_id())
-                       .unwrap().lock().unwrap().channel_by_id.get(&chan_2.2).unwrap().holder_dust_limit_satoshis * 1000
+                       .unwrap().lock().unwrap().channel_by_id.get(&chan_2.2).unwrap().context.holder_dust_limit_satoshis * 1000
        } else { 3000000 };
 
        let (_, first_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
@@ -4027,10 +4027,14 @@ fn test_drop_messages_peer_disconnect_dual_htlc() {
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init {
+               features: nodes[1].node.init_features(), networks: None, remote_network_address: None
+       }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 1);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
+               features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+       }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 1);
 
@@ -4986,7 +4990,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
        assert_eq!(get_local_commitment_txn!(nodes[3], chan_2_3.2)[0].output.len(), 2);
 
        let ds_dust_limit = nodes[3].node.per_peer_state.read().unwrap().get(&nodes[2].node.get_our_node_id())
-               .unwrap().lock().unwrap().channel_by_id.get(&chan_2_3.2).unwrap().holder_dust_limit_satoshis;
+               .unwrap().lock().unwrap().channel_by_id.get(&chan_2_3.2).unwrap().context.holder_dust_limit_satoshis;
        // 0th HTLC:
        let (_, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
        // 1st HTLC:
@@ -6095,7 +6099,7 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment()
        let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0);
        let max_accepted_htlcs = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[0].node.get_our_node_id())
-               .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().counterparty_max_accepted_htlcs as u64;
+               .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().context.counterparty_max_accepted_htlcs as u64;
 
        // Fetch a route in advance as we will be unable to once we're unable to send.
        let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
@@ -6168,7 +6172,7 @@ fn test_update_add_htlc_bolt2_receiver_check_amount_received_more_than_min() {
                let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
                let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
                let channel = chan_lock.channel_by_id.get(&chan.2).unwrap();
-               htlc_minimum_msat = channel.get_holder_htlc_minimum_msat();
+               htlc_minimum_msat = channel.context.get_holder_htlc_minimum_msat();
        }
 
        let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], htlc_minimum_msat);
@@ -6334,10 +6338,14 @@ fn test_update_add_htlc_bolt2_receiver_check_repeated_id_ignore() {
        //Disconnect and Reconnect
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init {
+               features: nodes[1].node.init_features(), networks: None, remote_network_address: None
+       }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 1);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
+               features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+       }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 1);
        nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]);
@@ -6766,7 +6774,7 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
        let chan =create_announced_chan_between_nodes(&nodes, 0, 1);
 
        let bs_dust_limit = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[0].node.get_our_node_id())
-               .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis;
+               .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().context.holder_dust_limit_satoshis;
 
        // We route 2 dust-HTLCs between A and B
        let (_, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
@@ -6859,7 +6867,7 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
 
        let bs_dust_limit = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[0].node.get_our_node_id())
-               .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis;
+               .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().context.holder_dust_limit_satoshis;
 
        let (_payment_preimage_1, dust_hash, _payment_secret_1) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
        let (_payment_preimage_2, non_dust_hash, _payment_secret_2) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
@@ -7100,10 +7108,14 @@ fn test_announce_disable_channels() {
                }
        }
        // Reconnect peers
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: nodes[1].node.init_features(), remote_network_address: None }, true).unwrap();
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init {
+               features: nodes[1].node.init_features(), networks: None, remote_network_address: None
+       }, true).unwrap();
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 3);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
+               features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+       }, false).unwrap();
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 3);
 
@@ -9430,7 +9442,7 @@ fn test_keysend_payments_to_public_node() {
        let payer_pubkey = nodes[0].node.get_our_node_id();
        let payee_pubkey = nodes[1].node.get_our_node_id();
        let route_params = RouteParameters {
-               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
+               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
                final_value_msat: 10000,
        };
        let scorer = test_utils::TestScorer::new();
@@ -9461,7 +9473,7 @@ fn test_keysend_payments_to_private_node() {
 
        let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
        let route_params = RouteParameters {
-               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
+               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
                final_value_msat: 10000,
        };
        let network_graph = nodes[0].network_graph.clone();
@@ -9592,7 +9604,7 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
                let mut node_0_per_peer_lock;
                let mut node_0_peer_state_lock;
                let mut chan = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, temporary_channel_id);
-               chan.holder_dust_limit_satoshis = 546;
+               chan.context.holder_dust_limit_satoshis = 546;
        }
 
        nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
@@ -9616,7 +9628,7 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
                let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
                let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
                let chan = chan_lock.channel_by_id.get(&channel_id).unwrap();
-               chan.get_dust_buffer_feerate(None) as u64
+               chan.context.get_dust_buffer_feerate(None) as u64
        };
        let dust_outbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_timeout_tx_weight(opt_anchors) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000;
        let dust_outbound_htlc_on_holder_tx: u64 = config.channel_config.max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat;
@@ -9909,3 +9921,132 @@ fn test_payment_with_custom_min_cltv_expiry_delta() {
        do_payment_with_custom_min_final_cltv_expiry(true, false);
        do_payment_with_custom_min_final_cltv_expiry(true, true);
 }
+
+#[test]
+fn test_disconnects_peer_awaiting_response_ticks() {
+       // Tests that nodes which are awaiting on a response critical for channel responsiveness
+       // disconnect their counterparty after `DISCONNECT_PEER_AWAITING_RESPONSE_TICKS`.
+       let mut chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       // Asserts a disconnect event is queued to the user.
+       let check_disconnect_event = |node: &Node, should_disconnect: bool| {
+               let disconnect_event = node.node.get_and_clear_pending_msg_events().iter().find_map(|event|
+                       if let MessageSendEvent::HandleError { action, .. } = event {
+                               if let msgs::ErrorAction::DisconnectPeerWithWarning { .. } = action {
+                                       Some(())
+                               } else {
+                                       None
+                               }
+                       } else {
+                               None
+                       }
+               );
+               assert_eq!(disconnect_event.is_some(), should_disconnect);
+       };
+
+       // Fires timer ticks ensuring we only attempt to disconnect peers after reaching
+       // `DISCONNECT_PEER_AWAITING_RESPONSE_TICKS`.
+       let check_disconnect = |node: &Node| {
+               // No disconnect without any timer ticks.
+               check_disconnect_event(node, false);
+
+               // No disconnect with 1 timer tick less than required.
+               for _ in 0..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS - 1 {
+                       node.node.timer_tick_occurred();
+                       check_disconnect_event(node, false);
+               }
+
+               // Disconnect after reaching the required ticks.
+               node.node.timer_tick_occurred();
+               check_disconnect_event(node, true);
+
+               // Disconnect again on the next tick if the peer hasn't been disconnected yet.
+               node.node.timer_tick_occurred();
+               check_disconnect_event(node, true);
+       };
+
+       create_chan_between_nodes(&nodes[0], &nodes[1]);
+
+       // We'll start by performing a fee update with Alice (nodes[0]) on the channel.
+       *nodes[0].fee_estimator.sat_per_kw.lock().unwrap() *= 2;
+       nodes[0].node.timer_tick_occurred();
+       check_added_monitors!(&nodes[0], 1);
+       let alice_fee_update = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
+       nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), alice_fee_update.update_fee.as_ref().unwrap());
+       nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &alice_fee_update.commitment_signed);
+       check_added_monitors!(&nodes[1], 1);
+
+       // This will prompt Bob (nodes[1]) to respond with his `CommitmentSigned` and `RevokeAndACK`.
+       let (bob_revoke_and_ack, bob_commitment_signed) = get_revoke_commit_msgs!(&nodes[1], nodes[0].node.get_our_node_id());
+       nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bob_revoke_and_ack);
+       check_added_monitors!(&nodes[0], 1);
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bob_commitment_signed);
+       check_added_monitors(&nodes[0], 1);
+
+       // Alice then needs to send her final `RevokeAndACK` to complete the commitment dance. We
+       // pretend Bob hasn't received the message and check whether he'll disconnect Alice after
+       // reaching `DISCONNECT_PEER_AWAITING_RESPONSE_TICKS`.
+       let alice_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+       check_disconnect(&nodes[1]);
+
+       // Now, we'll reconnect them to test awaiting a `ChannelReestablish` message.
+       //
+       // Note that since the commitment dance didn't complete above, Alice is expected to resend her
+       // final `RevokeAndACK` to Bob to complete it.
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+       let bob_init = msgs::Init {
+               features: nodes[1].node.init_features(), networks: None, remote_network_address: None
+       };
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &bob_init, true).unwrap();
+       let alice_init = msgs::Init {
+               features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+       };
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &alice_init, true).unwrap();
+
+       // Upon reconnection, Alice sends her `ChannelReestablish` to Bob. Alice, however, hasn't
+       // received Bob's yet, so she should disconnect him after reaching
+       // `DISCONNECT_PEER_AWAITING_RESPONSE_TICKS`.
+       let alice_channel_reestablish = get_event_msg!(
+               nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id()
+       );
+       nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &alice_channel_reestablish);
+       check_disconnect(&nodes[0]);
+
+       // Bob now sends his `ChannelReestablish` to Alice to resume the channel and consider it "live".
+       let bob_channel_reestablish = nodes[1].node.get_and_clear_pending_msg_events().iter().find_map(|event|
+               if let MessageSendEvent::SendChannelReestablish { node_id, msg } = event {
+                       assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+                       Some(msg.clone())
+               } else {
+                       None
+               }
+       ).unwrap();
+       nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bob_channel_reestablish);
+
+       // Sanity check that Alice won't disconnect Bob since she's no longer waiting for any messages.
+       for _ in 0..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS {
+               nodes[0].node.timer_tick_occurred();
+               check_disconnect_event(&nodes[0], false);
+       }
+
+       // However, Bob is still waiting on Alice's `RevokeAndACK`, so he should disconnect her after
+       // reaching `DISCONNECT_PEER_AWAITING_RESPONSE_TICKS`.
+       check_disconnect(&nodes[1]);
+
+       // Finally, have Bob process the last message.
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &alice_revoke_and_ack);
+       check_added_monitors(&nodes[1], 1);
+
+       // At this point, neither node should attempt to disconnect each other, since they aren't
+       // waiting on any messages.
+       for node in &nodes {
+               for _ in 0..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS {
+                       node.node.timer_tick_occurred();
+                       check_disconnect_event(node, false);
+               }
+       }
+}