Skip to content

Commit 4d12016

Browse files
committed
Block RAA ChannelMonitorUpdates on PaymentClaimed events
We added the ability to block `ChannelMonitorUpdate`s on receipt of an RAA in order to avoid dropping a payment preimage from a channel that created a `PaymentSent` event in 9ede794. We did not at the time use the same infrastructure for `PaymentClaimed` events, but really should have. While a `PaymentClaimed` event may seem a bit less critical than a `PaymentSent` event (it doesn't contain a payment preimage that the user needs to make sure they store for proof of payment), its still important for users to ensure their payment tracking logic is always correct. Here we take the (relatively straightforward) action of setting a `EventCompletionAction` to block RAA monitor updates on channels which created a `PaymentClaimed` event. Note that we only block one random channel from an MPP paymnet, not all of them, as any single channel should provide enough information for us to recreate the `PaymentClaimed` event on restart.
1 parent 0ab2e2d commit 4d12016

File tree

5 files changed

+124
-13
lines changed

5 files changed

+124
-13
lines changed

lightning/src/ln/async_signer_tests.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,7 @@ fn test_no_disconnect_while_async_commitment_signed_expecting_remote_revoke_and_
13951395
let (preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], payment_amount);
13961396
nodes[1].node.claim_funds(preimage);
13971397
check_added_monitors(&nodes[1], 1);
1398+
expect_payment_claimed!(nodes[1], payment_hash, payment_amount);
13981399

13991400
// We'll disable signing counterparty commitments on the payment sender.
14001401
nodes[0].disable_channel_signer_op(&node_b_id, &chan_id, SignerOp::SignCounterpartyCommitment);
@@ -1403,6 +1404,7 @@ fn test_no_disconnect_while_async_commitment_signed_expecting_remote_revoke_and_
14031404
// the `commitment_signed` is no longer pending.
14041405
let mut update = get_htlc_update_msgs!(&nodes[1], node_a_id);
14051406
nodes[0].node.handle_update_fulfill_htlc(node_b_id, update.update_fulfill_htlcs.remove(0));
1407+
expect_payment_sent(&nodes[0], preimage, None, false, false);
14061408
nodes[0].node.handle_commitment_signed_batch_test(node_b_id, &update.commitment_signed);
14071409
check_added_monitors(&nodes[0], 1);
14081410

@@ -1426,7 +1428,4 @@ fn test_no_disconnect_while_async_commitment_signed_expecting_remote_revoke_and_
14261428
};
14271429
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
14281430
assert!(nodes[1].node.get_and_clear_pending_msg_events().into_iter().any(has_disconnect_event));
1429-
1430-
expect_payment_sent(&nodes[0], preimage, None, false, false);
1431-
expect_payment_claimed!(nodes[1], payment_hash, payment_amount);
14321431
}

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4583,6 +4583,23 @@ fn test_single_channel_multiple_mpp() {
45834583
// `update_fulfill_htlc`/`commitment_signed` pair to pass to our counterparty.
45844584
do_a_write.send(()).unwrap();
45854585

4586+
let event_node: &'static TestChannelManager<'static, 'static> =
4587+
unsafe { std::mem::transmute(nodes[8].node as &TestChannelManager) };
4588+
let thrd_event = std::thread::spawn(move || {
4589+
let mut have_event = false;
4590+
while !have_event {
4591+
let mut events = event_node.get_and_clear_pending_events();
4592+
assert!(events.len() == 1 || events.len() == 0);
4593+
if events.len() == 1 {
4594+
if let Event::PaymentClaimed { .. } = events[0] {
4595+
} else {
4596+
panic!("Unexpected event {events:?}");
4597+
}
4598+
have_event = true;
4599+
}
4600+
}
4601+
});
4602+
45864603
// Then fetch the `update_fulfill_htlc`/`commitment_signed`. Note that the
45874604
// `get_and_clear_pending_msg_events` will immediately hang trying to take a peer lock which
45884605
// `claim_funds` is holding. Thus, we release a second write after a small sleep in the
@@ -4602,7 +4619,11 @@ fn test_single_channel_multiple_mpp() {
46024619
});
46034620
block_thrd2.store(false, Ordering::Release);
46044621
let mut first_updates = get_htlc_update_msgs(&nodes[8], &node_h_id);
4622+
4623+
// Thread 2 could unblock first, or it could get blocked waiting on us to process a
4624+
// `PaymentClaimed` event. Either way, wait until both have finished.
46054625
thrd2.join().unwrap();
4626+
thrd_event.join().unwrap();
46064627

