@@ -17,9 +17,9 @@ use crate::sign::EntropySource;
17
17
use crate :: chain:: transaction:: OutPoint ;
18
18
use crate :: events:: { ClosureReason , Event , HTLCDestination , MessageSendEvent , MessageSendEventsProvider , PathFailure , PaymentFailureReason } ;
19
19
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 } ;
21
21
use crate :: ln:: features:: InvoiceFeatures ;
22
- use crate :: ln:: msgs;
22
+ use crate :: ln:: { msgs, PaymentSecret } ;
23
23
use crate :: ln:: msgs:: ChannelMessageHandler ;
24
24
use crate :: ln:: outbound_payment:: Retry ;
25
25
use crate :: routing:: gossip:: { EffectiveCapacity , RoutingFees } ;
@@ -236,6 +236,130 @@ fn mpp_receive_timeout() {
236
236
do_mpp_receive_timeout ( false ) ;
237
237
}
238
238
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
+
239
363
#[ test]
240
364
fn no_pending_leak_on_initial_send_failure ( ) {
241
365
// In an earlier version of our payment tracking, we'd have a retry entry even when the initial
0 commit comments