Skip to content

Commit a80c855

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 10df89d commit a80c855

File tree

5 files changed

+126
-13
lines changed

5 files changed

+126
-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
@@ -4694,6 +4694,23 @@ fn test_single_channel_multiple_mpp() {
46944694
// `update_fulfill_htlc`/`commitment_signed` pair to pass to our counterparty.
46954695
do_a_write.send(()).unwrap();
46964696

4697+
let event_node: &'static TestChannelManager<'static, 'static> =
4698+
unsafe { std::mem::transmute(nodes[8].node as &TestChannelManager) };
4699+
let thrd_event = std::thread::spawn(move || {
4700+
let mut have_event = false;
4701+
while !have_event {
4702+
let mut events = event_node.get_and_clear_pending_events();
4703+
assert!(events.len() == 1 || events.len() == 0);
4704+
if events.len() == 1 {
4705+
if let Event::PaymentClaimed { .. } = events[0] {
4706+
} else {
4707+
panic!("Unexpected event {events:?}");
4708+
}
4709+
have_event = true;
4710+
}
4711+
}
4712+
});
4713+
46974714
// Then fetch the `update_fulfill_htlc`/`commitment_signed`. Note that the
46984715
// `get_and_clear_pending_msg_events` will immediately hang trying to take a peer lock which
46994716
// `claim_funds` is holding. Thus, we release a second write after a small sleep in the
@@ -4713,7 +4730,11 @@ fn test_single_channel_multiple_mpp() {
47134730
});
47144731
block_thrd2.store(false, Ordering::Release);
47154732
let mut first_updates = get_htlc_update_msgs(&nodes[8], &node_h_id);
4733+
4734+
// Thread 2 could unblock first, or it could get blocked waiting on us to process a
4735+
// `PaymentClaimed` event. Either way, wait until both have finished.
47164736
thrd2.join().unwrap();
4737+
thrd_event.join().unwrap();
47174738

47184739
// Disconnect node 6 from all its peers so it doesn't bother to fail the HTLCs back
47194740
nodes[7].node.peer_disconnected(node_b_id);
@@ -4760,8 +4781,6 @@ fn test_single_channel_multiple_mpp() {
47604781
thrd4.join().unwrap();
47614782
thrd.join().unwrap();
47624783

4763-
expect_payment_claimed!(nodes[8], payment_hash, 50_000_000);
4764-
47654784
// At the end, we should have 7 ChannelMonitorUpdates - 6 for HTLC claims, and one for the
47664785
// above `revoke_and_ack`.
47674786
check_added_monitors(&nodes[8], 7);

lightning/src/ln/channelmanager.rs

Lines changed: 38 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,16 @@ 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+
// Pick an "arbitrary" channel to block RAAs on until the `PaymentSent`
1097+
// event is processed, specifically the last channel to get claimed.
1098+
let durable_preimage_channel = payment.htlcs.last().map_or(None, |htlc| {
1099+
if let Some(node_id) = htlc.prev_hop.counterparty_node_id {
1100+
Some((htlc.prev_hop.outpoint, node_id, htlc.prev_hop.channel_id))
1101+
} else {
1102+
None
1103+
}
1104+
});
1105+
debug_assert!(durable_preimage_channel.is_some());
10861106
ClaimingPayment {
10871107
amount_msat: payment.htlcs.iter().map(|source| source.value).sum(),
10881108
payment_purpose: payment.purpose,
@@ -1091,6 +1111,7 @@ impl ClaimablePayments {
10911111
sender_intended_value,
10921112
onion_fields: payment.onion_fields,
10931113
payment_id: Some(payment_id),
1114+
durable_preimage_channel,
10941115
}
10951116
}).clone();
10961117

@@ -8704,6 +8725,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
87048725
sender_intended_value: sender_intended_total_msat,
87058726
onion_fields,
87068727
payment_id,
8728+
durable_preimage_channel,
87078729
}) = payment {
87088730
let event = events::Event::PaymentClaimed {
87098731
payment_hash,
@@ -8715,7 +8737,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
87158737
onion_fields,
87168738
payment_id,
87178739
};
8718-
let event_action = (event, None);
8740+
let action = if let Some((outpoint, counterparty_node_id, channel_id))
8741+
= durable_preimage_channel
8742+
{
8743+
Some(EventCompletionAction::ReleaseRAAChannelMonitorUpdate {
8744+
channel_funding_outpoint: Some(outpoint),
8745+
counterparty_node_id,
8746+
channel_id,
8747+
})
8748+
} else {
8749+
None
8750+
};
8751+
let event_action = (event, action);
87198752
let mut pending_events = self.pending_events.lock().unwrap();
87208753
// If we're replaying a claim on startup we may end up duplicating an event
87218754
// that's already in our queue, so check before we push another one. The
@@ -17104,6 +17137,10 @@ where
1710417137
onion_fields: payment.onion_fields,
1710517138
payment_id: Some(payment_id),
1710617139
},
17140+
// Note that we don't bother adding a EventCompletionAction here to
17141+
// ensure the `PaymentClaimed` event is durable processed as this
17142+
// should only be hit for particularly old channels and we don't have
17143+
// enough information to generate such an action.
1710717144
None,
1710817145
));
1710917146
}

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 PaymentClaimed 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)