@@ -16,10 +16,11 @@ use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS
16
16
use crate :: chain:: transaction:: OutPoint ;
17
17
use crate :: chain:: keysinterface:: KeysInterface ;
18
18
use 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 } ;
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 ;
@@ -1371,3 +1372,126 @@ fn test_holding_cell_inflight_htlcs() {
1371
1372
// Clear pending events so test doesn't throw a "Had excess message on node..." error
1372
1373
nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
1373
1374
}
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