46074628
// Disconnect node 6 from all its peers so it doesn't bother to fail the HTLCs back
46084629
nodes[7].node.peer_disconnected(node_b_id);
@@ -4649,8 +4670,6 @@ fn test_single_channel_multiple_mpp() {
46494670
thrd4.join().unwrap();
46504671
thrd.join().unwrap();
46514672

4652-
expect_payment_claimed!(nodes[8], payment_hash, 50_000_000);
4653-
46544673
// At the end, we should have 7 ChannelMonitorUpdates - 6 for HTLC claims, and one for the
46554674
// above `revoke_and_ack`.
46564675
check_added_monitors(&nodes[8], 7);

lightning/src/ln/channelmanager.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,19 @@ struct ClaimingPayment {
934934
sender_intended_value: Option<u64>,
935935
onion_fields: Option<RecipientOnionFields>,
936936
payment_id: Option<PaymentId>,
937+
/// When we claim and generate a [`Event::PaymentClaimed`], we want to block any
938+
/// payment-preimage-removing RAA [`ChannelMonitorUpdate`]s until the [`Event::PaymentClaimed`]
939+
/// is handled, ensuring we can regenerate the event on restart. We pick a random channel to
940+
/// block and store it here.
941+
///
942+
/// Note that once we disallow downgrades to 0.1 we should be able to simply use
943+
/// [`Self::htlcs`] to generate this rather than storing it here (as we won't need the funding
944+
/// outpoint), allowing us to remove this field.
945+
durable_preimage_channel: Option<(OutPoint, PublicKey, ChannelId)>,
937946
}
938947
impl_writeable_tlv_based!(ClaimingPayment, {
939948
(0, amount_msat, required),
949+
(1, durable_preimage_channel, option),
940950
(2, payment_purpose, required),
941951
(4, receiver_node_id, required),
942952
(5, htlcs, optional_vec),
@@ -1083,6 +1093,14 @@ impl ClaimablePayments {
10831093
.or_insert_with(|| {
10841094
let htlcs = payment.htlcs.iter().map(events::ClaimedHTLC::from).collect();
10851095
let sender_intended_value = payment.htlcs.first().map(|htlc| htlc.total_msat);
1096+
let durable_preimage_channel = payment.htlcs.last().map_or(None, |htlc| {
1097+
if let Some(node_id) = htlc.prev_hop.counterparty_node_id {
1098+
Some((htlc.prev_hop.outpoint, node_id, htlc.prev_hop.channel_id))
1099+
} else {
1100+
None
1101+
}
1102+
});
1103+
debug_assert!(durable_preimage_channel.is_some());
10861104
ClaimingPayment {
10871105
amount_msat: payment.htlcs.iter().map(|source| source.value).sum(),
10881106
payment_purpose: payment.purpose,
@@ -1091,6 +1109,7 @@ impl ClaimablePayments {
10911109
sender_intended_value,
10921110
onion_fields: payment.onion_fields,
10931111
payment_id: Some(payment_id),
1112+
durable_preimage_channel,
10941113
}
10951114
}).clone();
10961115

@@ -8687,6 +8706,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
86878706
sender_intended_value: sender_intended_total_msat,
86888707
onion_fields,
86898708
payment_id,
8709+
durable_preimage_channel,
86908710
}) = payment {
86918711
let event = events::Event::PaymentClaimed {
86928712
payment_hash,
@@ -8698,7 +8718,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
86988718
onion_fields,
86998719
payment_id,
87008720
};
8701-
let event_action = (event, None);
8721+
let action = if let Some((outpoint, counterparty_node_id, channel_id))
8722+
= durable_preimage_channel
8723+
{
8724+
Some(EventCompletionAction::ReleaseRAAChannelMonitorUpdate {
8725+
channel_funding_outpoint: Some(outpoint),
8726+
counterparty_node_id,
8727+
channel_id,
8728+
})
8729+
} else {
8730+
None
8731+
};
8732+
let event_action = (event, action);
87028733
let mut pending_events = self.pending_events.lock().unwrap();
87038734
// If we're replaying a claim on startup we may end up duplicating an event
87048735
// that's already in our queue, so check before we push another one. The
@@ -17087,6 +17118,10 @@ where
1708717118
onion_fields: payment.onion_fields,
1708817119
payment_id: Some(payment_id),
1708917120
},
17121+
// Note that we don't bother adding a EventCompletionAction here to
17122+
// ensure the `PaymentClaimed` event is durable processed as this
17123+
// should only be hit for particularly old channels and we don't have
17124+
// enough information to generate such an action.
1709017125
None,
1709117126
));
1709217127
}

