@@ -17,13 +17,13 @@ use crate::sign::EntropySource;
1717use crate :: chain:: transaction:: OutPoint ;
1818use crate :: events:: { ClosureReason , Event , HTLCDestination , MessageSendEvent , MessageSendEventsProvider , PathFailure , PaymentFailureReason } ;
1919use 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 } ;
2121use crate :: ln:: features:: InvoiceFeatures ;
22- use crate :: ln:: msgs;
22+ use crate :: ln:: { msgs, PaymentSecret , PaymentPreimage } ;
2323use crate :: ln:: msgs:: ChannelMessageHandler ;
2424use crate :: ln:: outbound_payment:: Retry ;
2525use crate :: routing:: gossip:: { EffectiveCapacity , RoutingFees } ;
26- use crate :: routing:: router:: { get_route, Path , PaymentParameters , Route , Router , RouteHint , RouteHintHop , RouteHop , RouteParameters } ;
26+ use crate :: routing:: router:: { get_route, Path , PaymentParameters , Route , Router , RouteHint , RouteHintHop , RouteHop , RouteParameters , find_route } ;
2727use crate :: routing:: scoring:: ChannelUsage ;
2828use crate :: util:: test_utils;
2929use crate :: util:: errors:: APIError ;
@@ -236,6 +236,177 @@ fn mpp_receive_timeout() {
236236 do_mpp_receive_timeout ( false ) ;
237237}
238238
239+ #[ test]
240+ fn test_mpp_keysend ( ) {
241+ let mut mpp_keysend_config = test_default_channel_config ( ) ;
242+ mpp_keysend_config. accept_mpp_keysend = true ;
243+ let chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
244+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
245+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , Some ( mpp_keysend_config) ] ) ;
246+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
247+
248+ create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
249+ create_announced_chan_between_nodes ( & nodes, 0 , 2 ) ;
250+ create_announced_chan_between_nodes ( & nodes, 1 , 3 ) ;
251+ create_announced_chan_between_nodes ( & nodes, 2 , 3 ) ;
252+ let network_graph = nodes[ 0 ] . network_graph . clone ( ) ;
253+
254+ let payer_pubkey = nodes[ 0 ] . node . get_our_node_id ( ) ;
255+ let payee_pubkey = nodes[ 3 ] . node . get_our_node_id ( ) ;
256+ let recv_value = 15_000_000 ;
257+ let route_params = RouteParameters {
258+ payment_params : PaymentParameters :: for_keysend ( payee_pubkey, 40 , true ) ,
259+ final_value_msat : recv_value,
260+ } ;
261+ let scorer = test_utils:: TestScorer :: new ( ) ;
262+ let random_seed_bytes = chanmon_cfgs[ 0 ] . keys_manager . get_secure_random_bytes ( ) ;
263+ let route = find_route ( & payer_pubkey, & route_params, & network_graph, None , nodes[ 0 ] . logger ,
264+ & scorer, & ( ) , & random_seed_bytes) . unwrap ( ) ;
265+
266+ let payment_preimage = PaymentPreimage ( [ 42 ; 32 ] ) ;
267+ let payment_secret = PaymentSecret ( payment_preimage. 0 ) ;
268+ let payment_hash = nodes[ 0 ] . node . send_spontaneous_payment ( & route, Some ( payment_preimage) ,
269+ RecipientOnionFields :: secret_only ( payment_secret) , PaymentId ( payment_preimage. 0 ) ) . unwrap ( ) ;
270+ check_added_monitors ! ( nodes[ 0 ] , 2 ) ;
271+
272+ let expected_route: & [ & [ & Node ] ] = & [ & [ & nodes[ 1 ] , & nodes[ 3 ] ] , & [ & nodes[ 2 ] , & nodes[ 3 ] ] ] ;
273+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
274+ assert_eq ! ( events. len( ) , 2 ) ;
275+
276+ let ev = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
277+ pass_along_path ( & nodes[ 0 ] , expected_route[ 0 ] , recv_value, payment_hash. clone ( ) ,
278+ Some ( payment_secret) , ev. clone ( ) , false , Some ( payment_preimage) ) ;
279+
280+ let ev = remove_first_msg_event_to_node ( & nodes[ 2 ] . node . get_our_node_id ( ) , & mut events) ;
281+ pass_along_path ( & nodes[ 0 ] , expected_route[ 1 ] , recv_value, payment_hash. clone ( ) ,
282+ Some ( payment_secret) , ev. clone ( ) , true , Some ( payment_preimage) ) ;
283+ claim_payment_along_route ( & nodes[ 0 ] , expected_route, false , payment_preimage) ;
284+ }
285+
286+ #[ test]
287+ fn test_reject_mpp_keysend_htlc ( ) {
288+ // This test enforces that we reject MPP keysend HTLCs if our config states we don't support
289+ // MPP keysend. When receiving a payment, if we don't support MPP keysend we'll reject the
290+ // payment if it's keysend and has a payment secret, never reaching our payment validation
291+ // logic. To check that we enforce rejecting MPP keysends in our payment logic, here we send
292+ // keysend payments without payment secrets, then modify them by adding payment secrets in the
293+ // final node in between receiving the HTLCs and actually processing them.
294+ let mut reject_mpp_keysend_cfg = test_default_channel_config ( ) ;
295+ reject_mpp_keysend_cfg. accept_mpp_keysend = false ;
296+
297+ let chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
298+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
299+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , Some ( reject_mpp_keysend_cfg) ] ) ;
300+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
301+ let chan_1_id = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) . 0 . contents . short_channel_id ;
302+ let chan_2_id = create_announced_chan_between_nodes ( & nodes, 0 , 2 ) . 0 . contents . short_channel_id ;
303+ let chan_3_id = create_announced_chan_between_nodes ( & nodes, 1 , 3 ) . 0 . contents . short_channel_id ;
304+ let ( update_a, _, chan_4_channel_id, _) = create_announced_chan_between_nodes ( & nodes, 2 , 3 ) ;
305+ let chan_4_id = update_a. contents . short_channel_id ;
306+ let amount = 40_000 ;
307+ let ( mut route, payment_hash, payment_preimage, _) = get_route_and_payment_hash ! ( nodes[ 0 ] , nodes[ 3 ] , amount) ;
308+
309+ // Pay along nodes[1]
310+ route. paths [ 0 ] . hops [ 0 ] . pubkey = nodes[ 1 ] . node . get_our_node_id ( ) ;
311+ route. paths [ 0 ] . hops [ 0 ] . short_channel_id = chan_1_id;
312+ route. paths [ 0 ] . hops [ 1 ] . short_channel_id = chan_3_id;
313+
314+ let payment_id_0 = PaymentId ( nodes[ 0 ] . keys_manager . backing . get_secure_random_bytes ( ) ) ;
315+ nodes[ 0 ] . node . send_spontaneous_payment ( & route, Some ( payment_preimage) , RecipientOnionFields :: spontaneous_empty ( ) , payment_id_0) . unwrap ( ) ;
316+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
317+
318+ let update_0 = get_htlc_update_msgs ! ( nodes[ 0 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
319+ let update_add_0 = update_0. update_add_htlcs [ 0 ] . clone ( ) ;
320+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & update_add_0) ;
321+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , & update_0. commitment_signed, false , true ) ;
322+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
323+
324+ check_added_monitors ! ( & nodes[ 1 ] , 1 ) ;
325+ let update_1 = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 3 ] . node. get_our_node_id( ) ) ;
326+ let update_add_1 = update_1. update_add_htlcs [ 0 ] . clone ( ) ;
327+ nodes[ 3 ] . node . handle_update_add_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & update_add_1) ;
328+ commitment_signed_dance ! ( nodes[ 3 ] , nodes[ 1 ] , update_1. commitment_signed, false , true ) ;
329+
330+ assert ! ( nodes[ 3 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
331+ for ( _, pending_forwards) in nodes[ 3 ] . node . forward_htlcs . lock ( ) . unwrap ( ) . iter_mut ( ) {
332+ for f in pending_forwards. iter_mut ( ) {
333+ match f {
334+ & mut HTLCForwardInfo :: AddHTLC ( PendingAddHTLCInfo { ref mut forward_info, .. } ) => {
335+ match forward_info. routing {
336+ PendingHTLCRouting :: ReceiveKeysend { ref mut payment_data, .. } => {
337+ * payment_data = Some ( msgs:: FinalOnionHopData {
338+ payment_secret : PaymentSecret ( [ 42 ; 32 ] ) ,
339+ total_msat : amount * 2 ,
340+ } ) ;
341+ } ,
342+ _ => panic ! ( "Expected PendingHTLCRouting::ReceiveKeysend" ) ,
343+ }
344+ } ,
345+ _ => { } ,
346+ }
347+ }
348+ }
349+ expect_pending_htlcs_forwardable ! ( nodes[ 3 ] ) ;
350+
351+ // Pay along nodes[2]
352+ route. paths [ 0 ] . hops [ 0 ] . pubkey = nodes[ 2 ] . node . get_our_node_id ( ) ;
353+ route. paths [ 0 ] . hops [ 0 ] . short_channel_id = chan_2_id;
354+ route. paths [ 0 ] . hops [ 1 ] . short_channel_id = chan_4_id;
355+
356+ let payment_id_1 = PaymentId ( nodes[ 0 ] . keys_manager . backing . get_secure_random_bytes ( ) ) ;
357+ nodes[ 0 ] . node . send_spontaneous_payment ( & route, Some ( payment_preimage) , RecipientOnionFields :: spontaneous_empty ( ) , payment_id_1) . unwrap ( ) ;
358+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
359+
360+ let update_2 = get_htlc_update_msgs ! ( nodes[ 0 ] , nodes[ 2 ] . node. get_our_node_id( ) ) ;
361+ let update_add_2 = update_2. update_add_htlcs [ 0 ] . clone ( ) ;
362+ nodes[ 2 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & update_add_2) ;
363+ commitment_signed_dance ! ( nodes[ 2 ] , nodes[ 0 ] , & update_2. commitment_signed, false , true ) ;
364+ expect_pending_htlcs_forwardable ! ( nodes[ 2 ] ) ;
365+
366+ check_added_monitors ! ( & nodes[ 2 ] , 1 ) ;
367+ let update_3 = get_htlc_update_msgs ! ( nodes[ 2 ] , nodes[ 3 ] . node. get_our_node_id( ) ) ;
368+ let update_add_3 = update_3. update_add_htlcs [ 0 ] . clone ( ) ;
369+ nodes[ 3 ] . node . handle_update_add_htlc ( & nodes[ 2 ] . node . get_our_node_id ( ) , & update_add_3) ;
370+ commitment_signed_dance ! ( nodes[ 3 ] , nodes[ 2 ] , update_3. commitment_signed, false , true ) ;
371+
372+ assert ! ( nodes[ 3 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
373+ for ( _, pending_forwards) in nodes[ 3 ] . node . forward_htlcs . lock ( ) . unwrap ( ) . iter_mut ( ) {
374+ for f in pending_forwards. iter_mut ( ) {
375+ match f {
376+ & mut HTLCForwardInfo :: AddHTLC ( PendingAddHTLCInfo { ref mut forward_info, .. } ) => {
377+ match forward_info. routing {
378+ PendingHTLCRouting :: ReceiveKeysend { ref mut payment_data, .. } => {
379+ * payment_data = Some ( msgs:: FinalOnionHopData {
380+ payment_secret : PaymentSecret ( [ 42 ; 32 ] ) ,
381+ total_msat : amount * 2 ,
382+ } ) ;
383+ } ,
384+ _ => panic ! ( "Expected PendingHTLCRouting::ReceiveKeysend" ) ,
385+ }
386+ } ,
387+ _ => { } ,
388+ }
389+ }
390+ }
391+ expect_pending_htlcs_forwardable ! ( nodes[ 3 ] ) ;
392+ check_added_monitors ! ( nodes[ 3 ] , 1 ) ;
393+
394+ // Fail back along nodes[2]
395+ let update_fail_0 = get_htlc_update_msgs ! ( & nodes[ 3 ] , & nodes[ 2 ] . node. get_our_node_id( ) ) ;
396+ nodes[ 2 ] . node . handle_update_fail_htlc ( & nodes[ 3 ] . node . get_our_node_id ( ) , & update_fail_0. update_fail_htlcs [ 0 ] ) ;
397+ commitment_signed_dance ! ( nodes[ 2 ] , nodes[ 3 ] , update_fail_0. commitment_signed, false ) ;
398+ 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 } ] ) ;
399+ check_added_monitors ! ( nodes[ 2 ] , 1 ) ;
400+
401+ let update_fail_1 = get_htlc_update_msgs ! ( nodes[ 2 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
402+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 2 ] . node . get_our_node_id ( ) , & update_fail_1. update_fail_htlcs [ 0 ] ) ;
403+ commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 2 ] , update_fail_1. commitment_signed, false ) ;
404+
405+ expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash, true , PaymentFailedConditions :: new ( ) ) ;
406+ expect_pending_htlcs_forwardable_and_htlc_handling_failed ! ( nodes[ 3 ] , vec![ HTLCDestination :: FailedPayment { payment_hash } ] ) ;
407+ }
408+
409+
239410#[ test]
240411fn no_pending_leak_on_initial_send_failure ( ) {
241412 // In an earlier version of our payment tracking, we'd have a retry entry even when the initial
0 commit comments