@@ -16,6 +16,7 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
16
16
use crate :: chain:: keysinterface:: { EntropySource , NodeSigner , Recipient } ;
17
17
use crate :: ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
18
18
use crate :: ln:: channelmanager:: { ChannelDetails , HTLCSource , IDEMPOTENCY_TIMEOUT_TICKS , MIN_HTLC_RELAY_HOLDING_CELL_MILLIS , PaymentId } ;
19
+ use crate :: ln:: channelmanager:: MIN_FINAL_CLTV_EXPIRY_DELTA as LDK_DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA ;
19
20
use crate :: ln:: msgs:: DecodeError ;
20
21
use crate :: ln:: onion_utils:: HTLCFailReason ;
21
22
use crate :: routing:: router:: { InFlightHtlcs , PaymentParameters , Route , RouteHop , RouteParameters , RoutePath , Router } ;
@@ -43,7 +44,7 @@ pub(crate) enum PendingOutboundPayment {
43
44
Retryable {
44
45
retry_strategy : Option < Retry > ,
45
46
attempts : PaymentAttempts ,
46
- route_params : Option < RouteParameters > ,
47
+ payment_params : Option < PaymentParameters > ,
47
48
session_privs : HashSet < [ u8 ; 32 ] > ,
48
49
payment_hash : PaymentHash ,
49
50
payment_secret : Option < PaymentSecret > ,
@@ -102,9 +103,17 @@ impl PendingOutboundPayment {
102
103
_ => false ,
103
104
}
104
105
}
106
+ fn payment_parameters ( & mut self ) -> Option < & mut PaymentParameters > {
107
+ match self {
108
+ PendingOutboundPayment :: Retryable { payment_params : Some ( ref mut params) , .. } => {
109
+ Some ( params)
110
+ } ,
111
+ _ => None ,
112
+ }
113
+ }
105
114
pub fn insert_previously_failed_scid ( & mut self , scid : u64 ) {
106
- if let PendingOutboundPayment :: Retryable { route_params : Some ( params) , .. } = self {
107
- params. payment_params . previously_failed_channels . push ( scid) ;
115
+ if let PendingOutboundPayment :: Retryable { payment_params : Some ( params) , .. } = self {
116
+ params. previously_failed_channels . push ( scid) ;
108
117
}
109
118
}
110
119
pub ( super ) fn is_fulfilled ( & self ) -> bool {
@@ -474,9 +483,18 @@ impl OutboundPayments {
474
483
let mut retry_id_route_params = None ;
475
484
for ( pmt_id, pmt) in outbounds. iter_mut ( ) {
476
485
if pmt. is_auto_retryable_now ( ) {
477
- if let PendingOutboundPayment :: Retryable { pending_amt_msat, total_msat, route_params : Some ( params) , .. } = pmt {
486
+ if let PendingOutboundPayment :: Retryable { pending_amt_msat, total_msat, payment_params : Some ( params) , .. } = pmt {
478
487
if pending_amt_msat < total_msat {
479
- retry_id_route_params = Some ( ( * pmt_id, params. clone ( ) ) ) ;
488
+ retry_id_route_params = Some ( ( * pmt_id, RouteParameters {
489
+ final_value_msat : * total_msat - * pending_amt_msat,
490
+ final_cltv_expiry_delta :
491
+ if let Some ( delta) = params. final_cltv_expiry_delta { delta }
492
+ else {
493
+ debug_assert ! ( false , "We always set the final_cltv_expiry_delta when a path fails" ) ;
494
+ LDK_DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA . into ( )
495
+ } ,
496
+ payment_params : params. clone ( ) ,
497
+ } ) ) ;
480
498
break
481
499
}
482
500
}
@@ -522,7 +540,7 @@ impl OutboundPayments {
522
540
} ) ) ?;
523
541
524
542
let res = if let Some ( ( payment_hash, payment_secret, retry_strategy) ) = initial_send_info {
525
- let onion_session_privs = self . add_new_pending_payment ( payment_hash, * payment_secret, payment_id, & route, Some ( retry_strategy) , Some ( route_params. clone ( ) ) , entropy_source, best_block_height) ?;
543
+ let onion_session_privs = self . add_new_pending_payment ( payment_hash, * payment_secret, payment_id, & route, Some ( retry_strategy) , Some ( route_params. payment_params . clone ( ) ) , entropy_source, best_block_height) ?;
526
544
self . pay_route_internal ( & route, payment_hash, payment_secret, None , payment_id, None , onion_session_privs, node_signer, best_block_height, send_payment_along_path)
527
545
} else {
528
546
self . retry_payment_with_route ( & route, payment_id, entropy_source, node_signer, best_block_height, send_payment_along_path)
@@ -672,7 +690,7 @@ impl OutboundPayments {
672
690
673
691
pub ( super ) fn add_new_pending_payment < ES : Deref > (
674
692
& self , payment_hash : PaymentHash , payment_secret : Option < PaymentSecret > , payment_id : PaymentId ,
675
- route : & Route , retry_strategy : Option < Retry > , route_params : Option < RouteParameters > ,
693
+ route : & Route , retry_strategy : Option < Retry > , payment_params : Option < PaymentParameters > ,
676
694
entropy_source : & ES , best_block_height : u32
677
695
) -> Result < Vec < [ u8 ; 32 ] > , PaymentSendFailure > where ES :: Target : EntropySource {
678
696
let mut onion_session_privs = Vec :: with_capacity ( route. paths . len ( ) ) ;
@@ -687,7 +705,7 @@ impl OutboundPayments {
687
705
let payment = entry. insert ( PendingOutboundPayment :: Retryable {
688
706
retry_strategy,
689
707
attempts : PaymentAttempts :: new ( ) ,
690
- route_params ,
708
+ payment_params ,
691
709
session_privs : HashSet :: new ( ) ,
692
710
pending_amt_msat : 0 ,
693
711
pending_fee_msat : Some ( 0 ) ,
@@ -965,6 +983,7 @@ impl OutboundPayments {
965
983
let mut all_paths_failed = false ;
966
984
let mut full_failure_ev = None ;
967
985
let mut pending_retry_ev = None ;
986
+ let mut retry = None ;
968
987
let attempts_remaining = if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( * payment_id) {
969
988
if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) {
970
989
log_trace ! ( logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -978,6 +997,33 @@ impl OutboundPayments {
978
997
if let Some ( scid) = short_channel_id {
979
998
payment. get_mut ( ) . insert_previously_failed_scid ( scid) ;
980
999
}
1000
+
1001
+ // We want to move towards only using the `PaymentParameters` in the outbound payments
1002
+ // map. However, for backwards-compatibility, we still need to support passing the
1003
+ // `PaymentParameters` data that was shoved in the HTLC (and given to us via
1004
+ // `payment_params`) back to the user.
1005
+ let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
1006
+ if let Some ( params) = payment. get_mut ( ) . payment_parameters ( ) {
1007
+ if params. final_cltv_expiry_delta . is_none ( ) {
1008
+ // This should be rare, but a user could provide None for the payment data, and
1009
+ // we need it when we go to retry the payment, so fill it in.
1010
+ params. final_cltv_expiry_delta = Some ( path_last_hop. cltv_expiry_delta ) ;
1011
+ }
1012
+ retry = Some ( RouteParameters {
1013
+ payment_params : params. clone ( ) ,
1014
+ final_value_msat : path_last_hop. fee_msat ,
1015
+ final_cltv_expiry_delta : params. final_cltv_expiry_delta . unwrap ( ) ,
1016
+ } ) ;
1017
+ } else if let Some ( params) = payment_params {
1018
+ retry = Some ( RouteParameters {
1019
+ payment_params : params. clone ( ) ,
1020
+ final_value_msat : path_last_hop. fee_msat ,
1021
+ final_cltv_expiry_delta :
1022
+ if let Some ( delta) = params. final_cltv_expiry_delta { delta }
1023
+ else { path_last_hop. cltv_expiry_delta } ,
1024
+ } ) ;
1025
+ }
1026
+
981
1027
if payment. get ( ) . remaining_parts ( ) == 0 {
982
1028
all_paths_failed = true ;
983
1029
if payment. get ( ) . abandoned ( ) {
@@ -994,16 +1040,6 @@ impl OutboundPayments {
994
1040
return
995
1041
} ;
996
1042
core:: mem:: drop ( outbounds) ;
997
- let mut retry = if let Some ( payment_params_data) = payment_params {
998
- let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
999
- Some ( RouteParameters {
1000
- payment_params : payment_params_data. clone ( ) ,
1001
- final_value_msat : path_last_hop. fee_msat ,
1002
- final_cltv_expiry_delta :
1003
- if let Some ( delta) = payment_params_data. final_cltv_expiry_delta { delta }
1004
- else { path_last_hop. cltv_expiry_delta } ,
1005
- } )
1006
- } else { None } ;
1007
1043
log_trace ! ( logger, "Failing outbound payment HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
1008
1044
1009
1045
let path_failure = {
@@ -1115,13 +1151,13 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
1115
1151
( 0 , session_privs, required) ,
1116
1152
( 1 , pending_fee_msat, option) ,
1117
1153
( 2 , payment_hash, required) ,
1118
- ( not_written , retry_strategy , ( static_value , None ) ) ,
1154
+ ( 3 , payment_params , option ) ,
1119
1155
( 4 , payment_secret, option) ,
1120
- ( not_written, attempts, ( static_value, PaymentAttempts :: new( ) ) ) ,
1121
1156
( 6 , total_msat, required) ,
1122
- ( not_written, route_params, ( static_value, None ) ) ,
1123
1157
( 8 , pending_amt_msat, required) ,
1124
1158
( 10 , starting_block_height, required) ,
1159
+ ( not_written, retry_strategy, ( static_value, None ) ) ,
1160
+ ( not_written, attempts, ( static_value, PaymentAttempts :: new( ) ) ) ,
1125
1161
} ,
1126
1162
( 3 , Abandoned ) => {
1127
1163
( 0 , session_privs, required) ,
@@ -1212,7 +1248,7 @@ mod tests {
1212
1248
1213
1249
let err = if on_retry {
1214
1250
outbound_payments. add_new_pending_payment ( PaymentHash ( [ 0 ; 32 ] ) , None , PaymentId ( [ 0 ; 32 ] ) ,
1215
- & Route { paths : vec ! [ ] , payment_params : None } , Some ( Retry :: Attempts ( 1 ) ) , Some ( route_params. clone ( ) ) ,
1251
+ & Route { paths : vec ! [ ] , payment_params : None } , Some ( Retry :: Attempts ( 1 ) ) , Some ( route_params. payment_params . clone ( ) ) ,
1216
1252
& & keys_manager, 0 ) . unwrap ( ) ;
1217
1253
outbound_payments. pay_internal (
1218
1254
PaymentId ( [ 0 ; 32 ] ) , None , route_params, & & router, vec ! [ ] , InFlightHtlcs :: new ( ) ,
0 commit comments