From 0e2542176b44519733f912de2973ed46915d2251 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 4 May 2022 18:12:09 +0000 Subject: [PATCH] Provide a redundant `Event::PaymentClaimed` on restart if needed If we crashed during a payment claim and then detected a partial claim on restart, we should ensure the user is aware that the payment has been claimed. We do so here by using the new partial-claim detection logic to create a `PaymentClaimed` event. --- lightning/src/ln/channelmanager.rs | 12 ++++++++++-- lightning/src/ln/functional_tests.rs | 11 ++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 98714252..03e07671 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -6837,9 +6837,12 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> for (_, monitor) in args.channel_monitors.iter() { for (payment_hash, payment_preimage) in monitor.get_stored_preimages() { - if let Some(claimable_htlcs) = claimable_htlcs.remove(&payment_hash) { + if let Some((payment_purpose, claimable_htlcs)) = claimable_htlcs.remove(&payment_hash) { log_info!(args.logger, "Re-claiming HTLCs with payment hash {} as we've released the preimage to a ChannelMonitor!", log_bytes!(payment_hash.0)); - for claimable_htlc in claimable_htlcs.1 { + let mut claimable_amt_msat = 0; + for claimable_htlc in claimable_htlcs { + claimable_amt_msat += claimable_htlc.value; + // Add a holding-cell claim of the payment to the Channel, which should be // applied ~immediately on peer reconnection. Because it won't generate a // new commitment transaction we can just provide the payment preimage to @@ -6863,6 +6866,11 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> previous_hop_monitor.provide_payment_preimage(&payment_hash, &payment_preimage, &args.tx_broadcaster, &args.fee_estimator, &args.logger); } } + pending_events_read.push(events::Event::PaymentClaimed { + payment_hash, + purpose: payment_purpose, + amt: claimable_amt_msat, + }); } } } diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index ed16a1c0..d033f85f 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -9881,6 +9881,9 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { // To get to the correct state, on startup we should propagate the preimage to the // still-off-chain channel, claiming the HTLC as soon as the peer connects, with the monitor // receiving the preimage without a state update. + // + // Further, we should generate a `PaymentClaimed` event to inform the user that the payment was + // definitely claimed. let chanmon_cfgs = create_chanmon_cfgs(4); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); @@ -9998,13 +10001,19 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { // commitment transaction. We should also still have the original PaymentReceived event we // never finished processing. let events = nodes[3].node.get_and_clear_pending_events(); - assert_eq!(events.len(), if persist_both_monitors { 3 } else { 2 }); + assert_eq!(events.len(), if persist_both_monitors { 4 } else { 3 }); if let Event::PaymentReceived { amt: 15_000_000, .. } = events[0] { } else { panic!(); } if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[1] { } else { panic!(); } if persist_both_monitors { if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[2] { } else { panic!(); } } + // On restart, we should also get a duplicate PaymentClaimed event as we persisted the + // ChannelManager prior to handling the original one. + if let Event::PaymentClaimed { payment_hash: our_payment_hash, amt: 15_000_000, .. } = events[if persist_both_monitors { 3 } else { 2 }] { + assert_eq!(payment_hash, our_payment_hash); + } else { panic!(); } + assert_eq!(nodes[3].node.list_channels().len(), if persist_both_monitors { 0 } else { 1 }); if !persist_both_monitors { // If one of the two channels is still live, reveal the payment preimage over it. -- 2.30.2