6969//! # &self, route: &Route, payment_id: PaymentId
7070//! # ) -> Result<(), PaymentSendFailure> { unimplemented!() }
7171//! # fn abandon_payment(&self, payment_id: PaymentId) { unimplemented!() }
72+ //! # fn inflight_htlcs(&self) -> InFlightHtlcs { unimplemented!() }
7273//! # }
7374//! #
7475//! # struct FakeRouter {}
@@ -289,6 +290,10 @@ pub trait Payer {
289290
290291 /// Signals that no further retries for the given payment will occur.
291292 fn abandon_payment ( & self , payment_id : PaymentId ) ;
293+
294+ /// Construct an [`InFlightHtlcs`] containing information about currently used up liquidity
295+ /// across payments.
296+ fn inflight_htlcs ( & self ) -> InFlightHtlcs ;
292297}
293298
294299/// A trait defining behavior for a [`Router`] implementation that also supports scoring channels
@@ -546,7 +551,7 @@ where
546551
547552 let payer = self . payer . node_id ( ) ;
548553 let first_hops = self . payer . first_hops ( ) ;
549- let inflight_htlcs = self . create_inflight_map ( ) ;
554+ let inflight_htlcs = self . payer . inflight_htlcs ( ) ;
550555 let route = self . router . find_route (
551556 & payer, & params, Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) , inflight_htlcs
552557 ) . map_err ( |e| PaymentError :: Routing ( e) ) ?;
@@ -650,7 +655,7 @@ where
650655
651656 let payer = self . payer . node_id ( ) ;
652657 let first_hops = self . payer . first_hops ( ) ;
653- let inflight_htlcs = self . create_inflight_map ( ) ;
658+ let inflight_htlcs = self . payer . inflight_htlcs ( ) ;
654659
655660 let route = self . router . find_route (
656661 & payer, & params, Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) , inflight_htlcs
@@ -709,23 +714,6 @@ where
709714 pub fn remove_cached_payment ( & self , payment_hash : & PaymentHash ) {
710715 self . payment_cache . lock ( ) . unwrap ( ) . remove ( payment_hash) ;
711716 }
712-
713- /// Use path information in the payment_cache to construct a HashMap mapping a channel's short
714- /// channel id and direction to the amount being sent through it.
715- ///
716- /// This function should be called whenever we need information about currently used up liquidity
717- /// across payments.
718- fn create_inflight_map ( & self ) -> InFlightHtlcs {
719- let mut total_inflight_map = InFlightHtlcs :: new ( ) ;
720- // Make an attempt at finding existing payment information from `payment_cache`.
721- for payment_info in self . payment_cache . lock ( ) . unwrap ( ) . values ( ) {
722- for path in & payment_info. paths {
723- total_inflight_map. process_path ( path, self . payer . node_id ( ) ) ;
724- }
725- }
726-
727- total_inflight_map
728- }
729717}
730718
731719fn expiry_time_from_unix_epoch ( invoice : & Invoice ) -> Duration {
@@ -870,7 +858,6 @@ mod tests {
870858 use std:: time:: { SystemTime , Duration } ;
871859 use crate :: time_utils:: tests:: SinceEpoch ;
872860 use crate :: DEFAULT_EXPIRY_TIME ;
873- use lightning:: util:: errors:: APIError :: { ChannelUnavailable , MonitorUpdateInProgress } ;
874861
875862 fn invoice ( payment_preimage : PaymentPreimage ) -> Invoice {
876863 let payment_hash = Sha256 :: hash ( & payment_preimage. 0 ) ;
@@ -1590,66 +1577,17 @@ mod tests {
15901577 }
15911578
15921579 #[ test]
1593- fn generates_correct_inflight_map_data ( ) {
1594- let event_handled = core:: cell:: RefCell :: new ( false ) ;
1595- let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
1596-
1597- let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1598- let invoice = invoice ( payment_preimage) ;
1599- let payment_hash = Some ( PaymentHash ( invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
1600- let final_value_msat = invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1601-
1602- let payer = TestPayer :: new ( ) . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1603- let final_value_msat = invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1604- let route = TestRouter :: route_for_value ( final_value_msat) ;
1605- let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1606- let logger = TestLogger :: new ( ) ;
1607- let invoice_payer =
1608- InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1609-
1610- let payment_id = invoice_payer. pay_invoice ( & invoice) . unwrap ( ) ;
1611-
1612- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1613- // First path check
1614- assert_eq ! ( inflight_map. 0 . get( & ( 0 , false ) ) . unwrap( ) . clone( ) , 94 ) ;
1615- assert_eq ! ( inflight_map. 0 . get( & ( 1 , true ) ) . unwrap( ) . clone( ) , 84 ) ;
1616- assert_eq ! ( inflight_map. 0 . get( & ( 2 , false ) ) . unwrap( ) . clone( ) , 64 ) ;
1617-
1618- // Second path check
1619- assert_eq ! ( inflight_map. 0 . get( & ( 3 , false ) ) . unwrap( ) . clone( ) , 74 ) ;
1620- assert_eq ! ( inflight_map. 0 . get( & ( 4 , false ) ) . unwrap( ) . clone( ) , 64 ) ;
1621-
1622- invoice_payer. handle_event ( Event :: PaymentPathSuccessful {
1623- payment_id, payment_hash, path : route. paths [ 0 ] . clone ( )
1624- } ) ;
1625-
1626- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1627-
1628- assert_eq ! ( inflight_map. 0 . get( & ( 0 , false ) ) , None ) ;
1629- assert_eq ! ( inflight_map. 0 . get( & ( 1 , true ) ) , None ) ;
1630- assert_eq ! ( inflight_map. 0 . get( & ( 2 , false ) ) , None ) ;
1631-
1632- // Second path should still be inflight
1633- assert_eq ! ( inflight_map. 0 . get( & ( 3 , false ) ) . unwrap( ) . clone( ) , 74 ) ;
1634- assert_eq ! ( inflight_map. 0 . get( & ( 4 , false ) ) . unwrap( ) . clone( ) , 64 )
1635- }
1636-
1637- #[ test]
1638- fn considers_inflight_htlcs_between_invoice_payments_when_path_succeeds ( ) {
1639- // First, let's just send a payment through, but only make sure one of the path completes
1580+ fn considers_inflight_htlcs_between_invoice_payments ( ) {
16401581 let event_handled = core:: cell:: RefCell :: new ( false ) ;
16411582 let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
16421583
16431584 let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
16441585 let payment_invoice = invoice ( payment_preimage) ;
1645- let payment_hash = Some ( PaymentHash ( payment_invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
16461586 let final_value_msat = payment_invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
16471587
16481588 let payer = TestPayer :: new ( )
16491589 . expect_send ( Amount :: ForInvoice ( final_value_msat) )
16501590 . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1651- let final_value_msat = payment_invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1652- let route = TestRouter :: route_for_value ( final_value_msat) ;
16531591 let scorer = TestScorer :: new ( )
16541592 // 1st invoice, 1st path
16551593 . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
@@ -1659,9 +1597,9 @@ mod tests {
16591597 . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
16601598 . expect_usage ( ChannelUsage { amount_msat : 74 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
16611599 // 2nd invoice, 1st path
1662- . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1663- . expect_usage ( ChannelUsage { amount_msat : 84 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1664- . expect_usage ( ChannelUsage { amount_msat : 94 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1600+ . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 64 , effective_capacity : EffectiveCapacity :: Unknown } )
1601+ . expect_usage ( ChannelUsage { amount_msat : 84 , inflight_htlc_msat : 84 , effective_capacity : EffectiveCapacity :: Unknown } )
1602+ . expect_usage ( ChannelUsage { amount_msat : 94 , inflight_htlc_msat : 94 , effective_capacity : EffectiveCapacity :: Unknown } )
16651603 // 2nd invoice, 2nd path
16661604 . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 64 , effective_capacity : EffectiveCapacity :: Unknown } )
16671605 . expect_usage ( ChannelUsage { amount_msat : 74 , inflight_htlc_msat : 74 , effective_capacity : EffectiveCapacity :: Unknown } ) ;
@@ -1670,16 +1608,12 @@ mod tests {
16701608 let invoice_payer =
16711609 InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
16721610
1673- // Succeed 1st path, leave 2nd path inflight
1674- let payment_id = invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ;
1675- invoice_payer. handle_event ( Event :: PaymentPathSuccessful {
1676- payment_id, payment_hash, path : route. paths [ 0 ] . clone ( )
1677- } ) ;
1611+ // Make first invoice payment.
1612+ invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ;
16781613
16791614 // Let's pay a second invoice that will be using the same path. This should trigger the
1680- // assertions that expect the last 4 ChannelUsage values above where TestScorer is initialized.
1681- // Particularly, the 2nd path of the 1st payment, since it is not yet complete, should still
1682- // have 64 msats inflight for paths considering the channel with scid of 1.
1615+ // assertions that expect `ChannelUsage` values of the first invoice payment that is still
1616+ // in-flight.
16831617 let payment_preimage_2 = PaymentPreimage ( [ 2 ; 32 ] ) ;
16841618 let payment_invoice_2 = invoice ( payment_preimage_2) ;
16851619 invoice_payer. pay_invoice ( & payment_invoice_2) . unwrap ( ) ;
@@ -1730,6 +1664,7 @@ mod tests {
17301664
17311665 // Fail 1st path, leave 2nd path inflight
17321666 let payment_id = Some ( invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ) ;
1667+ invoice_payer. payer . fail_path ( & TestRouter :: path_for_value ( final_value_msat) ) ;
17331668 invoice_payer. handle_event ( Event :: PaymentPathFailed {
17341669 payment_id,
17351670 payment_hash,
@@ -1742,6 +1677,7 @@ mod tests {
17421677 } ) ;
17431678
17441679 // Fails again the 1st path of our retry
1680+ invoice_payer. payer . fail_path ( & TestRouter :: path_for_value ( final_value_msat / 2 ) ) ;
17451681 invoice_payer. handle_event ( Event :: PaymentPathFailed {
17461682 payment_id,
17471683 payment_hash,
@@ -1757,67 +1693,6 @@ mod tests {
17571693 } ) ;
17581694 }
17591695
1760- #[ test]
1761- fn accounts_for_some_inflight_htlcs_sent_during_partial_failure ( ) {
1762- let event_handled = core:: cell:: RefCell :: new ( false ) ;
1763- let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
1764-
1765- let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1766- let invoice_to_pay = invoice ( payment_preimage) ;
1767- let final_value_msat = invoice_to_pay. amount_milli_satoshis ( ) . unwrap ( ) ;
1768-
1769- let retry = TestRouter :: retry_for_invoice ( & invoice_to_pay) ;
1770- let payer = TestPayer :: new ( )
1771- . fails_with_partial_failure (
1772- retry. clone ( ) , OnAttempt ( 1 ) ,
1773- Some ( vec ! [
1774- Err ( ChannelUnavailable { err: "abc" . to_string( ) } ) , Err ( MonitorUpdateInProgress )
1775- ] ) )
1776- . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1777-
1778- let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1779- let logger = TestLogger :: new ( ) ;
1780- let invoice_payer =
1781- InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1782-
1783- invoice_payer. pay_invoice ( & invoice_to_pay) . unwrap ( ) ;
1784- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1785-
1786- // Only the second path, which failed with `MonitorUpdateInProgress` should be added to our
1787- // inflight map because retries are disabled.
1788- assert_eq ! ( inflight_map. 0 . len( ) , 2 ) ;
1789- }
1790-
1791- #[ test]
1792- fn accounts_for_all_inflight_htlcs_sent_during_partial_failure ( ) {
1793- let event_handled = core:: cell:: RefCell :: new ( false ) ;
1794- let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
1795-
1796- let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1797- let invoice_to_pay = invoice ( payment_preimage) ;
1798- let final_value_msat = invoice_to_pay. amount_milli_satoshis ( ) . unwrap ( ) ;
1799-
1800- let retry = TestRouter :: retry_for_invoice ( & invoice_to_pay) ;
1801- let payer = TestPayer :: new ( )
1802- . fails_with_partial_failure (
1803- retry. clone ( ) , OnAttempt ( 1 ) ,
1804- Some ( vec ! [
1805- Ok ( ( ) ) , Err ( MonitorUpdateInProgress )
1806- ] ) )
1807- . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1808-
1809- let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1810- let logger = TestLogger :: new ( ) ;
1811- let invoice_payer =
1812- InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1813-
1814- invoice_payer. pay_invoice ( & invoice_to_pay) . unwrap ( ) ;
1815- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1816-
1817- // All paths successful, hence we check of the existence of all 5 hops.
1818- assert_eq ! ( inflight_map. 0 . len( ) , 5 ) ;
1819- }
1820-
18211696 struct TestRouter {
18221697 scorer : RefCell < TestScorer > ,
18231698 }
@@ -2105,6 +1980,7 @@ mod tests {
21051980 expectations : core:: cell:: RefCell < VecDeque < Amount > > ,
21061981 attempts : core:: cell:: RefCell < usize > ,
21071982 failing_on_attempt : core:: cell:: RefCell < HashMap < usize , PaymentSendFailure > > ,
1983+ inflight_htlcs_paths : core:: cell:: RefCell < Vec < Vec < RouteHop > > > ,
21081984 }
21091985
21101986 #[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -2122,6 +1998,7 @@ mod tests {
21221998 expectations : core:: cell:: RefCell :: new ( VecDeque :: new ( ) ) ,
21231999 attempts : core:: cell:: RefCell :: new ( 0 ) ,
21242000 failing_on_attempt : core:: cell:: RefCell :: new ( HashMap :: new ( ) ) ,
2001+ inflight_htlcs_paths : core:: cell:: RefCell :: new ( Vec :: new ( ) ) ,
21252002 }
21262003 }
21272004
@@ -2166,6 +2043,20 @@ mod tests {
21662043 panic ! ( "Unexpected amount: {:?}" , actual_value_msats) ;
21672044 }
21682045 }
2046+
2047+ fn track_inflight_htlcs ( & self , route : & Route ) {
2048+ for path in & route. paths {
2049+ self . inflight_htlcs_paths . borrow_mut ( ) . push ( path. clone ( ) ) ;
2050+ }
2051+ }
2052+
2053+ fn fail_path ( & self , path : & Vec < RouteHop > ) {
2054+ let path_idx = self . inflight_htlcs_paths . borrow ( ) . iter ( ) . position ( |p| p == path) ;
2055+
2056+ if let Some ( idx) = path_idx {
2057+ self . inflight_htlcs_paths . borrow_mut ( ) . swap_remove ( idx) ;
2058+ }
2059+ }
21692060 }
21702061
21712062 impl Drop for TestPayer {
@@ -2195,6 +2086,7 @@ mod tests {
21952086 _payment_secret : & Option < PaymentSecret > , _payment_id : PaymentId ,
21962087 ) -> Result < ( ) , PaymentSendFailure > {
21972088 self . check_value_msats ( Amount :: ForInvoice ( route. get_total_amount ( ) ) ) ;
2089+ self . track_inflight_htlcs ( route) ;
21982090 self . check_attempts ( )
21992091 }
22002092
@@ -2209,10 +2101,19 @@ mod tests {
22092101 & self , route : & Route , _payment_id : PaymentId
22102102 ) -> Result < ( ) , PaymentSendFailure > {
22112103 self . check_value_msats ( Amount :: OnRetry ( route. get_total_amount ( ) ) ) ;
2104+ self . track_inflight_htlcs ( route) ;
22122105 self . check_attempts ( )
22132106 }
22142107
22152108 fn abandon_payment ( & self , _payment_id : PaymentId ) { }
2109+
2110+ fn inflight_htlcs ( & self ) -> InFlightHtlcs {
2111+ let mut inflight_htlcs = InFlightHtlcs :: new ( ) ;
2112+ for path in self . inflight_htlcs_paths . clone ( ) . into_inner ( ) {
2113+ inflight_htlcs. process_path ( & path, self . node_id ( ) ) ;
2114+ }
2115+ inflight_htlcs
2116+ }
22162117 }
22172118
22182119 // *** Full Featured Functional Tests with a Real ChannelManager ***
0 commit comments