From 4b3ad40f26f61cc9f1191228efea9b39268b5f3f Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 16 Aug 2025 00:08:30 +0000 Subject: [PATCH 1/4] Move `channel_acceptance_tests.rs` to `channel_open_tests.rs` --- ...nnel_acceptance_tests.rs => channel_open_tests.rs} | 11 +++++++++++ lightning/src/ln/mod.rs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) rename lightning/src/ln/{channel_acceptance_tests.rs => channel_open_tests.rs} (97%) diff --git a/lightning/src/ln/channel_acceptance_tests.rs b/lightning/src/ln/channel_open_tests.rs similarity index 97% rename from lightning/src/ln/channel_acceptance_tests.rs rename to lightning/src/ln/channel_open_tests.rs index c0ab1d31ff5..7eea08ff4cf 100644 --- a/lightning/src/ln/channel_acceptance_tests.rs +++ b/lightning/src/ln/channel_open_tests.rs @@ -1,3 +1,14 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Tests that test the channel open process. + use crate::events::Event; use crate::ln::channelmanager::{MAX_UNFUNDED_CHANNEL_PEERS, MAX_UNFUNDED_CHANS_PER_PEER}; use crate::ln::msgs::{ diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index 3ca3b765dc2..865ef174da5 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -77,7 +77,7 @@ pub mod bolt11_payment_tests; mod chanmon_update_fail_tests; #[cfg(test)] #[allow(unused_mut)] -mod channel_acceptance_tests; +mod channel_open_tests; #[cfg(test)] #[allow(unused_mut)] mod channel_type_tests; From 399e6e7ce6c85d44f593b7cded14a94594f167e4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 18 Aug 2025 14:05:52 +0000 Subject: [PATCH 2/4] Move additional channel opening tests to `channel_open_tests.rs` `functional_tests.rs` is a rather large beast, but with this move we take it down to under 10k LoC. --- lightning/src/ln/channel_open_tests.rs | 2087 ++++++++++++++++++++++- lightning/src/ln/functional_tests.rs | 2146 +----------------------- 2 files changed, 2124 insertions(+), 2109 deletions(-) diff --git a/lightning/src/ln/channel_open_tests.rs b/lightning/src/ln/channel_open_tests.rs index 7eea08ff4cf..89bb50e25bd 100644 --- a/lightning/src/ln/channel_open_tests.rs +++ b/lightning/src/ln/channel_open_tests.rs @@ -9,17 +9,42 @@ //! Tests that test the channel open process. -use crate::events::Event; -use crate::ln::channelmanager::{MAX_UNFUNDED_CHANNEL_PEERS, MAX_UNFUNDED_CHANS_PER_PEER}; +use crate::chain::chaininterface::LowerBoundedFeeEstimator; +use crate::chain::channelmonitor::{self, ChannelMonitorUpdateStep}; +use crate::chain::transaction::OutPoint; +use crate::chain::{self, ChannelMonitorUpdateStatus}; +use crate::events::{ClosureReason, Event, FundingInfo}; +use crate::ln::channel::{ + get_holder_selected_channel_reserve_satoshis, ChannelError, InboundV1Channel, + OutboundV1Channel, COINBASE_MATURITY, UNFUNDED_CHANNEL_AGE_LIMIT_TICKS, +}; +use crate::ln::channelmanager::{ + self, BREAKDOWN_TIMEOUT, MAX_UNFUNDED_CHANNEL_PEERS, MAX_UNFUNDED_CHANS_PER_PEER, +}; use crate::ln::msgs::{ AcceptChannel, BaseMessageHandler, ChannelMessageHandler, ErrorAction, MessageSendEvent, }; use crate::ln::types::ChannelId; use crate::ln::{functional_test_utils::*, msgs}; use crate::sign::EntropySource; -use crate::util::config::{ChannelConfigOverrides, ChannelHandshakeConfigUpdate, UserConfig}; +use crate::util::config::{ + ChannelConfigOverrides, ChannelConfigUpdate, ChannelHandshakeConfigUpdate, UserConfig, +}; use crate::util::errors::APIError; +use crate::util::test_utils::{self, TestLogger}; + +use bitcoin::constants::ChainHash; +use bitcoin::hashes::Hash; +use bitcoin::locktime::absolute::LockTime; +use bitcoin::network::Network; +use bitcoin::script::ScriptBuf; use bitcoin::secp256k1::{PublicKey, SecretKey}; +use bitcoin::transaction::Version; +use bitcoin::OutPoint as BitcoinOutPoint; +use bitcoin::{Amount, Sequence, Transaction, TxIn, TxOut, Witness}; + +use lightning_macros::xtest; + use lightning_types::features::ChannelTypeFeatures; #[test] @@ -428,3 +453,2059 @@ fn test_no_channel_downgrade() { panic!(); } } + +#[xtest(feature = "_externalize_tests")] +fn test_channel_resumption_fail_post_funding() { + // If we fail to exchange funding with a peer prior to it disconnecting we'll resume the + // channel open on reconnect, however if we do exchange funding we do not currently support + // replaying it and here test that the channel closes. + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0].node.create_channel(node_b_id, 1_000_000, 0, 42, None, None).unwrap(); + let open_chan = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + nodes[1].node.handle_open_channel(node_a_id, &open_chan); + let accept_chan = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + nodes[0].node.handle_accept_channel(node_b_id, &accept_chan); + + let (temp_chan_id, tx, funding_output) = + create_funding_transaction(&nodes[0], &node_b_id, 1_000_000, 42); + let new_chan_id = ChannelId::v1_from_funding_outpoint(funding_output); + nodes[0].node.funding_transaction_generated(temp_chan_id, node_b_id, tx).unwrap(); + + nodes[0].node.peer_disconnected(node_b_id); + check_closed_events( + &nodes[0], + &[ExpectedCloseEvent::from_id_reason(new_chan_id, true, ClosureReason::DisconnectedPeer)], + ); + + // After ddf75afd16 we'd panic on reconnection if we exchanged funding info, so test that + // explicitly here. + let init_msg = msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }; + nodes[0].node.peer_connected(node_b_id, &init_msg, true).unwrap(); + assert_eq!(nodes[0].node.get_and_clear_pending_msg_events(), Vec::new()); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_insane_channel_opens() { + // Stand up a network of 2 nodes + use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS; + let mut cfg = UserConfig::default(); + cfg.channel_handshake_limits.max_funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1; + let 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, Some(cfg.clone())]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + // 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 = + 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 + nodes[0].node.create_channel(node_b_id, channel_value_sat, push_msat, 42, None, None).unwrap(); + + // Extract the channel open message from node0 to node1 + let open_channel_message = + get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + // Test helper that asserts we get the correct error string given a mutator + // that supposedly makes the channel open message insane + let insane_open_helper = + |expected_error_str: &str, message_mutator: fn(msgs::OpenChannel) -> msgs::OpenChannel| { + let open_channel_mutated = message_mutator(open_channel_message.clone()); + nodes[1].node.handle_open_channel(node_a_id, &open_channel_mutated); + let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), 1); + let expected_regex = regex::Regex::new(expected_error_str).unwrap(); + if let MessageSendEvent::HandleError { ref action, .. } = msg_events[0] { + match action { + &ErrorAction::SendErrorMessage { .. } => { + nodes[1].logger.assert_log_regex( + "lightning::ln::channelmanager", + expected_regex, + 1, + ); + }, + _ => panic!("unexpected event!"), + } + } else { + assert!(false); + } + }; + + use crate::ln::channelmanager::MAX_LOCAL_BREAKDOWN_TIMEOUT; + + // Test all mutations that would make the channel open message insane + insane_open_helper( + format!( + "Per our config, funding must be at most {}. It was {}", + TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1, + TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2 + ) + .as_str(), + |mut msg| { + msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2; + msg + }, + ); + insane_open_helper( + format!( + "Funding must be smaller than the total bitcoin supply. It was {}", + TOTAL_BITCOIN_SUPPLY_SATOSHIS + ) + .as_str(), + |mut msg| { + msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS; + msg + }, + ); + + insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { + msg.channel_reserve_satoshis = msg.common_fields.funding_satoshis + 1; + msg + }); + + insane_open_helper( + r"push_msat \d+ was larger than channel amount minus reserve \(\d+\)", + |mut msg| { + msg.push_msat = + (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000 + 1; + msg + }, + ); + + insane_open_helper("Peer never wants payout outputs?", |mut msg| { + msg.common_fields.dust_limit_satoshis = msg.common_fields.funding_satoshis + 1; + msg + }); + + insane_open_helper( + r"Minimum htlc value \(\d+\) was larger than full channel value \(\d+\)", + |mut msg| { + msg.common_fields.htlc_minimum_msat = + (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000; + msg + }, + ); + + insane_open_helper( + "They wanted our payments to be delayed by a needlessly long period", + |mut msg| { + msg.common_fields.to_self_delay = MAX_LOCAL_BREAKDOWN_TIMEOUT + 1; + msg + }, + ); + + insane_open_helper("0 max_accepted_htlcs makes for a useless channel", |mut msg| { + msg.common_fields.max_accepted_htlcs = 0; + msg + }); + + insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { + msg.common_fields.max_accepted_htlcs = 484; + msg + }); +} + +#[test] +fn test_insane_zero_fee_channel_open() { + let mut cfg = UserConfig::default(); + cfg.manually_accept_inbound_channels = true; + cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true; + + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg.clone())]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + + let open_channel_message = + get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + let insane_open_helper = + |expected_error_str: &str, message_mutator: fn(msgs::OpenChannel) -> msgs::OpenChannel| { + let open_channel_mutated = message_mutator(open_channel_message.clone()); + nodes[1].node.handle_open_channel(node_a_id, &open_channel_mutated); + + let events = nodes[1].node.get_and_clear_pending_events(); + match events[0] { + Event::OpenChannelRequest { temporary_channel_id, .. } => { + match nodes[1].node.accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 23, + None, + ) { + Ok(_) => panic!("Unexpected successful channel accept"), + Err(e) => assert!(format!("{:?}", e).contains(expected_error_str)), + } + }, + _ => panic!("Unexpected event"), + } + + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + assert!(matches!(events[0], MessageSendEvent::HandleError { .. })); + }; + + insane_open_helper( + "max_accepted_htlcs was 115. It must not be larger than 114".into(), + |mut msg| { + msg.common_fields.max_accepted_htlcs = 115; + msg + }, + ); + + insane_open_helper("Zero Fee Channels must never attempt to use a fee".into(), |mut msg| { + msg.common_fields.commitment_feerate_sat_per_1000_weight = 123; + msg + }); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_funding_exceeds_no_wumbo_limit() { + // Test that if a peer does not support wumbo channels, we'll refuse to open a wumbo channel to + // them. + use crate::ln::channel::MAX_FUNDING_SATOSHIS_NO_WUMBO; + let chanmon_cfgs = create_chanmon_cfgs(2); + let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let mut features = channelmanager::provided_init_features(&test_default_channel_config()); + features.clear_wumbo(); + *node_cfgs[1].override_init_features.borrow_mut() = Some(features); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_b_id = nodes[1].node.get_our_node_id(); + + match nodes[0].node.create_channel( + node_b_id, + MAX_FUNDING_SATOSHIS_NO_WUMBO + 1, + 0, + 42, + None, + None, + ) { + Err(APIError::APIMisuseError { err }) => { + let exp_err = format!( + "funding_value must not exceed {}, it was {}", + MAX_FUNDING_SATOSHIS_NO_WUMBO, + MAX_FUNDING_SATOSHIS_NO_WUMBO + 1 + ); + assert_eq!(err, exp_err); + }, + _ => panic!(), + } +} + +fn do_test_sanity_on_in_flight_opens(steps: u8) { + // Previously, we had issues deserializing channels when we hadn't connected the first block + // after creation. To catch that and similar issues, we lean on the Node::drop impl to test + // serialization round-trips and simply do steps towards opening a channel and then drop the + // Node objects. + + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + if steps & 0b1000_0000 != 0 { + let block = create_dummy_block(nodes[0].best_block_hash(), 42, Vec::new()); + connect_block(&nodes[0], &block); + connect_block(&nodes[1], &block); + } + + if steps & 0x0f == 0 { + return; + } + nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + if steps & 0x0f == 1 { + return; + } + nodes[1].node.handle_open_channel(node_a_id, &open_channel); + let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + + if steps & 0x0f == 2 { + return; + } + nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); + + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[0], &node_b_id, 100000, 42); + + if steps & 0x0f == 3 { + return; + } + nodes[0] + .node + .funding_transaction_generated(temporary_channel_id, node_b_id, tx.clone()) + .unwrap(); + check_added_monitors(&nodes[0], 0); + let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); + + let channel_id = ChannelId::v1_from_funding_txid( + funding_created.funding_txid.as_byte_array(), + funding_created.funding_output_index, + ); + + if steps & 0x0f == 4 { + return; + } + nodes[1].node.handle_funding_created(node_a_id, &funding_created); + { + let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); + assert_eq!(added_monitors.len(), 1); + assert_eq!(added_monitors[0].0, channel_id); + added_monitors.clear(); + } + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + + if steps & 0x0f == 5 { + return; + } + nodes[0].node.handle_funding_signed(node_b_id, &funding_signed); + { + let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); + assert_eq!(added_monitors.len(), 1); + assert_eq!(added_monitors[0].0, channel_id); + added_monitors.clear(); + } + + expect_channel_pending_event(&nodes[0], &node_b_id); + let events_4 = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events_4.len(), 0); + + if steps & 0x0f == 6 { + return; + } + create_chan_between_nodes_with_value_confirm_first(&nodes[0], &nodes[1], &tx, 2); + + if steps & 0x0f == 7 { + return; + } + confirm_transaction_at(&nodes[0], &tx, 2); + connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH); + create_chan_between_nodes_with_value_confirm_second(&nodes[1], &nodes[0]); + expect_channel_ready_event(&nodes[0], &node_b_id); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_sanity_on_in_flight_opens() { + do_test_sanity_on_in_flight_opens(0); + do_test_sanity_on_in_flight_opens(0 | 0b1000_0000); + do_test_sanity_on_in_flight_opens(1); + do_test_sanity_on_in_flight_opens(1 | 0b1000_0000); + do_test_sanity_on_in_flight_opens(2); + do_test_sanity_on_in_flight_opens(2 | 0b1000_0000); + do_test_sanity_on_in_flight_opens(3); + do_test_sanity_on_in_flight_opens(3 | 0b1000_0000); + do_test_sanity_on_in_flight_opens(4); + do_test_sanity_on_in_flight_opens(4 | 0b1000_0000); + do_test_sanity_on_in_flight_opens(5); + do_test_sanity_on_in_flight_opens(5 | 0b1000_0000); + do_test_sanity_on_in_flight_opens(6); + do_test_sanity_on_in_flight_opens(6 | 0b1000_0000); + do_test_sanity_on_in_flight_opens(7); + do_test_sanity_on_in_flight_opens(7 | 0b1000_0000); + do_test_sanity_on_in_flight_opens(8); + do_test_sanity_on_in_flight_opens(8 | 0b1000_0000); +} + +#[xtest(feature = "_externalize_tests")] +#[should_panic] +pub fn bolt2_open_channel_sending_node_checks_part1() { + //This test needs to be on its own as we are catching a panic + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + // Force duplicate randomness for every get-random call + for node in nodes.iter() { + *node.keys_manager.override_random_bytes.lock().unwrap() = Some([0; 32]); + } + + // BOLT #2 spec: Sending node must ensure temporary_channel_id is unique from any other channel ID with the same peer. + let channel_value_satoshis = 10000; + let push_msat = 10001; + nodes[0] + .node + .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) + .unwrap(); + let node0_to_1_send_open_channel = + get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + nodes[1].node.handle_open_channel(node_a_id, &node0_to_1_send_open_channel); + get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + + // Create a second channel with the same random values. This used to panic due to a colliding + // channel_id, but now panics due to a colliding outbound SCID alias. + assert!(nodes[0] + .node + .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) + .is_err()); +} + +#[xtest(feature = "_externalize_tests")] +pub fn bolt2_open_channel_sending_node_checks_part2() { + let 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); + + let node_b_id = nodes[1].node.get_our_node_id(); + + // BOLT #2 spec: Sending node must set push_msat to equal or less than 1000 * funding_satoshis + let channel_value_satoshis = 10000; + // Test when push_msat is equal to 1000 * funding_satoshis. + let push_msat = 1000 * channel_value_satoshis + 1; + assert!(nodes[0] + .node + .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) + .is_err()); + + nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + + let node0_to_1_send_open_channel = + get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + // BOLT #2 spec: Sending node should set to_self_delay sufficient to ensure the sender can irreversibly spend a commitment transaction output, in case of misbehaviour by the receiver. + assert!(BREAKDOWN_TIMEOUT > 0); + assert!(node0_to_1_send_open_channel.common_fields.to_self_delay == BREAKDOWN_TIMEOUT); + + // BOLT #2 spec: Sending node must ensure the chain_hash value identifies the chain it wishes to open the channel within. + let chain_hash = ChainHash::using_genesis_block(Network::Testnet); + assert_eq!(node0_to_1_send_open_channel.common_fields.chain_hash, chain_hash); +} + +#[xtest(feature = "_externalize_tests")] +pub fn bolt2_open_channel_sane_dust_limit() { + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + let value_sats = 1000000; + let push_msat = 10001; + nodes[0].node.create_channel(node_b_id, value_sats, push_msat, 42, None, None).unwrap(); + let mut node0_to_1_send_open_channel = + get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + node0_to_1_send_open_channel.common_fields.dust_limit_satoshis = 547; + node0_to_1_send_open_channel.channel_reserve_satoshis = 100001; + + nodes[1].node.handle_open_channel(node_a_id, &node0_to_1_send_open_channel); + let events = nodes[1].node.get_and_clear_pending_msg_events(); + let err_msg = match events[0] { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, .. + } => msg.clone(), + _ => panic!("Unexpected event"), + }; + assert_eq!( + err_msg.data, + "dust_limit_satoshis (547) is greater than the implementation limit (546)" + ); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_user_configurable_csv_delay() { + // We test our channel constructors yield errors when we pass them absurd csv delay + + let mut low_our_to_self_config = UserConfig::default(); + low_our_to_self_config.channel_handshake_config.our_to_self_delay = 6; + let mut high_their_to_self_config = UserConfig::default(); + high_their_to_self_config.channel_handshake_limits.their_to_self_delay = 100; + let user_cfgs = [Some(high_their_to_self_config.clone()), None]; + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &user_cfgs); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + let logger = TestLogger::new(); + + // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in OutboundV1Channel::new() + if let Err(error) = OutboundV1Channel::new( + &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), + &nodes[0].keys_manager, + &nodes[0].keys_manager, + node_b_id, + &nodes[1].node.init_features(), + 1000000, + 1000000, + 0, + &low_our_to_self_config, + 0, + 42, + None, + &logger, + ) { + match error { + APIError::APIMisuseError { err } => { + assert!(regex::Regex::new( + r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks" + ) + .unwrap() + .is_match(err.as_str())); + }, + _ => panic!("Unexpected event"), + } + } else { + assert!(false) + } + + // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in InboundV1Channel::new() + nodes[1].node.create_channel(node_a_id, 1000000, 1000000, 42, None, None).unwrap(); + let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); + open_channel.common_fields.to_self_delay = 200; + if let Err(error) = InboundV1Channel::new( + &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), + &nodes[0].keys_manager, + &nodes[0].keys_manager, + node_b_id, + &nodes[0].node.channel_type_features(), + &nodes[1].node.init_features(), + &open_channel, + 0, + &low_our_to_self_config, + 0, + &nodes[0].logger, + /*is_0conf=*/ false, + ) { + match error { + ChannelError::Close((err, _)) => { + let regex = regex::Regex::new( + r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks", + ) + .unwrap(); + assert!(regex.is_match(err.as_str())); + }, + _ => panic!("Unexpected event"), + } + } else { + assert!(false); + } + + // We test msg.to_self_delay <= config.their_to_self_delay is enforced in Chanel::accept_channel() + nodes[0].node.create_channel(node_b_id, 1000000, 1000000, 42, None, None).unwrap(); + let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + nodes[1].node.handle_open_channel(node_a_id, &open_channel); + + let mut accept_channel = + get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + accept_channel.common_fields.to_self_delay = 200; + nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); + let reason_msg; + if let MessageSendEvent::HandleError { ref action, .. } = + nodes[0].node.get_and_clear_pending_msg_events()[0] + { + match action { + &ErrorAction::SendErrorMessage { ref msg } => { + assert!(regex::Regex::new(r"They wanted our payments to be delayed by a needlessly long period\. Upper limit: \d+\. Actual: \d+").unwrap().is_match(msg.data.as_str())); + reason_msg = msg.data.clone(); + }, + _ => { + panic!(); + }, + } + } else { + panic!(); + } + let reason = ClosureReason::ProcessingError { err: reason_msg }; + check_closed_event!(nodes[0], 1, reason, [node_b_id], 1000000); + + // We test msg.to_self_delay <= config.their_to_self_delay is enforced in InboundV1Channel::new() + nodes[1].node.create_channel(node_a_id, 1000000, 1000000, 42, None, None).unwrap(); + let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); + open_channel.common_fields.to_self_delay = 200; + if let Err(error) = InboundV1Channel::new( + &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), + &nodes[0].keys_manager, + &nodes[0].keys_manager, + node_b_id, + &nodes[0].node.channel_type_features(), + &nodes[1].node.init_features(), + &open_channel, + 0, + &high_their_to_self_config, + 0, + &nodes[0].logger, + /*is_0conf=*/ false, + ) { + match error { + ChannelError::Close((err, _)) => { + let regex = regex::Regex::new(r"They wanted our payments to be delayed by a needlessly long period\. Upper limit: \d+\. Actual: \d+").unwrap(); + assert!(regex.is_match(err.as_str())); + }, + _ => panic!("Unexpected event"), + } + } else { + assert!(false); + } +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_manually_accept_inbound_channel_request() { + let mut manually_accept_conf = UserConfig::default(); + manually_accept_conf.manually_accept_inbound_channels = true; + manually_accept_conf.channel_handshake_config.minimum_depth = 1; + + let 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, Some(manually_accept_conf.clone())]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0] + .node + .create_channel(node_b_id, 100000, 10001, 42, None, Some(manually_accept_conf)) + .unwrap(); + let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + nodes[1].node.handle_open_channel(node_a_id, &res); + + // Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before + // accepting the inbound channel request. + assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); + + let config_overrides = ChannelConfigOverrides { + handshake_overrides: Some(ChannelHandshakeConfigUpdate { + max_inbound_htlc_value_in_flight_percent_of_channel: None, + htlc_minimum_msat: None, + minimum_depth: None, + to_self_delay: None, + max_accepted_htlcs: Some(3), + channel_reserve_proportional_millionths: None, + }), + update_overrides: Some(ChannelConfigUpdate { + forwarding_fee_proportional_millionths: None, + forwarding_fee_base_msat: Some(555), + cltv_expiry_delta: None, + max_dust_htlc_exposure_msat: None, + force_close_avoidance_max_fee_satoshis: None, + accept_underpaying_htlcs: None, + }), + }; + let events = nodes[1].node.get_and_clear_pending_events(); + match events[0] { + Event::OpenChannelRequest { temporary_channel_id, .. } => { + let config = Some(config_overrides); + nodes[1] + .node + .accept_inbound_channel(&temporary_channel_id, &node_a_id, 23, config) + .unwrap(); + }, + _ => panic!("Unexpected event"), + } + + let accept_msg_ev = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(accept_msg_ev.len(), 1); + + let ref accept_channel: AcceptChannel; + match accept_msg_ev[0] { + MessageSendEvent::SendAcceptChannel { ref node_id, ref msg } => { + assert_eq!(*node_id, node_a_id); + + // Assert overriden handshake parameter. + assert_eq!(msg.common_fields.max_accepted_htlcs, 3); + + accept_channel = msg; + }, + _ => panic!("Unexpected event"), + } + + // Continue channel opening process until channel update messages are sent. + nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); + let (temp_channel_id, tx, funding_outpoint) = + create_funding_transaction(&nodes[0], &node_b_id, 100_000, 42); + nodes[0] + .node + .unsafe_manual_funding_transaction_generated(temp_channel_id, node_b_id, funding_outpoint) + .unwrap(); + check_added_monitors(&nodes[0], 0); + + let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); + nodes[1].node.handle_funding_created(node_a_id, &funding_created); + check_added_monitors(&nodes[1], 1); + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + nodes[0].node.handle_funding_signed(node_b_id, &funding_signed); + check_added_monitors(&nodes[0], 1); + let events = &nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events.len(), 2); + match &events[0] { + crate::events::Event::FundingTxBroadcastSafe { funding_txo, .. } => { + assert_eq!(funding_txo.txid, funding_outpoint.txid); + assert_eq!(funding_txo.vout, funding_outpoint.index.into()); + }, + _ => panic!("Unexpected event"), + }; + match &events[1] { + crate::events::Event::ChannelPending { counterparty_node_id, .. } => { + assert_eq!(node_b_id, *counterparty_node_id); + }, + _ => panic!("Unexpected event"), + }; + + mine_transaction(&nodes[0], &tx); + mine_transaction(&nodes[1], &tx); + + let as_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, node_a_id); + nodes[1].node.handle_channel_ready(node_a_id, &as_channel_ready); + let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, node_b_id); + nodes[0].node.handle_channel_ready(node_b_id, &as_channel_ready); + + expect_channel_ready_event(&nodes[0], &node_b_id); + expect_channel_ready_event(&nodes[1], &node_a_id); + + // Assert that the overriden base fee surfaces in the channel update. + let channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, node_a_id); + assert_eq!(channel_update.contents.fee_base_msat, 555); + + get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, node_b_id); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_manually_reject_inbound_channel_request() { + let mut manually_accept_conf = UserConfig::default(); + manually_accept_conf.manually_accept_inbound_channels = true; + let 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, Some(manually_accept_conf.clone())]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0] + .node + .create_channel(node_b_id, 100000, 10001, 42, None, Some(manually_accept_conf)) + .unwrap(); + let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + nodes[1].node.handle_open_channel(node_a_id, &res); + + // Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before + // rejecting the inbound channel request. + assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); + let err = "Channel force-closed".to_string(); + let events = nodes[1].node.get_and_clear_pending_events(); + match events[0] { + Event::OpenChannelRequest { temporary_channel_id, .. } => { + nodes[1] + .node + .force_close_broadcasting_latest_txn(&temporary_channel_id, &node_a_id, err) + .unwrap(); + }, + _ => panic!("Unexpected event"), + } + + let close_msg_ev = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(close_msg_ev.len(), 1); + + match close_msg_ev[0] { + MessageSendEvent::HandleError { ref node_id, .. } => { + assert_eq!(*node_id, node_a_id); + }, + _ => panic!("Unexpected event"), + } + + // There should be no more events to process, as the channel was never opened. + assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_can_not_accept_inbound_channel_twice() { + let mut manually_accept_conf = UserConfig::default(); + manually_accept_conf.manually_accept_inbound_channels = true; + let 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, Some(manually_accept_conf.clone())]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0] + .node + .create_channel(node_b_id, 100000, 10001, 42, None, Some(manually_accept_conf)) + .unwrap(); + let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + nodes[1].node.handle_open_channel(node_a_id, &res); + + // Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before + // accepting the inbound channel request. + assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); + + let events = nodes[1].node.get_and_clear_pending_events(); + match events[0] { + Event::OpenChannelRequest { temporary_channel_id, .. } => { + nodes[1] + .node + .accept_inbound_channel(&temporary_channel_id, &node_a_id, 0, None) + .unwrap(); + let api_res = + nodes[1].node.accept_inbound_channel(&temporary_channel_id, &node_a_id, 0, None); + match api_res { + Err(APIError::APIMisuseError { err }) => { + assert_eq!(err, "No such channel awaiting to be accepted."); + }, + Ok(_) => panic!("Channel shouldn't be possible to be accepted twice"), + Err(e) => panic!("Unexpected Error {:?}", e), + } + }, + _ => panic!("Unexpected event"), + } + + // Ensure that the channel wasn't closed after attempting to accept it twice. + let accept_msg_ev = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(accept_msg_ev.len(), 1); + + match accept_msg_ev[0] { + MessageSendEvent::SendAcceptChannel { ref node_id, .. } => { + assert_eq!(*node_id, node_a_id); + }, + _ => panic!("Unexpected event"), + } +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_can_not_accept_unknown_inbound_channel() { + let chanmon_cfg = create_chanmon_cfgs(2); + let node_cfg = create_node_cfgs(2, &chanmon_cfg); + let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[None, None]); + let nodes = create_network(2, &node_cfg, &node_chanmgr); + + let node_b_id = nodes[1].node.get_our_node_id(); + + let unknown_channel_id = ChannelId::new_zero(); + let api_res = nodes[0].node.accept_inbound_channel(&unknown_channel_id, &node_b_id, 0, None); + match api_res { + Err(APIError::APIMisuseError { err }) => { + assert_eq!(err, "No such channel awaiting to be accepted."); + }, + Ok(_) => panic!("It shouldn't be possible to accept an unkown channel"), + Err(e) => panic!("Unexpected Error: {:?}", e), + } +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_duplicate_temporary_channel_id_from_different_peers() { + // Tests that we can accept two different `OpenChannel` requests with the same + // `temporary_channel_id`, as long as they are from different peers. + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + let node_c_id = nodes[2].node.get_our_node_id(); + + // Create an first channel channel + nodes[1].node.create_channel(node_a_id, 100000, 10001, 42, None, None).unwrap(); + let mut open_chan_msg_chan_1_0 = + get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); + + // Create an second channel + nodes[2].node.create_channel(node_a_id, 100000, 10001, 43, None, None).unwrap(); + let mut open_chan_msg_chan_2_0 = + get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, node_a_id); + + // Modify the `OpenChannel` from `nodes[2]` to `nodes[0]` to ensure that it uses the same + // `temporary_channel_id` as the `OpenChannel` from nodes[1] to nodes[0]. + open_chan_msg_chan_2_0.common_fields.temporary_channel_id = + open_chan_msg_chan_1_0.common_fields.temporary_channel_id; + + // Assert that `nodes[0]` can accept both `OpenChannel` requests, even though they use the same + // `temporary_channel_id` as they are from different peers. + nodes[0].node.handle_open_channel(node_b_id, &open_chan_msg_chan_1_0); + { + let events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match &events[0] { + MessageSendEvent::SendAcceptChannel { node_id, msg } => { + assert_eq!(node_id, &node_b_id); + assert_eq!( + msg.common_fields.temporary_channel_id, + open_chan_msg_chan_1_0.common_fields.temporary_channel_id + ); + }, + _ => panic!("Unexpected event"), + } + } + + nodes[0].node.handle_open_channel(node_c_id, &open_chan_msg_chan_2_0); + { + let events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match &events[0] { + MessageSendEvent::SendAcceptChannel { node_id, msg } => { + assert_eq!(node_id, &node_c_id); + assert_eq!( + msg.common_fields.temporary_channel_id, + open_chan_msg_chan_1_0.common_fields.temporary_channel_id + ); + }, + _ => panic!("Unexpected event"), + } + } +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_duplicate_funding_err_in_funding() { + // Test that if we have a live channel with one peer, then another peer comes along and tries + // to create a second channel with the same txid we'll fail and not overwrite the + // outpoint_to_peer map in `ChannelManager`. + // + // This was previously broken. + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + let node_b_id = nodes[1].node.get_our_node_id(); + let node_c_id = nodes[2].node.get_our_node_id(); + + let (_, _, _, real_channel_id, funding_tx) = create_chan_between_nodes(&nodes[0], &nodes[1]); + let real_chan_funding_txo = + chain::transaction::OutPoint { txid: funding_tx.compute_txid(), index: 0 }; + assert_eq!(ChannelId::v1_from_funding_outpoint(real_chan_funding_txo), real_channel_id); + + nodes[2].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let mut open_chan_msg = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, node_b_id); + let node_c_temp_chan_id = open_chan_msg.common_fields.temporary_channel_id; + open_chan_msg.common_fields.temporary_channel_id = real_channel_id; + nodes[1].node.handle_open_channel(node_c_id, &open_chan_msg); + let mut accept_chan_msg = + get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_c_id); + accept_chan_msg.common_fields.temporary_channel_id = node_c_temp_chan_id; + nodes[2].node.handle_accept_channel(node_b_id, &accept_chan_msg); + + // Now that we have a second channel with the same funding txo, send a bogus funding message + // and let nodes[1] remove the inbound channel. + let (_, fund_tx, _) = create_funding_transaction(&nodes[2], &node_b_id, 100_000, 42); + + nodes[2].node.funding_transaction_generated(node_c_temp_chan_id, node_b_id, fund_tx).unwrap(); + + let mut funding_created_msg = + get_event_msg!(nodes[2], MessageSendEvent::SendFundingCreated, node_b_id); + funding_created_msg.temporary_channel_id = real_channel_id; + // Make the signature invalid by changing the funding output + funding_created_msg.funding_output_index += 10; + nodes[1].node.handle_funding_created(node_c_id, &funding_created_msg); + get_err_msg(&nodes[1], &node_c_id); + let err = "Invalid funding_created signature from peer".to_owned(); + let reason = ClosureReason::ProcessingError { err }; + let expected_closing = ExpectedCloseEvent::from_id_reason(real_channel_id, false, reason); + check_closed_events(&nodes[1], &[expected_closing]); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_duplicate_chan_id() { + // Test that if a given peer tries to open a channel with the same channel_id as one that is + // already open we reject it and keep the old channel. + // + // Previously, full_stack_target managed to figure out that if you tried to open two channels + // with the same funding output (ie post-funding channel_id), we'd create a monitor update for + // the existing channel when we detect the duplicate new channel, screwing up our monitor + // updating logic for the existing channel. + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + // Create an initial channel + nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + nodes[1].node.handle_open_channel(node_a_id, &open_chan_msg); + nodes[0].node.handle_accept_channel( + node_b_id, + &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id), + ); + + // Try to create a second channel with the same temporary_channel_id as the first and check + // that it is rejected. + nodes[1].node.handle_open_channel(node_a_id, &open_chan_msg); + { + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { + // Technically, at this point, nodes[1] would be justified in thinking both the + // first (valid) and second (invalid) channels are closed, given they both have + // the same non-temporary channel_id. However, currently we do not, so we just + // move forward with it. + assert_eq!(msg.channel_id, open_chan_msg.common_fields.temporary_channel_id); + assert_eq!(node_id, node_a_id); + }, + _ => panic!("Unexpected event"), + } + } + + // Move the first channel through the funding flow... + let (temp_channel_id, tx, _) = create_funding_transaction(&nodes[0], &node_b_id, 100000, 42); + + nodes[0].node.funding_transaction_generated(temp_channel_id, node_b_id, tx.clone()).unwrap(); + check_added_monitors(&nodes[0], 0); + + let mut funding_created_msg = + get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); + let channel_id = ChannelId::v1_from_funding_txid( + funding_created_msg.funding_txid.as_byte_array(), + funding_created_msg.funding_output_index, + ); + + nodes[1].node.handle_funding_created(node_a_id, &funding_created_msg); + { + let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); + assert_eq!(added_monitors.len(), 1); + assert_eq!(added_monitors[0].0, channel_id); + added_monitors.clear(); + } + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed_msg = + get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + + let funding_outpoint = crate::chain::transaction::OutPoint { + txid: funding_created_msg.funding_txid, + index: funding_created_msg.funding_output_index, + }; + let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint); + + // Now we have the first channel past funding_created (ie it has a txid-based channel_id, not a + // temporary one). + + // First try to open a second channel with a temporary channel id equal to the txid-based one. + // Technically this is allowed by the spec, but we don't support it and there's little reason + // to. Still, it shouldn't cause any other issues. + open_chan_msg.common_fields.temporary_channel_id = channel_id; + nodes[1].node.handle_open_channel(node_a_id, &open_chan_msg); + { + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { + // Technically, at this point, nodes[1] would be justified in thinking both + // channels are closed, but currently we do not, so we just move forward with it. + assert_eq!(msg.channel_id, open_chan_msg.common_fields.temporary_channel_id); + assert_eq!(node_id, node_a_id); + }, + _ => panic!("Unexpected event"), + } + } + + // Now try to create a second channel which has a duplicate funding output. + nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + let open_chan_2_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + nodes[1].node.handle_open_channel(node_a_id, &open_chan_2_msg); + nodes[0].node.handle_accept_channel( + node_b_id, + &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id), + ); + create_funding_transaction(&nodes[0], &node_b_id, 100000, 42); // Get and check the FundingGenerationReady event + + let funding_created = { + let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); + let mut a_peer_state = per_peer_state.get(&node_b_id).unwrap().lock().unwrap(); + // Once we call `get_funding_created` the channel has a duplicate channel_id as + // another channel in the ChannelManager - an invalid state. Thus, we'd panic later when we + // try to create another channel. Instead, we drop the channel entirely here (leaving the + // channelmanager in a possibly nonsense state instead). + let chan_id = open_chan_2_msg.common_fields.temporary_channel_id; + let mut channel = a_peer_state.channel_by_id.remove(&chan_id).unwrap(); + + if let Some(mut chan) = channel.as_unfunded_outbound_v1_mut() { + let logger = test_utils::TestLogger::new(); + chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger) + .map_err(|_| ()) + .unwrap() + } else { + panic!("Unexpected Channel phase") + } + .unwrap() + }; + check_added_monitors(&nodes[0], 0); + nodes[1].node.handle_funding_created(node_a_id, &funding_created); + // At this point we'll look up if the channel_id is present and immediately fail the channel + // without trying to persist the `ChannelMonitor`. + check_added_monitors(&nodes[1], 0); + + let reason = ClosureReason::ProcessingError { + err: "Already had channel with the new channel_id".to_owned(), + }; + let close_event = + ExpectedCloseEvent::from_id_reason(funding_created.temporary_channel_id, false, reason); + check_closed_events(&nodes[1], &[close_event]); + + // ...still, nodes[1] will reject the duplicate channel. + { + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { + // Technically, at this point, nodes[1] would be justified in thinking both + // channels are closed, but currently we do not, so we just move forward with it. + assert_eq!(msg.channel_id, funding_created.temporary_channel_id); + assert_eq!(node_id, node_a_id); + }, + _ => panic!("Unexpected event"), + } + } + + // finally, finish creating the original channel and send a payment over it to make sure + // everything is functional. + nodes[0].node.handle_funding_signed(node_b_id, &funding_signed_msg); + { + let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); + assert_eq!(added_monitors.len(), 1); + assert_eq!(added_monitors[0].0, channel_id); + added_monitors.clear(); + } + expect_channel_pending_event(&nodes[0], &node_b_id); + + let events_4 = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events_4.len(), 0); + assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); + assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx); + + let (channel_ready, _) = + create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); + let (announcement, as_update, bs_update) = + create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); + update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update); + + send_payment(&nodes[0], &[&nodes[1]], 8000000); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_invalid_funding_tx() { + // Test that we properly handle invalid funding transactions sent to us from a peer. + // + // Previously, all other major lightning implementations had failed to properly sanitize + // funding transactions from their counterparties, leading to a multi-implementation critical + // security vulnerability (though we always sanitized properly, we've previously had + // un-released crashes in the sanitization process). + // + // Further, if the funding transaction is consensus-valid, confirms, and is later spent, we'd + // previously have crashed in `ChannelMonitor` even though we closed the channel as bogus and + // gave up on it. We test this here by generating such a transaction. + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0].node.create_channel(node_b_id, 100_000, 10_000, 42, None, None).unwrap(); + nodes[1].node.handle_open_channel( + node_a_id, + &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id), + ); + nodes[0].node.handle_accept_channel( + node_b_id, + &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id), + ); + + let (temporary_channel_id, mut tx, _) = + create_funding_transaction(&nodes[0], &node_b_id, 100_000, 42); + + // Create a witness program which can be spent by a 4-empty-stack-elements witness and which is + // 136 bytes long. This matches our "accepted HTLC preimage spend" matching, previously causing + // a panic as we'd try to extract a 32 byte preimage from a witness element without checking + // its length. + let mut wit_program: Vec = + channelmonitor::deliberately_bogus_accepted_htlc_witness_program(); + let wit_program_script: ScriptBuf = wit_program.into(); + for output in tx.output.iter_mut() { + // Make the confirmed funding transaction have a bogus script_pubkey + output.script_pubkey = ScriptBuf::new_p2wsh(&wit_program_script.wscript_hash()); + } + + nodes[0] + .node + .funding_transaction_generated_unchecked(temporary_channel_id, node_b_id, tx.clone(), 0) + .unwrap(); + nodes[1].node.handle_funding_created( + node_a_id, + &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id), + ); + check_added_monitors(&nodes[1], 1); + expect_channel_pending_event(&nodes[1], &node_a_id); + + nodes[0].node.handle_funding_signed( + node_b_id, + &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id), + ); + check_added_monitors(&nodes[0], 1); + expect_channel_pending_event(&nodes[0], &node_b_id); + + let events_1 = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events_1.len(), 0); + + assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); + assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx); + nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); + + let expected_err = "funding tx had wrong script/value or output index"; + confirm_transaction_at(&nodes[1], &tx, 1); + + let reason = ClosureReason::ProcessingError { err: expected_err.to_string() }; + check_closed_event!(nodes[1], 1, reason, [node_a_id], 100000); + + check_added_monitors(&nodes[1], 1); + let events_2 = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events_2.len(), 1); + if let MessageSendEvent::HandleError { node_id, action } = &events_2[0] { + assert_eq!(*node_id, node_a_id); + if let msgs::ErrorAction::SendErrorMessage { msg } = action { + assert_eq!( + msg.data, + "Channel closed because of an exception: ".to_owned() + expected_err + ); + } else { + panic!(); + } + } else { + panic!(); + } + assert_eq!(nodes[1].node.list_channels().len(), 0); + + // Now confirm a spend of the (bogus) funding transaction. As long as the witness is 5 elements + // long the ChannelMonitor will try to read 32 bytes from the second-to-last element, panicing + // as its not 32 bytes long. + let mut spend_tx = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: tx + .output + .iter() + .enumerate() + .map(|(idx, _)| TxIn { + previous_output: BitcoinOutPoint { txid: tx.compute_txid(), vout: idx as u32 }, + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, + witness: Witness::from_slice( + &channelmonitor::deliberately_bogus_accepted_htlc_witness(), + ), + }) + .collect(), + output: vec![TxOut { value: Amount::from_sat(1000), script_pubkey: ScriptBuf::new() }], + }; + check_spends!(spend_tx, tx); + mine_transaction(&nodes[1], &spend_tx); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_coinbase_funding_tx() { + // Miners are able to fund channels directly from coinbase transactions, however + // by consensus rules, outputs of a coinbase transaction are encumbered by a 100 + // block maturity timelock. To ensure that a (non-0conf) channel like this is enforceable + // on-chain, the minimum depth is updated to 100 blocks for coinbase funding transactions. + // + // Note that 0conf channels with coinbase funding transactions are unaffected and are + // immediately operational after opening. + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + nodes[1].node.handle_open_channel(node_a_id, &open_channel); + let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + + nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); + + // Create the coinbase funding transaction. + let (channel_id, tx, _) = + create_coinbase_funding_transaction(&nodes[0], &node_b_id, 100000, 42); + + nodes[0].node.funding_transaction_generated(channel_id, node_b_id, tx.clone()).unwrap(); + check_added_monitors(&nodes[0], 0); + let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); + + nodes[1].node.handle_funding_created(node_a_id, &funding_created); + check_added_monitors(&nodes[1], 1); + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + + nodes[0].node.handle_funding_signed(node_b_id, &funding_signed); + check_added_monitors(&nodes[0], 1); + + expect_channel_pending_event(&nodes[0], &node_b_id); + assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); + + // Starting at height 0, we "confirm" the coinbase at height 1. + confirm_transaction_at(&nodes[0], &tx, 1); + // We connect 98 more blocks to have 99 confirmations for the coinbase transaction. + connect_blocks(&nodes[0], COINBASE_MATURITY - 2); + // Check that we have no pending message events (we have not queued a `channel_ready` yet). + assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); + // Now connect one more block which results in 100 confirmations of the coinbase transaction. + connect_blocks(&nodes[0], 1); + // There should now be a `channel_ready` which can be handled. + let _ = &nodes[1].node.handle_channel_ready( + node_a_id, + &get_event_msg!(&nodes[0], MessageSendEvent::SendChannelReady, node_b_id), + ); + + confirm_transaction_at(&nodes[1], &tx, 1); + connect_blocks(&nodes[1], COINBASE_MATURITY - 2); + assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); + connect_blocks(&nodes[1], 1); + expect_channel_ready_event(&nodes[1], &node_a_id); + create_chan_between_nodes_with_value_confirm_second(&nodes[0], &nodes[1]); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_non_final_funding_tx() { + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + let temp_channel_id = + nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let open_channel_message = + get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + nodes[1].node.handle_open_channel(node_a_id, &open_channel_message); + let accept_channel_message = + get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + nodes[0].node.handle_accept_channel(node_b_id, &accept_channel_message); + + let best_height = nodes[0].node.best_block.read().unwrap().height; + + let chan_id = *nodes[0].network_chan_count.borrow(); + let events = nodes[0].node.get_and_clear_pending_events(); + let input = TxIn { + previous_output: BitcoinOutPoint::null(), + script_sig: bitcoin::ScriptBuf::new(), + sequence: Sequence(1), + witness: Witness::from_slice(&[&[1]]), + }; + assert_eq!(events.len(), 1); + let mut tx = match events[0] { + Event::FundingGenerationReady { ref channel_value_satoshis, ref output_script, .. } => { + // Timelock the transaction _beyond_ the best client height + 1. + Transaction { + version: Version(chan_id as i32), + lock_time: LockTime::from_height(best_height + 2).unwrap(), + input: vec![input], + output: vec![TxOut { + value: Amount::from_sat(*channel_value_satoshis), + script_pubkey: output_script.clone(), + }], + } + }, + _ => panic!("Unexpected event"), + }; + // Transaction should fail as it's evaluated as non-final for propagation. + match nodes[0].node.funding_transaction_generated(temp_channel_id, node_b_id, tx.clone()) { + Err(APIError::APIMisuseError { err }) => { + assert_eq!(format!("Funding transaction absolute timelock is non-final"), err); + }, + _ => panic!(), + } + let err = "Error in transaction funding: Misuse error: Funding transaction absolute timelock is non-final"; + let reason = ClosureReason::ProcessingError { err: err.to_owned() }; + let event = ExpectedCloseEvent::from_id_reason(temp_channel_id, false, reason); + check_closed_events(&nodes[0], &[event]); + assert_eq!(get_err_msg(&nodes[0], &node_b_id).data, err); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_non_final_funding_tx_within_headroom() { + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + let temp_channel_id = + nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let open_channel_message = + get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + nodes[1].node.handle_open_channel(node_a_id, &open_channel_message); + let accept_channel_message = + get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + nodes[0].node.handle_accept_channel(node_b_id, &accept_channel_message); + + let best_height = nodes[0].node.best_block.read().unwrap().height; + + let chan_id = *nodes[0].network_chan_count.borrow(); + let events = nodes[0].node.get_and_clear_pending_events(); + let input = TxIn { + previous_output: BitcoinOutPoint::null(), + script_sig: bitcoin::ScriptBuf::new(), + sequence: Sequence(1), + witness: Witness::from_slice(&[[1]]), + }; + assert_eq!(events.len(), 1); + let mut tx = match events[0] { + Event::FundingGenerationReady { ref channel_value_satoshis, ref output_script, .. } => { + // Timelock the transaction within a +1 headroom from the best block. + Transaction { + version: Version(chan_id as i32), + lock_time: LockTime::from_consensus(best_height + 1), + input: vec![input], + output: vec![TxOut { + value: Amount::from_sat(*channel_value_satoshis), + script_pubkey: output_script.clone(), + }], + } + }, + _ => panic!("Unexpected event"), + }; + + // Transaction should be accepted if it's in a +1 headroom from best block. + nodes[0].node.funding_transaction_generated(temp_channel_id, node_b_id, tx.clone()).unwrap(); + get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_channel_close_when_not_timely_accepted() { + // Create network of two nodes + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + // Simulate peer-disconnects mid-handshake + // The channel is initiated from the node 0 side, + // but the nodes disconnect before node 1 could send accept channel + let create_chan_id = + nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); + + nodes[0].node.peer_disconnected(node_b_id); + nodes[1].node.peer_disconnected(node_a_id); + + // Make sure that we have not removed the OutboundV1Channel from node[0] immediately. + assert_eq!(nodes[0].node.list_channels().len(), 1); + + // Since channel was inbound from node[1] perspective, it should have been dropped immediately. + assert_eq!(nodes[1].node.list_channels().len(), 0); + + // In the meantime, some time passes. + for _ in 0..UNFUNDED_CHANNEL_AGE_LIMIT_TICKS { + nodes[0].node.timer_tick_occurred(); + } + + // Since we disconnected from peer and did not connect back within time, + // we should have forced-closed the channel by now. + let reason = ClosureReason::FundingTimedOut; + check_closed_event!(nodes[0], 1, reason, [node_b_id], 100000); + assert_eq!(nodes[0].node.list_channels().len(), 0); + + { + // Since accept channel message was never received + // The channel should be forced close by now from node 0 side + // and the peer removed from per_peer_state + let node_0_per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); + assert_eq!(node_0_per_peer_state.len(), 0); + } +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_rebroadcast_open_channel_when_reconnect_mid_handshake() { + // Create network of two nodes + let 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); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + // Simulate peer-disconnects mid-handshake + // The channel is initiated from the node 0 side, + // but the nodes disconnect before node 1 could send accept channel + let create_chan_id = + nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); + + nodes[0].node.peer_disconnected(node_b_id); + nodes[1].node.peer_disconnected(node_a_id); + + // Make sure that we have not removed the OutboundV1Channel from node[0] immediately. + assert_eq!(nodes[0].node.list_channels().len(), 1); + + // Since channel was inbound from node[1] perspective, it should have been immediately dropped. + assert_eq!(nodes[1].node.list_channels().len(), 0); + + // The peers now reconnect + let init_msg = msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }; + nodes[0].node.peer_connected(node_b_id, &init_msg, true).unwrap(); + nodes[1].node.peer_connected(node_a_id, &init_msg, false).unwrap(); + + // Make sure the SendOpenChannel message is added to node_0 pending message events + let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), 1); + match &msg_events[0] { + MessageSendEvent::SendOpenChannel { msg, .. } => assert_eq!(msg, &open_channel_msg), + _ => panic!("Unexpected message."), + } +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_batch_channel_open() { + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + let node_c_id = nodes[2].node.get_our_node_id(); + + // Initiate channel opening and create the batch channel funding transaction. + let (tx, funding_created_msgs) = create_batch_channel_funding( + &nodes[0], + &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], + ); + + // Go through the funding_created and funding_signed flow with node 1. + nodes[1].node.handle_funding_created(node_a_id, &funding_created_msgs[0]); + check_added_monitors(&nodes[1], 1); + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed_msg = + get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + nodes[0].node.handle_funding_signed(node_b_id, &funding_signed_msg); + check_added_monitors(&nodes[0], 1); + + // The transaction should not have been broadcast before all channels are ready. + assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 0); + + // Go through the funding_created and funding_signed flow with node 2. + nodes[2].node.handle_funding_created(node_a_id, &funding_created_msgs[1]); + check_added_monitors(&nodes[2], 1); + expect_channel_pending_event(&nodes[2], &node_a_id); + + let funding_signed_msg = + get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, node_a_id); + chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); + nodes[0].node.handle_funding_signed(node_c_id, &funding_signed_msg); + check_added_monitors(&nodes[0], 1); + + // The transaction should not have been broadcast before persisting all monitors has been + // completed. + assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0); + assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); + + // Complete the persistence of the monitor. + nodes[0].chain_monitor.complete_sole_pending_chan_update(&ChannelId::v1_from_funding_outpoint( + OutPoint { txid: tx.compute_txid(), index: 1 }, + )); + let events = nodes[0].node.get_and_clear_pending_events(); + + // The transaction should only have been broadcast now. + let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast(); + assert_eq!(broadcasted_txs.len(), 1); + assert_eq!(broadcasted_txs[0], tx); + + assert_eq!(events.len(), 2); + assert!(events.iter().any(|e| matches!( + *e, + crate::events::Event::ChannelPending { + ref counterparty_node_id, + .. + } if counterparty_node_id == &node_b_id, + ))); + assert!(events.iter().any(|e| matches!( + *e, + crate::events::Event::ChannelPending { + ref counterparty_node_id, + .. + } if counterparty_node_id == &node_c_id, + ))); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_close_in_funding_batch() { + // This test ensures that if one of the channels + // in the batch closes, the complete batch will close. + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + // Initiate channel opening and create the batch channel funding transaction. + let (tx, funding_created_msgs) = create_batch_channel_funding( + &nodes[0], + &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], + ); + + // Go through the funding_created and funding_signed flow with node 1. + nodes[1].node.handle_funding_created(node_a_id, &funding_created_msgs[0]); + check_added_monitors(&nodes[1], 1); + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed_msg = + get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + nodes[0].node.handle_funding_signed(node_b_id, &funding_signed_msg); + check_added_monitors(&nodes[0], 1); + + // The transaction should not have been broadcast before all channels are ready. + assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0); + + // Force-close the channel for which we've completed the initial monitor. + let funding_txo_1 = OutPoint { txid: tx.compute_txid(), index: 0 }; + let funding_txo_2 = OutPoint { txid: tx.compute_txid(), index: 1 }; + let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1); + let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2); + let err = "Channel force-closed".to_string(); + nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &node_b_id, err).unwrap(); + + // The monitor should become closed. + check_added_monitors(&nodes[0], 1); + { + let mut monitor_updates = nodes[0].chain_monitor.monitor_updates.lock().unwrap(); + let monitor_updates_1 = monitor_updates.get(&channel_id_1).unwrap(); + assert_eq!(monitor_updates_1.len(), 1); + assert_eq!(monitor_updates_1[0].updates.len(), 1); + assert!(matches!( + monitor_updates_1[0].updates[0], + ChannelMonitorUpdateStep::ChannelForceClosed { .. } + )); + } + + let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); + match msg_events[0] { + MessageSendEvent::HandleError { .. } => (), + _ => panic!("Unexpected message."), + } + + // Because the funding was never broadcasted, we should never bother to broadcast the + // commitment transactions either. + let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast(); + assert_eq!(broadcasted_txs.len(), 0); + + // All channels in the batch should close immediately. + check_closed_events( + &nodes[0], + &[ + ExpectedCloseEvent { + channel_id: Some(channel_id_1), + discard_funding: true, + channel_funding_txo: Some(funding_txo_1), + user_channel_id: Some(42), + ..Default::default() + }, + ExpectedCloseEvent { + channel_id: Some(channel_id_2), + discard_funding: true, + channel_funding_txo: Some(funding_txo_2), + user_channel_id: Some(43), + ..Default::default() + }, + ], + ); + + // Ensure the channels don't exist anymore. + assert!(nodes[0].node.list_channels().is_empty()); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_batch_funding_close_after_funding_signed() { + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + let node_c_id = nodes[2].node.get_our_node_id(); + + // Initiate channel opening and create the batch channel funding transaction. + let (tx, funding_created_msgs) = create_batch_channel_funding( + &nodes[0], + &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], + ); + + // Go through the funding_created and funding_signed flow with node 1. + nodes[1].node.handle_funding_created(node_a_id, &funding_created_msgs[0]); + check_added_monitors(&nodes[1], 1); + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed_msg = + get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + nodes[0].node.handle_funding_signed(node_b_id, &funding_signed_msg); + check_added_monitors(&nodes[0], 1); + + // Go through the funding_created and funding_signed flow with node 2. + nodes[2].node.handle_funding_created(node_a_id, &funding_created_msgs[1]); + check_added_monitors(&nodes[2], 1); + expect_channel_pending_event(&nodes[2], &node_a_id); + + let funding_signed_msg = + get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, node_a_id); + chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); + nodes[0].node.handle_funding_signed(node_c_id, &funding_signed_msg); + check_added_monitors(&nodes[0], 1); + + // The transaction should not have been broadcast before all channels are ready. + assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0); + + // Force-close the channel for which we've completed the initial monitor. + let funding_txo_1 = OutPoint { txid: tx.compute_txid(), index: 0 }; + let funding_txo_2 = OutPoint { txid: tx.compute_txid(), index: 1 }; + let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1); + let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2); + let err = "Channel force-closed".to_string(); + nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &node_b_id, err).unwrap(); + check_added_monitors(&nodes[0], 2); + { + let mut monitor_updates = nodes[0].chain_monitor.monitor_updates.lock().unwrap(); + let monitor_updates_1 = monitor_updates.get(&channel_id_1).unwrap(); + assert_eq!(monitor_updates_1.len(), 1); + assert_eq!(monitor_updates_1[0].updates.len(), 1); + assert!(matches!( + monitor_updates_1[0].updates[0], + ChannelMonitorUpdateStep::ChannelForceClosed { .. } + )); + let monitor_updates_2 = monitor_updates.get(&channel_id_2).unwrap(); + assert_eq!(monitor_updates_2.len(), 1); + assert_eq!(monitor_updates_2[0].updates.len(), 1); + assert!(matches!( + monitor_updates_2[0].updates[0], + ChannelMonitorUpdateStep::ChannelForceClosed { .. } + )); + } + let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); + match msg_events[0] { + MessageSendEvent::HandleError { .. } => (), + _ => panic!("Unexpected message."), + } + + // Because the funding was never broadcasted, we should never bother to broadcast the + // commitment transactions either. + let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast(); + assert_eq!(broadcasted_txs.len(), 0); + + // All channels in the batch should close immediately. + check_closed_events( + &nodes[0], + &[ + ExpectedCloseEvent { + channel_id: Some(channel_id_1), + discard_funding: true, + channel_funding_txo: Some(funding_txo_1), + user_channel_id: Some(42), + ..Default::default() + }, + ExpectedCloseEvent { + channel_id: Some(channel_id_2), + discard_funding: true, + channel_funding_txo: Some(funding_txo_2), + user_channel_id: Some(43), + ..Default::default() + }, + ], + ); + + // Ensure the channels don't exist anymore. + assert!(nodes[0].node.list_channels().is_empty()); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_funding_and_commitment_tx_confirm_same_block() { + // Tests that a node will forget the channel (when it only requires 1 confirmation) if the + // funding and commitment transaction confirm in the same block. + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let mut min_depth_1_block_cfg = test_default_channel_config(); + min_depth_1_block_cfg.channel_handshake_config.minimum_depth = 1; + let node_chanmgrs = create_node_chanmgrs( + 2, + &node_cfgs, + &[Some(min_depth_1_block_cfg.clone()), Some(min_depth_1_block_cfg)], + ); + let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + let funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 0); + let chan_id = ChannelId::v1_from_funding_outpoint(chain::transaction::OutPoint { + txid: funding_tx.compute_txid(), + index: 0, + }); + + assert_eq!(nodes[0].node.list_channels().len(), 1); + assert_eq!(nodes[1].node.list_channels().len(), 1); + + let commitment_tx = { + let mon = get_monitor!(nodes[0], chan_id); + let mut txn = mon.unsafe_get_latest_holder_commitment_txn(&nodes[0].logger); + assert_eq!(txn.len(), 1); + txn.pop().unwrap() + }; + + mine_transactions(&nodes[0], &[&funding_tx, &commitment_tx]); + mine_transactions(&nodes[1], &[&funding_tx, &commitment_tx]); + + let check_msg_events = |node: &Node| { + let mut msg_events = node.node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), 3, "{msg_events:?}"); + if let MessageSendEvent::SendChannelReady { .. } = msg_events.remove(0) { + } else { + panic!(); + } + if let MessageSendEvent::HandleError { + action: msgs::ErrorAction::SendErrorMessage { .. }, + node_id: _, + } = msg_events.remove(0) + { + } else { + panic!(); + } + if let MessageSendEvent::BroadcastChannelUpdate { ref msg } = msg_events.remove(0) { + assert_eq!(msg.contents.channel_flags & 2, 2); + } else { + panic!(); + } + }; + check_msg_events(&nodes[0]); + check_added_monitors(&nodes[0], 1); + let reason = ClosureReason::CommitmentTxConfirmed; + check_closed_event(&nodes[0], 1, reason, false, &[node_b_id], 1_000_000); + + check_msg_events(&nodes[1]); + check_added_monitors(&nodes[1], 1); + let reason = ClosureReason::CommitmentTxConfirmed; + check_closed_event(&nodes[1], 1, reason, false, &[node_a_id], 1_000_000); + + assert!(nodes[0].node.list_channels().is_empty()); + assert!(nodes[1].node.list_channels().is_empty()); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_accept_inbound_channel_errors_queued() { + // For manually accepted inbound channels, tests that a close error is correctly handled + // and the channel fails for the initiator. + let mut config0 = test_default_channel_config(); + let mut config1 = config0.clone(); + config1.channel_handshake_limits.their_to_self_delay = 1000; + config1.manually_accept_inbound_channels = true; + config0.channel_handshake_config.our_to_self_delay = 2000; + + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config0), Some(config1)]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + nodes[1].node.handle_open_channel(node_a_id, &open_channel_msg); + let events = nodes[1].node.get_and_clear_pending_events(); + match events[0] { + Event::OpenChannelRequest { temporary_channel_id, .. } => { + match nodes[1].node.accept_inbound_channel(&temporary_channel_id, &node_a_id, 23, None) + { + Err(APIError::ChannelUnavailable { err: _ }) => (), + _ => panic!(), + } + }, + _ => panic!("Unexpected event"), + } + assert_eq!( + get_err_msg(&nodes[1], &node_a_id).channel_id, + open_channel_msg.common_fields.temporary_channel_id + ); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_manual_funding_abandon() { + let mut cfg = UserConfig::default(); + cfg.channel_handshake_config.minimum_depth = 1; + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg)]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + assert!(nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).is_ok()); + let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + nodes[1].node.handle_open_channel(node_a_id, &open_channel); + let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + + nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); + let (temp_channel_id, _tx, funding_outpoint) = + create_funding_transaction(&nodes[0], &node_b_id, 100_000, 42); + nodes[0] + .node + .unsafe_manual_funding_transaction_generated(temp_channel_id, node_b_id, funding_outpoint) + .unwrap(); + check_added_monitors(&nodes[0], 0); + + let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); + nodes[1].node.handle_funding_created(node_a_id, &funding_created); + check_added_monitors(&nodes[1], 1); + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + let err = msgs::ErrorMessage { channel_id: funding_signed.channel_id, data: "".to_string() }; + nodes[0].node.handle_error(node_b_id, &err); + + let close_events = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(close_events.len(), 2); + assert!(close_events.iter().any(|ev| matches!(ev, Event::ChannelClosed { .. }))); + assert!(close_events.iter().any(|ev| match ev { + Event::DiscardFunding { channel_id, funding_info: FundingInfo::OutPoint { outpoint } } => { + assert_eq!(*channel_id, err.channel_id); + assert_eq!(*outpoint, funding_outpoint); + true + }, + _ => false, + })); +} + +#[xtest(feature = "_externalize_tests")] +pub fn test_funding_signed_event() { + let mut cfg = UserConfig::default(); + cfg.channel_handshake_config.minimum_depth = 1; + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg)]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + + assert!(nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).is_ok()); + let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + nodes[1].node.handle_open_channel(node_a_id, &open_channel); + let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); + + nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); + let (temp_channel_id, tx, funding_outpoint) = + create_funding_transaction(&nodes[0], &node_b_id, 100_000, 42); + nodes[0] + .node + .unsafe_manual_funding_transaction_generated(temp_channel_id, node_b_id, funding_outpoint) + .unwrap(); + check_added_monitors(&nodes[0], 0); + + let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); + nodes[1].node.handle_funding_created(node_a_id, &funding_created); + check_added_monitors(&nodes[1], 1); + expect_channel_pending_event(&nodes[1], &node_a_id); + + let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); + nodes[0].node.handle_funding_signed(node_b_id, &funding_signed); + check_added_monitors(&nodes[0], 1); + let events = &nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events.len(), 2); + match &events[0] { + crate::events::Event::FundingTxBroadcastSafe { funding_txo, .. } => { + assert_eq!(funding_txo.txid, funding_outpoint.txid); + assert_eq!(funding_txo.vout, funding_outpoint.index.into()); + }, + _ => panic!("Unexpected event"), + }; + match &events[1] { + crate::events::Event::ChannelPending { counterparty_node_id, .. } => { + assert_eq!(node_b_id, *counterparty_node_id); + }, + _ => panic!("Unexpected event"), + }; + + mine_transaction(&nodes[0], &tx); + mine_transaction(&nodes[1], &tx); + + let as_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, node_a_id); + nodes[1].node.handle_channel_ready(node_a_id, &as_channel_ready); + let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, node_b_id); + nodes[0].node.handle_channel_ready(node_b_id, &as_channel_ready); + + expect_channel_ready_event(&nodes[0], &node_b_id); + expect_channel_ready_event(&nodes[1], &node_a_id); + nodes[0].node.get_and_clear_pending_msg_events(); + nodes[1].node.get_and_clear_pending_msg_events(); +} diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index a0258d32664..5e78049664c 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -15,13 +15,12 @@ use crate::chain; use crate::chain::chaininterface::LowerBoundedFeeEstimator; use crate::chain::channelmonitor; use crate::chain::channelmonitor::{ - Balance, ChannelMonitorUpdateStep, ANTI_REORG_DELAY, CLTV_CLAIM_BUFFER, - COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE, LATENCY_GRACE_PERIOD_BLOCKS, + Balance, ANTI_REORG_DELAY, CLTV_CLAIM_BUFFER, COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE, + LATENCY_GRACE_PERIOD_BLOCKS, }; -use crate::chain::transaction::OutPoint; use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; use crate::events::{ - ClosureReason, Event, FundingInfo, HTLCHandlingFailureType, PathFailure, PaymentFailureReason, + ClosureReason, Event, HTLCHandlingFailureType, PathFailure, PaymentFailureReason, PaymentPurpose, }; use crate::ln::chan_utils::{ @@ -29,18 +28,16 @@ use crate::ln::chan_utils::{ OFFERED_HTLC_SCRIPT_WEIGHT, }; use crate::ln::channel::{ - get_holder_selected_channel_reserve_satoshis, Channel, ChannelError, InboundV1Channel, - OutboundV1Channel, COINBASE_MATURITY, DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, - MIN_CHAN_DUST_LIMIT_SATOSHIS, + get_holder_selected_channel_reserve_satoshis, Channel, DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, + MIN_CHAN_DUST_LIMIT_SATOSHIS, UNFUNDED_CHANNEL_AGE_LIMIT_TICKS, }; use crate::ln::channelmanager::{ - self, PaymentId, RAACommitmentOrder, RecipientOnionFields, BREAKDOWN_TIMEOUT, - DISABLE_GOSSIP_TICKS, ENABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA, + PaymentId, RAACommitmentOrder, RecipientOnionFields, BREAKDOWN_TIMEOUT, DISABLE_GOSSIP_TICKS, + ENABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA, }; use crate::ln::msgs; use crate::ln::msgs::{ - AcceptChannel, BaseMessageHandler, ChannelMessageHandler, ErrorAction, MessageSendEvent, - RoutingMessageHandler, + BaseMessageHandler, ChannelMessageHandler, ErrorAction, MessageSendEvent, RoutingMessageHandler, }; use crate::ln::onion_utils::LocalHTLCFailureReason; use crate::ln::types::ChannelId; @@ -53,24 +50,19 @@ use crate::sign::{EntropySource, OutputSpender, SignerProvider}; use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; use crate::types::payment::{PaymentHash, PaymentSecret}; use crate::types::string::UntrustedString; -use crate::util::config::{ - ChannelConfigOverrides, ChannelConfigUpdate, ChannelHandshakeConfigUpdate, MaxDustHTLCExposure, - UserConfig, -}; +use crate::util::config::{ChannelConfigUpdate, MaxDustHTLCExposure, UserConfig}; use crate::util::errors::APIError; use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_channel_signer::TestChannelSigner; -use crate::util::test_utils::{self, TestLogger, WatchtowerPersister}; +use crate::util::test_utils::{self, WatchtowerPersister}; -use bitcoin::constants::ChainHash; use bitcoin::hash_types::BlockHash; use bitcoin::locktime::absolute::LockTime; use bitcoin::network::Network; use bitcoin::opcodes; -use bitcoin::script::{Builder, ScriptBuf}; +use bitcoin::script::Builder; use bitcoin::transaction::Version; -use bitcoin::OutPoint as BitcoinOutPoint; -use bitcoin::{Amount, Sequence, Transaction, TxIn, TxOut, Witness}; +use bitcoin::{Amount, Transaction, TxIn, TxOut}; use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::{PublicKey, SecretKey}; @@ -85,391 +77,6 @@ use lightning_macros::xtest; use crate::ln::functional_test_utils::*; -use super::channel::UNFUNDED_CHANNEL_AGE_LIMIT_TICKS; - -#[xtest(feature = "_externalize_tests")] -fn test_channel_resumption_fail_post_funding() { - // If we fail to exchange funding with a peer prior to it disconnecting we'll resume the - // channel open on reconnect, however if we do exchange funding we do not currently support - // replaying it and here test that the channel closes. - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - nodes[0].node.create_channel(node_b_id, 1_000_000, 0, 42, None, None).unwrap(); - let open_chan = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - nodes[1].node.handle_open_channel(node_a_id, &open_chan); - let accept_chan = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - nodes[0].node.handle_accept_channel(node_b_id, &accept_chan); - - let (temp_chan_id, tx, funding_output) = - create_funding_transaction(&nodes[0], &node_b_id, 1_000_000, 42); - let new_chan_id = ChannelId::v1_from_funding_outpoint(funding_output); - nodes[0].node.funding_transaction_generated(temp_chan_id, node_b_id, tx).unwrap(); - - nodes[0].node.peer_disconnected(node_b_id); - check_closed_events( - &nodes[0], - &[ExpectedCloseEvent::from_id_reason(new_chan_id, true, ClosureReason::DisconnectedPeer)], - ); - - // After ddf75afd16 we'd panic on reconnection if we exchanged funding info, so test that - // explicitly here. - let init_msg = msgs::Init { - features: nodes[1].node.init_features(), - networks: None, - remote_network_address: None, - }; - nodes[0].node.peer_connected(node_b_id, &init_msg, true).unwrap(); - assert_eq!(nodes[0].node.get_and_clear_pending_msg_events(), Vec::new()); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_insane_channel_opens() { - // Stand up a network of 2 nodes - use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS; - let mut cfg = UserConfig::default(); - cfg.channel_handshake_limits.max_funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1; - let 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, Some(cfg.clone())]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - // 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 = - 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 - nodes[0].node.create_channel(node_b_id, channel_value_sat, push_msat, 42, None, None).unwrap(); - - // Extract the channel open message from node0 to node1 - let open_channel_message = - get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - // Test helper that asserts we get the correct error string given a mutator - // that supposedly makes the channel open message insane - let insane_open_helper = - |expected_error_str: &str, message_mutator: fn(msgs::OpenChannel) -> msgs::OpenChannel| { - let open_channel_mutated = message_mutator(open_channel_message.clone()); - nodes[1].node.handle_open_channel(node_a_id, &open_channel_mutated); - let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(msg_events.len(), 1); - let expected_regex = regex::Regex::new(expected_error_str).unwrap(); - if let MessageSendEvent::HandleError { ref action, .. } = msg_events[0] { - match action { - &ErrorAction::SendErrorMessage { .. } => { - nodes[1].logger.assert_log_regex( - "lightning::ln::channelmanager", - expected_regex, - 1, - ); - }, - _ => panic!("unexpected event!"), - } - } else { - assert!(false); - } - }; - - use crate::ln::channelmanager::MAX_LOCAL_BREAKDOWN_TIMEOUT; - - // Test all mutations that would make the channel open message insane - insane_open_helper( - format!( - "Per our config, funding must be at most {}. It was {}", - TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1, - TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2 - ) - .as_str(), - |mut msg| { - msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2; - msg - }, - ); - insane_open_helper( - format!( - "Funding must be smaller than the total bitcoin supply. It was {}", - TOTAL_BITCOIN_SUPPLY_SATOSHIS - ) - .as_str(), - |mut msg| { - msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS; - msg - }, - ); - - insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { - msg.channel_reserve_satoshis = msg.common_fields.funding_satoshis + 1; - msg - }); - - insane_open_helper( - r"push_msat \d+ was larger than channel amount minus reserve \(\d+\)", - |mut msg| { - msg.push_msat = - (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000 + 1; - msg - }, - ); - - insane_open_helper("Peer never wants payout outputs?", |mut msg| { - msg.common_fields.dust_limit_satoshis = msg.common_fields.funding_satoshis + 1; - msg - }); - - insane_open_helper( - r"Minimum htlc value \(\d+\) was larger than full channel value \(\d+\)", - |mut msg| { - msg.common_fields.htlc_minimum_msat = - (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000; - msg - }, - ); - - insane_open_helper( - "They wanted our payments to be delayed by a needlessly long period", - |mut msg| { - msg.common_fields.to_self_delay = MAX_LOCAL_BREAKDOWN_TIMEOUT + 1; - msg - }, - ); - - insane_open_helper("0 max_accepted_htlcs makes for a useless channel", |mut msg| { - msg.common_fields.max_accepted_htlcs = 0; - msg - }); - - insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { - msg.common_fields.max_accepted_htlcs = 484; - msg - }); -} - -#[test] -fn test_insane_zero_fee_channel_open() { - let mut cfg = UserConfig::default(); - cfg.manually_accept_inbound_channels = true; - cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true; - - let chanmon_cfgs = create_chanmon_cfgs(2); - let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = - create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg.clone())]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); - - let open_channel_message = - get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - let insane_open_helper = - |expected_error_str: &str, message_mutator: fn(msgs::OpenChannel) -> msgs::OpenChannel| { - let open_channel_mutated = message_mutator(open_channel_message.clone()); - nodes[1].node.handle_open_channel(node_a_id, &open_channel_mutated); - - let events = nodes[1].node.get_and_clear_pending_events(); - match events[0] { - Event::OpenChannelRequest { temporary_channel_id, .. } => { - match nodes[1].node.accept_inbound_channel( - &temporary_channel_id, - &nodes[0].node.get_our_node_id(), - 23, - None, - ) { - Ok(_) => panic!("Unexpected successful channel accept"), - Err(e) => assert!(format!("{:?}", e).contains(expected_error_str)), - } - }, - _ => panic!("Unexpected event"), - } - - let events = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - assert!(matches!(events[0], MessageSendEvent::HandleError { .. })); - }; - - insane_open_helper( - "max_accepted_htlcs was 115. It must not be larger than 114".into(), - |mut msg| { - msg.common_fields.max_accepted_htlcs = 115; - msg - }, - ); - - insane_open_helper("Zero Fee Channels must never attempt to use a fee".into(), |mut msg| { - msg.common_fields.commitment_feerate_sat_per_1000_weight = 123; - msg - }); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_funding_exceeds_no_wumbo_limit() { - // Test that if a peer does not support wumbo channels, we'll refuse to open a wumbo channel to - // them. - use crate::ln::channel::MAX_FUNDING_SATOSHIS_NO_WUMBO; - let chanmon_cfgs = create_chanmon_cfgs(2); - let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let mut features = channelmanager::provided_init_features(&test_default_channel_config()); - features.clear_wumbo(); - *node_cfgs[1].override_init_features.borrow_mut() = Some(features); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_b_id = nodes[1].node.get_our_node_id(); - - match nodes[0].node.create_channel( - node_b_id, - MAX_FUNDING_SATOSHIS_NO_WUMBO + 1, - 0, - 42, - None, - None, - ) { - Err(APIError::APIMisuseError { err }) => { - let exp_err = format!( - "funding_value must not exceed {}, it was {}", - MAX_FUNDING_SATOSHIS_NO_WUMBO, - MAX_FUNDING_SATOSHIS_NO_WUMBO + 1 - ); - assert_eq!(err, exp_err); - }, - _ => panic!(), - } -} - -fn do_test_sanity_on_in_flight_opens(steps: u8) { - // Previously, we had issues deserializing channels when we hadn't connected the first block - // after creation. To catch that and similar issues, we lean on the Node::drop impl to test - // serialization round-trips and simply do steps towards opening a channel and then drop the - // Node objects. - - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - if steps & 0b1000_0000 != 0 { - let block = create_dummy_block(nodes[0].best_block_hash(), 42, Vec::new()); - connect_block(&nodes[0], &block); - connect_block(&nodes[1], &block); - } - - if steps & 0x0f == 0 { - return; - } - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - if steps & 0x0f == 1 { - return; - } - nodes[1].node.handle_open_channel(node_a_id, &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - - if steps & 0x0f == 2 { - return; - } - nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); - - let (temporary_channel_id, tx, _) = - create_funding_transaction(&nodes[0], &node_b_id, 100000, 42); - - if steps & 0x0f == 3 { - return; - } - nodes[0] - .node - .funding_transaction_generated(temporary_channel_id, node_b_id, tx.clone()) - .unwrap(); - check_added_monitors(&nodes[0], 0); - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); - - let channel_id = ChannelId::v1_from_funding_txid( - funding_created.funding_txid.as_byte_array(), - funding_created.funding_output_index, - ); - - if steps & 0x0f == 4 { - return; - } - nodes[1].node.handle_funding_created(node_a_id, &funding_created); - { - let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); - assert_eq!(added_monitors.len(), 1); - assert_eq!(added_monitors[0].0, channel_id); - added_monitors.clear(); - } - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - - if steps & 0x0f == 5 { - return; - } - nodes[0].node.handle_funding_signed(node_b_id, &funding_signed); - { - let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); - assert_eq!(added_monitors.len(), 1); - assert_eq!(added_monitors[0].0, channel_id); - added_monitors.clear(); - } - - expect_channel_pending_event(&nodes[0], &node_b_id); - let events_4 = nodes[0].node.get_and_clear_pending_events(); - assert_eq!(events_4.len(), 0); - - if steps & 0x0f == 6 { - return; - } - create_chan_between_nodes_with_value_confirm_first(&nodes[0], &nodes[1], &tx, 2); - - if steps & 0x0f == 7 { - return; - } - confirm_transaction_at(&nodes[0], &tx, 2); - connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH); - create_chan_between_nodes_with_value_confirm_second(&nodes[1], &nodes[0]); - expect_channel_ready_event(&nodes[0], &node_b_id); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_sanity_on_in_flight_opens() { - do_test_sanity_on_in_flight_opens(0); - do_test_sanity_on_in_flight_opens(0 | 0b1000_0000); - do_test_sanity_on_in_flight_opens(1); - do_test_sanity_on_in_flight_opens(1 | 0b1000_0000); - do_test_sanity_on_in_flight_opens(2); - do_test_sanity_on_in_flight_opens(2 | 0b1000_0000); - do_test_sanity_on_in_flight_opens(3); - do_test_sanity_on_in_flight_opens(3 | 0b1000_0000); - do_test_sanity_on_in_flight_opens(4); - do_test_sanity_on_in_flight_opens(4 | 0b1000_0000); - do_test_sanity_on_in_flight_opens(5); - do_test_sanity_on_in_flight_opens(5 | 0b1000_0000); - do_test_sanity_on_in_flight_opens(6); - do_test_sanity_on_in_flight_opens(6 | 0b1000_0000); - do_test_sanity_on_in_flight_opens(7); - do_test_sanity_on_in_flight_opens(7 | 0b1000_0000); - do_test_sanity_on_in_flight_opens(8); - do_test_sanity_on_in_flight_opens(8 | 0b1000_0000); -} - #[xtest(feature = "_externalize_tests")] pub fn fake_network_test() { // Simple test which builds a network of ChannelManagers, connects them to each other, and @@ -5448,107 +5055,6 @@ pub fn htlc_claim_single_commitment_only_b() { do_htlc_claim_previous_remote_commitment_only(false, true); } -#[xtest(feature = "_externalize_tests")] -#[should_panic] -pub fn bolt2_open_channel_sending_node_checks_part1() { - //This test needs to be on its own as we are catching a panic - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - // Force duplicate randomness for every get-random call - for node in nodes.iter() { - *node.keys_manager.override_random_bytes.lock().unwrap() = Some([0; 32]); - } - - // BOLT #2 spec: Sending node must ensure temporary_channel_id is unique from any other channel ID with the same peer. - let channel_value_satoshis = 10000; - let push_msat = 10001; - nodes[0] - .node - .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) - .unwrap(); - let node0_to_1_send_open_channel = - get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - nodes[1].node.handle_open_channel(node_a_id, &node0_to_1_send_open_channel); - get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - - // Create a second channel with the same random values. This used to panic due to a colliding - // channel_id, but now panics due to a colliding outbound SCID alias. - assert!(nodes[0] - .node - .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) - .is_err()); -} - -#[xtest(feature = "_externalize_tests")] -pub fn bolt2_open_channel_sending_node_checks_part2() { - let 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); - - let node_b_id = nodes[1].node.get_our_node_id(); - - // BOLT #2 spec: Sending node must set push_msat to equal or less than 1000 * funding_satoshis - let channel_value_satoshis = 10000; - // Test when push_msat is equal to 1000 * funding_satoshis. - let push_msat = 1000 * channel_value_satoshis + 1; - assert!(nodes[0] - .node - .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) - .is_err()); - - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); - - let node0_to_1_send_open_channel = - get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - // BOLT #2 spec: Sending node should set to_self_delay sufficient to ensure the sender can irreversibly spend a commitment transaction output, in case of misbehaviour by the receiver. - assert!(BREAKDOWN_TIMEOUT > 0); - assert!(node0_to_1_send_open_channel.common_fields.to_self_delay == BREAKDOWN_TIMEOUT); - - // BOLT #2 spec: Sending node must ensure the chain_hash value identifies the chain it wishes to open the channel within. - let chain_hash = ChainHash::using_genesis_block(Network::Testnet); - assert_eq!(node0_to_1_send_open_channel.common_fields.chain_hash, chain_hash); -} - -#[xtest(feature = "_externalize_tests")] -pub fn bolt2_open_channel_sane_dust_limit() { - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - let value_sats = 1000000; - let push_msat = 10001; - nodes[0].node.create_channel(node_b_id, value_sats, push_msat, 42, None, None).unwrap(); - let mut node0_to_1_send_open_channel = - get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - node0_to_1_send_open_channel.common_fields.dust_limit_satoshis = 547; - node0_to_1_send_open_channel.channel_reserve_satoshis = 100001; - - nodes[1].node.handle_open_channel(node_a_id, &node0_to_1_send_open_channel); - let events = nodes[1].node.get_and_clear_pending_msg_events(); - let err_msg = match events[0] { - MessageSendEvent::HandleError { - action: ErrorAction::SendErrorMessage { ref msg }, .. - } => msg.clone(), - _ => panic!("Unexpected event"), - }; - assert_eq!( - err_msg.data, - "dust_limit_satoshis (547) is greater than the implementation limit (546)" - ); -} - // Test that if we fail to send an HTLC that is being freed from the holding cell, and the HTLC // originated from our node, its failure is surfaced to the user. We trigger this failure to // free the HTLC by increasing our fee while the HTLC is in the holding cell such that the HTLC @@ -6365,160 +5871,21 @@ pub fn test_sweep_outbound_htlc_failure_update() { } #[xtest(feature = "_externalize_tests")] -pub fn test_user_configurable_csv_delay() { - // We test our channel constructors yield errors when we pass them absurd csv delay - - let mut low_our_to_self_config = UserConfig::default(); - low_our_to_self_config.channel_handshake_config.our_to_self_delay = 6; - let mut high_their_to_self_config = UserConfig::default(); - high_their_to_self_config.channel_handshake_limits.their_to_self_delay = 100; - let user_cfgs = [Some(high_their_to_self_config.clone()), None]; +pub fn test_check_htlc_underpaying() { + // Send payment through A -> B but A is maliciously + // sending a probe payment (i.e less than expected value0 + // to B, B should refuse payment. + let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &user_cfgs); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - let logger = TestLogger::new(); - - // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in OutboundV1Channel::new() - if let Err(error) = OutboundV1Channel::new( - &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), - &nodes[0].keys_manager, - &nodes[0].keys_manager, - node_b_id, - &nodes[1].node.init_features(), - 1000000, - 1000000, - 0, - &low_our_to_self_config, - 0, - 42, - None, - &logger, - ) { - match error { - APIError::APIMisuseError { err } => { - assert!(regex::Regex::new( - r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks" - ) - .unwrap() - .is_match(err.as_str())); - }, - _ => panic!("Unexpected event"), - } - } else { - assert!(false) - } - - // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in InboundV1Channel::new() - nodes[1].node.create_channel(node_a_id, 1000000, 1000000, 42, None, None).unwrap(); - let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); - open_channel.common_fields.to_self_delay = 200; - if let Err(error) = InboundV1Channel::new( - &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), - &nodes[0].keys_manager, - &nodes[0].keys_manager, - node_b_id, - &nodes[0].node.channel_type_features(), - &nodes[1].node.init_features(), - &open_channel, - 0, - &low_our_to_self_config, - 0, - &nodes[0].logger, - /*is_0conf=*/ false, - ) { - match error { - ChannelError::Close((err, _)) => { - let regex = regex::Regex::new( - r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks", - ) - .unwrap(); - assert!(regex.is_match(err.as_str())); - }, - _ => panic!("Unexpected event"), - } - } else { - assert!(false); - } - - // We test msg.to_self_delay <= config.their_to_self_delay is enforced in Chanel::accept_channel() - nodes[0].node.create_channel(node_b_id, 1000000, 1000000, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - nodes[1].node.handle_open_channel(node_a_id, &open_channel); - - let mut accept_channel = - get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - accept_channel.common_fields.to_self_delay = 200; - nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); - let reason_msg; - if let MessageSendEvent::HandleError { ref action, .. } = - nodes[0].node.get_and_clear_pending_msg_events()[0] - { - match action { - &ErrorAction::SendErrorMessage { ref msg } => { - assert!(regex::Regex::new(r"They wanted our payments to be delayed by a needlessly long period\. Upper limit: \d+\. Actual: \d+").unwrap().is_match(msg.data.as_str())); - reason_msg = msg.data.clone(); - }, - _ => { - panic!(); - }, - } - } else { - panic!(); - } - let reason = ClosureReason::ProcessingError { err: reason_msg }; - check_closed_event!(nodes[0], 1, reason, [node_b_id], 1000000); - - // We test msg.to_self_delay <= config.their_to_self_delay is enforced in InboundV1Channel::new() - nodes[1].node.create_channel(node_a_id, 1000000, 1000000, 42, None, None).unwrap(); - let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); - open_channel.common_fields.to_self_delay = 200; - if let Err(error) = InboundV1Channel::new( - &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), - &nodes[0].keys_manager, - &nodes[0].keys_manager, - node_b_id, - &nodes[0].node.channel_type_features(), - &nodes[1].node.init_features(), - &open_channel, - 0, - &high_their_to_self_config, - 0, - &nodes[0].logger, - /*is_0conf=*/ false, - ) { - match error { - ChannelError::Close((err, _)) => { - let regex = regex::Regex::new(r"They wanted our payments to be delayed by a needlessly long period\. Upper limit: \d+\. Actual: \d+").unwrap(); - assert!(regex.is_match(err.as_str())); - }, - _ => panic!("Unexpected event"), - } - } else { - assert!(false); - } -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_check_htlc_underpaying() { - // Send payment through A -> B but A is maliciously - // sending a probe payment (i.e less than expected value0 - // to B, B should refuse payment. - - let 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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - // Create some initial channels - create_announced_chan_between_nodes(&nodes, 0, 1); + // Create some initial channels + create_announced_chan_between_nodes(&nodes, 0, 1); let scorer = test_utils::TestScorer::new(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); @@ -7408,258 +6775,6 @@ pub fn test_channel_update_has_correct_htlc_maximum_msat() { assert_eq!(node_3_chan_update.contents.htlc_maximum_msat, channel_value_90_percent_msat); } -#[xtest(feature = "_externalize_tests")] -pub fn test_manually_accept_inbound_channel_request() { - let mut manually_accept_conf = UserConfig::default(); - manually_accept_conf.manually_accept_inbound_channels = true; - manually_accept_conf.channel_handshake_config.minimum_depth = 1; - - let 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, Some(manually_accept_conf.clone())]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - nodes[0] - .node - .create_channel(node_b_id, 100000, 10001, 42, None, Some(manually_accept_conf)) - .unwrap(); - let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - nodes[1].node.handle_open_channel(node_a_id, &res); - - // Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before - // accepting the inbound channel request. - assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - - let config_overrides = ChannelConfigOverrides { - handshake_overrides: Some(ChannelHandshakeConfigUpdate { - max_inbound_htlc_value_in_flight_percent_of_channel: None, - htlc_minimum_msat: None, - minimum_depth: None, - to_self_delay: None, - max_accepted_htlcs: Some(3), - channel_reserve_proportional_millionths: None, - }), - update_overrides: Some(ChannelConfigUpdate { - forwarding_fee_proportional_millionths: None, - forwarding_fee_base_msat: Some(555), - cltv_expiry_delta: None, - max_dust_htlc_exposure_msat: None, - force_close_avoidance_max_fee_satoshis: None, - accept_underpaying_htlcs: None, - }), - }; - let events = nodes[1].node.get_and_clear_pending_events(); - match events[0] { - Event::OpenChannelRequest { temporary_channel_id, .. } => { - let config = Some(config_overrides); - nodes[1] - .node - .accept_inbound_channel(&temporary_channel_id, &node_a_id, 23, config) - .unwrap(); - }, - _ => panic!("Unexpected event"), - } - - let accept_msg_ev = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(accept_msg_ev.len(), 1); - - let ref accept_channel: AcceptChannel; - match accept_msg_ev[0] { - MessageSendEvent::SendAcceptChannel { ref node_id, ref msg } => { - assert_eq!(*node_id, node_a_id); - - // Assert overriden handshake parameter. - assert_eq!(msg.common_fields.max_accepted_htlcs, 3); - - accept_channel = msg; - }, - _ => panic!("Unexpected event"), - } - - // Continue channel opening process until channel update messages are sent. - nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); - let (temp_channel_id, tx, funding_outpoint) = - create_funding_transaction(&nodes[0], &node_b_id, 100_000, 42); - nodes[0] - .node - .unsafe_manual_funding_transaction_generated(temp_channel_id, node_b_id, funding_outpoint) - .unwrap(); - check_added_monitors(&nodes[0], 0); - - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); - nodes[1].node.handle_funding_created(node_a_id, &funding_created); - check_added_monitors(&nodes[1], 1); - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - nodes[0].node.handle_funding_signed(node_b_id, &funding_signed); - check_added_monitors(&nodes[0], 1); - let events = &nodes[0].node.get_and_clear_pending_events(); - assert_eq!(events.len(), 2); - match &events[0] { - crate::events::Event::FundingTxBroadcastSafe { funding_txo, .. } => { - assert_eq!(funding_txo.txid, funding_outpoint.txid); - assert_eq!(funding_txo.vout, funding_outpoint.index.into()); - }, - _ => panic!("Unexpected event"), - }; - match &events[1] { - crate::events::Event::ChannelPending { counterparty_node_id, .. } => { - assert_eq!(node_b_id, *counterparty_node_id); - }, - _ => panic!("Unexpected event"), - }; - - mine_transaction(&nodes[0], &tx); - mine_transaction(&nodes[1], &tx); - - let as_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, node_a_id); - nodes[1].node.handle_channel_ready(node_a_id, &as_channel_ready); - let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, node_b_id); - nodes[0].node.handle_channel_ready(node_b_id, &as_channel_ready); - - expect_channel_ready_event(&nodes[0], &node_b_id); - expect_channel_ready_event(&nodes[1], &node_a_id); - - // Assert that the overriden base fee surfaces in the channel update. - let channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, node_a_id); - assert_eq!(channel_update.contents.fee_base_msat, 555); - - get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, node_b_id); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_manually_reject_inbound_channel_request() { - let mut manually_accept_conf = UserConfig::default(); - manually_accept_conf.manually_accept_inbound_channels = true; - let 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, Some(manually_accept_conf.clone())]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - nodes[0] - .node - .create_channel(node_b_id, 100000, 10001, 42, None, Some(manually_accept_conf)) - .unwrap(); - let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - nodes[1].node.handle_open_channel(node_a_id, &res); - - // Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before - // rejecting the inbound channel request. - assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - let err = "Channel force-closed".to_string(); - let events = nodes[1].node.get_and_clear_pending_events(); - match events[0] { - Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1] - .node - .force_close_broadcasting_latest_txn(&temporary_channel_id, &node_a_id, err) - .unwrap(); - }, - _ => panic!("Unexpected event"), - } - - let close_msg_ev = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(close_msg_ev.len(), 1); - - match close_msg_ev[0] { - MessageSendEvent::HandleError { ref node_id, .. } => { - assert_eq!(*node_id, node_a_id); - }, - _ => panic!("Unexpected event"), - } - - // There should be no more events to process, as the channel was never opened. - assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_can_not_accept_inbound_channel_twice() { - let mut manually_accept_conf = UserConfig::default(); - manually_accept_conf.manually_accept_inbound_channels = true; - let 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, Some(manually_accept_conf.clone())]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - nodes[0] - .node - .create_channel(node_b_id, 100000, 10001, 42, None, Some(manually_accept_conf)) - .unwrap(); - let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - nodes[1].node.handle_open_channel(node_a_id, &res); - - // Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in `msg_events` before - // accepting the inbound channel request. - assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - - let events = nodes[1].node.get_and_clear_pending_events(); - match events[0] { - Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1] - .node - .accept_inbound_channel(&temporary_channel_id, &node_a_id, 0, None) - .unwrap(); - let api_res = - nodes[1].node.accept_inbound_channel(&temporary_channel_id, &node_a_id, 0, None); - match api_res { - Err(APIError::APIMisuseError { err }) => { - assert_eq!(err, "No such channel awaiting to be accepted."); - }, - Ok(_) => panic!("Channel shouldn't be possible to be accepted twice"), - Err(e) => panic!("Unexpected Error {:?}", e), - } - }, - _ => panic!("Unexpected event"), - } - - // Ensure that the channel wasn't closed after attempting to accept it twice. - let accept_msg_ev = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(accept_msg_ev.len(), 1); - - match accept_msg_ev[0] { - MessageSendEvent::SendAcceptChannel { ref node_id, .. } => { - assert_eq!(*node_id, node_a_id); - }, - _ => panic!("Unexpected event"), - } -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_can_not_accept_unknown_inbound_channel() { - let chanmon_cfg = create_chanmon_cfgs(2); - let node_cfg = create_node_cfgs(2, &chanmon_cfg); - let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[None, None]); - let nodes = create_network(2, &node_cfg, &node_chanmgr); - - let node_b_id = nodes[1].node.get_our_node_id(); - - let unknown_channel_id = ChannelId::new_zero(); - let api_res = nodes[0].node.accept_inbound_channel(&unknown_channel_id, &node_b_id, 0, None); - match api_res { - Err(APIError::APIMisuseError { err }) => { - assert_eq!(err, "No such channel awaiting to be accepted."); - }, - Ok(_) => panic!("It shouldn't be possible to accept an unkown channel"), - Err(e) => panic!("Unexpected Error: {:?}", e), - } -} - #[xtest(feature = "_externalize_tests")] pub fn test_onion_value_mpp_set_calculation() { // Test that we use the onion value `amt_to_forward` when @@ -8649,69 +7764,6 @@ pub fn test_onchain_htlc_settlement_after_close() { do_test_onchain_htlc_settlement_after_close(false, false); } -#[xtest(feature = "_externalize_tests")] -pub fn test_duplicate_temporary_channel_id_from_different_peers() { - // Tests that we can accept two different `OpenChannel` requests with the same - // `temporary_channel_id`, as long as they are from different peers. - let chanmon_cfgs = create_chanmon_cfgs(3); - let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); - let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - let node_c_id = nodes[2].node.get_our_node_id(); - - // Create an first channel channel - nodes[1].node.create_channel(node_a_id, 100000, 10001, 42, None, None).unwrap(); - let mut open_chan_msg_chan_1_0 = - get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); - - // Create an second channel - nodes[2].node.create_channel(node_a_id, 100000, 10001, 43, None, None).unwrap(); - let mut open_chan_msg_chan_2_0 = - get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, node_a_id); - - // Modify the `OpenChannel` from `nodes[2]` to `nodes[0]` to ensure that it uses the same - // `temporary_channel_id` as the `OpenChannel` from nodes[1] to nodes[0]. - open_chan_msg_chan_2_0.common_fields.temporary_channel_id = - open_chan_msg_chan_1_0.common_fields.temporary_channel_id; - - // Assert that `nodes[0]` can accept both `OpenChannel` requests, even though they use the same - // `temporary_channel_id` as they are from different peers. - nodes[0].node.handle_open_channel(node_b_id, &open_chan_msg_chan_1_0); - { - let events = nodes[0].node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match &events[0] { - MessageSendEvent::SendAcceptChannel { node_id, msg } => { - assert_eq!(node_id, &node_b_id); - assert_eq!( - msg.common_fields.temporary_channel_id, - open_chan_msg_chan_1_0.common_fields.temporary_channel_id - ); - }, - _ => panic!("Unexpected event"), - } - } - - nodes[0].node.handle_open_channel(node_c_id, &open_chan_msg_chan_2_0); - { - let events = nodes[0].node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match &events[0] { - MessageSendEvent::SendAcceptChannel { node_id, msg } => { - assert_eq!(node_id, &node_c_id); - assert_eq!( - msg.common_fields.temporary_channel_id, - open_chan_msg_chan_1_0.common_fields.temporary_channel_id - ); - }, - _ => panic!("Unexpected event"), - } - } -} - #[xtest(feature = "_externalize_tests")] pub fn test_peer_funding_sidechannel() { // Test that if a peer somehow learns which txid we'll use for our channel funding before we @@ -8818,266 +7870,27 @@ pub fn test_duplicate_conflicting_funding_from_second_peer() { } #[xtest(feature = "_externalize_tests")] -pub fn test_duplicate_funding_err_in_funding() { - // Test that if we have a live channel with one peer, then another peer comes along and tries - // to create a second channel with the same txid we'll fail and not overwrite the - // outpoint_to_peer map in `ChannelManager`. +pub fn test_error_chans_closed() { + // Test that we properly handle error messages, closing appropriate channels. // - // This was previously broken. + // Prior to #787 we'd allow a peer to make us force-close a channel we had with a different + // peer. The "real" fix for that is to index channels with peers_ids, however in the mean time + // we can test various edge cases around it to ensure we don't regress. let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let node_b_id = nodes[1].node.get_our_node_id(); - let node_c_id = nodes[2].node.get_our_node_id(); - - let (_, _, _, real_channel_id, funding_tx) = create_chan_between_nodes(&nodes[0], &nodes[1]); - let real_chan_funding_txo = - chain::transaction::OutPoint { txid: funding_tx.compute_txid(), index: 0 }; - assert_eq!(ChannelId::v1_from_funding_outpoint(real_chan_funding_txo), real_channel_id); - - nodes[2].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); - let mut open_chan_msg = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, node_b_id); - let node_c_temp_chan_id = open_chan_msg.common_fields.temporary_channel_id; - open_chan_msg.common_fields.temporary_channel_id = real_channel_id; - nodes[1].node.handle_open_channel(node_c_id, &open_chan_msg); - let mut accept_chan_msg = - get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_c_id); - accept_chan_msg.common_fields.temporary_channel_id = node_c_temp_chan_id; - nodes[2].node.handle_accept_channel(node_b_id, &accept_chan_msg); - // Now that we have a second channel with the same funding txo, send a bogus funding message - // and let nodes[1] remove the inbound channel. - let (_, fund_tx, _) = create_funding_transaction(&nodes[2], &node_b_id, 100_000, 42); + // Create some initial channels + let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); + let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); + let chan_3 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); - nodes[2].node.funding_transaction_generated(node_c_temp_chan_id, node_b_id, fund_tx).unwrap(); - - let mut funding_created_msg = - get_event_msg!(nodes[2], MessageSendEvent::SendFundingCreated, node_b_id); - funding_created_msg.temporary_channel_id = real_channel_id; - // Make the signature invalid by changing the funding output - funding_created_msg.funding_output_index += 10; - nodes[1].node.handle_funding_created(node_c_id, &funding_created_msg); - get_err_msg(&nodes[1], &node_c_id); - let err = "Invalid funding_created signature from peer".to_owned(); - let reason = ClosureReason::ProcessingError { err }; - let expected_closing = ExpectedCloseEvent::from_id_reason(real_channel_id, false, reason); - check_closed_events(&nodes[1], &[expected_closing]); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_duplicate_chan_id() { - // Test that if a given peer tries to open a channel with the same channel_id as one that is - // already open we reject it and keep the old channel. - // - // Previously, full_stack_target managed to figure out that if you tried to open two channels - // with the same funding output (ie post-funding channel_id), we'd create a monitor update for - // the existing channel when we detect the duplicate new channel, screwing up our monitor - // updating logic for the existing channel. - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - // Create an initial channel - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); - let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - nodes[1].node.handle_open_channel(node_a_id, &open_chan_msg); - nodes[0].node.handle_accept_channel( - node_b_id, - &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id), - ); - - // Try to create a second channel with the same temporary_channel_id as the first and check - // that it is rejected. - nodes[1].node.handle_open_channel(node_a_id, &open_chan_msg); - { - let events = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match events[0] { - MessageSendEvent::HandleError { - action: ErrorAction::SendErrorMessage { ref msg }, - node_id, - } => { - // Technically, at this point, nodes[1] would be justified in thinking both the - // first (valid) and second (invalid) channels are closed, given they both have - // the same non-temporary channel_id. However, currently we do not, so we just - // move forward with it. - assert_eq!(msg.channel_id, open_chan_msg.common_fields.temporary_channel_id); - assert_eq!(node_id, node_a_id); - }, - _ => panic!("Unexpected event"), - } - } - - // Move the first channel through the funding flow... - let (temp_channel_id, tx, _) = create_funding_transaction(&nodes[0], &node_b_id, 100000, 42); - - nodes[0].node.funding_transaction_generated(temp_channel_id, node_b_id, tx.clone()).unwrap(); - check_added_monitors(&nodes[0], 0); - - let mut funding_created_msg = - get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); - let channel_id = ChannelId::v1_from_funding_txid( - funding_created_msg.funding_txid.as_byte_array(), - funding_created_msg.funding_output_index, - ); - - nodes[1].node.handle_funding_created(node_a_id, &funding_created_msg); - { - let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); - assert_eq!(added_monitors.len(), 1); - assert_eq!(added_monitors[0].0, channel_id); - added_monitors.clear(); - } - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed_msg = - get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - - let funding_outpoint = crate::chain::transaction::OutPoint { - txid: funding_created_msg.funding_txid, - index: funding_created_msg.funding_output_index, - }; - let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint); - - // Now we have the first channel past funding_created (ie it has a txid-based channel_id, not a - // temporary one). - - // First try to open a second channel with a temporary channel id equal to the txid-based one. - // Technically this is allowed by the spec, but we don't support it and there's little reason - // to. Still, it shouldn't cause any other issues. - open_chan_msg.common_fields.temporary_channel_id = channel_id; - nodes[1].node.handle_open_channel(node_a_id, &open_chan_msg); - { - let events = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match events[0] { - MessageSendEvent::HandleError { - action: ErrorAction::SendErrorMessage { ref msg }, - node_id, - } => { - // Technically, at this point, nodes[1] would be justified in thinking both - // channels are closed, but currently we do not, so we just move forward with it. - assert_eq!(msg.channel_id, open_chan_msg.common_fields.temporary_channel_id); - assert_eq!(node_id, node_a_id); - }, - _ => panic!("Unexpected event"), - } - } - - // Now try to create a second channel which has a duplicate funding output. - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); - let open_chan_2_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - nodes[1].node.handle_open_channel(node_a_id, &open_chan_2_msg); - nodes[0].node.handle_accept_channel( - node_b_id, - &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id), - ); - create_funding_transaction(&nodes[0], &node_b_id, 100000, 42); // Get and check the FundingGenerationReady event - - let funding_created = { - let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let mut a_peer_state = per_peer_state.get(&node_b_id).unwrap().lock().unwrap(); - // Once we call `get_funding_created` the channel has a duplicate channel_id as - // another channel in the ChannelManager - an invalid state. Thus, we'd panic later when we - // try to create another channel. Instead, we drop the channel entirely here (leaving the - // channelmanager in a possibly nonsense state instead). - let chan_id = open_chan_2_msg.common_fields.temporary_channel_id; - let mut channel = a_peer_state.channel_by_id.remove(&chan_id).unwrap(); - - if let Some(mut chan) = channel.as_unfunded_outbound_v1_mut() { - let logger = test_utils::TestLogger::new(); - chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger) - .map_err(|_| ()) - .unwrap() - } else { - panic!("Unexpected Channel phase") - } - .unwrap() - }; - check_added_monitors(&nodes[0], 0); - nodes[1].node.handle_funding_created(node_a_id, &funding_created); - // At this point we'll look up if the channel_id is present and immediately fail the channel - // without trying to persist the `ChannelMonitor`. - check_added_monitors(&nodes[1], 0); - - let reason = ClosureReason::ProcessingError { - err: "Already had channel with the new channel_id".to_owned(), - }; - let close_event = - ExpectedCloseEvent::from_id_reason(funding_created.temporary_channel_id, false, reason); - check_closed_events(&nodes[1], &[close_event]); - - // ...still, nodes[1] will reject the duplicate channel. - { - let events = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match events[0] { - MessageSendEvent::HandleError { - action: ErrorAction::SendErrorMessage { ref msg }, - node_id, - } => { - // Technically, at this point, nodes[1] would be justified in thinking both - // channels are closed, but currently we do not, so we just move forward with it. - assert_eq!(msg.channel_id, funding_created.temporary_channel_id); - assert_eq!(node_id, node_a_id); - }, - _ => panic!("Unexpected event"), - } - } - - // finally, finish creating the original channel and send a payment over it to make sure - // everything is functional. - nodes[0].node.handle_funding_signed(node_b_id, &funding_signed_msg); - { - let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); - assert_eq!(added_monitors.len(), 1); - assert_eq!(added_monitors[0].0, channel_id); - added_monitors.clear(); - } - expect_channel_pending_event(&nodes[0], &node_b_id); - - let events_4 = nodes[0].node.get_and_clear_pending_events(); - assert_eq!(events_4.len(), 0); - assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); - assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx); - - let (channel_ready, _) = - create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); - let (announcement, as_update, bs_update) = - create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); - update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update); - - send_payment(&nodes[0], &[&nodes[1]], 8000000); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_error_chans_closed() { - // Test that we properly handle error messages, closing appropriate channels. - // - // Prior to #787 we'd allow a peer to make us force-close a channel we had with a different - // peer. The "real" fix for that is to index channels with peers_ids, however in the mean time - // we can test various edge cases around it to ensure we don't regress. - let chanmon_cfgs = create_chanmon_cfgs(3); - let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); - let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - - let node_b_id = nodes[1].node.get_our_node_id(); - - // Create some initial channels - let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); - let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); - let chan_3 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); - - assert_eq!(nodes[0].node.list_usable_channels().len(), 3); - assert_eq!(nodes[1].node.list_usable_channels().len(), 2); - assert_eq!(nodes[2].node.list_usable_channels().len(), 1); + assert_eq!(nodes[0].node.list_usable_channels().len(), 3); + assert_eq!(nodes[1].node.list_usable_channels().len(), 2); + assert_eq!(nodes[2].node.list_usable_channels().len(), 1); // Closing a channel from a different peer has no effect nodes[0].node.handle_error( @@ -9145,192 +7958,6 @@ pub fn test_error_chans_closed() { assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2); } -#[xtest(feature = "_externalize_tests")] -pub fn test_invalid_funding_tx() { - // Test that we properly handle invalid funding transactions sent to us from a peer. - // - // Previously, all other major lightning implementations had failed to properly sanitize - // funding transactions from their counterparties, leading to a multi-implementation critical - // security vulnerability (though we always sanitized properly, we've previously had - // un-released crashes in the sanitization process). - // - // Further, if the funding transaction is consensus-valid, confirms, and is later spent, we'd - // previously have crashed in `ChannelMonitor` even though we closed the channel as bogus and - // gave up on it. We test this here by generating such a transaction. - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - nodes[0].node.create_channel(node_b_id, 100_000, 10_000, 42, None, None).unwrap(); - nodes[1].node.handle_open_channel( - node_a_id, - &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id), - ); - nodes[0].node.handle_accept_channel( - node_b_id, - &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id), - ); - - let (temporary_channel_id, mut tx, _) = - create_funding_transaction(&nodes[0], &node_b_id, 100_000, 42); - - // Create a witness program which can be spent by a 4-empty-stack-elements witness and which is - // 136 bytes long. This matches our "accepted HTLC preimage spend" matching, previously causing - // a panic as we'd try to extract a 32 byte preimage from a witness element without checking - // its length. - let mut wit_program: Vec = - channelmonitor::deliberately_bogus_accepted_htlc_witness_program(); - let wit_program_script: ScriptBuf = wit_program.into(); - for output in tx.output.iter_mut() { - // Make the confirmed funding transaction have a bogus script_pubkey - output.script_pubkey = ScriptBuf::new_p2wsh(&wit_program_script.wscript_hash()); - } - - nodes[0] - .node - .funding_transaction_generated_unchecked(temporary_channel_id, node_b_id, tx.clone(), 0) - .unwrap(); - nodes[1].node.handle_funding_created( - node_a_id, - &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id), - ); - check_added_monitors(&nodes[1], 1); - expect_channel_pending_event(&nodes[1], &node_a_id); - - nodes[0].node.handle_funding_signed( - node_b_id, - &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id), - ); - check_added_monitors(&nodes[0], 1); - expect_channel_pending_event(&nodes[0], &node_b_id); - - let events_1 = nodes[0].node.get_and_clear_pending_events(); - assert_eq!(events_1.len(), 0); - - assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); - assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx); - nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); - - let expected_err = "funding tx had wrong script/value or output index"; - confirm_transaction_at(&nodes[1], &tx, 1); - - let reason = ClosureReason::ProcessingError { err: expected_err.to_string() }; - check_closed_event!(nodes[1], 1, reason, [node_a_id], 100000); - - check_added_monitors(&nodes[1], 1); - let events_2 = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(events_2.len(), 1); - if let MessageSendEvent::HandleError { node_id, action } = &events_2[0] { - assert_eq!(*node_id, node_a_id); - if let msgs::ErrorAction::SendErrorMessage { msg } = action { - assert_eq!( - msg.data, - "Channel closed because of an exception: ".to_owned() + expected_err - ); - } else { - panic!(); - } - } else { - panic!(); - } - assert_eq!(nodes[1].node.list_channels().len(), 0); - - // Now confirm a spend of the (bogus) funding transaction. As long as the witness is 5 elements - // long the ChannelMonitor will try to read 32 bytes from the second-to-last element, panicing - // as its not 32 bytes long. - let mut spend_tx = Transaction { - version: Version::TWO, - lock_time: LockTime::ZERO, - input: tx - .output - .iter() - .enumerate() - .map(|(idx, _)| TxIn { - previous_output: BitcoinOutPoint { txid: tx.compute_txid(), vout: idx as u32 }, - script_sig: ScriptBuf::new(), - sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, - witness: Witness::from_slice( - &channelmonitor::deliberately_bogus_accepted_htlc_witness(), - ), - }) - .collect(), - output: vec![TxOut { value: Amount::from_sat(1000), script_pubkey: ScriptBuf::new() }], - }; - check_spends!(spend_tx, tx); - mine_transaction(&nodes[1], &spend_tx); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_coinbase_funding_tx() { - // Miners are able to fund channels directly from coinbase transactions, however - // by consensus rules, outputs of a coinbase transaction are encumbered by a 100 - // block maturity timelock. To ensure that a (non-0conf) channel like this is enforceable - // on-chain, the minimum depth is updated to 100 blocks for coinbase funding transactions. - // - // Note that 0conf channels with coinbase funding transactions are unaffected and are - // immediately operational after opening. - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - nodes[1].node.handle_open_channel(node_a_id, &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - - nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); - - // Create the coinbase funding transaction. - let (channel_id, tx, _) = - create_coinbase_funding_transaction(&nodes[0], &node_b_id, 100000, 42); - - nodes[0].node.funding_transaction_generated(channel_id, node_b_id, tx.clone()).unwrap(); - check_added_monitors(&nodes[0], 0); - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); - - nodes[1].node.handle_funding_created(node_a_id, &funding_created); - check_added_monitors(&nodes[1], 1); - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - - nodes[0].node.handle_funding_signed(node_b_id, &funding_signed); - check_added_monitors(&nodes[0], 1); - - expect_channel_pending_event(&nodes[0], &node_b_id); - assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); - - // Starting at height 0, we "confirm" the coinbase at height 1. - confirm_transaction_at(&nodes[0], &tx, 1); - // We connect 98 more blocks to have 99 confirmations for the coinbase transaction. - connect_blocks(&nodes[0], COINBASE_MATURITY - 2); - // Check that we have no pending message events (we have not queued a `channel_ready` yet). - assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - // Now connect one more block which results in 100 confirmations of the coinbase transaction. - connect_blocks(&nodes[0], 1); - // There should now be a `channel_ready` which can be handled. - let _ = &nodes[1].node.handle_channel_ready( - node_a_id, - &get_event_msg!(&nodes[0], MessageSendEvent::SendChannelReady, node_b_id), - ); - - confirm_transaction_at(&nodes[1], &tx, 1); - connect_blocks(&nodes[1], COINBASE_MATURITY - 2); - assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - connect_blocks(&nodes[1], 1); - expect_channel_ready_event(&nodes[1], &node_a_id); - create_chan_between_nodes_with_value_confirm_second(&nodes[0], &nodes[1]); -} - fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_timelock: bool) { // In the first version of the chain::Confirm interface, after a refactor was made to not // broadcast CSV-locked transactions until their CSV lock is up, we wouldn't reliably broadcast @@ -10602,9 +9229,8 @@ fn test_nondust_htlc_fees_dust_exposure_delta() { ); } -#[xtest(feature = "_externalize_tests")] -pub fn test_non_final_funding_tx() { - let chanmon_cfgs = create_chanmon_cfgs(2); +fn do_payment_with_custom_min_final_cltv_expiry(valid_delta: bool, use_user_hash: bool) { + 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); @@ -10612,121 +9238,12 @@ pub fn test_non_final_funding_tx() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - let temp_channel_id = - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); - let open_channel_message = - get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - nodes[1].node.handle_open_channel(node_a_id, &open_channel_message); - let accept_channel_message = - get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - nodes[0].node.handle_accept_channel(node_b_id, &accept_channel_message); + let min_cltv_expiry_delta = 120; + let final_cltv_expiry_delta = + if valid_delta { min_cltv_expiry_delta + 2 } else { min_cltv_expiry_delta - 2 }; + let recv_value = 100_000; - let best_height = nodes[0].node.best_block.read().unwrap().height; - - let chan_id = *nodes[0].network_chan_count.borrow(); - let events = nodes[0].node.get_and_clear_pending_events(); - let input = TxIn { - previous_output: BitcoinOutPoint::null(), - script_sig: bitcoin::ScriptBuf::new(), - sequence: Sequence(1), - witness: Witness::from_slice(&[&[1]]), - }; - assert_eq!(events.len(), 1); - let mut tx = match events[0] { - Event::FundingGenerationReady { ref channel_value_satoshis, ref output_script, .. } => { - // Timelock the transaction _beyond_ the best client height + 1. - Transaction { - version: Version(chan_id as i32), - lock_time: LockTime::from_height(best_height + 2).unwrap(), - input: vec![input], - output: vec![TxOut { - value: Amount::from_sat(*channel_value_satoshis), - script_pubkey: output_script.clone(), - }], - } - }, - _ => panic!("Unexpected event"), - }; - // Transaction should fail as it's evaluated as non-final for propagation. - match nodes[0].node.funding_transaction_generated(temp_channel_id, node_b_id, tx.clone()) { - Err(APIError::APIMisuseError { err }) => { - assert_eq!(format!("Funding transaction absolute timelock is non-final"), err); - }, - _ => panic!(), - } - let err = "Error in transaction funding: Misuse error: Funding transaction absolute timelock is non-final"; - let reason = ClosureReason::ProcessingError { err: err.to_owned() }; - let event = ExpectedCloseEvent::from_id_reason(temp_channel_id, false, reason); - check_closed_events(&nodes[0], &[event]); - assert_eq!(get_err_msg(&nodes[0], &node_b_id).data, err); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_non_final_funding_tx_within_headroom() { - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - let temp_channel_id = - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); - let open_channel_message = - get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - nodes[1].node.handle_open_channel(node_a_id, &open_channel_message); - let accept_channel_message = - get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - nodes[0].node.handle_accept_channel(node_b_id, &accept_channel_message); - - let best_height = nodes[0].node.best_block.read().unwrap().height; - - let chan_id = *nodes[0].network_chan_count.borrow(); - let events = nodes[0].node.get_and_clear_pending_events(); - let input = TxIn { - previous_output: BitcoinOutPoint::null(), - script_sig: bitcoin::ScriptBuf::new(), - sequence: Sequence(1), - witness: Witness::from_slice(&[[1]]), - }; - assert_eq!(events.len(), 1); - let mut tx = match events[0] { - Event::FundingGenerationReady { ref channel_value_satoshis, ref output_script, .. } => { - // Timelock the transaction within a +1 headroom from the best block. - Transaction { - version: Version(chan_id as i32), - lock_time: LockTime::from_consensus(best_height + 1), - input: vec![input], - output: vec![TxOut { - value: Amount::from_sat(*channel_value_satoshis), - script_pubkey: output_script.clone(), - }], - } - }, - _ => panic!("Unexpected event"), - }; - - // Transaction should be accepted if it's in a +1 headroom from best block. - nodes[0].node.funding_transaction_generated(temp_channel_id, node_b_id, tx.clone()).unwrap(); - get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); -} - -fn do_payment_with_custom_min_final_cltv_expiry(valid_delta: bool, use_user_hash: bool) { - 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - let min_cltv_expiry_delta = 120; - let final_cltv_expiry_delta = - if valid_delta { min_cltv_expiry_delta + 2 } else { min_cltv_expiry_delta - 2 }; - let recv_value = 100_000; - - create_chan_between_nodes(&nodes[0], &nodes[1]); + create_chan_between_nodes(&nodes[0], &nodes[1]); let payment_parameters = PaymentParameters::from_node_id(node_b_id, final_cltv_expiry_delta as u32); @@ -11053,100 +9570,6 @@ pub fn test_remove_expired_inbound_unfunded_channels() { check_closed_event(&nodes[1], 1, reason, false, &[node_a_id], 100000); } -#[xtest(feature = "_externalize_tests")] -pub fn test_channel_close_when_not_timely_accepted() { - // Create network of two nodes - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - // Simulate peer-disconnects mid-handshake - // The channel is initiated from the node 0 side, - // but the nodes disconnect before node 1 could send accept channel - let create_chan_id = - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); - - nodes[0].node.peer_disconnected(node_b_id); - nodes[1].node.peer_disconnected(node_a_id); - - // Make sure that we have not removed the OutboundV1Channel from node[0] immediately. - assert_eq!(nodes[0].node.list_channels().len(), 1); - - // Since channel was inbound from node[1] perspective, it should have been dropped immediately. - assert_eq!(nodes[1].node.list_channels().len(), 0); - - // In the meantime, some time passes. - for _ in 0..UNFUNDED_CHANNEL_AGE_LIMIT_TICKS { - nodes[0].node.timer_tick_occurred(); - } - - // Since we disconnected from peer and did not connect back within time, - // we should have forced-closed the channel by now. - let reason = ClosureReason::FundingTimedOut; - check_closed_event!(nodes[0], 1, reason, [node_b_id], 100000); - assert_eq!(nodes[0].node.list_channels().len(), 0); - - { - // Since accept channel message was never received - // The channel should be forced close by now from node 0 side - // and the peer removed from per_peer_state - let node_0_per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - assert_eq!(node_0_per_peer_state.len(), 0); - } -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_rebroadcast_open_channel_when_reconnect_mid_handshake() { - // Create network of two nodes - let 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); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - // Simulate peer-disconnects mid-handshake - // The channel is initiated from the node 0 side, - // but the nodes disconnect before node 1 could send accept channel - let create_chan_id = - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); - - nodes[0].node.peer_disconnected(node_b_id); - nodes[1].node.peer_disconnected(node_a_id); - - // Make sure that we have not removed the OutboundV1Channel from node[0] immediately. - assert_eq!(nodes[0].node.list_channels().len(), 1); - - // Since channel was inbound from node[1] perspective, it should have been immediately dropped. - assert_eq!(nodes[1].node.list_channels().len(), 0); - - // The peers now reconnect - let init_msg = msgs::Init { - features: nodes[0].node.init_features(), - networks: None, - remote_network_address: None, - }; - nodes[0].node.peer_connected(node_b_id, &init_msg, true).unwrap(); - nodes[1].node.peer_connected(node_a_id, &init_msg, false).unwrap(); - - // Make sure the SendOpenChannel message is added to node_0 pending message events - let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); - assert_eq!(msg_events.len(), 1); - match &msg_events[0] { - MessageSendEvent::SendOpenChannel { msg, .. } => assert_eq!(msg, &open_channel_msg), - _ => panic!("Unexpected message."), - } -} - fn do_test_multi_post_event_actions(do_reload: bool) { // Tests handling multiple post-Event actions at once. // There is specific code in ChannelManager to handle channels where multiple post-Event @@ -11253,492 +9676,3 @@ pub fn test_multi_post_event_actions() { do_test_multi_post_event_actions(true); do_test_multi_post_event_actions(false); } - -#[xtest(feature = "_externalize_tests")] -pub fn test_batch_channel_open() { - let chanmon_cfgs = create_chanmon_cfgs(3); - let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); - let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - let node_c_id = nodes[2].node.get_our_node_id(); - - // Initiate channel opening and create the batch channel funding transaction. - let (tx, funding_created_msgs) = create_batch_channel_funding( - &nodes[0], - &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], - ); - - // Go through the funding_created and funding_signed flow with node 1. - nodes[1].node.handle_funding_created(node_a_id, &funding_created_msgs[0]); - check_added_monitors(&nodes[1], 1); - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed_msg = - get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - nodes[0].node.handle_funding_signed(node_b_id, &funding_signed_msg); - check_added_monitors(&nodes[0], 1); - - // The transaction should not have been broadcast before all channels are ready. - assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 0); - - // Go through the funding_created and funding_signed flow with node 2. - nodes[2].node.handle_funding_created(node_a_id, &funding_created_msgs[1]); - check_added_monitors(&nodes[2], 1); - expect_channel_pending_event(&nodes[2], &node_a_id); - - let funding_signed_msg = - get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, node_a_id); - chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[0].node.handle_funding_signed(node_c_id, &funding_signed_msg); - check_added_monitors(&nodes[0], 1); - - // The transaction should not have been broadcast before persisting all monitors has been - // completed. - assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0); - assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); - - // Complete the persistence of the monitor. - nodes[0].chain_monitor.complete_sole_pending_chan_update(&ChannelId::v1_from_funding_outpoint( - OutPoint { txid: tx.compute_txid(), index: 1 }, - )); - let events = nodes[0].node.get_and_clear_pending_events(); - - // The transaction should only have been broadcast now. - let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast(); - assert_eq!(broadcasted_txs.len(), 1); - assert_eq!(broadcasted_txs[0], tx); - - assert_eq!(events.len(), 2); - assert!(events.iter().any(|e| matches!( - *e, - crate::events::Event::ChannelPending { - ref counterparty_node_id, - .. - } if counterparty_node_id == &node_b_id, - ))); - assert!(events.iter().any(|e| matches!( - *e, - crate::events::Event::ChannelPending { - ref counterparty_node_id, - .. - } if counterparty_node_id == &node_c_id, - ))); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_close_in_funding_batch() { - // This test ensures that if one of the channels - // in the batch closes, the complete batch will close. - let chanmon_cfgs = create_chanmon_cfgs(3); - let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); - let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - // Initiate channel opening and create the batch channel funding transaction. - let (tx, funding_created_msgs) = create_batch_channel_funding( - &nodes[0], - &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], - ); - - // Go through the funding_created and funding_signed flow with node 1. - nodes[1].node.handle_funding_created(node_a_id, &funding_created_msgs[0]); - check_added_monitors(&nodes[1], 1); - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed_msg = - get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - nodes[0].node.handle_funding_signed(node_b_id, &funding_signed_msg); - check_added_monitors(&nodes[0], 1); - - // The transaction should not have been broadcast before all channels are ready. - assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0); - - // Force-close the channel for which we've completed the initial monitor. - let funding_txo_1 = OutPoint { txid: tx.compute_txid(), index: 0 }; - let funding_txo_2 = OutPoint { txid: tx.compute_txid(), index: 1 }; - let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1); - let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2); - let err = "Channel force-closed".to_string(); - nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &node_b_id, err).unwrap(); - - // The monitor should become closed. - check_added_monitors(&nodes[0], 1); - { - let mut monitor_updates = nodes[0].chain_monitor.monitor_updates.lock().unwrap(); - let monitor_updates_1 = monitor_updates.get(&channel_id_1).unwrap(); - assert_eq!(monitor_updates_1.len(), 1); - assert_eq!(monitor_updates_1[0].updates.len(), 1); - assert!(matches!( - monitor_updates_1[0].updates[0], - ChannelMonitorUpdateStep::ChannelForceClosed { .. } - )); - } - - let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); - match msg_events[0] { - MessageSendEvent::HandleError { .. } => (), - _ => panic!("Unexpected message."), - } - - // Because the funding was never broadcasted, we should never bother to broadcast the - // commitment transactions either. - let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast(); - assert_eq!(broadcasted_txs.len(), 0); - - // All channels in the batch should close immediately. - check_closed_events( - &nodes[0], - &[ - ExpectedCloseEvent { - channel_id: Some(channel_id_1), - discard_funding: true, - channel_funding_txo: Some(funding_txo_1), - user_channel_id: Some(42), - ..Default::default() - }, - ExpectedCloseEvent { - channel_id: Some(channel_id_2), - discard_funding: true, - channel_funding_txo: Some(funding_txo_2), - user_channel_id: Some(43), - ..Default::default() - }, - ], - ); - - // Ensure the channels don't exist anymore. - assert!(nodes[0].node.list_channels().is_empty()); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_batch_funding_close_after_funding_signed() { - let chanmon_cfgs = create_chanmon_cfgs(3); - let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); - let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - let node_c_id = nodes[2].node.get_our_node_id(); - - // Initiate channel opening and create the batch channel funding transaction. - let (tx, funding_created_msgs) = create_batch_channel_funding( - &nodes[0], - &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], - ); - - // Go through the funding_created and funding_signed flow with node 1. - nodes[1].node.handle_funding_created(node_a_id, &funding_created_msgs[0]); - check_added_monitors(&nodes[1], 1); - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed_msg = - get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - nodes[0].node.handle_funding_signed(node_b_id, &funding_signed_msg); - check_added_monitors(&nodes[0], 1); - - // Go through the funding_created and funding_signed flow with node 2. - nodes[2].node.handle_funding_created(node_a_id, &funding_created_msgs[1]); - check_added_monitors(&nodes[2], 1); - expect_channel_pending_event(&nodes[2], &node_a_id); - - let funding_signed_msg = - get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, node_a_id); - chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[0].node.handle_funding_signed(node_c_id, &funding_signed_msg); - check_added_monitors(&nodes[0], 1); - - // The transaction should not have been broadcast before all channels are ready. - assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0); - - // Force-close the channel for which we've completed the initial monitor. - let funding_txo_1 = OutPoint { txid: tx.compute_txid(), index: 0 }; - let funding_txo_2 = OutPoint { txid: tx.compute_txid(), index: 1 }; - let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1); - let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2); - let err = "Channel force-closed".to_string(); - nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &node_b_id, err).unwrap(); - check_added_monitors(&nodes[0], 2); - { - let mut monitor_updates = nodes[0].chain_monitor.monitor_updates.lock().unwrap(); - let monitor_updates_1 = monitor_updates.get(&channel_id_1).unwrap(); - assert_eq!(monitor_updates_1.len(), 1); - assert_eq!(monitor_updates_1[0].updates.len(), 1); - assert!(matches!( - monitor_updates_1[0].updates[0], - ChannelMonitorUpdateStep::ChannelForceClosed { .. } - )); - let monitor_updates_2 = monitor_updates.get(&channel_id_2).unwrap(); - assert_eq!(monitor_updates_2.len(), 1); - assert_eq!(monitor_updates_2[0].updates.len(), 1); - assert!(matches!( - monitor_updates_2[0].updates[0], - ChannelMonitorUpdateStep::ChannelForceClosed { .. } - )); - } - let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); - match msg_events[0] { - MessageSendEvent::HandleError { .. } => (), - _ => panic!("Unexpected message."), - } - - // Because the funding was never broadcasted, we should never bother to broadcast the - // commitment transactions either. - let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast(); - assert_eq!(broadcasted_txs.len(), 0); - - // All channels in the batch should close immediately. - check_closed_events( - &nodes[0], - &[ - ExpectedCloseEvent { - channel_id: Some(channel_id_1), - discard_funding: true, - channel_funding_txo: Some(funding_txo_1), - user_channel_id: Some(42), - ..Default::default() - }, - ExpectedCloseEvent { - channel_id: Some(channel_id_2), - discard_funding: true, - channel_funding_txo: Some(funding_txo_2), - user_channel_id: Some(43), - ..Default::default() - }, - ], - ); - - // Ensure the channels don't exist anymore. - assert!(nodes[0].node.list_channels().is_empty()); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_funding_and_commitment_tx_confirm_same_block() { - // Tests that a node will forget the channel (when it only requires 1 confirmation) if the - // funding and commitment transaction confirm in the same block. - let chanmon_cfgs = create_chanmon_cfgs(2); - let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let mut min_depth_1_block_cfg = test_default_channel_config(); - min_depth_1_block_cfg.channel_handshake_config.minimum_depth = 1; - let node_chanmgrs = create_node_chanmgrs( - 2, - &node_cfgs, - &[Some(min_depth_1_block_cfg.clone()), Some(min_depth_1_block_cfg)], - ); - let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - let funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 0); - let chan_id = ChannelId::v1_from_funding_outpoint(chain::transaction::OutPoint { - txid: funding_tx.compute_txid(), - index: 0, - }); - - assert_eq!(nodes[0].node.list_channels().len(), 1); - assert_eq!(nodes[1].node.list_channels().len(), 1); - - let commitment_tx = { - let mon = get_monitor!(nodes[0], chan_id); - let mut txn = mon.unsafe_get_latest_holder_commitment_txn(&nodes[0].logger); - assert_eq!(txn.len(), 1); - txn.pop().unwrap() - }; - - mine_transactions(&nodes[0], &[&funding_tx, &commitment_tx]); - mine_transactions(&nodes[1], &[&funding_tx, &commitment_tx]); - - let check_msg_events = |node: &Node| { - let mut msg_events = node.node.get_and_clear_pending_msg_events(); - assert_eq!(msg_events.len(), 3, "{msg_events:?}"); - if let MessageSendEvent::SendChannelReady { .. } = msg_events.remove(0) { - } else { - panic!(); - } - if let MessageSendEvent::HandleError { - action: msgs::ErrorAction::SendErrorMessage { .. }, - node_id: _, - } = msg_events.remove(0) - { - } else { - panic!(); - } - if let MessageSendEvent::BroadcastChannelUpdate { ref msg } = msg_events.remove(0) { - assert_eq!(msg.contents.channel_flags & 2, 2); - } else { - panic!(); - } - }; - check_msg_events(&nodes[0]); - check_added_monitors(&nodes[0], 1); - let reason = ClosureReason::CommitmentTxConfirmed; - check_closed_event(&nodes[0], 1, reason, false, &[node_b_id], 1_000_000); - - check_msg_events(&nodes[1]); - check_added_monitors(&nodes[1], 1); - let reason = ClosureReason::CommitmentTxConfirmed; - check_closed_event(&nodes[1], 1, reason, false, &[node_a_id], 1_000_000); - - assert!(nodes[0].node.list_channels().is_empty()); - assert!(nodes[1].node.list_channels().is_empty()); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_accept_inbound_channel_errors_queued() { - // For manually accepted inbound channels, tests that a close error is correctly handled - // and the channel fails for the initiator. - let mut config0 = test_default_channel_config(); - let mut config1 = config0.clone(); - config1.channel_handshake_limits.their_to_self_delay = 1000; - config1.manually_accept_inbound_channels = true; - config0.channel_handshake_config.our_to_self_delay = 2000; - - let chanmon_cfgs = create_chanmon_cfgs(2); - let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config0), Some(config1)]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - nodes[1].node.handle_open_channel(node_a_id, &open_channel_msg); - let events = nodes[1].node.get_and_clear_pending_events(); - match events[0] { - Event::OpenChannelRequest { temporary_channel_id, .. } => { - match nodes[1].node.accept_inbound_channel(&temporary_channel_id, &node_a_id, 23, None) - { - Err(APIError::ChannelUnavailable { err: _ }) => (), - _ => panic!(), - } - }, - _ => panic!("Unexpected event"), - } - assert_eq!( - get_err_msg(&nodes[1], &node_a_id).channel_id, - open_channel_msg.common_fields.temporary_channel_id - ); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_manual_funding_abandon() { - let mut cfg = UserConfig::default(); - cfg.channel_handshake_config.minimum_depth = 1; - let chanmon_cfgs = create_chanmon_cfgs(2); - let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg)]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - assert!(nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).is_ok()); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - nodes[1].node.handle_open_channel(node_a_id, &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - - nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); - let (temp_channel_id, _tx, funding_outpoint) = - create_funding_transaction(&nodes[0], &node_b_id, 100_000, 42); - nodes[0] - .node - .unsafe_manual_funding_transaction_generated(temp_channel_id, node_b_id, funding_outpoint) - .unwrap(); - check_added_monitors(&nodes[0], 0); - - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); - nodes[1].node.handle_funding_created(node_a_id, &funding_created); - check_added_monitors(&nodes[1], 1); - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - let err = msgs::ErrorMessage { channel_id: funding_signed.channel_id, data: "".to_string() }; - nodes[0].node.handle_error(node_b_id, &err); - - let close_events = nodes[0].node.get_and_clear_pending_events(); - assert_eq!(close_events.len(), 2); - assert!(close_events.iter().any(|ev| matches!(ev, Event::ChannelClosed { .. }))); - assert!(close_events.iter().any(|ev| match ev { - Event::DiscardFunding { channel_id, funding_info: FundingInfo::OutPoint { outpoint } } => { - assert_eq!(*channel_id, err.channel_id); - assert_eq!(*outpoint, funding_outpoint); - true - }, - _ => false, - })); -} - -#[xtest(feature = "_externalize_tests")] -pub fn test_funding_signed_event() { - let mut cfg = UserConfig::default(); - cfg.channel_handshake_config.minimum_depth = 1; - let chanmon_cfgs = create_chanmon_cfgs(2); - let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg)]); - let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - - let node_a_id = nodes[0].node.get_our_node_id(); - let node_b_id = nodes[1].node.get_our_node_id(); - - assert!(nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).is_ok()); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); - - nodes[1].node.handle_open_channel(node_a_id, &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); - - nodes[0].node.handle_accept_channel(node_b_id, &accept_channel); - let (temp_channel_id, tx, funding_outpoint) = - create_funding_transaction(&nodes[0], &node_b_id, 100_000, 42); - nodes[0] - .node - .unsafe_manual_funding_transaction_generated(temp_channel_id, node_b_id, funding_outpoint) - .unwrap(); - check_added_monitors(&nodes[0], 0); - - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id); - nodes[1].node.handle_funding_created(node_a_id, &funding_created); - check_added_monitors(&nodes[1], 1); - expect_channel_pending_event(&nodes[1], &node_a_id); - - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id); - nodes[0].node.handle_funding_signed(node_b_id, &funding_signed); - check_added_monitors(&nodes[0], 1); - let events = &nodes[0].node.get_and_clear_pending_events(); - assert_eq!(events.len(), 2); - match &events[0] { - crate::events::Event::FundingTxBroadcastSafe { funding_txo, .. } => { - assert_eq!(funding_txo.txid, funding_outpoint.txid); - assert_eq!(funding_txo.vout, funding_outpoint.index.into()); - }, - _ => panic!("Unexpected event"), - }; - match &events[1] { - crate::events::Event::ChannelPending { counterparty_node_id, .. } => { - assert_eq!(node_b_id, *counterparty_node_id); - }, - _ => panic!("Unexpected event"), - }; - - mine_transaction(&nodes[0], &tx); - mine_transaction(&nodes[1], &tx); - - let as_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, node_a_id); - nodes[1].node.handle_channel_ready(node_a_id, &as_channel_ready); - let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, node_b_id); - nodes[0].node.handle_channel_ready(node_b_id, &as_channel_ready); - - expect_channel_ready_event(&nodes[0], &node_b_id); - expect_channel_ready_event(&nodes[1], &node_a_id); - nodes[0].node.get_and_clear_pending_msg_events(); - nodes[1].node.get_and_clear_pending_msg_events(); -} From e2988543a06a2370a71bc531eec327eb520116bd Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 16 Aug 2025 12:50:23 +0000 Subject: [PATCH 3/4] Fix panic when calling `batch_funding_transaction_generated` early If a user calls `batch_funding_transaction_generated` before a channel is ready to fund its possible to hit an `unwrap` when the transaction-scanning logic attempts to fetch the channel's expected output `scriptPubKey`. While users shouldn't be doing this, we should also avoid the panic, so here check the channel state first. Found by the `full_stack_target` fuzzer. --- lightning/src/ln/channel.rs | 16 ++++++ lightning/src/ln/channel_open_tests.rs | 35 +++++++++++++ lightning/src/ln/channelmanager.rs | 70 ++++++++++++++------------ 3 files changed, 89 insertions(+), 32 deletions(-) diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index c72559c366b..bfd63289bde 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -1565,6 +1565,22 @@ where ) } + /// Returns true if this channel is waiting on a (batch) funding transaction to be provided. + /// + /// If this method returns true, [`Self::into_unfunded_outbound_v1`] will also succeed. + pub fn ready_to_fund(&self) -> bool { + if !self.funding().is_outbound() { + return false; + } + match self.context().channel_state { + ChannelState::NegotiatingFunding(flags) => { + debug_assert!(matches!(self.phase, ChannelPhase::UnfundedOutboundV1(_))); + flags.is_our_init_sent() && flags.is_their_init_sent() + }, + _ => false, + } + } + pub fn into_unfunded_outbound_v1(self) -> Result, Self> { if let ChannelPhase::UnfundedOutboundV1(channel) = self.phase { Ok(channel) diff --git a/lightning/src/ln/channel_open_tests.rs b/lightning/src/ln/channel_open_tests.rs index 89bb50e25bd..72d9ccafaf6 100644 --- a/lightning/src/ln/channel_open_tests.rs +++ b/lightning/src/ln/channel_open_tests.rs @@ -2509,3 +2509,38 @@ pub fn test_funding_signed_event() { nodes[0].node.get_and_clear_pending_msg_events(); nodes[1].node.get_and_clear_pending_msg_events(); } + +#[xtest(feature = "_externalize_tests")] +fn test_fund_pending_channel() { + // Previously, we would panic if a user called `batch_funding_transaction_generated` for a + // channel which wasn't ready to receive funding. While this isn't a major bug - users + // shouldn't do that - we shouldn't panic and should instead return an error. + let 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); + + let node_b_id = nodes[1].node.get_our_node_id(); + + nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let open_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); + + let tx = Transaction { + version: Version(2), + lock_time: LockTime::ZERO, + input: vec![], + output: vec![], + }; + let pending_chan = [(&open_msg.common_fields.temporary_channel_id, &node_b_id)]; + let res = nodes[0].node.batch_funding_transaction_generated(&pending_chan, tx); + if let Err(APIError::APIMisuseError { err }) = res { + assert_eq!(err, "Channel f7fee84016d554015f5166c0a0df6479942ef55fd70713883b0493493a38e13a with counterparty 0355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c23 is not an unfunded, outbound channel ready to fund"); + } else { + panic!("Unexpected result {res:?}"); + } + get_err_msg(&nodes[0], &node_b_id); + let reason = ClosureReason::ProcessingError { + err: "Error in transaction funding: Misuse error: Channel f7fee84016d554015f5166c0a0df6479942ef55fd70713883b0493493a38e13a with counterparty 0355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c23 is not an unfunded, outbound channel ready to fund".to_owned(), + }; + check_closed_event!(nodes[0], 1, reason, [node_b_id], 100_000); +} diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index cc2110a9785..27d6f3964f4 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -5608,42 +5608,48 @@ where Err($api_err) } } } - let funding_txo; - let (mut chan, msg_opt) = match peer_state.channel_by_id.remove(&temporary_channel_id) - .map(Channel::into_unfunded_outbound_v1) - { - Some(Ok(mut chan)) => { - match find_funding_output(&chan) { - Ok(found_funding_txo) => funding_txo = found_funding_txo, - Err(err) => { - let chan_err = ChannelError::close(err.to_owned()); - let api_err = APIError::APIMisuseError { err: err.to_owned() }; - return abandon_chan!(chan_err, api_err, chan); - }, + let mut chan = match peer_state.channel_by_id.entry(temporary_channel_id) { + hash_map::Entry::Occupied(chan) => { + if !chan.get().ready_to_fund() { + return Err(APIError::APIMisuseError { + err: format!("Channel {temporary_channel_id} with counterparty {counterparty_node_id} is not an unfunded, outbound channel ready to fund"), + }); } - - let logger = WithChannelContext::from(&self.logger, &chan.context, None); - let funding_res = chan.get_funding_created(funding_transaction, funding_txo, is_batch_funding, &&logger); - match funding_res { - Ok(funding_msg) => (chan, funding_msg), - Err((mut chan, chan_err)) => { - let api_err = APIError::ChannelUnavailable { err: "Signer refused to sign the initial commitment transaction".to_owned() }; - return abandon_chan!(chan_err, api_err, chan); - } + match chan.remove().into_unfunded_outbound_v1() { + Ok(chan) => chan, + Err(chan) => { + debug_assert!(false, "ready_to_fund guarantees into_unfunded_outbound_v1 will succeed"); + peer_state.channel_by_id.insert(temporary_channel_id, chan); + return Err(APIError::APIMisuseError { + err: "Invalid state, please report this bug".to_owned(), + }); + }, } }, - Some(Err(chan)) => { - peer_state.channel_by_id.insert(temporary_channel_id, chan); - return Err(APIError::APIMisuseError { - err: format!( - "Channel with id {} for the passed counterparty node_id {} is not an unfunded, outbound V1 channel", - temporary_channel_id, counterparty_node_id), - }) + hash_map::Entry::Vacant(_) => { + return Err(APIError::ChannelUnavailable { + err: format!("Channel {temporary_channel_id} with counterparty {counterparty_node_id} not found"), + }); }, - None => return Err(APIError::ChannelUnavailable {err: format!( - "Channel with id {} not found for the passed counterparty node_id {}", - temporary_channel_id, counterparty_node_id), - }), + }; + + let funding_txo = match find_funding_output(&chan) { + Ok(found_funding_txo) => found_funding_txo, + Err(err) => { + let chan_err = ChannelError::close(err.to_owned()); + let api_err = APIError::APIMisuseError { err: err.to_owned() }; + return abandon_chan!(chan_err, api_err, chan); + }, + }; + + let logger = WithChannelContext::from(&self.logger, &chan.context, None); + let funding_res = chan.get_funding_created(funding_transaction, funding_txo, is_batch_funding, &&logger); + let (mut chan, msg_opt) = match funding_res { + Ok(funding_msg) => (chan, funding_msg), + Err((mut chan, chan_err)) => { + let api_err = APIError::ChannelUnavailable { err: "Signer refused to sign the initial commitment transaction".to_owned() }; + return abandon_chan!(chan_err, api_err, chan); + } }; match peer_state.channel_by_id.entry(chan.context.channel_id()) { From c1fefcfe8ec459cb2e08cf5461ca8905aeede115 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 16 Aug 2025 13:34:07 +0000 Subject: [PATCH 4/4] Allow funding errors in `full_stack_target` fuzzer When a channel gets replaced before we can fund it, its possible now (due to RNG output repetition) to hit the "trying to fund channel before its ready to be funded" error in the `full_stack_target` fuzzer. Thus, we now simply ignore errors when funding. --- fuzz/src/full_stack.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 3a5a549dbbc..88e68e5e01d 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -857,21 +857,15 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { } if tx.version.0 <= 0xff && !channels.is_empty() { let chans = channels.iter().map(|(a, b)| (a, b)).collect::>(); - if let Err(e) = - channelmanager.batch_funding_transaction_generated(&chans, tx.clone()) - { - // It's possible the channel has been closed in the mean time, but any other - // failure may be a bug. - if let APIError::ChannelUnavailable { .. } = e { - } else { - panic!(); + let res = + channelmanager.batch_funding_transaction_generated(&chans, tx.clone()); + if res.is_ok() { + let funding_txid = tx.compute_txid(); + for idx in 0..tx.output.len() { + let outpoint = OutPoint { txid: funding_txid, index: idx as u16 }; + pending_funding_signatures.insert(outpoint, tx.clone()); } } - let funding_txid = tx.compute_txid(); - for idx in 0..tx.output.len() { - let outpoint = OutPoint { txid: funding_txid, index: idx as u16 }; - pending_funding_signatures.insert(outpoint, tx.clone()); - } } }, 11 => {