@@ -19,7 +19,8 @@ use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
1919use crate :: ln:: channelmanager:: { self , BREAKDOWN_TIMEOUT , ChannelManager , ChannelManagerReadArgs , MPP_TIMEOUT_TICKS , MIN_CLTV_EXPIRY_DELTA , PaymentId , PaymentSendFailure , IDEMPOTENCY_TIMEOUT_TICKS } ;
2020use crate :: ln:: msgs;
2121use crate :: ln:: msgs:: ChannelMessageHandler ;
22- use crate :: routing:: router:: { PaymentParameters , get_route} ;
22+ use crate :: routing:: gossip:: RoutingFees ;
23+ use crate :: routing:: router:: { find_route, get_route, PaymentParameters , RouteHint , RouteHintHop , RouteParameters } ;
2324use crate :: util:: events:: { ClosureReason , Event , HTLCDestination , MessageSendEvent , MessageSendEventsProvider } ;
2425use crate :: util:: test_utils;
2526use crate :: util:: errors:: APIError ;
@@ -1385,3 +1386,115 @@ fn abandoned_send_payment_idempotent() {
13851386 pass_along_route ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] ] ] , 100_000 , second_payment_hash, second_payment_secret) ;
13861387 claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , second_payment_preimage) ;
13871388}
1389+
1390+ #[ test]
1391+ fn forward_intercepted_payment ( ) {
1392+ // Test that detecting an intercept scid on payment forward will signal LDK to generate an
1393+ // intercept event, which the LSP can then use to open a JIT channel to forward the payment.
1394+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
1395+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
1396+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
1397+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
1398+ let scorer = test_utils:: TestScorer :: with_penalty ( 0 ) ;
1399+ let random_seed_bytes = chanmon_cfgs[ 0 ] . keys_manager . get_secure_random_bytes ( ) ;
1400+
1401+ let _ = create_announced_chan_between_nodes ( & nodes, 0 , 1 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) . 2 ;
1402+
1403+ let amt_msat = 100_000 ;
1404+ let intercept_scid = nodes[ 1 ] . node . get_intercept_scid ( ) ;
1405+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 2 ] . node . get_our_node_id ( ) )
1406+ . with_route_hints ( vec ! [
1407+ RouteHint ( vec![ RouteHintHop {
1408+ src_node_id: nodes[ 1 ] . node. get_our_node_id( ) ,
1409+ short_channel_id: intercept_scid,
1410+ fees: RoutingFees {
1411+ base_msat: 1000 ,
1412+ proportional_millionths: 0 ,
1413+ } ,
1414+ cltv_expiry_delta: 130 ,
1415+ htlc_minimum_msat: None ,
1416+ htlc_maximum_msat: None ,
1417+ } ] )
1418+ ] )
1419+ . with_features ( channelmanager:: provided_invoice_features ( ) ) ;
1420+ let route_params = RouteParameters {
1421+ payment_params,
1422+ final_value_msat : amt_msat,
1423+ final_cltv_expiry_delta : TEST_FINAL_CLTV ,
1424+ } ;
1425+ let route = find_route (
1426+ & nodes[ 0 ] . node . get_our_node_id ( ) , & route_params, & nodes[ 0 ] . network_graph , None , nodes[ 0 ] . logger ,
1427+ & scorer, & random_seed_bytes
1428+ ) . unwrap ( ) ;
1429+
1430+ let ( payment_hash, payment_secret) = nodes[ 2 ] . node . create_inbound_payment ( Some ( amt_msat) , 60 * 60 ) . unwrap ( ) ;
1431+ nodes[ 0 ] . node . send_payment ( & route, payment_hash, & Some ( payment_secret) , PaymentId ( payment_hash. 0 ) ) . unwrap ( ) ;
1432+ let payment_event = {
1433+ {
1434+ let mut added_monitors = nodes[ 0 ] . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1435+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1436+ added_monitors. clear ( ) ;
1437+ }
1438+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
1439+ assert_eq ! ( events. len( ) , 1 ) ;
1440+ SendEvent :: from_event ( events. remove ( 0 ) )
1441+ } ;
1442+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
1443+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , & payment_event. commitment_msg, false , true ) ;
1444+
1445+ // Check that we generate the PaymentIntercepted event when an intercept forward is detected.
1446+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
1447+ assert_eq ! ( events. len( ) , 1 ) ;
1448+ let ( intercept_id, expected_outbound_amount_msat) = match events[ 0 ] {
1449+ crate :: util:: events:: Event :: PaymentIntercepted {
1450+ intercept_id, expected_outbound_amount_msat, payment_hash : pmt_hash, inbound_amount_msat, short_channel_id
1451+ } => {
1452+ assert_eq ! ( pmt_hash, payment_hash) ;
1453+ assert_eq ! ( inbound_amount_msat, route. get_total_amount( ) + route. get_total_fees( ) ) ;
1454+ assert_eq ! ( short_channel_id, intercept_scid) ;
1455+ ( intercept_id, expected_outbound_amount_msat)
1456+ } ,
1457+ _ => panic ! ( )
1458+ } ;
1459+
1460+ // Open the just-in-time channel so the payment can then be forwarded.
1461+ let scid = create_announced_chan_between_nodes ( & nodes, 1 , 2 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) . 0 . contents . short_channel_id ;
1462+
1463+ // Finally, forward the intercepted payment through and claim it.
1464+ nodes[ 1 ] . node . forward_intercepted_payment ( intercept_id, scid, expected_outbound_amount_msat) . unwrap ( ) ;
1465+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
1466+
1467+ let payment_event = {
1468+ {
1469+ let mut added_monitors = nodes[ 1 ] . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1470+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1471+ added_monitors. clear ( ) ;
1472+ }
1473+ let mut events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
1474+ assert_eq ! ( events. len( ) , 1 ) ;
1475+ SendEvent :: from_event ( events. remove ( 0 ) )
1476+ } ;
1477+ nodes[ 2 ] . node . handle_update_add_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
1478+ commitment_signed_dance ! ( nodes[ 2 ] , nodes[ 1 ] , & payment_event. commitment_msg, false , true ) ;
1479+ expect_pending_htlcs_forwardable ! ( nodes[ 2 ] ) ;
1480+
1481+ let payment_preimage = nodes[ 2 ] . node . get_payment_preimage ( payment_hash, payment_secret) . unwrap ( ) ;
1482+ expect_payment_received ! ( & nodes[ 2 ] , payment_hash, payment_secret, amt_msat, Some ( payment_preimage) ) ;
1483+ do_claim_payment_along_route ( & nodes[ 0 ] , & vec ! ( & vec!( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] ) , false , payment_preimage) ;
1484+ let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
1485+ assert_eq ! ( events. len( ) , 2 ) ;
1486+ match events[ 0 ] {
1487+ Event :: PaymentSent { payment_preimage : ref ev_preimage, payment_hash : ref ev_hash, ref fee_paid_msat, .. } => {
1488+ assert_eq ! ( payment_preimage, * ev_preimage) ;
1489+ assert_eq ! ( payment_hash, * ev_hash) ;
1490+ assert_eq ! ( fee_paid_msat, & Some ( 1000 ) ) ;
1491+ } ,
1492+ _ => panic ! ( "Unexpected event" )
1493+ }
1494+ match events[ 1 ] {
1495+ Event :: PaymentPathSuccessful { payment_hash : hash, .. } => {
1496+ assert_eq ! ( hash, Some ( payment_hash) ) ;
1497+ } ,
1498+ _ => panic ! ( "Unexpected event" )
1499+ }
1500+ }
0 commit comments