@@ -285,7 +285,7 @@ impl KeyProvider {
285285}
286286
287287#[ inline]
288- fn check_api_err ( api_err : APIError ) {
288+ fn check_api_err ( api_err : APIError , sendable_bounds_violated : bool ) {
289289 match api_err {
290290 APIError :: APIMisuseError { .. } => panic ! ( "We can't misuse the API" ) ,
291291 APIError :: FeeRateTooHigh { .. } => panic ! ( "We can't send too much fee?" ) ,
@@ -296,15 +296,11 @@ fn check_api_err(api_err: APIError) {
296296 // is probably just stale and you should add new messages here.
297297 match err. as_str ( ) {
298298 "Peer for first hop currently disconnected" => { } ,
299- _ if err. starts_with ( "Cannot push more than their max accepted HTLCs " ) => { } ,
300- _ if err. starts_with ( "Cannot send value that would put us over the max HTLC value in flight our peer will accept " ) => { } ,
301- _ if err. starts_with ( "Cannot send value that would put our balance under counterparty-announced channel reserve value" ) => { } ,
302- _ if err. starts_with ( "Cannot send value that would put counterparty balance under holder-announced channel reserve value" ) => { } ,
303- _ if err. starts_with ( "Cannot send value that would overdraw remaining funds." ) => { } ,
304- _ if err. starts_with ( "Cannot send value that would not leave enough to pay for fees." ) => { } ,
305- _ if err. starts_with ( "Cannot send value that would put our exposure to dust HTLCs at" ) => { } ,
299+ _ if err. starts_with ( "Cannot send less than our next-HTLC minimum - " ) => { } ,
300+ _ if err. starts_with ( "Cannot send more than our next-HTLC maximum - " ) => { } ,
306301 _ => panic ! ( "{}" , err) ,
307302 }
303+ assert ! ( sendable_bounds_violated) ;
308304 } ,
309305 APIError :: MonitorUpdateInProgress => {
310306 // We can (obviously) temp-fail a monitor update
@@ -313,17 +309,17 @@ fn check_api_err(api_err: APIError) {
313309 }
314310}
315311#[ inline]
316- fn check_payment_err ( send_err : PaymentSendFailure ) {
312+ fn check_payment_err ( send_err : PaymentSendFailure , sendable_bounds_violated : bool ) {
317313 match send_err {
318- PaymentSendFailure :: ParameterError ( api_err) => check_api_err ( api_err) ,
314+ PaymentSendFailure :: ParameterError ( api_err) => check_api_err ( api_err, sendable_bounds_violated ) ,
319315 PaymentSendFailure :: PathParameterError ( per_path_results) => {
320- for res in per_path_results { if let Err ( api_err) = res { check_api_err ( api_err) ; } }
316+ for res in per_path_results { if let Err ( api_err) = res { check_api_err ( api_err, sendable_bounds_violated ) ; } }
321317 } ,
322318 PaymentSendFailure :: AllFailedResendSafe ( per_path_results) => {
323- for api_err in per_path_results { check_api_err ( api_err) ; }
319+ for api_err in per_path_results { check_api_err ( api_err, sendable_bounds_violated ) ; }
324320 } ,
325321 PaymentSendFailure :: PartialFailure { results, .. } => {
326- for res in results { if let Err ( api_err) = res { check_api_err ( api_err) ; } }
322+ for res in results { if let Err ( api_err) = res { check_api_err ( api_err, sendable_bounds_violated ) ; } }
327323 } ,
328324 PaymentSendFailure :: DuplicatePayment => panic ! ( ) ,
329325 }
@@ -351,6 +347,11 @@ fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, p
351347 let mut payment_id = [ 0 ; 32 ] ;
352348 payment_id[ 0 ..8 ] . copy_from_slice ( & payment_idx. to_ne_bytes ( ) ) ;
353349 * payment_idx += 1 ;
350+ let ( min_value_sendable, max_value_sendable) = source. list_usable_channels ( )
351+ . iter ( ) . find ( |chan| chan. short_channel_id == Some ( dest_chan_id) )
352+ . map ( |chan|
353+ ( chan. next_outbound_htlc_minimum_msat , chan. next_outbound_htlc_limit_msat ) )
354+ . unwrap_or ( ( 0 , 0 ) ) ;
354355 if let Err ( err) = source. send_payment_with_route ( & Route {
355356 paths : vec ! [ Path { hops: vec![ RouteHop {
356357 pubkey: dest. get_our_node_id( ) ,
@@ -362,9 +363,15 @@ fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, p
362363 } ] , blinded_tail: None } ] ,
363364 payment_params : None ,
364365 } , payment_hash, RecipientOnionFields :: secret_only ( payment_secret) , PaymentId ( payment_id) ) {
365- check_payment_err ( err) ;
366+ check_payment_err ( err, amt > max_value_sendable || amt < min_value_sendable ) ;
366367 false
367- } else { true }
368+ } else {
369+ // Note that while the max is a strict upper-bound, we can occasionally send substantially
370+ // below the minimum, with some gap which is unusable immediately below the minimum. Thus,
371+ // we don't check against min_value_sendable here.
372+ assert ! ( amt <= max_value_sendable) ;
373+ true
374+ }
368375}
369376#[ inline]
370377fn send_hop_payment ( source : & ChanMan , middle : & ChanMan , middle_chan_id : u64 , dest : & ChanMan , dest_chan_id : u64 , amt : u64 , payment_id : & mut u8 , payment_idx : & mut u64 ) -> bool {
@@ -373,13 +380,19 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
373380 let mut payment_id = [ 0 ; 32 ] ;
374381 payment_id[ 0 ..8 ] . copy_from_slice ( & payment_idx. to_ne_bytes ( ) ) ;
375382 * payment_idx += 1 ;
383+ let ( min_value_sendable, max_value_sendable) = source. list_usable_channels ( )
384+ . iter ( ) . find ( |chan| chan. short_channel_id == Some ( middle_chan_id) )
385+ . map ( |chan|
386+ ( chan. next_outbound_htlc_minimum_msat , chan. next_outbound_htlc_limit_msat ) )
387+ . unwrap_or ( ( 0 , 0 ) ) ;
388+ let first_hop_fee = 50_000 ;
376389 if let Err ( err) = source. send_payment_with_route ( & Route {
377390 paths : vec ! [ Path { hops: vec![ RouteHop {
378391 pubkey: middle. get_our_node_id( ) ,
379392 node_features: middle. node_features( ) ,
380393 short_channel_id: middle_chan_id,
381394 channel_features: middle. channel_features( ) ,
382- fee_msat: 50000 ,
395+ fee_msat: first_hop_fee ,
383396 cltv_expiry_delta: 100 ,
384397 } , RouteHop {
385398 pubkey: dest. get_our_node_id( ) ,
@@ -391,9 +404,16 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
391404 } ] , blinded_tail: None } ] ,
392405 payment_params : None ,
393406 } , payment_hash, RecipientOnionFields :: secret_only ( payment_secret) , PaymentId ( payment_id) ) {
394- check_payment_err ( err) ;
407+ let sent_amt = amt + first_hop_fee;
408+ check_payment_err ( err, sent_amt < min_value_sendable || sent_amt > max_value_sendable) ;
395409 false
396- } else { true }
410+ } else {
411+ // Note that while the max is a strict upper-bound, we can occasionally send substantially
412+ // below the minimum, with some gap which is unusable immediately below the minimum. Thus,
413+ // we don't check against min_value_sendable here.
414+ assert ! ( amt + first_hop_fee <= max_value_sendable) ;
415+ true
416+ }
397417}
398418
399419#[ inline]
0 commit comments