diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 515a3dc5f1d..284facfb2c5 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -635,6 +635,9 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent, #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum ChannelMonitorUpdateStep { + EventGenerated { + event: Event, + }, LatestHolderCommitmentTXInfo { commitment_tx: HolderCommitmentTransaction, /// Note that LDK after 0.0.115 supports this only containing dust HTLCs (implying the @@ -724,6 +727,7 @@ impl ChannelMonitorUpdateStep { ChannelMonitorUpdateStep::RenegotiatedFunding { .. } => "RenegotiatedFunding", ChannelMonitorUpdateStep::RenegotiatedFundingLocked { .. } => "RenegotiatedFundingLocked", ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => "ReleasePaymentComplete", + ChannelMonitorUpdateStep::EventGenerated { .. } => "EventGenerated", } } } @@ -778,6 +782,9 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep, (12, RenegotiatedFundingLocked) => { (1, funding_txid, required), }, + (13, EventGenerated) => { + (0, event, upgradable_required), + } ); /// Indicates whether the balance is derived from a cooperative close, a force-close @@ -1283,6 +1290,7 @@ pub(crate) struct ChannelMonitorImpl { pending_monitor_events: Vec, pub(super) pending_events: Vec, + pub(super) pending_mgr_events: Vec, pub(super) is_processing_pending_events: bool, // Used to track on-chain events (i.e., transactions part of channels confirmed on chain) on @@ -1961,6 +1969,7 @@ impl ChannelMonitor { payment_preimages: new_hash_map(), pending_monitor_events: Vec::new(), + pending_mgr_events: Vec::new(), pending_events: Vec::new(), is_processing_pending_events: false, @@ -4244,6 +4253,7 @@ impl ChannelMonitorImpl { // provide a preimage at this point. ChannelMonitorUpdateStep::PaymentPreimage { .. } => debug_assert!(self.lockdown_from_offchain), + ChannelMonitorUpdateStep::EventGenerated { .. } => {}, _ => { log_error!(logger, "Attempted to apply post-force-close ChannelMonitorUpdate of type {}", updates.updates[0].variant_name()); panic!("Attempted to apply post-force-close ChannelMonitorUpdate that wasn't providing a payment preimage"); @@ -4370,6 +4380,10 @@ impl ChannelMonitorImpl { log_trace!(logger, "HTLC {htlc:?} permanently and fully resolved"); self.htlcs_resolved_to_user.insert(*htlc); }, + ChannelMonitorUpdateStep::EventGenerated { event } => { + log_trace!(logger, "Updating ChannelMonitor with channel manager event: {:?}", event); + self.pending_mgr_events.push(event.clone()); + }, } } @@ -4402,6 +4416,7 @@ impl ChannelMonitorImpl { ChannelMonitorUpdateStep::PaymentPreimage { .. } => {}, ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {}, ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => {}, + ChannelMonitorUpdateStep::EventGenerated { .. } => {}, } } @@ -6644,6 +6659,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let mut alternative_funding_confirmed = None; let mut is_manual_broadcast = RequiredWrapper(None); let mut funding_seen_onchain = RequiredWrapper(None); + let mut pending_mgr_events = Some(Vec::new()); read_tlv_fields!(reader, { (1, funding_spend_confirmed, option), (3, htlcs_resolved_on_chain, optional_vec), @@ -6666,6 +6682,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP (34, alternative_funding_confirmed, option), (35, is_manual_broadcast, (default_value, false)), (37, funding_seen_onchain, (default_value, true)), + (38, pending_mgr_events, optional_vec), }); // Note that `payment_preimages_with_info` was added (and is always written) in LDK 0.1, so // we can use it to determine if this monitor was last written by LDK 0.1 or later. @@ -6812,6 +6829,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP payment_preimages, pending_monitor_events: pending_monitor_events.unwrap(), + pending_mgr_events: pending_mgr_events.unwrap(), pending_events, is_processing_pending_events: false, diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index bfaf1e68d6a..8a9ddf41a1c 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -4686,8 +4686,7 @@ where } { - let mut pending_events = self.pending_events.lock().unwrap(); - pending_events.push_back(( + let closed_event = ( events::Event::ChannelClosed { channel_id: shutdown_res.channel_id, user_channel_id: shutdown_res.user_channel_id, @@ -4698,7 +4697,68 @@ where last_local_balance_msat: Some(shutdown_res.last_local_balance_msat), }, None, - )); + ); + + let mut per_peer_state = self.per_peer_state.write().unwrap(); + let mut peer_state_lock = per_peer_state + .get_mut(&shutdown_res.counterparty_node_id) + .expect("We must always have a peer entry for a peer with which we have channels") + .lock() + .unwrap(); + let peer_state = &mut *peer_state_lock; + let channel = peer_state.channel_by_id.get_mut(&shutdown_res.channel_id); + + let monitor_update_step = + ChannelMonitorUpdateStep::EventGenerated { event: closed_event.0.clone() }; + if let Some(channel) = channel { + let funded_chan = channel + .as_funded_mut() + .expect("We should only be finishing the closure of a funded channel here"); + + let update_id = funded_chan.get_latest_unblocked_monitor_update_id(); + let monitor_update = ChannelMonitorUpdate { + update_id, + updates: vec![monitor_update_step], + channel_id: Some(shutdown_res.channel_id), + }; + handle_new_monitor_update!( + self, + funded_chan.funding.get_funding_txo().unwrap(), + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + funded_chan + ); + } else { + let update_id = if let Some(latest_update_id) = + peer_state.closed_channel_monitor_update_ids.get_mut(&shutdown_res.channel_id) + { + *latest_update_id = latest_update_id.saturating_add(1); + *latest_update_id + } else { + panic!("We need the latest ChannelMonitorUpdate ID to build a new update"); + }; + let monitor_update = ChannelMonitorUpdate { + update_id, + updates: vec![monitor_update_step], + channel_id: Some(shutdown_res.channel_id), + }; + handle_post_close_monitor_update!( + self, + shutdown_res.channel_funding_txo + .expect("We must have had a funding txo if we are applying a post-close monitor update"), + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + shutdown_res.counterparty_node_id, + shutdown_res.channel_id + ); + } + + let mut pending_events = self.pending_events.lock().unwrap(); + pending_events.push_back(closed_event); if let Some(splice_funding_failed) = shutdown_res.splice_funding_failed.take() { pending_events.push_back((