lightning/src/ln/monitor_tests.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,3 +3211,65 @@ fn test_update_replay_panics() {
32113211
monitor.update_monitor(&updates[2], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger).unwrap();
32123212
monitor.update_monitor(&updates[3], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger).unwrap();
32133213
}
3214+
3215+
#[test]
3216+
fn test_claim_event_never_handled() {
3217+
// When a payment is claimed, the `ChannelMonitorUpdate` containing the payment preimage goes
3218+
// out and when it completes the `PaymentClaimed` event is generated. If the channel then
3219+
// progresses forward a few steps, the payment preimage will then eventually be removed from
3220+
// the channel. By that point, we have to make sure that the `PaymentClaimed` event has been
3221+
// handled (which ensures the user has maked the payment received).
3222+
// Otherwise, it is possible that, on restart, we load with a stale `ChannelManager` which
3223+
// doesn't have the `PaymentClaimed` event and it needs to rebuild it from the
3224+
// `ChannelMonitor`'s payment information and preimage.
3225+
let chanmon_cfgs = create_chanmon_cfgs(2);
3226+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
3227+
let persister;
3228+
let new_chain_mon;
3229+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
3230+
let nodes_1_reload;
3231+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
3232+
3233+
let node_a_id = nodes[0].node.get_our_node_id();
3234+
let node_b_id = nodes[1].node.get_our_node_id();
3235+
3236+
let init_node_ser = nodes[1].node.encode();
3237+
3238+
let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
3239+
3240+
// Send the payment we'll ultimately test the PaymentSent event for.
3241+
let (preimage_a, payment_hash_a, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
3242+
3243+
nodes[1].node.claim_funds(preimage_a);
3244+
check_added_monitors(&nodes[1], 1);
3245+
3246+
let mut updates = get_htlc_update_msgs(&nodes[1], &node_a_id);
3247+
nodes[0].node.handle_update_fulfill_htlc(node_b_id, updates.update_fulfill_htlcs.remove(0));
3248+
expect_payment_sent(&nodes[0], preimage_a, None, false, false);
3249+
3250+
nodes[0].node.handle_commitment_signed_batch_test(node_b_id, &updates.commitment_signed);
3251+
check_added_monitors(&nodes[0], 1);
3252+
3253+
// Once the `PaymentClaimed` event is generated, further RAA `ChannelMonitorUpdate`s will be
3254+
// blocked until it is handled, ensuring we never get far enough to remove the preimage.
3255+
let (raa, cs) = get_revoke_commit_msgs(&nodes[0], &node_b_id);
3256+
nodes[1].node.handle_revoke_and_ack(node_a_id, &raa);
3257+
nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &cs);
3258+
check_added_monitors(&nodes[1], 0);
3259+
3260+
// The last RAA here should be blocked waiting on us to handle the PaymentClaimed event before
3261+
// continuing. Otherwise, we'd be able to make enough progress that the payment preimage is
3262+
// removed from node A's `ChannelMonitor`. This leaves us unable to make further progress.
3263+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
3264+
3265+
// Finally, reload node B with an empty `ChannelManager` and check that we get the
3266+
// `PaymentClaimed` event.
3267+
let chan_0_monitor_serialized = get_monitor!(nodes[1], chan.2).encode();
3268+
let mons = &[&chan_0_monitor_serialized[..]];
3269+
reload_node!(nodes[1], &init_node_ser, mons, persister, new_chain_mon, nodes_1_reload);
3270+
3271+
expect_payment_claimed!(nodes[1], payment_hash_a, 1_000_000);
3272+
// The reload logic spuriously generates a redundant payment preimage-containing
3273+
// `ChannelMonitorUpdate`.
3274+
check_added_monitors(&nodes[1], 2);
3275+
}

