@@ -45,7 +45,7 @@ use chain::transaction::{OutPoint, TransactionData};
45
45
use ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
46
46
use ln:: channel:: { Channel , ChannelError , ChannelUpdateStatus , UpdateFulfillCommitFetch } ;
47
47
use ln:: features:: { InitFeatures , NodeFeatures } ;
48
- use routing:: router:: { Payee , Route , RouteHop , RouteParameters } ;
48
+ use routing:: router:: { Payee , Route , RouteHop , RoutePath , RouteParameters } ;
49
49
use ln:: msgs;
50
50
use ln:: msgs:: NetAddress ;
51
51
use ln:: onion_utils;
@@ -436,6 +436,8 @@ pub(crate) enum PendingOutboundPayment {
436
436
payment_hash : PaymentHash ,
437
437
payment_secret : Option < PaymentSecret > ,
438
438
pending_amt_msat : u64 ,
439
+ /// Used to track the fee paid. Only present if the payment was serialized on 0.0.103+.
440
+ pending_fee_msat : Option < u64 > ,
439
441
/// The total payment amount across all paths, used to verify that a retry is not overpaying.
440
442
total_msat : u64 ,
441
443
/// Our best known block height at the time this payment was initiated.
@@ -462,6 +464,12 @@ impl PendingOutboundPayment {
462
464
_ => false ,
463
465
}
464
466
}
467
+ fn get_pending_fee_msat ( & self ) -> Option < u64 > {
468
+ match self {
469
+ PendingOutboundPayment :: Retryable { pending_fee_msat, .. } => pending_fee_msat. clone ( ) ,
470
+ _ => None ,
471
+ }
472
+ }
465
473
466
474
fn mark_fulfilled ( & mut self ) {
467
475
let mut session_privs = HashSet :: new ( ) ;
@@ -474,8 +482,8 @@ impl PendingOutboundPayment {
474
482
* self = PendingOutboundPayment :: Fulfilled { session_privs } ;
475
483
}
476
484
477
- /// panics if part_amt_msat is None and !self.is_fulfilled
478
- fn remove ( & mut self , session_priv : & [ u8 ; 32 ] , part_amt_msat : Option < u64 > ) -> bool {
485
+ /// panics if path is None and !self.is_fulfilled
486
+ fn remove ( & mut self , session_priv : & [ u8 ; 32 ] , path : Option < & Vec < RouteHop > > ) -> bool {
479
487
let remove_res = match self {
480
488
PendingOutboundPayment :: Legacy { session_privs } |
481
489
PendingOutboundPayment :: Retryable { session_privs, .. } |
@@ -484,14 +492,19 @@ impl PendingOutboundPayment {
484
492
}
485
493
} ;
486
494
if remove_res {
487
- if let PendingOutboundPayment :: Retryable { ref mut pending_amt_msat, .. } = self {
488
- * pending_amt_msat -= part_amt_msat. expect ( "We must only not provide an amount if the payment was already fulfilled" ) ;
495
+ if let PendingOutboundPayment :: Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
496
+ let path = path. expect ( "Fulfilling a payment should always come with a path" ) ;
497
+ let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
498
+ * pending_amt_msat -= path_last_hop. fee_msat ;
499
+ if let Some ( fee_msat) = pending_fee_msat. as_mut ( ) {
500
+ * fee_msat -= path. get_path_fees ( ) ;
501
+ }
489
502
}
490
503
}
491
504
remove_res
492
505
}
493
506
494
- fn insert ( & mut self , session_priv : [ u8 ; 32 ] , part_amt_msat : u64 ) -> bool {
507
+ fn insert ( & mut self , session_priv : [ u8 ; 32 ] , path : & Vec < RouteHop > ) -> bool {
495
508
let insert_res = match self {
496
509
PendingOutboundPayment :: Legacy { session_privs } |
497
510
PendingOutboundPayment :: Retryable { session_privs, .. } => {
@@ -500,8 +513,12 @@ impl PendingOutboundPayment {
500
513
PendingOutboundPayment :: Fulfilled { .. } => false
501
514
} ;
502
515
if insert_res {
503
- if let PendingOutboundPayment :: Retryable { ref mut pending_amt_msat, .. } = self {
504
- * pending_amt_msat += part_amt_msat;
516
+ if let PendingOutboundPayment :: Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
517
+ let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
518
+ * pending_amt_msat += path_last_hop. fee_msat ;
519
+ if let Some ( fee_msat) = pending_fee_msat. as_mut ( ) {
520
+ * fee_msat += path. get_path_fees ( ) ;
521
+ }
505
522
}
506
523
}
507
524
insert_res
@@ -2081,12 +2098,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2081
2098
let payment = payment_entry. or_insert_with ( || PendingOutboundPayment :: Retryable {
2082
2099
session_privs : HashSet :: new ( ) ,
2083
2100
pending_amt_msat : 0 ,
2101
+ pending_fee_msat : Some ( 0 ) ,
2084
2102
payment_hash : * payment_hash,
2085
2103
payment_secret : * payment_secret,
2086
2104
starting_block_height : self . best_block . read ( ) . unwrap ( ) . height ( ) ,
2087
2105
total_msat : total_value,
2088
2106
} ) ;
2089
- assert ! ( payment. insert( session_priv_bytes, path. last ( ) . unwrap ( ) . fee_msat ) ) ;
2107
+ assert ! ( payment. insert( session_priv_bytes, path) ) ;
2090
2108
2091
2109
send_res
2092
2110
} {
@@ -3107,11 +3125,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3107
3125
session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
3108
3126
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
3109
3127
if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
3110
- let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
3111
- if payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( path_last_hop. fee_msat ) ) &&
3112
- !payment. get ( ) . is_fulfilled ( )
3113
- {
3128
+ if payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) && !payment. get ( ) . is_fulfilled ( ) {
3114
3129
let retry = if let Some ( payee_data) = payee {
3130
+ let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
3115
3131
Some ( RouteParameters {
3116
3132
payee : payee_data,
3117
3133
final_value_msat : path_last_hop. fee_msat ,
@@ -3164,9 +3180,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3164
3180
session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
3165
3181
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
3166
3182
let mut all_paths_failed = false ;
3167
- let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
3168
3183
if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
3169
- if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( path_last_hop . fee_msat ) ) {
3184
+ if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path ) ) {
3170
3185
log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
3171
3186
return ;
3172
3187
}
@@ -3183,6 +3198,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3183
3198
}
3184
3199
mem:: drop ( channel_state_lock) ;
3185
3200
let retry = if let Some ( payee_data) = payee {
3201
+ let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
3186
3202
Some ( RouteParameters {
3187
3203
payee : payee_data. clone ( ) ,
3188
3204
final_value_msat : path_last_hop. fee_msat ,
@@ -3457,8 +3473,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3457
3473
let mut session_priv_bytes = [ 0 ; 32 ] ;
3458
3474
session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
3459
3475
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
3460
- let found_payment = if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
3476
+ if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
3461
3477
let found_payment = !payment. get ( ) . is_fulfilled ( ) ;
3478
+ let fee_paid_msat = payment. get ( ) . get_pending_fee_msat ( ) ;
3462
3479
payment. get_mut ( ) . mark_fulfilled ( ) ;
3463
3480
if from_onchain {
3464
3481
// We currently immediately remove HTLCs which were fulfilled on-chain.
@@ -3467,22 +3484,22 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3467
3484
// restart.
3468
3485
// TODO: We should have a second monitor event that informs us of payments
3469
3486
// irrevocably fulfilled.
3470
- payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( path. last ( ) . unwrap ( ) . fee_msat ) ) ;
3487
+ payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) ;
3471
3488
if payment. get ( ) . remaining_parts ( ) == 0 {
3472
3489
payment. remove ( ) ;
3473
3490
}
3474
3491
}
3475
- found_payment
3476
- } else { false } ;
3477
- if found_payment {
3478
- let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage . 0 ) . into_inner ( ) ) ;
3479
- self . pending_events . lock ( ) . unwrap ( ) . push (
3480
- events :: Event :: PaymentSent {
3481
- payment_id : Some ( payment_id ) ,
3482
- payment_preimage ,
3483
- payment_hash : payment_hash
3484
- }
3485
- ) ;
3492
+ if found_payment {
3493
+ let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage . 0 ) . into_inner ( ) ) ;
3494
+ self . pending_events . lock ( ) . unwrap ( ) . push (
3495
+ events :: Event :: PaymentSent {
3496
+ payment_id : Some ( payment_id ) ,
3497
+ payment_preimage ,
3498
+ payment_hash : payment_hash ,
3499
+ fee_paid_msat ,
3500
+ }
3501
+ ) ;
3502
+ }
3486
3503
} else {
3487
3504
log_trace ! ( self . logger, "Received duplicative fulfill for HTLC with payment_preimage {}" , log_bytes!( payment_preimage. 0 ) ) ;
3488
3505
}
@@ -5495,6 +5512,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
5495
5512
} ,
5496
5513
( 2 , Retryable ) => {
5497
5514
( 0 , session_privs, required) ,
5515
+ ( 1 , pending_fee_msat, option) ,
5498
5516
( 2 , payment_hash, required) ,
5499
5517
( 4 , payment_secret, option) ,
5500
5518
( 6 , total_msat, required) ,
@@ -5951,16 +5969,18 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
5951
5969
session_priv_bytes[ ..] . copy_from_slice ( & session_priv[ ..] ) ;
5952
5970
match pending_outbound_payments. as_mut ( ) . unwrap ( ) . entry ( payment_id) {
5953
5971
hash_map:: Entry :: Occupied ( mut entry) => {
5954
- let newly_added = entry. get_mut ( ) . insert ( session_priv_bytes, path_amt ) ;
5972
+ let newly_added = entry. get_mut ( ) . insert ( session_priv_bytes, & path ) ;
5955
5973
log_info ! ( args. logger, "{} a pending payment path for {} msat for session priv {} on an existing pending payment with payment hash {}" ,
5956
5974
if newly_added { "Added" } else { "Had" } , path_amt, log_bytes!( session_priv_bytes) , log_bytes!( htlc. payment_hash. 0 ) ) ;
5957
5975
} ,
5958
5976
hash_map:: Entry :: Vacant ( entry) => {
5977
+ let path_fee = path. get_path_fees ( ) ;
5959
5978
entry. insert ( PendingOutboundPayment :: Retryable {
5960
5979
session_privs : [ session_priv_bytes] . iter ( ) . map ( |a| * a) . collect ( ) ,
5961
5980
payment_hash : htlc. payment_hash ,
5962
5981
payment_secret,
5963
5982
pending_amt_msat : path_amt,
5983
+ pending_fee_msat : Some ( path_fee) ,
5964
5984
total_msat : path_amt,
5965
5985
starting_block_height : best_block_height,
5966
5986
} ) ;
@@ -6259,7 +6279,7 @@ mod tests {
6259
6279
// further events will be generated for subsequence path successes.
6260
6280
let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
6261
6281
match events[ 0 ] {
6262
- Event :: PaymentSent { payment_id : ref id, payment_preimage : ref preimage, payment_hash : ref hash } => {
6282
+ Event :: PaymentSent { payment_id : ref id, payment_preimage : ref preimage, payment_hash : ref hash, .. } => {
6263
6283
assert_eq ! ( Some ( payment_id) , * id) ;
6264
6284
assert_eq ! ( payment_preimage, * preimage) ;
6265
6285
assert_eq ! ( our_payment_hash, * hash) ;
0 commit comments