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) ) ?;
@@ -649,7 +654,7 @@ where
649
654
650
655
let payer = self . payer . node_id ( ) ;
651
656
let first_hops = self . payer . first_hops ( ) ;
652
- let inflight_htlcs = self . create_inflight_map ( ) ;
657
+ let inflight_htlcs = self . payer . inflight_htlcs ( ) ;
653
658
654
659
let route = self . router . find_route (
655
660
& payer, & params, Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) , inflight_htlcs
@@ -704,23 +709,6 @@ where
704
709
pub fn remove_cached_payment ( & self , payment_hash : & PaymentHash ) {
705
710
self . payment_cache . lock ( ) . unwrap ( ) . remove ( payment_hash) ;
706
711
}
707
-
708
- /// Use path information in the payment_cache to construct a HashMap mapping a channel's short
709
- /// channel id and direction to the amount being sent through it.
710
- ///
711
- /// This function should be called whenever we need information about currently used up liquidity
712
- /// across payments.
713
- fn create_inflight_map ( & self ) -> InFlightHtlcs {
714
- let mut total_inflight_map = InFlightHtlcs :: new ( ) ;
715
- // Make an attempt at finding existing payment information from `payment_cache`.
716
- for payment_info in self . payment_cache . lock ( ) . unwrap ( ) . values ( ) {
717
- for path in & payment_info. paths {
718
- total_inflight_map. process_path ( path, self . payer . node_id ( ) ) ;
719
- }
720
- }
721
-
722
- total_inflight_map
723
- }
724
712
}
725
713
726
714
fn expiry_time_from_unix_epoch ( invoice : & Invoice ) -> Duration {
@@ -865,7 +853,6 @@ mod tests {
865
853
use std:: time:: { SystemTime , Duration } ;
866
854
use crate :: time_utils:: tests:: SinceEpoch ;
867
855
use crate :: DEFAULT_EXPIRY_TIME ;
868
- use lightning:: util:: errors:: APIError :: { ChannelUnavailable , MonitorUpdateInProgress } ;
869
856
870
857
fn invoice ( payment_preimage : PaymentPreimage ) -> Invoice {
871
858
let payment_hash = Sha256 :: hash ( & payment_preimage. 0 ) ;
@@ -1585,66 +1572,17 @@ mod tests {
1585
1572
}
1586
1573
1587
1574
#[ test]
1588
- fn generates_correct_inflight_map_data ( ) {
1589
- let event_handled = core:: cell:: RefCell :: new ( false ) ;
1590
- let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
1591
-
1592
- let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1593
- let invoice = invoice ( payment_preimage) ;
1594
- let payment_hash = Some ( PaymentHash ( invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
1595
- let final_value_msat = invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1596
-
1597
- let payer = TestPayer :: new ( ) . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1598
- let final_value_msat = invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1599
- let route = TestRouter :: route_for_value ( final_value_msat) ;
1600
- let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1601
- let logger = TestLogger :: new ( ) ;
1602
- let invoice_payer =
1603
- InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1604
-
1605
- let payment_id = invoice_payer. pay_invoice ( & invoice) . unwrap ( ) ;
1606
-
1607
- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1608
- // First path check
1609
- assert_eq ! ( inflight_map. 0 . get( & ( 0 , false ) ) . unwrap( ) . clone( ) , 94 ) ;
1610
- assert_eq ! ( inflight_map. 0 . get( & ( 1 , true ) ) . unwrap( ) . clone( ) , 84 ) ;
1611
- assert_eq ! ( inflight_map. 0 . get( & ( 2 , false ) ) . unwrap( ) . clone( ) , 64 ) ;
1612
-
1613
- // Second path check
1614
- assert_eq ! ( inflight_map. 0 . get( & ( 3 , false ) ) . unwrap( ) . clone( ) , 74 ) ;
1615
- assert_eq ! ( inflight_map. 0 . get( & ( 4 , false ) ) . unwrap( ) . clone( ) , 64 ) ;
1616
-
1617
- invoice_payer. handle_event ( Event :: PaymentPathSuccessful {
1618
- payment_id, payment_hash, path : route. paths [ 0 ] . clone ( )
1619
- } ) ;
1620
-
1621
- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1622
-
1623
- assert_eq ! ( inflight_map. 0 . get( & ( 0 , false ) ) , None ) ;
1624
- assert_eq ! ( inflight_map. 0 . get( & ( 1 , true ) ) , None ) ;
1625
- assert_eq ! ( inflight_map. 0 . get( & ( 2 , false ) ) , None ) ;
1626
-
1627
- // Second path should still be inflight
1628
- assert_eq ! ( inflight_map. 0 . get( & ( 3 , false ) ) . unwrap( ) . clone( ) , 74 ) ;
1629
- assert_eq ! ( inflight_map. 0 . get( & ( 4 , false ) ) . unwrap( ) . clone( ) , 64 )
1630
- }
1631
-
1632
- #[ test]
1633
- fn considers_inflight_htlcs_between_invoice_payments_when_path_succeeds ( ) {
1634
- // First, let's just send a payment through, but only make sure one of the path completes
1575
+ fn considers_inflight_htlcs_between_invoice_payments ( ) {
1635
1576
let event_handled = core:: cell:: RefCell :: new ( false ) ;
1636
1577
let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
1637
1578
1638
1579
let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1639
1580
let payment_invoice = invoice ( payment_preimage) ;
1640
- let payment_hash = Some ( PaymentHash ( payment_invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
1641
1581
let final_value_msat = payment_invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1642
1582
1643
1583
let payer = TestPayer :: new ( )
1644
1584
. expect_send ( Amount :: ForInvoice ( final_value_msat) )
1645
1585
. expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1646
- let final_value_msat = payment_invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1647
- let route = TestRouter :: route_for_value ( final_value_msat) ;
1648
1586
let scorer = TestScorer :: new ( )
1649
1587
// 1st invoice, 1st path
1650
1588
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
@@ -1654,9 +1592,9 @@ mod tests {
1654
1592
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1655
1593
. expect_usage ( ChannelUsage { amount_msat : 74 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1656
1594
// 2nd invoice, 1st path
1657
- . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1658
- . expect_usage ( ChannelUsage { amount_msat : 84 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1659
- . expect_usage ( ChannelUsage { amount_msat : 94 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1595
+ . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 64 , effective_capacity : EffectiveCapacity :: Unknown } )
1596
+ . expect_usage ( ChannelUsage { amount_msat : 84 , inflight_htlc_msat : 84 , effective_capacity : EffectiveCapacity :: Unknown } )
1597
+ . expect_usage ( ChannelUsage { amount_msat : 94 , inflight_htlc_msat : 94 , effective_capacity : EffectiveCapacity :: Unknown } )
1660
1598
// 2nd invoice, 2nd path
1661
1599
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 64 , effective_capacity : EffectiveCapacity :: Unknown } )
1662
1600
. expect_usage ( ChannelUsage { amount_msat : 74 , inflight_htlc_msat : 74 , effective_capacity : EffectiveCapacity :: Unknown } ) ;
@@ -1665,16 +1603,12 @@ mod tests {
1665
1603
let invoice_payer =
1666
1604
InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1667
1605
1668
- // Succeed 1st path, leave 2nd path inflight
1669
- let payment_id = invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ;
1670
- invoice_payer. handle_event ( Event :: PaymentPathSuccessful {
1671
- payment_id, payment_hash, path : route. paths [ 0 ] . clone ( )
1672
- } ) ;
1606
+ // Make first invoice payment.
1607
+ invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ;
1673
1608
1674
1609
// Let's pay a second invoice that will be using the same path. This should trigger the
1675
- // assertions that expect the last 4 ChannelUsage values above where TestScorer is initialized.
1676
- // Particularly, the 2nd path of the 1st payment, since it is not yet complete, should still
1677
- // have 64 msats inflight for paths considering the channel with scid of 1.
1610
+ // assertions that expect `ChannelUsage` values of the first invoice payment that is still
1611
+ // in-flight.
1678
1612
let payment_preimage_2 = PaymentPreimage ( [ 2 ; 32 ] ) ;
1679
1613
let payment_invoice_2 = invoice ( payment_preimage_2) ;
1680
1614
invoice_payer. pay_invoice ( & payment_invoice_2) . unwrap ( ) ;
@@ -1725,6 +1659,7 @@ mod tests {
1725
1659
1726
1660
// Fail 1st path, leave 2nd path inflight
1727
1661
let payment_id = Some ( invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ) ;
1662
+ invoice_payer. payer . fail_path ( & TestRouter :: path_for_value ( final_value_msat) ) ;
1728
1663
invoice_payer. handle_event ( Event :: PaymentPathFailed {
1729
1664
payment_id,
1730
1665
payment_hash,
@@ -1737,6 +1672,7 @@ mod tests {
1737
1672
} ) ;
1738
1673
1739
1674
// Fails again the 1st path of our retry
1675
+ invoice_payer. payer . fail_path ( & TestRouter :: path_for_value ( final_value_msat / 2 ) ) ;
1740
1676
invoice_payer. handle_event ( Event :: PaymentPathFailed {
1741
1677
payment_id,
1742
1678
payment_hash,
@@ -1752,67 +1688,6 @@ mod tests {
1752
1688
} ) ;
1753
1689
}
1754
1690
1755
- #[ test]
1756
- fn accounts_for_some_inflight_htlcs_sent_during_partial_failure ( ) {
1757
- let event_handled = core:: cell:: RefCell :: new ( false ) ;
1758
- let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
1759
-
1760
- let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1761
- let invoice_to_pay = invoice ( payment_preimage) ;
1762
- let final_value_msat = invoice_to_pay. amount_milli_satoshis ( ) . unwrap ( ) ;
1763
-
1764
- let retry = TestRouter :: retry_for_invoice ( & invoice_to_pay) ;
1765
- let payer = TestPayer :: new ( )
1766
- . fails_with_partial_failure (
1767
- retry. clone ( ) , OnAttempt ( 1 ) ,
1768
- Some ( vec ! [
1769
- Err ( ChannelUnavailable { err: "abc" . to_string( ) } ) , Err ( MonitorUpdateInProgress )
1770
- ] ) )
1771
- . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1772
-
1773
- let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1774
- let logger = TestLogger :: new ( ) ;
1775
- let invoice_payer =
1776
- InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1777
-
1778
- invoice_payer. pay_invoice ( & invoice_to_pay) . unwrap ( ) ;
1779
- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1780
-
1781
- // Only the second path, which failed with `MonitorUpdateInProgress` should be added to our
1782
- // inflight map because retries are disabled.
1783
- assert_eq ! ( inflight_map. 0 . len( ) , 2 ) ;
1784
- }
1785
-
1786
- #[ test]
1787
- fn accounts_for_all_inflight_htlcs_sent_during_partial_failure ( ) {
1788
- let event_handled = core:: cell:: RefCell :: new ( false ) ;
1789
- let event_handler = |_: Event | { * event_handled. borrow_mut ( ) = true ; } ;
1790
-
1791
- let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1792
- let invoice_to_pay = invoice ( payment_preimage) ;
1793
- let final_value_msat = invoice_to_pay. amount_milli_satoshis ( ) . unwrap ( ) ;
1794
-
1795
- let retry = TestRouter :: retry_for_invoice ( & invoice_to_pay) ;
1796
- let payer = TestPayer :: new ( )
1797
- . fails_with_partial_failure (
1798
- retry. clone ( ) , OnAttempt ( 1 ) ,
1799
- Some ( vec ! [
1800
- Ok ( ( ) ) , Err ( MonitorUpdateInProgress )
1801
- ] ) )
1802
- . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1803
-
1804
- let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1805
- let logger = TestLogger :: new ( ) ;
1806
- let invoice_payer =
1807
- InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1808
-
1809
- invoice_payer. pay_invoice ( & invoice_to_pay) . unwrap ( ) ;
1810
- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1811
-
1812
- // All paths successful, hence we check of the existence of all 5 hops.
1813
- assert_eq ! ( inflight_map. 0 . len( ) , 5 ) ;
1814
- }
1815
-
1816
1691
struct TestRouter {
1817
1692
scorer : RefCell < TestScorer > ,
1818
1693
}
@@ -2100,6 +1975,7 @@ mod tests {
2100
1975
expectations : core:: cell:: RefCell < VecDeque < Amount > > ,
2101
1976
attempts : core:: cell:: RefCell < usize > ,
2102
1977
failing_on_attempt : core:: cell:: RefCell < HashMap < usize , PaymentSendFailure > > ,
1978
+ inflight_htlcs_paths : core:: cell:: RefCell < Vec < Vec < RouteHop > > > ,
2103
1979
}
2104
1980
2105
1981
#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -2117,6 +1993,7 @@ mod tests {
2117
1993
expectations : core:: cell:: RefCell :: new ( VecDeque :: new ( ) ) ,
2118
1994
attempts : core:: cell:: RefCell :: new ( 0 ) ,
2119
1995
failing_on_attempt : core:: cell:: RefCell :: new ( HashMap :: new ( ) ) ,
1996
+ inflight_htlcs_paths : core:: cell:: RefCell :: new ( Vec :: new ( ) ) ,
2120
1997
}
2121
1998
}
2122
1999
@@ -2161,6 +2038,20 @@ mod tests {
2161
2038
panic ! ( "Unexpected amount: {:?}" , actual_value_msats) ;
2162
2039
}
2163
2040
}
2041
+
2042
+ fn track_inflight_htlcs ( & self , route : & Route ) {
2043
+ for path in & route. paths {
2044
+ self . inflight_htlcs_paths . borrow_mut ( ) . push ( path. clone ( ) ) ;
2045
+ }
2046
+ }
2047
+
2048
+ fn fail_path ( & self , path : & Vec < RouteHop > ) {
2049
+ let path_idx = self . inflight_htlcs_paths . borrow ( ) . iter ( ) . position ( |p| p == path) ;
2050
+
2051
+ if let Some ( idx) = path_idx {
2052
+ self . inflight_htlcs_paths . borrow_mut ( ) . swap_remove ( idx) ;
2053
+ }
2054
+ }
2164
2055
}
2165
2056
2166
2057
impl Drop for TestPayer {
@@ -2190,6 +2081,7 @@ mod tests {
2190
2081
_payment_secret : & Option < PaymentSecret > , _payment_id : PaymentId ,
2191
2082
) -> Result < ( ) , PaymentSendFailure > {
2192
2083
self . check_value_msats ( Amount :: ForInvoice ( route. get_total_amount ( ) ) ) ;
2084
+ self . track_inflight_htlcs ( route) ;
2193
2085
self . check_attempts ( )
2194
2086
}
2195
2087
@@ -2204,10 +2096,19 @@ mod tests {
2204
2096
& self , route : & Route , _payment_id : PaymentId
2205
2097
) -> Result < ( ) , PaymentSendFailure > {
2206
2098
self . check_value_msats ( Amount :: OnRetry ( route. get_total_amount ( ) ) ) ;
2099
+ self . track_inflight_htlcs ( route) ;
2207
2100
self . check_attempts ( )
2208
2101
}
2209
2102
2210
2103
fn abandon_payment ( & self , _payment_id : PaymentId ) { }
2104
+
2105
+ fn inflight_htlcs ( & self ) -> InFlightHtlcs {
2106
+ let mut inflight_htlcs = InFlightHtlcs :: new ( ) ;
2107
+ for path in self . inflight_htlcs_paths . clone ( ) . into_inner ( ) {
2108
+ inflight_htlcs. process_path ( & path, self . node_id ( ) ) ;
2109
+ }
2110
+ inflight_htlcs
2111
+ }
2211
2112
}
2212
2113
2213
2114
// *** Full Featured Functional Tests with a Real ChannelManager ***
0 commit comments