@@ -120,7 +120,10 @@ pub(super) struct PendingHTLCInfo {
120
120
pub ( super ) routing : PendingHTLCRouting ,
121
121
pub ( super ) incoming_shared_secret : [ u8 ; 32 ] ,
122
122
payment_hash : PaymentHash ,
123
+ /// Amount received
123
124
pub ( super ) incoming_amt_msat : Option < u64 > , // Added in 0.0.113
125
+ /// Sender intended amount to forward or receive (actual amount received
126
+ /// may overshoot this in either case)
124
127
pub ( super ) outgoing_amt_msat : u64 ,
125
128
pub ( super ) outgoing_cltv_value : u32 ,
126
129
}
@@ -192,9 +195,15 @@ struct ClaimableHTLC {
192
195
cltv_expiry : u32 ,
193
196
/// The amount (in msats) of this MPP part
194
197
value : u64 ,
198
+ /// The amount (in msats) that the sender intended to be sent in this MPP
199
+ /// part (used for validating total MPP amount)
200
+ sender_intended_value : u64 ,
195
201
onion_payload : OnionPayload ,
196
202
timer_ticks : u8 ,
197
- /// The sum total of all MPP parts
203
+ /// The total value received for a payment (sum of all MPP parts if the payment is a MPP).
204
+ /// Gets set to the amount reported when pushing [`Event::PaymentClaimable`].
205
+ total_value_received : Option < u64 > ,
206
+ /// The sender intended sum total of all MPP parts specified in the onion
198
207
total_msat : u64 ,
199
208
}
200
209
@@ -2092,9 +2101,9 @@ where
2092
2101
payment_hash : PaymentHash , amt_msat : u64 , cltv_expiry : u32 , phantom_shared_secret : Option < [ u8 ; 32 ] > ) -> Result < PendingHTLCInfo , ReceiveError >
2093
2102
{
2094
2103
// final_incorrect_cltv_expiry
2095
- if hop_data. outgoing_cltv_value != cltv_expiry {
2104
+ if hop_data. outgoing_cltv_value > cltv_expiry {
2096
2105
return Err ( ReceiveError {
2097
- msg : "Upstream node set CLTV to the wrong value " ,
2106
+ msg : "Upstream node set CLTV to less than the CLTV set by the sender " ,
2098
2107
err_code : 18 ,
2099
2108
err_data : cltv_expiry. to_be_bytes ( ) . to_vec ( )
2100
2109
} )
@@ -2178,7 +2187,7 @@ where
2178
2187
payment_hash,
2179
2188
incoming_shared_secret : shared_secret,
2180
2189
incoming_amt_msat : Some ( amt_msat) ,
2181
- outgoing_amt_msat : amt_msat ,
2190
+ outgoing_amt_msat : hop_data . amt_to_forward ,
2182
2191
outgoing_cltv_value : hop_data. outgoing_cltv_value ,
2183
2192
} )
2184
2193
}
@@ -2660,7 +2669,7 @@ where
2660
2669
}
2661
2670
2662
2671
#[ cfg( test) ]
2663
- fn test_send_payment_internal ( & self , route : & Route , payment_hash : PaymentHash , payment_secret : & Option < PaymentSecret > , keysend_preimage : Option < PaymentPreimage > , payment_id : PaymentId , recv_value_msat : Option < u64 > , onion_session_privs : Vec < [ u8 ; 32 ] > ) -> Result < ( ) , PaymentSendFailure > {
2672
+ pub ( super ) fn test_send_payment_internal ( & self , route : & Route , payment_hash : PaymentHash , payment_secret : & Option < PaymentSecret > , keysend_preimage : Option < PaymentPreimage > , payment_id : PaymentId , recv_value_msat : Option < u64 > , onion_session_privs : Vec < [ u8 ; 32 ] > ) -> Result < ( ) , PaymentSendFailure > {
2664
2673
let best_block_height = self . best_block . read ( ) . unwrap ( ) . height ( ) ;
2665
2674
let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
2666
2675
self . pending_outbound_payments . test_send_payment_internal ( route, payment_hash, payment_secret, keysend_preimage, payment_id, recv_value_msat, onion_session_privs, & self . node_signer , best_block_height,
@@ -3258,7 +3267,7 @@ where
3258
3267
HTLCForwardInfo :: AddHTLC ( PendingAddHTLCInfo {
3259
3268
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint, prev_user_channel_id,
3260
3269
forward_info : PendingHTLCInfo {
3261
- routing, incoming_shared_secret, payment_hash, outgoing_amt_msat, ..
3270
+ routing, incoming_shared_secret, payment_hash, incoming_amt_msat , outgoing_amt_msat, ..
3262
3271
}
3263
3272
} ) => {
3264
3273
let ( cltv_expiry, onion_payload, payment_data, phantom_shared_secret) = match routing {
@@ -3272,16 +3281,21 @@ where
3272
3281
panic ! ( "short_channel_id == 0 should imply any pending_forward entries are of type Receive" ) ;
3273
3282
}
3274
3283
} ;
3275
- let claimable_htlc = ClaimableHTLC {
3284
+ let mut claimable_htlc = ClaimableHTLC {
3276
3285
prev_hop : HTLCPreviousHopData {
3277
3286
short_channel_id : prev_short_channel_id,
3278
3287
outpoint : prev_funding_outpoint,
3279
3288
htlc_id : prev_htlc_id,
3280
3289
incoming_packet_shared_secret : incoming_shared_secret,
3281
3290
phantom_shared_secret,
3282
3291
} ,
3283
- value : outgoing_amt_msat,
3292
+ // We differentiate the received value from the sender intended value
3293
+ // if possible so that we don't prematurely mark MPP payments complete
3294
+ // if routing nodes overpay
3295
+ value : incoming_amt_msat. unwrap_or ( outgoing_amt_msat) ,
3296
+ sender_intended_value : outgoing_amt_msat,
3284
3297
timer_ticks : 0 ,
3298
+ total_value_received : None ,
3285
3299
total_msat : if let Some ( data) = & payment_data { data. total_msat } else { outgoing_amt_msat } ,
3286
3300
cltv_expiry,
3287
3301
onion_payload,
@@ -3326,7 +3340,7 @@ where
3326
3340
fail_htlc!( claimable_htlc, payment_hash) ;
3327
3341
continue
3328
3342
}
3329
- let ( _, htlcs) = claimable_payments. claimable_htlcs. entry( payment_hash)
3343
+ let ( _, ref mut htlcs) = claimable_payments. claimable_htlcs. entry( payment_hash)
3330
3344
. or_insert_with( || ( purpose( ) , Vec :: new( ) ) ) ;
3331
3345
if htlcs. len( ) == 1 {
3332
3346
if let OnionPayload :: Spontaneous ( _) = htlcs[ 0 ] . onion_payload {
@@ -3335,9 +3349,9 @@ where
3335
3349
continue
3336
3350
}
3337
3351
}
3338
- let mut total_value = claimable_htlc. value ;
3352
+ let mut total_value = claimable_htlc. sender_intended_value ;
3339
3353
for htlc in htlcs. iter( ) {
3340
- total_value += htlc. value ;
3354
+ total_value += htlc. sender_intended_value ;
3341
3355
match & htlc. onion_payload {
3342
3356
OnionPayload :: Invoice { .. } => {
3343
3357
if htlc. total_msat != $payment_data. total_msat {
@@ -3350,18 +3364,24 @@ where
3350
3364
_ => unreachable!( ) ,
3351
3365
}
3352
3366
}
3353
- if total_value >= msgs :: MAX_VALUE_MSAT || total_value > $payment_data . total_msat {
3354
- log_trace! ( self . logger , "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)" ,
3355
- log_bytes! ( payment_hash . 0 ) , total_value, $payment_data . total_msat ) ;
3367
+ // The condition determining whether an MPP is complete must
3368
+ // match exactly the condition used in `timer_tick_occurred`
3369
+ if total_value >= msgs :: MAX_VALUE_MSAT {
3356
3370
fail_htlc!( claimable_htlc, payment_hash) ;
3357
- } else if total_value == $payment_data. total_msat {
3371
+ } else if total_value - claimable_htlc. sender_intended_value >= $payment_data. total_msat {
3372
+ log_trace!( self . logger, "Failing HTLC with payment_hash {} as payment is already claimable" ,
3373
+ log_bytes!( payment_hash. 0 ) ) ;
3374
+ fail_htlc!( claimable_htlc, payment_hash) ;
3375
+ } else if total_value >= $payment_data. total_msat {
3358
3376
let prev_channel_id = prev_funding_outpoint. to_channel_id( ) ;
3359
3377
htlcs. push( claimable_htlc) ;
3378
+ let amount_msat = htlcs. iter( ) . map( |htlc| htlc. value) . sum( ) ;
3379
+ htlcs. iter_mut( ) . for_each( |htlc| htlc. total_value_received = Some ( amount_msat) ) ;
3360
3380
new_events. push( events:: Event :: PaymentClaimable {
3361
3381
receiver_node_id: Some ( receiver_node_id) ,
3362
3382
payment_hash,
3363
3383
purpose: purpose( ) ,
3364
- amount_msat: total_value ,
3384
+ amount_msat,
3365
3385
via_channel_id: Some ( prev_channel_id) ,
3366
3386
via_user_channel_id: Some ( prev_user_channel_id) ,
3367
3387
} ) ;
@@ -3415,13 +3435,15 @@ where
3415
3435
}
3416
3436
match claimable_payments. claimable_htlcs . entry ( payment_hash) {
3417
3437
hash_map:: Entry :: Vacant ( e) => {
3438
+ let amount_msat = claimable_htlc. value ;
3439
+ claimable_htlc. total_value_received = Some ( amount_msat) ;
3418
3440
let purpose = events:: PaymentPurpose :: SpontaneousPayment ( preimage) ;
3419
3441
e. insert ( ( purpose. clone ( ) , vec ! [ claimable_htlc] ) ) ;
3420
3442
let prev_channel_id = prev_funding_outpoint. to_channel_id ( ) ;
3421
3443
new_events. push ( events:: Event :: PaymentClaimable {
3422
3444
receiver_node_id : Some ( receiver_node_id) ,
3423
3445
payment_hash,
3424
- amount_msat : outgoing_amt_msat ,
3446
+ amount_msat,
3425
3447
purpose,
3426
3448
via_channel_id : Some ( prev_channel_id) ,
3427
3449
via_user_channel_id : Some ( prev_user_channel_id) ,
@@ -3681,7 +3703,9 @@ where
3681
3703
if let OnionPayload :: Invoice { .. } = htlcs[ 0 ] . onion_payload {
3682
3704
// Check if we've received all the parts we need for an MPP (the value of the parts adds to total_msat).
3683
3705
// In this case we're not going to handle any timeouts of the parts here.
3684
- if htlcs[ 0 ] . total_msat == htlcs. iter ( ) . fold ( 0 , |total, htlc| total + htlc. value ) {
3706
+ // This condition determining whether the MPP is complete here must match
3707
+ // exactly the condition used in `process_pending_htlc_forwards`.
3708
+ if htlcs[ 0 ] . total_msat <= htlcs. iter ( ) . fold ( 0 , |total, htlc| total + htlc. sender_intended_value ) {
3685
3709
return true ;
3686
3710
} else if htlcs. into_iter ( ) . any ( |htlc| {
3687
3711
htlc. timer_ticks += 1 ;
@@ -3960,6 +3984,7 @@ where
3960
3984
// provide the preimage, so worrying too much about the optimal handling isn't worth
3961
3985
// it.
3962
3986
let mut claimable_amt_msat = 0 ;
3987
+ let mut prev_total_msat = None ;
3963
3988
let mut expected_amt_msat = None ;
3964
3989
let mut valid_mpp = true ;
3965
3990
let mut errs = Vec :: new ( ) ;
@@ -3987,14 +4012,22 @@ where
3987
4012
break ;
3988
4013
}
3989
4014
3990
- if expected_amt_msat. is_some ( ) && expected_amt_msat != Some ( htlc. total_msat ) {
3991
- log_error ! ( self . logger, "Somehow ended up with an MPP payment with different total amounts - this should not be reachable!" ) ;
4015
+ if prev_total_msat. is_some ( ) && prev_total_msat != Some ( htlc. total_msat ) {
4016
+ log_error ! ( self . logger, "Somehow ended up with an MPP payment with different expected total amounts - this should not be reachable!" ) ;
4017
+ debug_assert ! ( false ) ;
4018
+ valid_mpp = false ;
4019
+ break ;
4020
+ }
4021
+ prev_total_msat = Some ( htlc. total_msat ) ;
4022
+
4023
+ if expected_amt_msat. is_some ( ) && expected_amt_msat != htlc. total_value_received {
4024
+ log_error ! ( self . logger, "Somehow ended up with an MPP payment with different received total amounts - this should not be reachable!" ) ;
3992
4025
debug_assert ! ( false ) ;
3993
4026
valid_mpp = false ;
3994
4027
break ;
3995
4028
}
4029
+ expected_amt_msat = htlc. total_value_received ;
3996
4030
3997
- expected_amt_msat = Some ( htlc. total_msat ) ;
3998
4031
if let OnionPayload :: Spontaneous ( _) = & htlc. onion_payload {
3999
4032
// We don't currently support MPP for spontaneous payments, so just check
4000
4033
// that there's one payment here and move on.
@@ -6794,7 +6827,9 @@ impl Writeable for ClaimableHTLC {
6794
6827
( 0 , self . prev_hop, required) ,
6795
6828
( 1 , self . total_msat, required) ,
6796
6829
( 2 , self . value, required) ,
6830
+ ( 3 , self . sender_intended_value, required) ,
6797
6831
( 4 , payment_data, option) ,
6832
+ ( 5 , self . total_value_received, option) ,
6798
6833
( 6 , self . cltv_expiry, required) ,
6799
6834
( 8 , keysend_preimage, option) ,
6800
6835
} ) ;
@@ -6806,15 +6841,19 @@ impl Readable for ClaimableHTLC {
6806
6841
fn read < R : Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
6807
6842
let mut prev_hop = crate :: util:: ser:: RequiredWrapper ( None ) ;
6808
6843
let mut value = 0 ;
6844
+ let mut sender_intended_value = None ;
6809
6845
let mut payment_data: Option < msgs:: FinalOnionHopData > = None ;
6810
6846
let mut cltv_expiry = 0 ;
6847
+ let mut total_value_received = None ;
6811
6848
let mut total_msat = None ;
6812
6849
let mut keysend_preimage: Option < PaymentPreimage > = None ;
6813
6850
read_tlv_fields ! ( reader, {
6814
6851
( 0 , prev_hop, required) ,
6815
6852
( 1 , total_msat, option) ,
6816
6853
( 2 , value, required) ,
6854
+ ( 3 , sender_intended_value, option) ,
6817
6855
( 4 , payment_data, option) ,
6856
+ ( 5 , total_value_received, option) ,
6818
6857
( 6 , cltv_expiry, required) ,
6819
6858
( 8 , keysend_preimage, option)
6820
6859
} ) ;
@@ -6842,6 +6881,8 @@ impl Readable for ClaimableHTLC {
6842
6881
prev_hop : prev_hop. 0 . unwrap ( ) ,
6843
6882
timer_ticks : 0 ,
6844
6883
value,
6884
+ sender_intended_value : sender_intended_value. unwrap_or ( value) ,
6885
+ total_value_received,
6845
6886
total_msat : total_msat. unwrap ( ) ,
6846
6887
onion_payload,
6847
6888
cltv_expiry,
0 commit comments