@@ -16,10 +16,11 @@ use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS
1616use crate :: chain:: transaction:: OutPoint ;
1717use crate :: chain:: keysinterface:: KeysInterface ;
1818use crate :: ln:: channel:: EXPIRE_PREV_CONFIG_TICKS ;
19- use crate :: ln:: channelmanager:: { self , BREAKDOWN_TIMEOUT , ChannelManager , MPP_TIMEOUT_TICKS , MIN_CLTV_EXPIRY_DELTA , PaymentId , PaymentSendFailure , IDEMPOTENCY_TIMEOUT_TICKS } ;
19+ use crate :: ln:: channelmanager:: { self , BREAKDOWN_TIMEOUT , ChannelManager , InterceptId , 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 ;
@@ -1371,3 +1372,126 @@ fn test_holding_cell_inflight_htlcs() {
13711372 // Clear pending events so test doesn't throw a "Had excess message on node..." error
13721373 nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
13731374}
1375+
1376+ #[ test]
1377+ fn forward_intercepted_payment ( ) {
1378+ // Test that detecting an intercept scid on payment forward will signal LDK to generate an
1379+ // intercept event, which the LSP can then use to open a JIT channel to forward the payment.
1380+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
1381+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
1382+ let mut chan_config = test_default_channel_config ( ) ;
1383+ chan_config. manually_accept_inbound_channels = true ;
1384+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , Some ( chan_config) ] ) ;
1385+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
1386+ let scorer = test_utils:: TestScorer :: with_penalty ( 0 ) ;
1387+ let random_seed_bytes = chanmon_cfgs[ 0 ] . keys_manager . get_secure_random_bytes ( ) ;
1388+
1389+ let _ = create_announced_chan_between_nodes ( & nodes, 0 , 1 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) . 2 ;
1390+
1391+ let amt_msat = 100_000 ;
1392+ let intercept_scid = nodes[ 1 ] . node . get_intercept_scid ( ) ;
1393+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 2 ] . node . get_our_node_id ( ) )
1394+ . with_route_hints ( vec ! [
1395+ RouteHint ( vec![ RouteHintHop {
1396+ src_node_id: nodes[ 1 ] . node. get_our_node_id( ) ,
1397+ short_channel_id: intercept_scid,
1398+ fees: RoutingFees {
1399+ base_msat: 1000 ,
1400+ proportional_millionths: 0 ,
1401+ } ,
1402+ cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA ,
1403+ htlc_minimum_msat: None ,
1404+ htlc_maximum_msat: None ,
1405+ } ] )
1406+ ] )
1407+ . with_features ( channelmanager:: provided_invoice_features ( ) ) ;
1408+ let route_params = RouteParameters {
1409+ payment_params,
1410+ final_value_msat : amt_msat,
1411+ final_cltv_expiry_delta : TEST_FINAL_CLTV ,
1412+ } ;
1413+ let route = find_route (
1414+ & nodes[ 0 ] . node . get_our_node_id ( ) , & route_params, & nodes[ 0 ] . network_graph , None , nodes[ 0 ] . logger ,
1415+ & scorer, & random_seed_bytes
1416+ ) . unwrap ( ) ;
1417+
1418+ let ( payment_hash, payment_secret) = nodes[ 2 ] . node . create_inbound_payment ( Some ( amt_msat) , 60 * 60 ) . unwrap ( ) ;
1419+ nodes[ 0 ] . node . send_payment ( & route, payment_hash, & Some ( payment_secret) , PaymentId ( payment_hash. 0 ) ) . unwrap ( ) ;
1420+ let payment_event = {
1421+ {
1422+ let mut added_monitors = nodes[ 0 ] . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1423+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1424+ added_monitors. clear ( ) ;
1425+ }
1426+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
1427+ assert_eq ! ( events. len( ) , 1 ) ;
1428+ SendEvent :: from_event ( events. remove ( 0 ) )
1429+ } ;
1430+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
1431+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , & payment_event. commitment_msg, false , true ) ;
1432+
1433+ // Check that we generate the PaymentIntercepted event when an intercept forward is detected.
1434+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
1435+ assert_eq ! ( events. len( ) , 1 ) ;
1436+ let ( intercept_id, expected_outbound_amount_msat) = match events[ 0 ] {
1437+ crate :: util:: events:: Event :: HTLCIntercepted {
1438+ intercept_id, expected_outbound_amount_msat, payment_hash : pmt_hash, inbound_amount_msat, requested_next_hop_scid : short_channel_id
1439+ } => {
1440+ assert_eq ! ( pmt_hash, payment_hash) ;
1441+ assert_eq ! ( inbound_amount_msat, route. get_total_amount( ) + route. get_total_fees( ) ) ;
1442+ assert_eq ! ( short_channel_id, intercept_scid) ;
1443+ ( intercept_id, expected_outbound_amount_msat)
1444+ } ,
1445+ _ => panic ! ( )
1446+ } ;
1447+
1448+ // Check for unknown channel id error.
1449+ let unknown_chan_id_err = nodes[ 1 ] . node . forward_intercepted_htlc ( intercept_id, & [ 42 ; 32 ] , nodes[ 2 ] . node . get_our_node_id ( ) , expected_outbound_amount_msat) . unwrap_err ( ) ;
1450+ assert_eq ! ( unknown_chan_id_err , APIError :: APIMisuseError { err: format!( "Channel with id {:?} not found" , [ 42 ; 32 ] ) } ) ;
1451+
1452+ // Open the just-in-time channel so the payment can then be forwarded.
1453+ let ( _, channel_id) = open_zero_conf_channel ( & nodes[ 1 ] , & nodes[ 2 ] , None ) ;
1454+
1455+ // Check for unknown intercept id error.
1456+ let unknown_intercept_id = InterceptId ( [ 42 ; 32 ] ) ;
1457+ let unknown_intercept_id_err = nodes[ 1 ] . node . forward_intercepted_htlc ( unknown_intercept_id, & channel_id, nodes[ 2 ] . node . get_our_node_id ( ) , expected_outbound_amount_msat) . unwrap_err ( ) ;
1458+ assert_eq ! ( unknown_intercept_id_err , APIError :: APIMisuseError { err: format!( "Payment with intercept id {:?} not found" , unknown_intercept_id. 0 ) } ) ;
1459+
1460+ // Finally, forward the intercepted payment through and claim it.
1461+ nodes[ 1 ] . node . forward_intercepted_htlc ( intercept_id, & channel_id, nodes[ 2 ] . node . get_our_node_id ( ) , expected_outbound_amount_msat) . unwrap ( ) ;
1462+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
1463+
1464+ let payment_event = {
1465+ {
1466+ let mut added_monitors = nodes[ 1 ] . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1467+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1468+ added_monitors. clear ( ) ;
1469+ }
1470+ let mut events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
1471+ assert_eq ! ( events. len( ) , 1 ) ;
1472+ SendEvent :: from_event ( events. remove ( 0 ) )
1473+ } ;
1474+ nodes[ 2 ] . node . handle_update_add_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
1475+ commitment_signed_dance ! ( nodes[ 2 ] , nodes[ 1 ] , & payment_event. commitment_msg, false , true ) ;
1476+ expect_pending_htlcs_forwardable ! ( nodes[ 2 ] ) ;
1477+
1478+ let payment_preimage = nodes[ 2 ] . node . get_payment_preimage ( payment_hash, payment_secret) . unwrap ( ) ;
1479+ expect_payment_received ! ( & nodes[ 2 ] , payment_hash, payment_secret, amt_msat, Some ( payment_preimage) , nodes[ 2 ] . node. get_our_node_id( ) ) ;
1480+ do_claim_payment_along_route ( & nodes[ 0 ] , & vec ! ( & vec!( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] ) , false , payment_preimage) ;
1481+ let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
1482+ assert_eq ! ( events. len( ) , 2 ) ;
1483+ match events[ 0 ] {
1484+ Event :: PaymentSent { payment_preimage : ref ev_preimage, payment_hash : ref ev_hash, ref fee_paid_msat, .. } => {
1485+ assert_eq ! ( payment_preimage, * ev_preimage) ;
1486+ assert_eq ! ( payment_hash, * ev_hash) ;
1487+ assert_eq ! ( fee_paid_msat, & Some ( 1000 ) ) ;
1488+ } ,
1489+ _ => panic ! ( "Unexpected event" )
1490+ }
1491+ match events[ 1 ] {
1492+ Event :: PaymentPathSuccessful { payment_hash : hash, .. } => {
1493+ assert_eq ! ( hash, Some ( payment_hash) ) ;
1494+ } ,
1495+ _ => panic ! ( "Unexpected event" )
1496+ }
1497+ }
0 commit comments