X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fshutdown_tests.rs;h=0e03fd8db139353001f8fe1b0f12e717a213e49b;hb=1e580668684d4dbf11d69d75e5d4a5c4f8cc40bf;hp=0eb56434169bec971cdf9853cb3245a1916190d5;hpb=7c9463668a4f71663746e57bdb09ee6b91797d5a;p=rust-lightning diff --git a/lightning/src/ln/shutdown_tests.rs b/lightning/src/ln/shutdown_tests.rs index 0eb56434..0e03fd8d 100644 --- a/lightning/src/ln/shutdown_tests.rs +++ b/lightning/src/ln/shutdown_tests.rs @@ -14,9 +14,11 @@ use crate::sign::{EntropySource, SignerProvider}; use crate::chain::ChannelMonitorUpdateStatus; use crate::chain::transaction::OutPoint; use crate::events::{Event, MessageSendEvent, HTLCDestination, MessageSendEventsProvider, ClosureReason}; -use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields, Retry, ChannelShutdownState, ChannelDetails}; +use crate::ln::channel_state::{ChannelDetails, ChannelShutdownState}; +use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields, Retry}; use crate::routing::router::{PaymentParameters, get_route, RouteParameters}; -use crate::ln::{ChannelId, msgs}; +use crate::ln::msgs; +use crate::ln::types::ChannelId; use crate::ln::msgs::{ChannelMessageHandler, ErrorAction}; use crate::ln::onion_utils::INVALID_ONION_BLINDING; use crate::ln::script::ShutdownScript; @@ -25,18 +27,15 @@ use crate::util::test_utils::OnGetShutdownScriptpubkey; use crate::util::errors::APIError; use crate::util::config::UserConfig; use crate::util::string::UntrustedString; +use crate::prelude::*; -use bitcoin::{Transaction, TxOut}; +use bitcoin::{Transaction, TxOut, WitnessProgram, WitnessVersion}; +use bitcoin::amount::Amount; use bitcoin::blockdata::locktime::absolute::LockTime; use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::opcodes; -use bitcoin::network::constants::Network; -use bitcoin::address::{WitnessProgram, WitnessVersion}; - -use regex; - -use core::default::Default; -use std::convert::TryFrom; +use bitcoin::network::Network; +use bitcoin::transaction::Version; use crate::ln::functional_test_utils::*; @@ -68,8 +67,8 @@ fn pre_funding_lock_shutdown_test() { assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[1].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 8000000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 8000000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 8000000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 8000000); } #[test] @@ -113,8 +112,8 @@ fn expect_channel_shutdown_state() { assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[1].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); } #[test] @@ -196,8 +195,8 @@ fn expect_channel_shutdown_state_with_htlc() { nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); // Shutdown basically removes the channelDetails, testing of shutdowncomplete state unnecessary assert!(nodes[0].node.list_channels().is_empty()); @@ -251,8 +250,8 @@ fn test_lnd_bug_6039() { nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); // Shutdown basically removes the channelDetails, testing of shutdowncomplete state unnecessary assert!(nodes[0].node.list_channels().is_empty()); @@ -275,7 +274,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); } @@ -303,11 +302,12 @@ fn expect_channel_shutdown_state_with_force_closure() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); + let error_message = "Channel force-closed"; expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NotShuttingDown); expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown); - nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap(); + nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); @@ -404,8 +404,8 @@ fn updates_shutdown_wait() { nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); assert!(nodes[0].node.list_channels().is_empty()); @@ -414,8 +414,8 @@ fn updates_shutdown_wait() { close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true); assert!(nodes[1].node.list_channels().is_empty()); assert!(nodes[2].node.list_channels().is_empty()); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!(nodes[2], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); } #[test] @@ -437,7 +437,7 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); let route_params = if blinded_recipient { crate::ln::blinded_payment_tests::get_blinded_route_parameters( - amt_msat, our_payment_secret, + amt_msat, our_payment_secret, 1, 100000000, nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_2.0.contents], &chanmon_cfgs[2].keys_manager) } else { @@ -509,9 +509,27 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true); assert!(nodes[1].node.list_channels().is_empty()); assert!(nodes[2].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 2, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id(), nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + let event1 = ExpectedCloseEvent { + channel_capacity_sats: Some(100000), + channel_id: None, + counterparty_node_id: Some(nodes[0].node.get_our_node_id()), + discard_funding: false, + reason: Some(ClosureReason::LocallyInitiatedCooperativeClosure), + channel_funding_txo: None, + user_channel_id: None, + }; + let event2 = ExpectedCloseEvent { + channel_capacity_sats: Some(100000), + channel_id: None, + counterparty_node_id: Some(nodes[2].node.get_our_node_id()), + discard_funding: false, + reason: Some(ClosureReason::CounterpartyInitiatedCooperativeClosure), + channel_funding_txo: None, + user_channel_id: None, + }; + check_closed_events(&nodes[1], &[event1, event2]); + check_closed_event!(nodes[2], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); } fn do_test_shutdown_rebroadcast(recv_count: u8) { @@ -652,7 +670,7 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); } else { // If one node, however, received + responded with an identical closing_signed we end // up erroring and node[0] will try to broadcast its own latest commitment transaction. @@ -692,9 +710,9 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true); assert!(nodes[1].node.list_channels().is_empty()); assert!(nodes[2].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!(nodes[2], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); } #[test] @@ -813,7 +831,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(); @@ -838,7 +856,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(); @@ -865,7 +883,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); @@ -1135,9 +1153,9 @@ fn do_test_closing_signed_reinit_timeout(timeout_step: TimeoutStep) { let node_0_2nd_closing_signed = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); if timeout_step == TimeoutStep::NoTimeout { nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.1.unwrap()); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); } - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); } if timeout_step != TimeoutStep::NoTimeout { @@ -1154,17 +1172,17 @@ fn do_test_closing_signed_reinit_timeout(timeout_step: TimeoutStep) { assert_eq!(txn[0].output.len(), 2); if timeout_step != TimeoutStep::NoTimeout { - assert!((txn[0].output[0].script_pubkey.is_v0_p2wpkh() && - txn[0].output[1].script_pubkey.is_v0_p2wsh()) || - (txn[0].output[1].script_pubkey.is_v0_p2wpkh() && - txn[0].output[0].script_pubkey.is_v0_p2wsh())); + assert!((txn[0].output[0].script_pubkey.is_p2wpkh() && + txn[0].output[1].script_pubkey.is_p2wsh()) || + (txn[0].output[1].script_pubkey.is_p2wpkh() && + txn[0].output[0].script_pubkey.is_p2wsh())); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "closing_signed negotiation failed to finish within two timer ticks".to_string() } , [nodes[0].node.get_our_node_id()], 100000); } else { - assert!(txn[0].output[0].script_pubkey.is_v0_p2wpkh()); - assert!(txn[0].output[1].script_pubkey.is_v0_p2wpkh()); + assert!(txn[0].output[0].script_pubkey.is_p2wpkh()); + assert!(txn[0].output[1].script_pubkey.is_p2wpkh()); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -1221,8 +1239,8 @@ fn do_simple_legacy_shutdown_test(high_initiator_fee: bool) { nodes[0].node.handle_closing_signed(&nodes[1].node.get_our_node_id(), &node_1_closing_signed.unwrap()); let (_, node_0_none) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); assert!(node_0_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); } #[test] @@ -1276,8 +1294,8 @@ fn simple_target_feerate_shutdown() { nodes[0].node.handle_closing_signed(&nodes[1].node.get_our_node_id(), &node_1_closing_signed); let (_, node_0_none) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); assert!(node_0_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); } fn do_outbound_update_no_early_closing_signed(use_htlc: bool) { @@ -1369,8 +1387,8 @@ fn do_outbound_update_no_early_closing_signed(use_htlc: bool) { let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); } #[test] @@ -1387,32 +1405,62 @@ fn batch_funding_failure() { 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 temp_chan_id_a = exchange_open_accept_chan(&nodes[0], &nodes[1], 1_000_000, 0); + let temp_chan_id_b = 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 tx = Transaction { version: Version::TWO, 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() }); + tx.output.push(TxOut { value: Amount::from_sat(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 })]; + let temp_err = "No output matched the script_pubkey and value in the FundingGenerationReady event".to_string(); + let post_funding_chan_id_a = ChannelId::v1_from_funding_txid(tx.txid().as_ref(), 0); + let close = [ + ExpectedCloseEvent::from_id_reason(post_funding_chan_id_a, true, ClosureReason::ProcessingError { err: err.clone() }), + ExpectedCloseEvent::from_id_reason(temp_chan_id_b, false, ClosureReason::ProcessingError { err: temp_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()); + let msgs = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(msgs.len(), 3); + // We currently spuriously send `FundingCreated` for the first channel and then immediately + // fail both channels, which isn't ideal but should be fine. + assert!(msgs.iter().any(|msg| { + if let MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { channel_id, .. }, .. + }, .. } = msg { + *channel_id == temp_chan_id_b + } else { false } + })); + let funding_created_pos = msgs.iter().position(|msg| { + if let MessageSendEvent::SendFundingCreated { msg: msgs::FundingCreated { temporary_channel_id, .. }, .. } = msg { + assert_eq!(*temporary_channel_id, temp_chan_id_a); + true + } else { false } + }).unwrap(); + let funded_channel_close_pos = msgs.iter().position(|msg| { + if let MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { channel_id, .. }, .. + }, .. } = msg { + *channel_id == post_funding_chan_id_a + } else { false } + }).unwrap(); + + // The error message uses the funded channel_id so must come after the funding_created + assert!(funded_channel_close_pos > funding_created_pos); + check_closed_events(&nodes[0], &close); assert_eq!(nodes[0].node.list_channels().len(), 0); }