69
69
//! # &self, route: &Route, payment_id: PaymentId
70
70
//! # ) -> Result<(), PaymentSendFailure> { unimplemented!() }
71
71
//! # fn abandon_payment(&self, payment_id: PaymentId) { unimplemented!() }
72
+ //! # fn inflight_htlcs(&self) -> InFlightHtlcs { unimplemented!() }
72
73
//! # }
73
74
//! #
74
75
//! # struct FakeRouter {}
@@ -289,6 +290,10 @@ pub trait Payer {
289
290
290
291
/// Signals that no further retries for the given payment will occur.
291
292
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 ;
292
297
}
293
298
294
299
/// A trait defining behavior for a [`Router`] implementation that also supports scoring channels
@@ -546,7 +551,7 @@ where
546
551
547
552
let payer = self . payer . node_id ( ) ;
548
553
let first_hops = self . payer . first_hops ( ) ;
549
- let inflight_htlcs = self . create_inflight_map ( ) ;
554
+ let inflight_htlcs = self . payer . inflight_htlcs ( ) ;
550
555
let route = self . router . find_route (
551
556
& payer, & params, Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) , inflight_htlcs
552
557
) . map_err ( |e| PaymentError :: Routing ( e) ) ?;
@@ -650,7 +655,7 @@ where
650
655
651
656
let payer = self . payer . node_id ( ) ;
652
657
let first_hops = self . payer . first_hops ( ) ;
653
- let inflight_htlcs = self . create_inflight_map ( ) ;
658
+ let inflight_htlcs = self . payer . inflight_htlcs ( ) ;
654
659
655
660
let route = self . router . find_route (
656
661
& payer, & params, Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) , inflight_htlcs
@@ -709,23 +714,6 @@ where
709
714
pub fn remove_cached_payment ( & self , payment_hash : & PaymentHash ) {
710
715
self . payment_cache . lock ( ) . unwrap ( ) . remove ( payment_hash) ;
711
716
}
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
- }
729
717
}
730
718
731
719
fn expiry_time_from_unix_epoch ( invoice : & Invoice ) -> Duration {
@@ -870,7 +858,6 @@ mod tests {
870
858
use std:: time:: { SystemTime , Duration } ;
871
859
use crate :: time_utils:: tests:: SinceEpoch ;
872
860
use crate :: DEFAULT_EXPIRY_TIME ;
873
- use lightning:: util:: errors:: APIError :: { ChannelUnavailable , MonitorUpdateInProgress } ;
874
861
875
862
fn invoice ( payment_preimage : PaymentPreimage ) -> Invoice {
876
863
let payment_hash = Sha256 :: hash ( & payment_preimage. 0 ) ;
@@ -1590,66 +1577,17 @@ mod tests {
1590
1577
}
1591
1578
1592
1579
#[ 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 ( ) {
1640
1581
let event_handled = core:: cell:: RefCell :: new ( false ) ;
1641
1582
let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
1642
1583
1643
1584
let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1644
1585
let payment_invoice = invoice ( payment_preimage) ;
1645
- let payment_hash = Some ( PaymentHash ( payment_invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
1646
1586
let final_value_msat = payment_invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1647
1587
1648
1588
let payer = TestPayer :: new ( )
1649
1589
. expect_send ( Amount :: ForInvoice ( final_value_msat) )
1650
1590
. 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) ;
1653
1591
let scorer = TestScorer :: new ( )
1654
1592
// 1st invoice, 1st path
1655
1593
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
@@ -1659,9 +1597,9 @@ mod tests {
1659
1597
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1660
1598
. expect_usage ( ChannelUsage { amount_msat : 74 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1661
1599
// 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 } )
1665
1603
// 2nd invoice, 2nd path
1666
1604
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 64 , effective_capacity : EffectiveCapacity :: Unknown } )
1667
1605
. expect_usage ( ChannelUsage { amount_msat : 74 , inflight_htlc_msat : 74 , effective_capacity : EffectiveCapacity :: Unknown } ) ;
@@ -1670,16 +1608,12 @@ mod tests {
1670
1608
let invoice_payer =
1671
1609
InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1672
1610
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 ( ) ;
1678
1613
1679
1614
// 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.
1683
1617
let payment_preimage_2 = PaymentPreimage ( [ 2 ; 32 ] ) ;
1684
1618
let payment_invoice_2 = invoice ( payment_preimage_2) ;
1685
1619
invoice_payer. pay_invoice ( & payment_invoice_2) . unwrap ( ) ;
@@ -1730,6 +1664,7 @@ mod tests {
1730
1664
1731
1665
// Fail 1st path, leave 2nd path inflight
1732
1666
let payment_id = Some ( invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ) ;
1667
+ invoice_payer. payer . fail_path ( & TestRouter :: path_for_value ( final_value_msat) ) ;
1733
1668
invoice_payer. handle_event ( Event :: PaymentPathFailed {
1734
1669
payment_id,
1735
1670
payment_hash,
@@ -1742,6 +1677,7 @@ mod tests {
1742
1677
} ) ;
1743
1678
1744
1679
// Fails again the 1st path of our retry
1680
+ invoice_payer. payer . fail_path ( & TestRouter :: path_for_value ( final_value_msat / 2 ) ) ;
1745
1681
invoice_payer. handle_event ( Event :: PaymentPathFailed {
1746
1682
payment_id,
1747
1683
payment_hash,
@@ -1757,67 +1693,6 @@ mod tests {
1757
1693
} ) ;
1758
1694
}
1759
1695
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
-
1821
1696
struct TestRouter {
1822
1697
scorer : RefCell < TestScorer > ,
1823
1698
}
@@ -2105,6 +1980,7 @@ mod tests {
2105
1980
expectations : core:: cell:: RefCell < VecDeque < Amount > > ,
2106
1981
attempts : core:: cell:: RefCell < usize > ,
2107
1982
failing_on_attempt : core:: cell:: RefCell < HashMap < usize , PaymentSendFailure > > ,
1983
+ inflight_htlcs_paths : core:: cell:: RefCell < Vec < Vec < RouteHop > > > ,
2108
1984
}
2109
1985
2110
1986
#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -2122,6 +1998,7 @@ mod tests {
2122
1998
expectations : core:: cell:: RefCell :: new ( VecDeque :: new ( ) ) ,
2123
1999
attempts : core:: cell:: RefCell :: new ( 0 ) ,
2124
2000
failing_on_attempt : core:: cell:: RefCell :: new ( HashMap :: new ( ) ) ,
2001
+ inflight_htlcs_paths : core:: cell:: RefCell :: new ( Vec :: new ( ) ) ,
2125
2002
}
2126
2003
}
2127
2004
@@ -2166,6 +2043,20 @@ mod tests {
2166
2043
panic ! ( "Unexpected amount: {:?}" , actual_value_msats) ;
2167
2044
}
2168
2045
}
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
+ }
2169
2060
}
2170
2061
2171
2062
impl Drop for TestPayer {
@@ -2195,6 +2086,7 @@ mod tests {
2195
2086
_payment_secret : & Option < PaymentSecret > , _payment_id : PaymentId ,
2196
2087
) -> Result < ( ) , PaymentSendFailure > {
2197
2088
self . check_value_msats ( Amount :: ForInvoice ( route. get_total_amount ( ) ) ) ;
2089
+ self . track_inflight_htlcs ( route) ;
2198
2090
self . check_attempts ( )
2199
2091
}
2200
2092
@@ -2209,10 +2101,19 @@ mod tests {
2209
2101
& self , route : & Route , _payment_id : PaymentId
2210
2102
) -> Result < ( ) , PaymentSendFailure > {
2211
2103
self . check_value_msats ( Amount :: OnRetry ( route. get_total_amount ( ) ) ) ;
2104
+ self . track_inflight_htlcs ( route) ;
2212
2105
self . check_attempts ( )
2213
2106
}
2214
2107
2215
2108
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
+ }
2216
2117
}
2217
2118
2218
2119
// *** Full Featured Functional Tests with a Real ChannelManager ***
0 commit comments