Skip to content

Commit 3c27653

Browse files
committed
f - add test to enforce rejecting mpp keysend htlcs when config is off
1 parent 3a121d1 commit 3c27653

File tree

1 file changed

+126
-2
lines changed

1 file changed

+126
-2
lines changed

lightning/src/ln/payment_tests.rs

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ use crate::sign::EntropySource;
1717
use crate::chain::transaction::OutPoint;
1818
use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentFailureReason};
1919
use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
20-
use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, IDEMPOTENCY_TIMEOUT_TICKS, RecentPaymentDetails, RecipientOnionFields};
20+
use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, IDEMPOTENCY_TIMEOUT_TICKS, RecentPaymentDetails, RecipientOnionFields, HTLCForwardInfo, PendingHTLCRouting, PendingAddHTLCInfo};
2121
use crate::ln::features::InvoiceFeatures;
22-
use crate::ln::msgs;
22+
use crate::ln::{msgs, PaymentSecret};
2323
use crate::ln::msgs::ChannelMessageHandler;
2424
use crate::ln::outbound_payment::Retry;
2525
use crate::routing::gossip::{EffectiveCapacity, RoutingFees};
@@ -236,6 +236,130 @@ fn mpp_receive_timeout() {
236236
do_mpp_receive_timeout(false);
237237
}
238238

