@@ -225,11 +225,7 @@ impl PaymentPath {
225
225
// to change fees may result in an inconsistency. Also, it's only safe to reduce the value,
226
226
// to not violate channel upper bounds.
227
227
fn update_value_and_recompute_fees ( & mut self , value_msat : u64 ) {
228
- if value_msat == self . hops . last ( ) . unwrap ( ) . route_hop . fee_msat {
229
- // Nothing to change.
230
- return ;
231
- }
232
- assert ! ( value_msat < self . hops. last( ) . unwrap( ) . route_hop. fee_msat) ;
228
+ assert ! ( value_msat <= self . hops. last( ) . unwrap( ) . route_hop. fee_msat) ;
233
229
234
230
let mut total_fee_paid_msat = 0 as u64 ;
235
231
for i in ( 0 ..self . hops . len ( ) ) . rev ( ) {
@@ -251,6 +247,14 @@ impl PaymentPath {
251
247
// match htlc_minimum_msat logic.
252
248
let mut cur_hop_transferred_amount_msat = total_fee_paid_msat + value_msat;
253
249
if let Some ( extra_fees_msat) = cur_hop. htlc_minimum_msat . checked_sub ( cur_hop_transferred_amount_msat) {
250
+ // Note that there is a risk that *previous hops* (those closer to us, as we go
251
+ // payee->our_node here) would exceed their htlc_maximum_msat or available balance.
252
+ //
253
+ // This might make us end up with a broken route, although this should be super-rare
254
+ // in practice, both because of how healthy channels look like, and how we pick
255
+ // channels in add_entry.
256
+ // Also, this can't be exploited more heavily than *announce a free path and fail
257
+ // all payments*.
254
258
cur_hop_transferred_amount_msat += extra_fees_msat;
255
259
total_fee_paid_msat += extra_fees_msat;
256
260
cur_hop_fees_msat += extra_fees_msat;
@@ -490,6 +494,10 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
490
494
// as not sufficient.
491
495
// TODO: Explore simply adding fee to hit htlc_minimum_msat
492
496
if contributes_sufficient_value && amount_to_transfer_over_msat >= $directional_info. htlc_minimum_msat {
497
+ // Note that low contribution here (limited by available_liquidity_msat)
498
+ // might violate htlc_minimum_msat on the following hops. To avoid that,
499
+ // we recompute path fees knowing the final path contribution after
500
+ // constructing it.
493
501
let hm_entry = dist. entry( & $src_node_id) ;
494
502
let old_entry = hm_entry. or_insert_with( || {
495
503
// If there was previously no known way to access
@@ -795,7 +803,15 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
795
803
ordered_hops. last_mut ( ) . unwrap ( ) . hop_use_fee_msat = 0 ;
796
804
ordered_hops. last_mut ( ) . unwrap ( ) . route_hop . cltv_expiry_delta = final_cltv;
797
805
798
- let payment_path = PaymentPath { hops : ordered_hops} ;
806
+ let mut payment_path = PaymentPath { hops : ordered_hops} ;
807
+
808
+ // We could have possibly constructed a slightly inconsistent path: since we reduce
809
+ // value being transferred all the way, we could have violated htlc_minimum_msat on
810
+ // some channels we already passed (assuming dest->source direction). Here, we
811
+ // recompute the fees again, so that if that's the case, we match the currently
812
+ // underpaid htlc_minimum_msat with fees.
813
+ payment_path. update_value_and_recompute_fees ( value_contribution_msat) ;
814
+
799
815
// Since a path allows to transfer as much value as
800
816
// the smallest channel it has ("bottleneck"), we should recompute
801
817
// the fees so sender HTLC don't overpay fees when traversing
0 commit comments