@@ -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 ;
@@ -3327,6 +3327,170 @@ fn claim_from_closed_chan() {
3327
3327
do_claim_from_closed_chan ( false ) ;
3328
3328
}
3329
3329
3330
+ #[ test]
3331
+ fn test_custom_tlvs ( ) {
3332
+ do_test_custom_tlvs ( true ) ;
3333
+ do_test_custom_tlvs ( false ) ;
3334
+ }
3335
+
3336
+ fn do_test_custom_tlvs ( spontaneous : bool ) {
3337
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
3338
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
3339
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None ; 2 ] ) ;
3340
+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
3341
+
3342
+ create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
3343
+
3344
+ let amt_msat = 100_000 ;
3345
+ let ( mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash ! ( & nodes[ 0 ] , & nodes[ 1 ] , amt_msat) ;
3346
+ let payment_id = PaymentId ( our_payment_hash. 0 ) ;
3347
+ let custom_tlvs = vec ! [
3348
+ ( 5482373483 , vec![ 1 , 2 , 3 , 4 ] ) ,
3349
+ ( 5482373487 , vec![ 0x42u8 ; 16 ] ) ,
3350
+ ] ;
3351
+ let onion_fields = RecipientOnionFields {
3352
+ payment_secret : if spontaneous { None } else { Some ( our_payment_secret) } ,
3353
+ payment_metadata : None ,
3354
+ custom_tlvs : custom_tlvs. clone ( )
3355
+ } ;
3356
+ if spontaneous {
3357
+ nodes[ 0 ] . node . send_spontaneous_payment ( & route, Some ( our_payment_preimage) , onion_fields, payment_id) . unwrap ( ) ;
3358
+ } else {
3359
+ nodes[ 0 ] . node . send_payment_with_route ( & route, our_payment_hash, onion_fields, payment_id) . unwrap ( ) ;
3360
+ }
3361
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
3362
+
3363
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
3364
+ let ev = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
3365
+ let mut payment_event = SendEvent :: from_event ( ev) ;
3366
+
3367
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
3368
+ check_added_monitors ! ( & nodes[ 1 ] , 0 ) ;
3369
+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , payment_event. commitment_msg, false ) ;
3370
+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
3371
+
3372
+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
3373
+ assert_eq ! ( events. len( ) , 1 ) ;
3374
+ match events[ 0 ] {
3375
+ Event :: PaymentClaimable { ref purpose, amount_msat, ref onion_fields, .. } => {
3376
+ match & purpose {
3377
+ PaymentPurpose :: InvoicePayment { payment_secret, .. } => {
3378
+ assert_eq ! ( our_payment_secret, * payment_secret) ;
3379
+ assert_eq ! ( Some ( * payment_secret) , onion_fields. as_ref( ) . unwrap( ) . payment_secret) ;
3380
+ } ,
3381
+ PaymentPurpose :: SpontaneousPayment ( payment_preimage) => {
3382
+ assert_eq ! ( our_payment_preimage, * payment_preimage) ;
3383
+ } ,
3384
+ }
3385
+ assert_eq ! ( amount_msat, amt_msat) ;
3386
+ assert_eq ! ( onion_fields. clone( ) . unwrap( ) . custom_tlvs( ) . clone( ) , custom_tlvs) ;
3387
+ } ,
3388
+ _ => panic ! ( "Unexpected event" ) ,
3389
+ }
3390
+
3391
+ claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , our_payment_preimage) ;
3392
+ }
3393
+
3394
+ #[ test]
3395
+ fn test_retry_custom_tlvs ( ) {
3396
+ // Test that custom TLVs are successfully sent on retries
3397
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
3398
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
3399
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
3400
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
3401
+
3402
+ create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
3403
+ let ( chan_2_update, _, chan_2_id, _) = create_announced_chan_between_nodes ( & nodes, 2 , 1 ) ;
3404
+
3405
+ // Rebalance
3406
+ send_payment ( & nodes[ 2 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 1_500_000 ) ;
3407
+
3408
+ let amt_msat = 1_000_000 ;
3409
+ let ( route, payment_hash, payment_preimage, payment_secret) =
3410
+ get_route_and_payment_hash ! ( nodes[ 0 ] , nodes[ 2 ] , amt_msat) ;
3411
+
3412
+ // Initiate the payment
3413
+ let payment_id = PaymentId ( payment_hash. 0 ) ;
3414
+ let mut route_params = RouteParameters {
3415
+ payment_params : route. payment_params . clone ( ) . unwrap ( ) ,
3416
+ final_value_msat : amt_msat,
3417
+ } ;
3418
+
3419
+ let custom_tlvs = vec ! [ ( ( 1 << 16 ) + 1 , vec![ 0x42u8 ; 16 ] ) ] ;
3420
+ let onion_fields = RecipientOnionFields :: secret_only ( payment_secret) ;
3421
+ let onion_fields = onion_fields. with_custom_tlvs ( custom_tlvs. clone ( ) ) . unwrap ( ) ;
3422
+
3423
+ nodes[ 0 ] . router . expect_find_route ( route_params. clone ( ) , Ok ( route. clone ( ) ) ) ;
3424
+ nodes[ 0 ] . node . send_payment ( payment_hash, onion_fields,
3425
+ payment_id, route_params. clone ( ) , Retry :: Attempts ( 1 ) ) . unwrap ( ) ;
3426
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ; // one monitor per path
3427
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
3428
+ assert_eq ! ( events. len( ) , 1 ) ;
3429
+
3430
+ // Add the HTLC along the first hop.
3431
+ let fail_path_msgs_1 = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
3432
+ let ( update_add, commitment_signed) = match fail_path_msgs_1 {
3433
+ MessageSendEvent :: UpdateHTLCs { node_id : _, updates : msgs:: CommitmentUpdate {
3434
+ ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs,
3435
+ ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed }
3436
+ } => {
3437
+ assert_eq ! ( update_add_htlcs. len( ) , 1 ) ;
3438
+ assert ! ( update_fail_htlcs. is_empty( ) ) ;
3439
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
3440
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
3441
+ assert ! ( update_fee. is_none( ) ) ;
3442
+ ( update_add_htlcs[ 0 ] . clone ( ) , commitment_signed. clone ( ) )
3443
+ } ,
3444
+ _ => panic ! ( "Unexpected event" ) ,
3445
+ } ;
3446
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & update_add) ;
3447
+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , commitment_signed, false ) ;
3448
+
3449
+ // Attempt to forward the payment and complete the path's failure.
3450
+ expect_pending_htlcs_forwardable ! ( & nodes[ 1 ] ) ;
3451
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed ! ( & nodes[ 1 ] ,
3452
+ vec![ HTLCDestination :: NextHopChannel {
3453
+ node_id: Some ( nodes[ 2 ] . node. get_our_node_id( ) ) ,
3454
+ channel_id: chan_2_id
3455
+ } ] ) ;
3456
+ let htlc_updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
3457
+ assert ! ( htlc_updates. update_add_htlcs. is_empty( ) ) ;
3458
+ assert_eq ! ( htlc_updates. update_fail_htlcs. len( ) , 1 ) ;
3459
+ assert ! ( htlc_updates. update_fulfill_htlcs. is_empty( ) ) ;
3460
+ assert ! ( htlc_updates. update_fail_malformed_htlcs. is_empty( ) ) ;
3461
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
3462
+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) ,
3463
+ & htlc_updates. update_fail_htlcs [ 0 ] ) ;
3464
+ commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 1 ] , htlc_updates. commitment_signed, false ) ;
3465
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
3466
+ match events[ 1 ] {
3467
+ Event :: PendingHTLCsForwardable { .. } => { } ,
3468
+ _ => panic ! ( "Unexpected event" )
3469
+ }
3470
+ events. remove ( 1 ) ;
3471
+ expect_payment_failed_conditions_event ( events, payment_hash, false ,
3472
+ PaymentFailedConditions :: new ( ) . mpp_parts_remain ( ) ) ;
3473
+
3474
+ // Rebalance the channel so the retry of the payment can succeed.
3475
+ send_payment ( & nodes[ 2 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 1_500_000 ) ;
3476
+
3477
+ // Retry the payment and make sure it succeeds
3478
+ route_params. payment_params . previously_failed_channels . push ( chan_2_update. contents . short_channel_id ) ;
3479
+ nodes[ 0 ] . router . expect_find_route ( route_params, Ok ( route) ) ;
3480
+ nodes[ 0 ] . node . process_pending_htlc_forwards ( ) ;
3481
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
3482
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
3483
+ assert_eq ! ( events. len( ) , 1 ) ;
3484
+ let payment_claimable = pass_along_path ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , 1_000_000 ,
3485
+ payment_hash, Some ( payment_secret) , events. pop ( ) . unwrap ( ) , true , None ) . unwrap ( ) ;
3486
+ let onion_fields = match payment_claimable {
3487
+ Event :: PaymentClaimable { onion_fields, .. } => onion_fields,
3488
+ _ => panic ! ( "Unexpected event" ) ,
3489
+ } ;
3490
+ assert_eq ! ( onion_fields. unwrap( ) . custom_tlvs( ) , & custom_tlvs) ;
3491
+ claim_payment_along_route ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] , & nodes[ 2 ] ] ] , false , payment_preimage) ;
3492
+ }
3493
+
3330
3494
fn do_test_payment_metadata_consistency ( do_reload : bool , do_modify : bool ) {
3331
3495
// Check that a payment metadata received on one HTLC that doesn't match the one received on
3332
3496
// another results in the HTLC being rejected.
0 commit comments