From 13e4fd586ed0c8439dcada150c4fffa33fa67db9 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 10 Nov 2021 04:40:33 +0000 Subject: [PATCH] Test fixed channel reserve checks on channel open --- lightning/src/ln/functional_tests.rs | 35 ++++++++++++++++++++++++++++ lightning/src/ln/script.rs | 4 ++-- lightning/src/util/errors.rs | 2 +- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index c593d7af8..520a86f4c 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -1560,6 +1560,41 @@ fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() { assert_eq!(err, "Cannot send value that would put counterparty balance under holder-announced channel reserve value")); } +#[test] +fn test_chan_init_feerate_unaffordability() { + // Test that we will reject channel opens which do not leave enough to pay for any HTLCs due to + // channel reserve and feerate requirements. + let mut chanmon_cfgs = create_chanmon_cfgs(2); + let feerate_per_kw = *chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap(); + 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); + + // Set the push_msat amount such that nodes[0] will not be able to afford to add even a single + // HTLC. + let mut push_amt = 100_000_000; + push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64); + assert_eq!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, push_amt + 1, 42, None).unwrap_err(), + APIError::APIMisuseError { err: "Funding amount (356) can't even pay fee for initial commitment transaction fee of 357.".to_string() }); + + // During open, we don't have a "counterparty channel reserve" to check against, so that + // requirement only comes into play on the open_channel handling side. + push_amt -= Channel::::get_holder_selected_channel_reserve_satoshis(100_000) * 1000; + nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, push_amt, 42, None).unwrap(); + let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + open_channel_msg.push_msat += 1; + nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel_msg); + + let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), 1); + match msg_events[0] { + MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => { + assert_eq!(msg.data, "Insufficient funding amount for initial reserve"); + }, + _ => panic!("Unexpected event"), + } +} + #[test] fn test_chan_reserve_dust_inbound_htlcs_inbound_chan() { // Test that if we receive many dust HTLCs over an inbound channel, they don't count when diff --git a/lightning/src/ln/script.rs b/lightning/src/ln/script.rs index 00ad48bb1..0c060e452 100644 --- a/lightning/src/ln/script.rs +++ b/lightning/src/ln/script.rs @@ -17,7 +17,7 @@ use io; /// A script pubkey for shutting down a channel as defined by [BOLT #2]. /// /// [BOLT #2]: https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub struct ShutdownScript(ShutdownScriptImpl); /// An error occurring when converting from [`Script`] to [`ShutdownScript`]. @@ -29,7 +29,7 @@ pub struct InvalidShutdownScript { pub script: Script } -#[derive(Clone)] +#[derive(Clone, PartialEq)] enum ShutdownScriptImpl { /// [`PublicKey`] used to form a P2WPKH script pubkey. Used to support backward-compatible /// serialization. diff --git a/lightning/src/util/errors.rs b/lightning/src/util/errors.rs index 94ad96566..6495d9de4 100644 --- a/lightning/src/util/errors.rs +++ b/lightning/src/util/errors.rs @@ -16,7 +16,7 @@ use core::fmt; /// Indicates an error on the client's part (usually some variant of attempting to use too-low or /// too-high values) -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum APIError { /// Indicates the API was wholly misused (see err for more). Cases where these can be returned /// are documented, but generally indicates some precondition of a function was violated. -- 2.39.5