diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index 76e5f25c0e5..836de5a45ec 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -21,6 +21,7 @@ pub use bump_transaction::BumpTransactionEvent; use crate::sign::SpendableOutputDescriptor; use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields}; use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; +use crate::chain::transaction; use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs; use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret}; @@ -886,6 +887,8 @@ pub enum Event { /// /// This field will be `None` for objects serialized prior to LDK 0.0.117. channel_capacity_sats: Option, + /// The original channel funding TXO; this helps checking for the existence and confirmation status of the closing tx + channel_funding_txo: Option, }, /// Used to indicate to the user that they can abandon the funding transaction and recycle the /// inputs for another purpose. @@ -1091,7 +1094,7 @@ impl Writeable for Event { }); }, &Event::ChannelClosed { ref channel_id, ref user_channel_id, ref reason, - ref counterparty_node_id, ref channel_capacity_sats + ref counterparty_node_id, ref channel_capacity_sats, ref channel_funding_txo } => { 9u8.write(writer)?; // `user_channel_id` used to be a single u64 value. In order to remain backwards @@ -1106,6 +1109,7 @@ impl Writeable for Event { (3, user_channel_id_high, required), (5, counterparty_node_id, option), (7, channel_capacity_sats, option), + (9, channel_funding_txo, option), }); }, &Event::DiscardFunding { ref channel_id, ref transaction } => { @@ -1405,6 +1409,7 @@ impl MaybeReadable for Event { let mut user_channel_id_high_opt: Option = None; let mut counterparty_node_id = None; let mut channel_capacity_sats = None; + let mut channel_funding_txo = None; read_tlv_fields!(reader, { (0, channel_id, required), (1, user_channel_id_low_opt, option), @@ -1412,6 +1417,7 @@ impl MaybeReadable for Event { (3, user_channel_id_high_opt, option), (5, counterparty_node_id, option), (7, channel_capacity_sats, option), + (9, channel_funding_txo, option), }); // `user_channel_id` used to be a single u64 value. In order to remain @@ -1421,7 +1427,7 @@ impl MaybeReadable for Event { ((user_channel_id_high_opt.unwrap_or(0) as u128) << 64); Ok(Some(Event::ChannelClosed { channel_id, user_channel_id, reason: _init_tlv_based_struct_field!(reason, upgradable_required), - counterparty_node_id, channel_capacity_sats })) + counterparty_node_id, channel_capacity_sats, channel_funding_txo })) }; f() }, diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index b2b28cdf365..cd9858f63ef 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -546,8 +546,10 @@ impl Into for FailureCode { struct MsgHandleErrInternal { err: msgs::LightningError, chan_id: Option<(ChannelId, u128)>, // If Some a channel of ours has been closed - shutdown_finish: Option<(ShutdownResult, Option)>, + shutdown_finish: Option<(ShutdownResult, + Option)>, channel_capacity: Option, + channel_funding_txo: Option, } impl MsgHandleErrInternal { #[inline] @@ -565,14 +567,15 @@ impl MsgHandleErrInternal { chan_id: None, shutdown_finish: None, channel_capacity: None, + channel_funding_txo: None, } } #[inline] fn from_no_close(err: msgs::LightningError) -> Self { - Self { err, chan_id: None, shutdown_finish: None, channel_capacity: None } + Self { err, chan_id: None, shutdown_finish: None, channel_capacity: None, channel_funding_txo: None } } #[inline] - fn from_finish_shutdown(err: String, channel_id: ChannelId, user_channel_id: u128, shutdown_res: ShutdownResult, channel_update: Option, channel_capacity: u64) -> Self { + fn from_finish_shutdown(err: String, channel_id: ChannelId, user_channel_id: u128, shutdown_res: ShutdownResult, channel_update: Option, channel_capacity: u64, channel_funding_txo: Option) -> Self { let err_msg = msgs::ErrorMessage { channel_id, data: err.clone() }; let action = if shutdown_res.monitor_update.is_some() { // We have a closing `ChannelMonitorUpdate`, which means the channel was funded and we @@ -586,7 +589,8 @@ impl MsgHandleErrInternal { err: LightningError { err, action }, chan_id: Some((channel_id, user_channel_id)), shutdown_finish: Some((shutdown_res, channel_update)), - channel_capacity: Some(channel_capacity) + channel_capacity: Some(channel_capacity), + channel_funding_txo, } } #[inline] @@ -620,6 +624,7 @@ impl MsgHandleErrInternal { chan_id: None, shutdown_finish: None, channel_capacity: None, + channel_funding_txo: None, } } @@ -1956,7 +1961,7 @@ macro_rules! handle_error { match $internal { Ok(msg) => Ok(msg), - Err(MsgHandleErrInternal { err, chan_id, shutdown_finish, channel_capacity }) => { + Err(MsgHandleErrInternal { err, chan_id, shutdown_finish, channel_capacity, channel_funding_txo }) => { let mut msg_events = Vec::with_capacity(2); if let Some((shutdown_res, update_option)) = shutdown_finish { @@ -1972,6 +1977,7 @@ macro_rules! handle_error { reason: ClosureReason::ProcessingError { err: err.err.clone() }, counterparty_node_id: Some($counterparty_node_id), channel_capacity_sats: channel_capacity, + channel_funding_txo, }, None)); } } @@ -2042,9 +2048,10 @@ macro_rules! convert_chan_phase_err { let shutdown_res = $channel.context.force_shutdown(true); let user_id = $channel.context.get_user_id(); let channel_capacity_satoshis = $channel.context.get_value_satoshis(); + let channel_funding_txo = $channel.context.get_funding_txo(); (true, MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, user_id, - shutdown_res, $channel_update, channel_capacity_satoshis)) + shutdown_res, $channel_update, channel_capacity_satoshis, channel_funding_txo)) }, } }; @@ -2718,6 +2725,7 @@ where reason: closure_reason, counterparty_node_id: Some(context.get_counterparty_node_id()), channel_capacity_sats: Some(context.get_value_satoshis()), + channel_funding_txo: context.get_funding_txo(), }, None)); } @@ -3761,7 +3769,8 @@ where let user_id = chan.context.get_user_id(); let shutdown_res = chan.context.force_shutdown(false); let channel_capacity = chan.context.get_value_satoshis(); - (chan, MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, user_id, shutdown_res, None, channel_capacity)) + let channel_funding_txo = chan.context.get_funding_txo(); + (chan, MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, user_id, shutdown_res, None, channel_capacity, channel_funding_txo)) } else { unreachable!(); }); match funding_res { Ok(funding_msg) => (chan, funding_msg), @@ -10308,6 +10317,7 @@ where reason: ClosureReason::OutdatedChannelManager, counterparty_node_id: Some(channel.context.get_counterparty_node_id()), channel_capacity_sats: Some(channel.context.get_value_satoshis()), + channel_funding_txo: channel.context.get_funding_txo(), }, None)); for (channel_htlc_source, payment_hash) in channel.inflight_htlc_sources() { let mut found_htlc = false; @@ -10361,6 +10371,7 @@ where reason: ClosureReason::DisconnectedPeer, counterparty_node_id: Some(channel.context.get_counterparty_node_id()), channel_capacity_sats: Some(channel.context.get_value_satoshis()), + channel_funding_txo: channel.context.get_funding_txo(), }, None)); } else { log_error!(logger, "Missing ChannelMonitor for channel {} needed by ChannelManager.", &channel.context.channel_id());