@@ -951,7 +951,10 @@ impl<'a> CandidateRouteHop<'a> {
951
951
liquidity_msat : details. next_outbound_htlc_limit_msat ,
952
952
} ,
953
953
CandidateRouteHop :: PublicHop { info, .. } => info. effective_capacity ( ) ,
954
- CandidateRouteHop :: PrivateHop { .. } => EffectiveCapacity :: Infinite ,
954
+ CandidateRouteHop :: PrivateHop { hint } => {
955
+ hint. htlc_maximum_msat . map_or ( EffectiveCapacity :: Infinite ,
956
+ |max| EffectiveCapacity :: HintMaxHTLC { amount_msat : max } )
957
+ } ,
955
958
}
956
959
}
957
960
}
@@ -965,6 +968,7 @@ fn max_htlc_from_capacity(capacity: EffectiveCapacity, max_channel_saturation_po
965
968
EffectiveCapacity :: Unknown => EffectiveCapacity :: Unknown . as_msat ( ) ,
966
969
EffectiveCapacity :: AdvertisedMaxHTLC { amount_msat } =>
967
970
amount_msat. checked_shr ( saturation_shift) . unwrap_or ( 0 ) ,
971
+ EffectiveCapacity :: HintMaxHTLC { amount_msat } => amount_msat,
968
972
EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat } =>
969
973
cmp:: min ( capacity_msat. checked_shr ( saturation_shift) . unwrap_or ( 0 ) , htlc_maximum_msat) ,
970
974
}
@@ -6050,6 +6054,57 @@ mod tests {
6050
6054
assert_eq ! ( route. paths[ 0 ] . blinded_tail. as_ref( ) . unwrap( ) . excess_final_cltv_expiry_delta, 40 ) ;
6051
6055
assert_eq ! ( route. paths[ 0 ] . hops. last( ) . unwrap( ) . cltv_expiry_delta, 40 ) ;
6052
6056
}
6057
+
6058
+ #[ test]
6059
+ fn respect_route_hint_max_htlc ( ) {
6060
+ // Make sure that any max_htlc provided in the route hints of the payment params is respected in
6061
+ // the final route.
6062
+ let ( secp_ctx, network_graph, _, _, logger) = build_graph ( ) ;
6063
+ let netgraph = network_graph. read_only ( ) ;
6064
+ let ( _, our_id, _, nodes) = get_nodes ( & secp_ctx) ;
6065
+ let scorer = ln_test_utils:: TestScorer :: new ( ) ;
6066
+ let keys_manager = ln_test_utils:: TestKeysInterface :: new ( & [ 0u8 ; 32 ] , Network :: Testnet ) ;
6067
+ let random_seed_bytes = keys_manager. get_secure_random_bytes ( ) ;
6068
+ let config = UserConfig :: default ( ) ;
6069
+
6070
+ let max_htlc_msat = 50_000 ;
6071
+ let route_hint_1 = RouteHint ( vec ! [ RouteHintHop {
6072
+ src_node_id: nodes[ 2 ] ,
6073
+ short_channel_id: 42 ,
6074
+ fees: RoutingFees {
6075
+ base_msat: 100 ,
6076
+ proportional_millionths: 0 ,
6077
+ } ,
6078
+ cltv_expiry_delta: 10 ,
6079
+ htlc_minimum_msat: None ,
6080
+ htlc_maximum_msat: Some ( max_htlc_msat) ,
6081
+ } ] ) ;
6082
+ let dest_node_id = ln_test_utils:: pubkey ( 42 ) ;
6083
+ let payment_params = PaymentParameters :: from_node_id ( dest_node_id, 42 )
6084
+ . with_route_hints ( vec ! [ route_hint_1. clone( ) ] ) . unwrap ( )
6085
+ . with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) ;
6086
+
6087
+ // Make sure we'll error if our route hints don't have enough liquidity according to their
6088
+ // max_htlc.
6089
+ if let Err ( LightningError { err, action : ErrorAction :: IgnoreError } ) = get_route ( & our_id,
6090
+ & payment_params, & netgraph, None , max_htlc_msat + 1 , Arc :: clone ( & logger) , & scorer, & ( ) ,
6091
+ & random_seed_bytes)
6092
+ {
6093
+ assert_eq ! ( err, "Failed to find a sufficient route to the given destination" ) ;
6094
+ } else { panic ! ( ) ; }
6095
+
6096
+ // Make sure we'll split an MPP payment across route hints if their max_htlcs warrant it.
6097
+ let mut route_hint_2 = route_hint_1. clone ( ) ;
6098
+ route_hint_2. 0 [ 0 ] . short_channel_id = 43 ;
6099
+ let payment_params = PaymentParameters :: from_node_id ( dest_node_id, 42 )
6100
+ . with_route_hints ( vec ! [ route_hint_1, route_hint_2] ) . unwrap ( )
6101
+ . with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) ;
6102
+ let route = get_route ( & our_id, & payment_params, & netgraph, None , max_htlc_msat + 1 ,
6103
+ Arc :: clone ( & logger) , & scorer, & ( ) , & random_seed_bytes) . unwrap ( ) ;
6104
+ assert_eq ! ( route. paths. len( ) , 2 ) ;
6105
+ assert ! ( route. paths[ 0 ] . hops. last( ) . unwrap( ) . fee_msat <= max_htlc_msat) ;
6106
+ assert ! ( route. paths[ 1 ] . hops. last( ) . unwrap( ) . fee_msat <= max_htlc_msat) ;
6107
+ }
6053
6108
}
6054
6109
6055
6110
#[ cfg( all( test, not( feature = "no-std" ) ) ) ]
0 commit comments