diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 515a3dc5f1d..0e0faf12b79 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 @@ -1755,6 +1763,7 @@ pub(crate) fn write_chanmon_internal( (34, channel_monitor.alternative_funding_confirmed, option), (35, channel_monitor.is_manual_broadcast, required), (37, channel_monitor.funding_seen_onchain, required), + (38, channel_monitor.pending_mgr_events, optional_vec), }); Ok(()) @@ -1961,6 +1970,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 +4254,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 +4381,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 +4417,7 @@ impl ChannelMonitorImpl { ChannelMonitorUpdateStep::PaymentPreimage { .. } => {}, ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {}, ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => {}, + ChannelMonitorUpdateStep::EventGenerated { .. } => {}, } } @@ -6644,6 +6660,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 +6683,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 +6830,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..6c5bf6bfcbd 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,67 @@ 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 { + 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); + let monitor_update = ChannelMonitorUpdate { + update_id: *latest_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 + ); + } else { + log_trace!(logger, "No channel or monitor to persist closed channel event"); + }; + } + + 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(( diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 50514e0a894..45208bc51c0 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -663,6 +663,13 @@ impl<'a> chain::Watch for TestChainMonitor<'a> { } else { assert!(new_monitor == *monitor); } + + if update.updates.len() == 1 { + if let ChannelMonitorUpdateStep::EventGenerated { .. } = update.updates[0] { + return update_res; + } + } + self.added_monitors.lock().unwrap().push((channel_id, new_monitor)); update_res }