@@ -285,7 +285,7 @@ impl KeyProvider {
285
285
}
286
286
287
287
#[ inline]
288
- fn check_api_err ( api_err : APIError ) {
288
+ fn check_api_err ( api_err : APIError , sendable_bounds_violated : bool ) {
289
289
match api_err {
290
290
APIError :: APIMisuseError { .. } => panic ! ( "We can't misuse the API" ) ,
291
291
APIError :: FeeRateTooHigh { .. } => panic ! ( "We can't send too much fee?" ) ,
@@ -296,15 +296,11 @@ fn check_api_err(api_err: APIError) {
296
296
// is probably just stale and you should add new messages here.
297
297
match err. as_str ( ) {
298
298
"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 - " ) => { } ,
306
301
_ => panic ! ( "{}" , err) ,
307
302
}
303
+ assert ! ( sendable_bounds_violated) ;
308
304
} ,
309
305
APIError :: MonitorUpdateInProgress => {
310
306
// We can (obviously) temp-fail a monitor update
@@ -313,17 +309,17 @@ fn check_api_err(api_err: APIError) {
313
309
}
314
310
}
315
311
#[ inline]
316
- fn check_payment_err ( send_err : PaymentSendFailure ) {
312
+ fn check_payment_err ( send_err : PaymentSendFailure , sendable_bounds_violated : bool ) {
317
313
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 ) ,
319
315
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 ) ; } }
321
317
} ,
322
318
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 ) ; }
324
320
} ,
325
321
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 ) ; } }
327
323
} ,
328
324
PaymentSendFailure :: DuplicatePayment => panic ! ( ) ,
329
325
}
@@ -351,6 +347,11 @@ fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, p
351
347
let mut payment_id = [ 0 ; 32 ] ;
352
348
payment_id[ 0 ..8 ] . copy_from_slice ( & payment_idx. to_ne_bytes ( ) ) ;
353
349
* 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 ) ) ;
354
355
if let Err ( err) = source. send_payment_with_route ( & Route {
355
356
paths : vec ! [ Path { hops: vec![ RouteHop {
356
357
pubkey: dest. get_our_node_id( ) ,
@@ -362,9 +363,15 @@ fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, p
362
363
} ] , blinded_tail: None } ] ,
363
364
payment_params : None ,
364
365
} , 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 ) ;
366
367
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
+ }
368
375
}
369
376
#[ inline]
370
377
fn 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
373
380
let mut payment_id = [ 0 ; 32 ] ;
374
381
payment_id[ 0 ..8 ] . copy_from_slice ( & payment_idx. to_ne_bytes ( ) ) ;
375
382
* 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 ;
376
389
if let Err ( err) = source. send_payment_with_route ( & Route {
377
390
paths : vec ! [ Path { hops: vec![ RouteHop {
378
391
pubkey: middle. get_our_node_id( ) ,
379
392
node_features: middle. node_features( ) ,
380
393
short_channel_id: middle_chan_id,
381
394
channel_features: middle. channel_features( ) ,
382
- fee_msat: 50000 ,
395
+ fee_msat: first_hop_fee ,
383
396
cltv_expiry_delta: 100 ,
384
397
} , RouteHop {
385
398
pubkey: dest. get_our_node_id( ) ,
@@ -391,9 +404,16 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
391
404
} ] , blinded_tail: None } ] ,
392
405
payment_params : None ,
393
406
} , 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) ;
395
409
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
+ }
397
417
}
398
418
399
419
#[ inline]
0 commit comments