lightning/src/ln/quiescence_tests.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ fn test_quiescence_waits_for_async_signer_and_monitor_update() {
197197
let (preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], payment_amount);
198198
nodes[1].node.claim_funds(preimage);
199199
check_added_monitors(&nodes[1], 1);
200+
expect_payment_claimed!(&nodes[1], payment_hash, payment_amount);
200201

201202
let mut update = get_htlc_update_msgs!(&nodes[1], node_id_0);
202203
nodes[0].node.handle_update_fulfill_htlc(node_id_1, update.update_fulfill_htlcs.remove(0));
@@ -223,8 +224,6 @@ fn test_quiescence_waits_for_async_signer_and_monitor_update() {
223224
nodes[1].enable_channel_signer_op(&node_id_0, &chan_id, SignerOp::ReleaseCommitmentSecret);
224225
nodes[1].node.signer_unblocked(Some((node_id_0, chan_id)));
225226

226-
expect_payment_claimed!(&nodes[1], payment_hash, payment_amount);
227-
228227
macro_rules! find_msg {
229228
($events: expr, $msg: ident) => {{
230229
$events
@@ -418,14 +417,11 @@ fn quiescence_updates_go_to_holding_cell(fail_htlc: bool) {
418417
if fail_htlc {
419418
nodes[0].node.handle_update_fail_htlc(node_id_1, &update.update_fail_htlcs[0]);
420419
} else {
420+
expect_payment_claimed!(nodes[1], payment_hash2, payment_amount);
421421
nodes[0].node.handle_update_fulfill_htlc(node_id_1, update.update_fulfill_htlcs.remove(0));
422422
}
423423
commitment_signed_dance!(&nodes[0], &nodes[1], update.commitment_signed, false);
424424

425-
if !fail_htlc {
426-
expect_payment_claimed!(nodes[1], payment_hash2, payment_amount);
427-
}
428-
429425
// The payment from nodes[0] should now be seen as failed/successful.
430426
let events = nodes[0].node.get_and_clear_pending_events();
431427
assert_eq!(events.len(), 2);
@@ -454,6 +450,7 @@ fn quiescence_updates_go_to_holding_cell(fail_htlc: bool) {
454450
if fail_htlc {
455451
nodes[1].node.handle_update_fail_htlc(node_id_0, &update.update_fail_htlcs[0]);
456452
} else {
453+
expect_payment_claimed!(nodes[0], payment_hash1, payment_amount);
457454
nodes[1].node.handle_update_fulfill_htlc(node_id_0, update.update_fulfill_htlcs.remove(0));
458455
}
459456
commitment_signed_dance!(&nodes[1], &nodes[0], update.commitment_signed, false);
@@ -463,7 +460,6 @@ fn quiescence_updates_go_to_holding_cell(fail_htlc: bool) {
463460
let conditions = PaymentFailedConditions::new();
464461
expect_payment_failed_conditions(&nodes[1], payment_hash1, true, conditions);
465462
} else {
466-
expect_payment_claimed!(nodes[0], payment_hash1, payment_amount);
467463
expect_payment_sent(&nodes[1], payment_preimage1, None, true, true);
468464
}
469465
}

0 commit comments

Comments
 (0)