@@ -15,7 +15,7 @@ use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
15
15
use crate :: chain:: channelmonitor:: { ANTI_REORG_DELAY , HTLC_FAIL_BACK_BUFFER , LATENCY_GRACE_PERIOD_BLOCKS } ;
16
16
use crate :: sign:: EntropySource ;
17
17
use crate :: chain:: transaction:: OutPoint ;
18
- use crate :: events:: { ClosureReason , Event , HTLCDestination , MessageSendEvent , MessageSendEventsProvider , PathFailure , PaymentFailureReason } ;
18
+ use crate :: events:: { ClosureReason , Event , HTLCDestination , MessageSendEvent , MessageSendEventsProvider , PathFailure , PaymentFailureReason , PaymentPurpose } ;
19
19
use crate :: ln:: channel:: EXPIRE_PREV_CONFIG_TICKS ;
20
20
use crate :: ln:: channelmanager:: { BREAKDOWN_TIMEOUT , ChannelManager , MPP_TIMEOUT_TICKS , MIN_CLTV_EXPIRY_DELTA , PaymentId , PaymentSendFailure , IDEMPOTENCY_TIMEOUT_TICKS , RecentPaymentDetails , RecipientOnionFields , HTLCForwardInfo , PendingHTLCRouting , PendingAddHTLCInfo } ;
21
21
use crate :: ln:: features:: Bolt11InvoiceFeatures ;
@@ -3385,6 +3385,170 @@ fn claim_from_closed_chan() {
3385
3385
do_claim_from_closed_chan ( false ) ;
3386
3386
}
3387
3387
3388
+ #[ test]
3389
+ fn test_custom_tlvs ( ) {
3390
+ do_test_custom_tlvs ( true ) ;
3391
+ do_test_custom_tlvs ( false ) ;
3392
+ }
3393
+
3394
+ fn do_test_custom_tlvs ( spontaneous : bool ) {
3395
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
3396
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
3397
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None ; 2 ] ) ;
3398
+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
3399
+
3400
+ create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
3401
+
3402
+ let amt_msat = 100_000 ;
3403
+ let ( mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash ! ( & nodes[ 0 ] , & nodes[ 1 ] , amt_msat) ;
3404
+ let payment_id = PaymentId ( our_payment_hash. 0 ) ;
3405
+ let custom_tlvs = vec ! [
3406
+ ( 5482373483 , vec![ 1 , 2 , 3 , 4 ] ) ,
3407
+ ( 5482373487 , vec![ 0x42u8 ; 16 ] ) ,
3408
+ ] ;
3409
+ let onion_fields = RecipientOnionFields {
3410
+ payment_secret : if spontaneous { None } else { Some ( our_payment_secret) } ,
3411
+ payment_metadata : None ,
3412
+ custom_tlvs : custom_tlvs. clone ( )
3413
+ } ;
3414
+ if spontaneous {
3415
+ nodes[ 0 ] . node . send_spontaneous_payment ( & route, Some ( our_payment_preimage) , onion_fields, payment_id) . unwrap ( ) ;
3416
+ } else {
3417
+ nodes[ 0 ] . node . send_payment_with_route ( & route, our_payment_hash, onion_fields, payment_id) . unwrap ( ) ;
3418
+ }
3419
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
3420
+
3421
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
3422
+ let ev = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
3423
+ let mut payment_event = SendEvent :: from_event ( ev) ;
3424
+
3425
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
3426
+ check_added_monitors ! ( & nodes[ 1 ] , 0 ) ;
3427
+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , payment_event. commitment_msg, false ) ;
3428
+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
3429
+
3430
+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
3431
+ assert_eq ! ( events. len( ) , 1 ) ;
3432
+ match events[ 0 ] {
3433
+ Event :: PaymentClaimable { ref purpose, amount_msat, ref onion_fields, .. } => {
3434
+ match & purpose {
3435
+ PaymentPurpose :: InvoicePayment { payment_secret, .. } => {
3436
+ assert_eq ! ( our_payment_secret, * payment_secret) ;
3437
+ assert_eq ! ( Some ( * payment_secret) , onion_fields. as_ref( ) . unwrap( ) . payment_secret) ;
3438
+ } ,
3439
+ PaymentPurpose :: SpontaneousPayment ( payment_preimage) => {
3440
+ assert_eq ! ( our_payment_preimage, * payment_preimage) ;
3441
+ } ,
3442
+ }
3443
+ assert_eq ! ( amount_msat, amt_msat) ;
3444
+ assert_eq ! ( onion_fields. clone( ) . unwrap( ) . custom_tlvs( ) . clone( ) , custom_tlvs) ;
3445
+ } ,
3446
+ _ => panic ! ( "Unexpected event" ) ,
3447
+ }
3448
+
3449
+ claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , our_payment_preimage) ;
3450
+ }
3451
+
3452
+ #[ test]
3453
+ fn test_retry_custom_tlvs ( ) {
3454
+ // Test that custom TLVs are successfully sent on retries
3455
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
3456
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
3457
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
3458
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
3459
+
3460
+ create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
3461
+ let ( chan_2_update, _, chan_2_id, _) = create_announced_chan_between_nodes ( & nodes, 2 , 1 ) ;
3462
+
3463
+ // Rebalance
3464
+ send_payment ( & nodes[ 2 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 1_500_000 ) ;
3465
+
3466
+ let amt_msat = 1_000_000 ;
3467
+ let ( route, payment_hash, payment_preimage, payment_secret) =
3468
+ get_route_and_payment_hash ! ( nodes[ 0 ] , nodes[ 2 ] , amt_msat) ;
3469
+
3470
+ // Initiate the payment
3471
+ let payment_id = PaymentId ( payment_hash. 0 ) ;
3472
+ let mut route_params = RouteParameters {
3473
+ payment_params : route. payment_params . clone ( ) . unwrap ( ) ,
3474
+ final_value_msat : amt_msat,
3475
+ } ;
3476
+
3477
+ let custom_tlvs = vec ! [ ( ( 1 << 16 ) + 1 , vec![ 0x42u8 ; 16 ] ) ] ;
3478
+ let onion_fields = RecipientOnionFields :: secret_only ( payment_secret) ;
3479
+ let onion_fields = onion_fields. with_custom_tlvs ( custom_tlvs. clone ( ) ) . unwrap ( ) ;
3480
+
3481
+ nodes[ 0 ] . router . expect_find_route ( route_params. clone ( ) , Ok ( route. clone ( ) ) ) ;
3482
+ nodes[ 0 ] . node . send_payment ( payment_hash, onion_fields,
3483
+ payment_id, route_params. clone ( ) , Retry :: Attempts ( 1 ) ) . unwrap ( ) ;
3484
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ; // one monitor per path
3485
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
3486
+ assert_eq ! ( events. len( ) , 1 ) ;
3487
+
3488
+ // Add the HTLC along the first hop.
3489
+ let fail_path_msgs_1 = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
3490
+ let ( update_add, commitment_signed) = match fail_path_msgs_1 {
3491
+ MessageSendEvent :: UpdateHTLCs { node_id : _, updates : msgs:: CommitmentUpdate {
3492
+ ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs,
3493
+ ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed }
3494
+ } => {
3495
+ assert_eq ! ( update_add_htlcs. len( ) , 1 ) ;
3496
+ assert ! ( update_fail_htlcs. is_empty( ) ) ;
3497
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
3498
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
3499
+ assert ! ( update_fee. is_none( ) ) ;
3500
+ ( update_add_htlcs[ 0 ] . clone ( ) , commitment_signed. clone ( ) )
3501
+ } ,
3502
+ _ => panic ! ( "Unexpected event" ) ,
3503
+ } ;
3504
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & update_add) ;
3505
+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , commitment_signed, false ) ;
3506
+
3507
+ // Attempt to forward the payment and complete the path's failure.
3508
+ expect_pending_htlcs_forwardable ! ( & nodes[ 1 ] ) ;
3509
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed ! ( & nodes[ 1 ] ,
3510
+ vec![ HTLCDestination :: NextHopChannel {
3511
+ node_id: Some ( nodes[ 2 ] . node. get_our_node_id( ) ) ,
3512
+ channel_id: chan_2_id
3513
+ } ] ) ;
3514
+ let htlc_updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
3515
+ assert ! ( htlc_updates. update_add_htlcs. is_empty( ) ) ;
3516
+ assert_eq ! ( htlc_updates. update_fail_htlcs. len( ) , 1 ) ;
3517
+ assert ! ( htlc_updates. update_fulfill_htlcs. is_empty( ) ) ;
3518
+ assert ! ( htlc_updates. update_fail_malformed_htlcs. is_empty( ) ) ;
3519
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
3520
+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) ,
3521
+ & htlc_updates. update_fail_htlcs [ 0 ] ) ;
3522
+ commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 1 ] , htlc_updates. commitment_signed, false ) ;
3523
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
3524
+ match events[ 1 ] {
3525
+ Event :: PendingHTLCsForwardable { .. } => { } ,
3526
+ _ => panic ! ( "Unexpected event" )
3527
+ }
3528
+ events. remove ( 1 ) ;
3529
+ expect_payment_failed_conditions_event ( events, payment_hash, false ,
3530
+ PaymentFailedConditions :: new ( ) . mpp_parts_remain ( ) ) ;
3531
+
3532
+ // Rebalance the channel so the retry of the payment can succeed.
3533
+ send_payment ( & nodes[ 2 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 1_500_000 ) ;
3534
+
3535
+ // Retry the payment and make sure it succeeds
3536
+ route_params. payment_params . previously_failed_channels . push ( chan_2_update. contents . short_channel_id ) ;
3537
+ nodes[ 0 ] . router . expect_find_route ( route_params, Ok ( route) ) ;
3538
+ nodes[ 0 ] . node . process_pending_htlc_forwards ( ) ;
3539
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
3540
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
3541
+ assert_eq ! ( events. len( ) , 1 ) ;
3542
+ let payment_claimable = pass_along_path ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , 1_000_000 ,
3543
+ payment_hash, Some ( payment_secret) , events. pop ( ) . unwrap ( ) , true , None ) . unwrap ( ) ;
3544
+ let onion_fields = match payment_claimable {
3545
+ Event :: PaymentClaimable { onion_fields, .. } => onion_fields,
3546
+ _ => panic ! ( "Unexpected event" ) ,
3547
+ } ;
3548
+ assert_eq ! ( onion_fields. unwrap( ) . custom_tlvs( ) , & custom_tlvs) ;
3549
+ claim_payment_along_route ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] , & nodes[ 2 ] ] ] , false , payment_preimage) ;
3550
+ }
3551
+
3388
3552
fn do_test_payment_metadata_consistency ( do_reload : bool , do_modify : bool ) {
3389
3553
// Check that a payment metadata received on one HTLC that doesn't match the one received on
3390
3554
// another results in the HTLC being rejected.
0 commit comments