@@ -16,13 +16,13 @@ use crate::chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor, LATENCY_GRA
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 , ChannelManagerReadArgs , InterceptId , MPP_TIMEOUT_TICKS , MIN_CLTV_EXPIRY_DELTA , PaymentId , PaymentSendFailure , IDEMPOTENCY_TIMEOUT_TICKS } ;
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
22
use crate :: routing:: gossip:: RoutingFees ;
23
23
use crate :: routing:: router:: { find_route, get_route, PaymentParameters , RouteHint , RouteHintHop , RouteParameters } ;
24
24
use crate :: util:: events:: { ClosureReason , Event , HTLCDestination , MessageSendEvent , MessageSendEventsProvider } ;
25
- use crate :: util:: test_utils;
25
+ use crate :: util:: { byte_utils , test_utils} ;
26
26
use crate :: util:: errors:: APIError ;
27
27
use crate :: util:: enforcing_trait_impls:: EnforcingSigner ;
28
28
use crate :: util:: ser:: { ReadableArgs , Writeable } ;
@@ -1387,16 +1387,25 @@ fn abandoned_send_payment_idempotent() {
1387
1387
claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , second_payment_preimage) ;
1388
1388
}
1389
1389
1390
+ #[ derive( PartialEq ) ]
1391
+ enum InterceptTest {
1392
+ Forward ,
1393
+ Fail ,
1394
+ Timeout ,
1395
+ }
1396
+
1390
1397
#[ test]
1391
1398
fn intercepted_payment ( ) {
1392
1399
// Test that detecting an intercept scid on payment forward will signal LDK to generate an
1393
1400
// intercept event, which the LSP can then use to either (a) open a JIT channel to forward the
1394
1401
// payment or (b) fail the payment.
1395
- do_test_intercepted_payment ( false ) ;
1396
- do_test_intercepted_payment ( true ) ;
1402
+ do_test_intercepted_payment ( InterceptTest :: Forward ) ;
1403
+ do_test_intercepted_payment ( InterceptTest :: Fail ) ;
1404
+ // Make sure that intercepted payments will be automatically failed back if too many blocks pass.
1405
+ do_test_intercepted_payment ( InterceptTest :: Timeout ) ;
1397
1406
}
1398
1407
1399
- fn do_test_intercepted_payment ( fail_intercept : bool ) {
1408
+ fn do_test_intercepted_payment ( test : InterceptTest ) {
1400
1409
let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
1401
1410
let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
1402
1411
@@ -1471,7 +1480,7 @@ fn do_test_intercepted_payment(fail_intercept: bool) {
1471
1480
let unknown_scid_err = nodes[ 1 ] . node . forward_intercepted_htlc ( intercept_id, 4242 , nodes[ 2 ] . node . get_our_node_id ( ) , expected_outbound_amount_msat) . unwrap_err ( ) ;
1472
1481
assert_eq ! ( unknown_scid_err, APIError :: APIMisuseError { err: "Channel with short channel id 4242 not found" . to_string( ) } ) ;
1473
1482
1474
- if fail_intercept {
1483
+ if test == InterceptTest :: Fail {
1475
1484
// Ensure we can fail the intercepted payment back.
1476
1485
nodes[ 1 ] . node . fail_intercepted_htlc ( intercept_id) . unwrap ( ) ;
1477
1486
expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore ! ( nodes[ 1 ] , vec![ HTLCDestination :: UnknownNextHop { requested_forward_scid: intercept_scid } ] ) ;
@@ -1489,15 +1498,10 @@ fn do_test_intercepted_payment(fail_intercept: bool) {
1489
1498
. blamed_chan_closed ( true )
1490
1499
. expected_htlc_error_data ( 0x4000 | 10 , & [ ] ) ;
1491
1500
expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash, false , fail_conditions) ;
1492
- } else {
1501
+ } else if test == InterceptTest :: Forward {
1493
1502
// Open the just-in-time channel so the payment can then be forwarded.
1494
1503
let scid = create_announced_chan_between_nodes ( & nodes, 1 , 2 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) . 0 . contents . short_channel_id ;
1495
1504
1496
- // Check for unknown intercept id error.
1497
- let unknown_intercept_id = InterceptId ( [ 42 ; 32 ] ) ;
1498
- let unknown_intercept_id_err = nodes[ 1 ] . node . forward_intercepted_htlc ( unknown_intercept_id, scid, nodes[ 2 ] . node . get_our_node_id ( ) , expected_outbound_amount_msat) . unwrap_err ( ) ;
1499
- assert_eq ! ( unknown_intercept_id_err , APIError :: APIMisuseError { err: format!( "Payment with intercept id {:?} not found" , unknown_intercept_id. 0 ) } ) ;
1500
-
1501
1505
// Finally, forward the intercepted payment through and claim it.
1502
1506
nodes[ 1 ] . node . forward_intercepted_htlc ( intercept_id, scid, nodes[ 2 ] . node . get_our_node_id ( ) , expected_outbound_amount_msat) . unwrap ( ) ;
1503
1507
expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
@@ -1535,5 +1539,38 @@ fn do_test_intercepted_payment(fail_intercept: bool) {
1535
1539
} ,
1536
1540
_ => panic ! ( "Unexpected event" )
1537
1541
}
1542
+ } else if test == InterceptTest :: Timeout {
1543
+ let mut block = Block {
1544
+ header : BlockHeader { version : 0x20000000 , prev_blockhash : nodes[ 0 ] . best_block_hash ( ) , merkle_root : TxMerkleNode :: all_zeros ( ) , time : 42 , bits : 42 , nonce : 42 } ,
1545
+ txdata : vec ! [ ] ,
1546
+ } ;
1547
+ connect_block ( & nodes[ 0 ] , & block) ;
1548
+ connect_block ( & nodes[ 1 ] , & block) ;
1549
+ let block_count = 183 ; // find_route adds a random CLTV offset, so hardcode rather than summing consts
1550
+ for _ in 0 ..block_count {
1551
+ block. header . prev_blockhash = block. block_hash ( ) ;
1552
+ connect_block ( & nodes[ 0 ] , & block) ;
1553
+ connect_block ( & nodes[ 1 ] , & block) ;
1554
+ }
1555
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed ! ( nodes[ 1 ] , vec![ HTLCDestination :: FailedPayment { payment_hash } ] ) ;
1556
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
1557
+ let htlc_timeout_updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
1558
+ assert ! ( htlc_timeout_updates. update_add_htlcs. is_empty( ) ) ;
1559
+ assert_eq ! ( htlc_timeout_updates. update_fail_htlcs. len( ) , 1 ) ;
1560
+ assert ! ( htlc_timeout_updates. update_fail_malformed_htlcs. is_empty( ) ) ;
1561
+ assert ! ( htlc_timeout_updates. update_fee. is_none( ) ) ;
1562
+
1563
+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & htlc_timeout_updates. update_fail_htlcs [ 0 ] ) ;
1564
+ commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 1 ] , htlc_timeout_updates. commitment_signed, false ) ;
1565
+ // amt_msat as u64, followed by the height at which we failed back above
1566
+ let mut expected_failure_data = byte_utils:: be64_to_array ( amt_msat) . to_vec ( ) ;
1567
+ expected_failure_data. extend_from_slice ( & byte_utils:: be32_to_array ( block_count - 1 ) ) ;
1568
+ expect_payment_failed ! ( nodes[ 0 ] , payment_hash, false , 0x4000 | 15 , & expected_failure_data[ ..] ) ;
1569
+
1570
+ let scid = create_announced_chan_between_nodes ( & nodes, 1 , 2 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) . 0 . contents . short_channel_id ;
1571
+
1572
+ // Check for unknown intercept id error.
1573
+ let unknown_intercept_id_err = nodes[ 1 ] . node . forward_intercepted_htlc ( intercept_id, scid, nodes[ 2 ] . node . get_our_node_id ( ) , expected_outbound_amount_msat) . unwrap_err ( ) ;
1574
+ assert_eq ! ( unknown_intercept_id_err , APIError :: APIMisuseError { err: format!( "Payment with intercept id {:?} not found" , intercept_id. 0 ) } ) ;
1538
1575
}
1539
1576
}
0 commit comments