Skip to content

Commit f58e7fe

Browse files
committed
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.
1 parent 072cd9e commit f58e7fe

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6772,8 +6772,21 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
67726772
for (_, monitor) in args.channel_monitors.iter() {
67736773
for (payment_hash, payment_preimage) in monitor.get_stored_preimages() {
67746774
if let Some(claimable_htlcs) = claimable_htlcs.remove(&payment_hash) {
6775+
67756776
log_info!(args.logger, "Re-claimaing HTLCs with payment hash {} due to partial-claim.", log_bytes!(payment_hash.0));
6777+
let mut purpose = None;
6778+
let mut claimable_amt_msat = 0;
67766779
for claimable_htlc in claimable_htlcs {
6780+
if purpose.is_none() {
6781+
purpose = Some(match claimable_htlc.onion_payload {
6782+
OnionPayload::Spontaneous(preimage) => events::PaymentPurpose::SpontaneousPayment(preimage),
6783+
OnionPayload::Invoice(hop_data) => events::PaymentPurpose::InvoicePayment {
6784+
payment_secret: hop_data.payment_secret,
6785+
payment_preimage: Some(payment_preimage),
6786+
}
6787+
});
6788+
}
6789+
claimable_amt_msat += claimable_htlc.value;
67776790
let previous_channel_id = claimable_htlc.prev_hop.outpoint.to_channel_id();
67786791
if let Some(channel) = by_id.get_mut(&previous_channel_id) {
67796792
channel.claim_htlc_while_disconnected_dropping_mon_update(claimable_htlc.prev_hop.htlc_id, payment_preimage, &args.logger);
@@ -6782,6 +6795,11 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
67826795
previous_hop_monitor.provide_payment_preimage(&payment_hash, &payment_preimage, &args.tx_broadcaster, &args.fee_estimator, &args.logger);
67836796
}
67846797
}
6798+
pending_events_read.push(events::Event::PaymentClaimed {
6799+
payment_hash,
6800+
purpose: purpose.unwrap(),
6801+
amt: claimable_amt_msat,
6802+
});
67856803
}
67866804
}
67876805
}

lightning/src/ln/functional_tests.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9600,6 +9600,9 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
96009600
// To get to the correct state, on startup we should propagate the preimage to the
96019601
// still-off-chain channel, claiming the HTLC as soon as the peer connects, with the monitor
96029602
// receiving the preimage without a state update.
9603+
//
9604+
// Further, we should generate a `PaymentClaimed` event to inform the user that the payment was
9605+
// definitely claimed.
96039606
let chanmon_cfgs = create_chanmon_cfgs(4);
96049607
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
96059608
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
@@ -9717,13 +9720,19 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
97179720
// commitment transaction. We should also still have the original PaymentReceived event we
97189721
// never finished processing.
97199722
let events = nodes[3].node.get_and_clear_pending_events();
9720-
assert_eq!(events.len(), if persist_both_monitors { 3 } else { 2 });
9723+
assert_eq!(events.len(), if persist_both_monitors { 4 } else { 3 });
97219724
if let Event::PaymentReceived { amt: 15_000_000, .. } = events[0] { } else { panic!(); }
97229725
if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[1] { } else { panic!(); }
97239726
if persist_both_monitors {
97249727
if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[2] { } else { panic!(); }
97259728
}
97269729

9730+
// On restart, we should also get a duplicate PaymentClaimed event as we persisted the
9731+
// ChannelManager prior to handling the original one.
9732+
if let Event::PaymentClaimed { payment_hash: our_payment_hash, amt: 15_000_000, .. } = events[if persist_both_monitors { 3 } else { 2 }] {
9733+
assert_eq!(payment_hash, our_payment_hash);
9734+
} else { panic!(); }
9735+
97279736
assert_eq!(nodes[3].node.list_channels().len(), if persist_both_monitors { 0 } else { 1 });
97289737
if !persist_both_monitors {
97299738
// If one of the two channels is still live, reveal the payment preimage over it.

0 commit comments

Comments
 (0)