Combine common fields of `AcceptChannel` & `AcceptChannelV2` into struct
[rust-lightning] / lightning / src / ln / shutdown_tests.rs
index bdd32e90d0ace1cca8b1fd46c4eac99ecb486b61..f59ae6692f5187b7ef0a173fb5524cb113f6d859 100644 (file)
@@ -7,15 +7,16 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-//! Tests of our shutdown and closing_signed negotiation logic.
+//! Tests of our shutdown and closing_signed negotiation logic as well as some assorted force-close
+//! handling tests.
 
 use crate::sign::{EntropySource, SignerProvider};
 use crate::chain::ChannelMonitorUpdateStatus;
 use crate::chain::transaction::OutPoint;
-use crate::events::{MessageSendEvent, HTLCDestination, MessageSendEventsProvider, ClosureReason};
+use crate::events::{Event, MessageSendEvent, HTLCDestination, MessageSendEventsProvider, ClosureReason};
 use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields, Retry, ChannelShutdownState, ChannelDetails};
 use crate::routing::router::{PaymentParameters, get_route, RouteParameters};
-use crate::ln::msgs;
+use crate::ln::{ChannelId, msgs};
 use crate::ln::msgs::{ChannelMessageHandler, ErrorAction};
 use crate::ln::onion_utils::INVALID_ONION_BLINDING;
 use crate::ln::script::ShutdownScript;
@@ -25,6 +26,8 @@ use crate::util::errors::APIError;
 use crate::util::config::UserConfig;
 use crate::util::string::UntrustedString;
 
+use bitcoin::{Transaction, TxOut};
+use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::blockdata::script::Builder;
 use bitcoin::blockdata::opcodes;
 use bitcoin::network::constants::Network;
@@ -48,7 +51,7 @@ fn pre_funding_lock_shutdown_test() {
        mine_transaction(&nodes[0], &tx);
        mine_transaction(&nodes[1], &tx);
 
-       nodes[0].node.close_channel(&OutPoint { txid: tx.txid(), index: 0 }.to_channel_id(), &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.close_channel(&ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.txid(), index: 0 }), &nodes[1].node.get_our_node_id()).unwrap();
        let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
        nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &node_0_shutdown);
        let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
@@ -272,7 +275,7 @@ fn shutdown_on_unfunded_channel() {
                .into_script();
 
        nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &msgs::Shutdown {
-               channel_id: open_chan.temporary_channel_id, scriptpubkey: script,
+               channel_id: open_chan.common_fields.temporary_channel_id, scriptpubkey: script,
        });
        check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyCoopClosedUnfundedChannel, [nodes[1].node.get_our_node_id()], 1_000_000);
 }
@@ -718,7 +721,7 @@ fn test_upfront_shutdown_script() {
 
        // We test that in case of peer committing upfront to a script, if it changes at closing, we refuse to sign
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1000000, 1000000);
-       nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[2].node.get_our_node_id()).unwrap();
+       nodes[0].node.close_channel(&chan.2, &nodes[2].node.get_our_node_id()).unwrap();
        let node_0_orig_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id());
        let mut node_0_shutdown = node_0_orig_shutdown.clone();
        node_0_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
@@ -733,7 +736,7 @@ fn test_upfront_shutdown_script() {
 
        // We test that in case of peer committing upfront to a script, if it doesn't change at closing, we sign
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1000000, 1000000);
-       nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[2].node.get_our_node_id()).unwrap();
+       nodes[0].node.close_channel(&chan.2, &nodes[2].node.get_our_node_id()).unwrap();
        let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id());
        // We test that in case of peer committing upfront to a script, if it oesn't change at closing, we sign
        nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &node_0_shutdown);
@@ -747,7 +750,7 @@ fn test_upfront_shutdown_script() {
        // We test that if case of peer non-signaling we don't enforce committed script at channel opening
        *nodes[0].override_init_features.borrow_mut() = Some(nodes[0].node.init_features().clear_upfront_shutdown_script());
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000);
-       nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.close_channel(&chan.2, &nodes[1].node.get_our_node_id()).unwrap();
        let node_1_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
        nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &node_1_shutdown);
        check_added_monitors!(nodes[1], 1);
@@ -762,7 +765,7 @@ fn test_upfront_shutdown_script() {
        // channel smoothly, opt-out is from channel initiator here
        *nodes[0].override_init_features.borrow_mut() = None;
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 1, 0, 1000000, 1000000);
-       nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
        check_added_monitors!(nodes[1], 1);
        let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
        nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &node_0_shutdown);
@@ -776,7 +779,7 @@ fn test_upfront_shutdown_script() {
        //// We test that if user opt-out, we provide a zero-length script at channel opening and we are able to close
        //// channel smoothly
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000);
-       nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
        check_added_monitors!(nodes[1], 1);
        let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
        nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &node_0_shutdown);
@@ -810,7 +813,7 @@ fn test_unsupported_anysegwit_upfront_shutdown_script() {
        // Check script when handling an open_channel message
        nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap();
        let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
-       open_channel.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone());
+       open_channel.common_fields.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone());
        nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);
 
        let events = nodes[1].node.get_and_clear_pending_msg_events();
@@ -835,7 +838,7 @@ fn test_unsupported_anysegwit_upfront_shutdown_script() {
        let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
        nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);
        let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
