@@ -47,8 +47,7 @@ use lightning::events::MessageSendEventsProvider;
4747use lightning:: ln:: channel:: FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE ;
4848use lightning:: ln:: channel_state:: ChannelDetails ;
4949use lightning:: ln:: channelmanager:: {
50- ChainParameters , ChannelManager , ChannelManagerReadArgs , PaymentId , PaymentSendFailure ,
51- RecipientOnionFields ,
50+ ChainParameters , ChannelManager , ChannelManagerReadArgs , PaymentId , RecipientOnionFields , Retry ,
5251} ;
5352use lightning:: ln:: functional_test_utils:: * ;
5453use lightning:: ln:: msgs:: {
@@ -58,7 +57,9 @@ use lightning::ln::script::ShutdownScript;
5857use lightning:: ln:: types:: ChannelId ;
5958use lightning:: offers:: invoice:: UnsignedBolt12Invoice ;
6059use lightning:: onion_message:: messenger:: { Destination , MessageRouter , OnionMessagePath } ;
61- use lightning:: routing:: router:: { InFlightHtlcs , Path , Route , RouteHop , RouteParameters , Router } ;
60+ use lightning:: routing:: router:: {
61+ InFlightHtlcs , Path , PaymentParameters , Route , RouteHop , RouteParameters , Router ,
62+ } ;
6263use lightning:: sign:: {
6364 EntropySource , InMemorySigner , KeyMaterial , NodeSigner , Recipient , SignerProvider ,
6465} ;
@@ -82,6 +83,7 @@ use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey}
8283
8384use lightning:: io:: Cursor ;
8485use std:: cmp:: { self , Ordering } ;
86+ use std:: collections:: VecDeque ;
8587use std:: mem;
8688use std:: sync:: atomic;
8789use std:: sync:: { Arc , Mutex } ;
@@ -112,13 +114,18 @@ impl FeeEstimator for FuzzEstimator {
112114 }
113115}
114116
115- struct FuzzRouter { }
117+ struct FuzzRouter {
118+ pub next_routes : Mutex < VecDeque < Route > > ,
119+ }
116120
117121impl Router for FuzzRouter {
118122 fn find_route (
119123 & self , _payer : & PublicKey , _params : & RouteParameters ,
120124 _first_hops : Option < & [ & ChannelDetails ] > , _inflight_htlcs : InFlightHtlcs ,
121125 ) -> Result < Route , msgs:: LightningError > {
126+ if let Some ( route) = self . next_routes . lock ( ) . unwrap ( ) . pop_front ( ) {
127+ return Ok ( route) ;
128+ }
122129 Err ( msgs:: LightningError {
123130 err : String :: from ( "Not implemented" ) ,
124131 action : msgs:: ErrorAction :: IgnoreError ,
@@ -434,6 +441,34 @@ impl KeyProvider {
434441 }
435442}
436443
444+ // Returns a bool indicating whether the payment failed.
445+ #[ inline]
446+ fn check_payment_send_events (
447+ source : & ChanMan , amt : u64 , min_sendable : u64 , max_sendable : u64 ,
448+ ) -> bool {
449+ let mut payment_failed = false ;
450+ let events = source. get_and_clear_pending_events ( ) ;
451+ assert ! ( events. len( ) == 2 || events. len( ) == 0 ) ;
452+ for ev in events {
453+ match ev {
454+ events:: Event :: PaymentPathFailed {
455+ failure : events:: PathFailure :: InitialSend { err } ,
456+ ..
457+ } => {
458+ check_api_err ( err, amt > max_sendable || amt < min_sendable) ;
459+ } ,
460+ events:: Event :: PaymentFailed { .. } => { } ,
461+ _ => panic ! ( ) ,
462+ } ;
463+ payment_failed = true ;
464+ }
465+ // Note that while the max is a strict upper-bound, we can occasionally send substantially
466+ // below the minimum, with some gap which is unusable immediately below the minimum. Thus,
467+ // we don't check against min_value_sendable here.
468+ assert ! ( payment_failed || ( amt <= max_sendable) ) ;
469+ payment_failed
470+ }
471+
437472#[ inline]
438473fn check_api_err ( api_err : APIError , sendable_bounds_violated : bool ) {
439474 match api_err {
@@ -460,34 +495,6 @@ fn check_api_err(api_err: APIError, sendable_bounds_violated: bool) {
460495 } ,
461496 }
462497}
463- #[ inline]
464- fn check_payment_err ( send_err : PaymentSendFailure , sendable_bounds_violated : bool ) {
465- match send_err {
466- PaymentSendFailure :: ParameterError ( api_err) => {
467- check_api_err ( api_err, sendable_bounds_violated)
468- } ,
469- PaymentSendFailure :: PathParameterError ( per_path_results) => {
470- for res in per_path_results {
471- if let Err ( api_err) = res {
472- check_api_err ( api_err, sendable_bounds_violated) ;
473- }
474- }
475- } ,
476- PaymentSendFailure :: AllFailedResendSafe ( per_path_results) => {
477- for api_err in per_path_results {
478- check_api_err ( api_err, sendable_bounds_violated) ;
479- }
480- } ,
481- PaymentSendFailure :: PartialFailure { results, .. } => {
482- for res in results {
483- if let Err ( api_err) = res {
484- check_api_err ( api_err, sendable_bounds_violated) ;
485- }
486- }
487- } ,
488- PaymentSendFailure :: DuplicatePayment => panic ! ( ) ,
489- }
490- }
491498
492499type ChanMan < ' a > = ChannelManager <
493500 Arc < TestChainMonitor > ,
@@ -546,34 +553,36 @@ fn send_payment(
546553 . find ( |chan| chan. short_channel_id == Some ( dest_chan_id) )
547554 . map ( |chan| ( chan. next_outbound_htlc_minimum_msat , chan. next_outbound_htlc_limit_msat ) )
548555 . unwrap_or ( ( 0 , 0 ) ) ;
549- if let Err ( err) = source. send_payment_with_route (
550- Route {
551- paths : vec ! [ Path {
552- hops: vec![ RouteHop {
553- pubkey: dest. get_our_node_id( ) ,
554- node_features: dest. node_features( ) ,
555- short_channel_id: dest_chan_id,
556- channel_features: dest. channel_features( ) ,
557- fee_msat: amt,
558- cltv_expiry_delta: 200 ,
559- maybe_announced_channel: true ,
560- } ] ,
561- blinded_tail: None ,
556+ let mut next_routes = source. router . next_routes . lock ( ) . unwrap ( ) ;
557+ next_routes. push_back ( Route {
558+ paths : vec ! [ Path {
559+ hops: vec![ RouteHop {
560+ pubkey: dest. get_our_node_id( ) ,
561+ node_features: dest. node_features( ) ,
562+ short_channel_id: dest_chan_id,
563+ channel_features: dest. channel_features( ) ,
564+ fee_msat: amt,
565+ cltv_expiry_delta: 200 ,
566+ maybe_announced_channel: true ,
562567 } ] ,
563- route_params : None ,
564- } ,
568+ blinded_tail: None ,
569+ } ] ,
570+ route_params : None ,
571+ } ) ;
572+ let route_params = RouteParameters :: from_payment_params_and_value (
573+ PaymentParameters :: from_node_id ( source. get_our_node_id ( ) , TEST_FINAL_CLTV ) ,
574+ amt,
575+ ) ;
576+ if let Err ( err) = source. send_payment (
565577 payment_hash,
566578 RecipientOnionFields :: secret_only ( payment_secret) ,
567579 PaymentId ( payment_id) ,
580+ route_params,
581+ Retry :: Attempts ( 0 ) ,
568582 ) {
569- check_payment_err ( err, amt > max_value_sendable || amt < min_value_sendable) ;
570- false
583+ panic ! ( "Errored with {:?} on initial payment send" , err) ;
571584 } else {
572- // Note that while the max is a strict upper-bound, we can occasionally send substantially
573- // below the minimum, with some gap which is unusable immediately below the minimum. Thus,
574- // we don't check against min_value_sendable here.
575- assert ! ( amt <= max_value_sendable) ;
576- true
585+ check_payment_send_events ( source, amt, min_value_sendable, max_value_sendable)
577586 }
578587}
579588
@@ -615,54 +624,56 @@ fn send_hop_payment(
615624 . map ( |chan| ( chan. next_outbound_htlc_minimum_msat , chan. next_outbound_htlc_limit_msat ) )
616625 . unwrap_or ( ( 0 , 0 ) ) ;
617626 let first_hop_fee = 50_000 ;
618- if let Err ( err) = source. send_payment_with_route (
619- Route {
620- paths : vec ! [ Path {
621- hops: vec![
622- RouteHop {
623- pubkey: middle. get_our_node_id( ) ,
624- node_features: middle. node_features( ) ,
625- short_channel_id: middle_chan_id,
626- channel_features: middle. channel_features( ) ,
627- fee_msat: first_hop_fee,
628- cltv_expiry_delta: 100 ,
629- maybe_announced_channel: true ,
630- } ,
631- RouteHop {
632- pubkey: dest. get_our_node_id( ) ,
633- node_features: dest. node_features( ) ,
634- short_channel_id: dest_chan_id,
635- channel_features: dest. channel_features( ) ,
636- fee_msat: amt,
637- cltv_expiry_delta: 200 ,
638- maybe_announced_channel: true ,
639- } ,
640- ] ,
641- blinded_tail: None ,
642- } ] ,
643- route_params : None ,
644- } ,
627+ let mut next_routes = source. router . next_routes . lock ( ) . unwrap ( ) ;
628+ next_routes. push_back ( Route {
629+ paths : vec ! [ Path {
630+ hops: vec![
631+ RouteHop {
632+ pubkey: middle. get_our_node_id( ) ,
633+ node_features: middle. node_features( ) ,
634+ short_channel_id: middle_chan_id,
635+ channel_features: middle. channel_features( ) ,
636+ fee_msat: first_hop_fee,
637+ cltv_expiry_delta: 100 ,
638+ maybe_announced_channel: true ,
639+ } ,
640+ RouteHop {
641+ pubkey: dest. get_our_node_id( ) ,
642+ node_features: dest. node_features( ) ,
643+ short_channel_id: dest_chan_id,
644+ channel_features: dest. channel_features( ) ,
645+ fee_msat: amt,
646+ cltv_expiry_delta: 200 ,
647+ maybe_announced_channel: true ,
648+ } ,
649+ ] ,
650+ blinded_tail: None ,
651+ } ] ,
652+ route_params : None ,
653+ } ) ;
654+ let route_params = RouteParameters :: from_payment_params_and_value (
655+ PaymentParameters :: from_node_id ( source. get_our_node_id ( ) , TEST_FINAL_CLTV ) ,
656+ amt,
657+ ) ;
658+ if let Err ( err) = source. send_payment (
645659 payment_hash,
646660 RecipientOnionFields :: secret_only ( payment_secret) ,
647661 PaymentId ( payment_id) ,
662+ route_params,
663+ Retry :: Attempts ( 0 ) ,
648664 ) {
649- let sent_amt = amt + first_hop_fee;
650- check_payment_err ( err, sent_amt < min_value_sendable || sent_amt > max_value_sendable) ;
651- false
665+ panic ! ( "Errored with {:?} on initial payment send" , err) ;
652666 } else {
653- // Note that while the max is a strict upper-bound, we can occasionally send substantially
654- // below the minimum, with some gap which is unusable immediately below the minimum. Thus,
655- // we don't check against min_value_sendable here.
656- assert ! ( amt + first_hop_fee <= max_value_sendable) ;
657- true
667+ let sent_amt = amt + first_hop_fee;
668+ check_payment_send_events ( source, sent_amt, min_value_sendable, max_value_sendable)
658669 }
659670}
660671
661672#[ inline]
662673pub fn do_test < Out : Output > ( data : & [ u8 ] , underlying_out : Out , anchors : bool ) {
663674 let out = SearchingOutput :: new ( underlying_out) ;
664675 let broadcast = Arc :: new ( TestBroadcaster { } ) ;
665- let router = FuzzRouter { } ;
676+ let router = FuzzRouter { next_routes : Mutex :: new ( VecDeque :: new ( ) ) } ;
666677
667678 macro_rules! make_node {
668679 ( $node_id: expr, $fee_estimator: expr) => { {
0 commit comments