@@ -19,7 +19,8 @@ use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
19
19
use crate :: ln:: channelmanager:: { self , BREAKDOWN_TIMEOUT , ChannelManager , ChannelManagerReadArgs , MPP_TIMEOUT_TICKS , MIN_CLTV_EXPIRY_DELTA , PaymentId , PaymentSendFailure , IDEMPOTENCY_TIMEOUT_TICKS } ;
20
20
use crate :: ln:: msgs;
21
21
use 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 } ;
23
24
use crate :: util:: events:: { ClosureReason , Event , HTLCDestination , MessageSendEvent , MessageSendEventsProvider } ;
24
25
use crate :: util:: test_utils;
25
26
use crate :: util:: errors:: APIError ;
@@ -1385,3 +1386,115 @@ fn abandoned_send_payment_idempotent() {
1385
1386
pass_along_route ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] ] ] , 100_000 , second_payment_hash, second_payment_secret) ;
1386
1387
claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , second_payment_preimage) ;
1387
1388
}
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 :: HTLCIntercepted {
1450
+ intercept_id, expected_outbound_amount_msat, payment_hash : pmt_hash, inbound_amount_msat, requested_next_hop_scid : 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_htlc ( 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