-       accept_channel.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone());
+       accept_channel.common_fields.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone());
        nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_channel);
 
        let events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -862,7 +865,7 @@ fn test_invalid_upfront_shutdown_script() {
 
        // Use a segwit v0 script with an unsupported witness program
        let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
-       open_channel.shutdown_scriptpubkey = Some(Builder::new().push_int(0)
+       open_channel.common_fields.shutdown_scriptpubkey = Some(Builder::new().push_int(0)
                .push_slice(&[0, 0])
                .into_script());
        nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);
@@ -891,7 +894,7 @@ fn test_segwit_v0_shutdown_script() {
        let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
 
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-       nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
        check_added_monitors!(nodes[1], 1);
 
        // Use a segwit v0 script supported even without option_shutdown_anysegwit
@@ -926,7 +929,7 @@ fn test_anysegwit_shutdown_script() {
        let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
 
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-       nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
        check_added_monitors!(nodes[1], 1);
 
        // Use a non-v0 segwit script supported by option_shutdown_anysegwit
@@ -972,14 +975,14 @@ fn test_unsupported_anysegwit_shutdown_script() {
                .expect(OnGetShutdownScriptpubkey { returns: supported_shutdown_script });
 
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-       match nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()) {
+       match nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()) {
                Err(APIError::IncompatibleShutdownScript { script }) => {
                        assert_eq!(script.into_inner(), unsupported_shutdown_script.clone().into_inner());
                },
                Err(e) => panic!("Unexpected error: {:?}", e),
                Ok(_) => panic!("Expected error"),
        }
-       nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
        check_added_monitors!(nodes[1], 1);
 
        // Use a non-v0 segwit script unsupported without option_shutdown_anysegwit
@@ -1004,7 +1007,7 @@ fn test_invalid_shutdown_script() {
        let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
 
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-       nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id()).unwrap();
+       nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()).unwrap();
        check_added_monitors!(nodes[1], 1);
 
        // Use a segwit v0 script with an unsupported witness program
@@ -1038,7 +1041,7 @@ fn test_user_shutdown_script() {
        let shutdown_script = ShutdownScript::try_from(script.clone()).unwrap();
 
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-       nodes[1].node.close_channel_with_feerate_and_script(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id(), None, Some(shutdown_script)).unwrap();
+       nodes[1].node.close_channel_with_feerate_and_script(&chan.2, &nodes[0].node.get_our_node_id(), None, Some(shutdown_script)).unwrap();
        check_added_monitors!(nodes[1], 1);
 
        let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
@@ -1065,7 +1068,7 @@ fn test_already_set_user_shutdown_script() {
        let shutdown_script = ShutdownScript::try_from(script).unwrap();
 
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-       let result = nodes[1].node.close_channel_with_feerate_and_script(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[0].node.get_our_node_id(), None, Some(shutdown_script));
+       let result = nodes[1].node.close_channel_with_feerate_and_script(&chan.2, &nodes[0].node.get_our_node_id(), None, Some(shutdown_script));
 
        assert_eq!(result, Err(APIError::APIMisuseError { err: "Cannot override shutdown script for a channel with one already set".to_string() }));
 }
@@ -1197,7 +1200,7 @@ fn do_simple_legacy_shutdown_test(high_initiator_fee: bool) {
                *feerate_lock *= 10;
        }
 
-       nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id(), &nodes[1].node.get_our_node_id()).unwrap();
+       nodes[0].node.close_channel(&chan.2, &nodes[1].node.get_our_node_id()).unwrap();
        let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
        nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &node_0_shutdown);
        let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
@@ -1237,7 +1240,7 @@ fn simple_target_feerate_shutdown() {
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
-       let chan_id = OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id();
+       let chan_id = chan.2;
 
        nodes[0].node.close_channel_with_feerate_and_script(&chan_id, &nodes[1].node.get_our_node_id(), Some(253 * 10), None).unwrap();
        let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
@@ -1375,3 +1378,41 @@ fn outbound_update_no_early_closing_signed() {
        do_outbound_update_no_early_closing_signed(true);
        do_outbound_update_no_early_closing_signed(false);
 }
+
+#[test]
+fn batch_funding_failure() {
+       // Provides test coverage of batch funding failure, which previously deadlocked
+       let chanmon_cfgs = create_chanmon_cfgs(4);
+       let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
+       let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
+
+       exchange_open_accept_chan(&nodes[0], &nodes[1], 1_000_000, 0);
+       exchange_open_accept_chan(&nodes[0], &nodes[2], 1_000_000, 0);
+
+       let events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 2);
+       // Build a transaction which only has the output for one of the two channels we're trying to
+       // confirm. Previously this led to a deadlock in channel closure handling.
+       let mut tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+       let mut chans = Vec::new();
+       for (idx, ev) in events.iter().enumerate() {
+               if let Event::FundingGenerationReady { temporary_channel_id, counterparty_node_id, output_script, .. } = ev {
+                       if idx == 0 {
+                               tx.output.push(TxOut { value: 1_000_000, script_pubkey: output_script.clone() });
+                       }
+                       chans.push((temporary_channel_id, counterparty_node_id));
+               } else { panic!(); }
+       }
+
+       // We should probably end up with an error for both channels, but currently we don't generate
+       // an error for the failing channel itself.
+       let err = "Error in transaction funding: Misuse error: No output matched the script_pubkey and value in the FundingGenerationReady event".to_string();
+       let close = [ExpectedCloseEvent::from_id_reason(ChannelId::v1_from_funding_txid(tx.txid().as_ref(), 0), true, ClosureReason::ProcessingError { err })];
+
+       nodes[0].node.batch_funding_transaction_generated(&chans, tx).unwrap_err();
+
+       get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
+       check_closed_events(&nodes[0], &close);
+       assert_eq!(nodes[0].node.list_channels().len(), 0);
+}