239+
#[test]
240+
fn test_reject_mpp_keysend_htlc() {
241+
// This test enforces that we reject MPP keysend HTLCs if our config states we don't support
242+
// MPP keysend. When receiving a payment, if we don't support MPP keysend we'll reject the
243+
// payment if it's keysend and has a payment secret, never reaching our payment validation
244+
// logic. To check that we enforce rejecting MPP keysends in our payment logic, here we send
245+
// keysend payments without payment secrets, then modify them by adding payment secrets in the
246+
// final node in between receiving the HTLCs and actually processing them.
247+
let mut reject_mpp_keysend_cfg = test_default_channel_config();
248+
reject_mpp_keysend_cfg.accept_mpp_keysend = false;
249+
250+
let chanmon_cfgs = create_chanmon_cfgs(4);
251+
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
252+
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, Some(reject_mpp_keysend_cfg)]);
253+
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
254+
let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id;
255+
let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2).0.contents.short_channel_id;
256+
let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3).0.contents.short_channel_id;
257+
let (update_a, _, chan_4_channel_id, _) = create_announced_chan_between_nodes(&nodes, 2, 3);
258+
let chan_4_id = update_a.contents.short_channel_id;
259+
let amount = 40_000;
260+
let (mut route, payment_hash, payment_preimage, _) = get_route_and_payment_hash!(nodes[0], nodes[3], amount);
261+
262+
// Pay along nodes[1]
263+
route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id();
264+
route.paths[0].hops[0].short_channel_id = chan_1_id;
265+
route.paths[0].hops[1].short_channel_id = chan_3_id;
266+
267+
let payment_id_0 = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
268+
nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_0).unwrap();
269+
check_added_monitors!(nodes[0], 1);
270+
271+
let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
272+
let update_add_0 = update_0.update_add_htlcs[0].clone();
273+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &update_add_0);
274+
commitment_signed_dance!(nodes[1], nodes[0], &update_0.commitment_signed, false, true);
275+
expect_pending_htlcs_forwardable!(nodes[1]);
276+
277+
check_added_monitors!(&nodes[1], 1);
278+
let update_1 = get_htlc_update_msgs!(nodes[1], nodes[3].node.get_our_node_id());
279+
let update_add_1 = update_1.update_add_htlcs[0].clone();
280+
nodes[3].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &update_add_1);
281+
commitment_signed_dance!(nodes[3], nodes[1], update_1.commitment_signed, false, true);
282+
283+
assert!(nodes[3].node.get_and_clear_pending_msg_events().is_empty());
284+
for (_, pending_forwards) in nodes[3].node.forward_htlcs.lock().unwrap().iter_mut() {
285+
for f in pending_forwards.iter_mut() {
286+
match f {
287+
&mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => {
288+
match forward_info.routing {
289+
PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => {
290+
*payment_data = Some(msgs::FinalOnionHopData {
291+
payment_secret: PaymentSecret([42; 32]),
292+
total_msat: amount * 2,
293+
});
294+
},
295+
_ => panic!("Expected PendingHTLCRouting::ReceiveKeysend"),
296+
}
297+
},
298+
_ => {},
299+
}
300+
}
301+
}
302+
expect_pending_htlcs_forwardable!(nodes[3]);
303+
304+
// Pay along nodes[2]
305+
route.paths[0].hops[0].pubkey = nodes[2].node.get_our_node_id();
306+
route.paths[0].hops[0].short_channel_id = chan_2_id;
307+
route.paths[0].hops[1].short_channel_id = chan_4_id;
308+
309+
let payment_id_1 = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
310+
nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_1).unwrap();
311+
check_added_monitors!(nodes[0], 1);
312+
313+
let update_2 = get_htlc_update_msgs!(nodes[0], nodes[2].node.get_our_node_id());
314+
let update_add_2 = update_2.update_add_htlcs[0].clone();
315+
nodes[2].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &update_add_2);
316+
commitment_signed_dance!(nodes[2], nodes[0], &update_2.commitment_signed, false, true);
317+
expect_pending_htlcs_forwardable!(nodes[2]);
318+
319+
check_added_monitors!(&nodes[2], 1);
320+
let update_3 = get_htlc_update_msgs!(nodes[2], nodes[3].node.get_our_node_id());
321+
let update_add_3 = update_3.update_add_htlcs[0].clone();
322+
nodes[3].node.handle_update_add_htlc(&nodes[2].node.get_our_node_id(), &update_add_3);
323+
commitment_signed_dance!(nodes[3], nodes[2], update_3.commitment_signed, false, true);
324+
325+
assert!(nodes[3].node.get_and_clear_pending_msg_events().is_empty());
326+
for (_, pending_forwards) in nodes[3].node.forward_htlcs.lock().unwrap().iter_mut() {
327+
for f in pending_forwards.iter_mut() {
328+
match f {
329+
&mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => {
330+
match forward_info.routing {
331+
PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => {
332+
*payment_data = Some(msgs::FinalOnionHopData {
333+
payment_secret: PaymentSecret([42; 32]),
334+
total_msat: amount * 2,
335+
});
336+
},
337+
_ => panic!("Expected PendingHTLCRouting::ReceiveKeysend"),
338+
}
339+
},
340+
_ => {},
341+
}
342+
}
343+
}
344+
expect_pending_htlcs_forwardable!(nodes[3]);
345+
check_added_monitors!(nodes[3], 1);
346+
347+
// Fail back along nodes[2]
348+
let update_fail_0 = get_htlc_update_msgs!(&nodes[3], &nodes[2].node.get_our_node_id());
349+
nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &update_fail_0.update_fail_htlcs[0]);
350+
commitment_signed_dance!(nodes[2], nodes[3], update_fail_0.commitment_signed, false);
351+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_4_channel_id }]);
352+
check_added_monitors!(nodes[2], 1);
353+
354+
let update_fail_1 = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id());
355+
nodes[0].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &update_fail_1.update_fail_htlcs[0]);
356+
commitment_signed_dance!(nodes[0], nodes[2], update_fail_1.commitment_signed, false);
357+
358+
expect_payment_failed_conditions(&nodes[0], payment_hash, true, PaymentFailedConditions::new());
359+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[3], vec![HTLCDestination::FailedPayment { payment_hash }]);
360+
}
361+
362+
239363
#[test]
240364
fn no_pending_leak_on_initial_send_failure() {
241365
// In an earlier version of our payment tracking, we'd have a retry entry even when the initial

0 commit comments

Comments
 (0)