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 {}
@@ -276,6 +277,10 @@ pub trait Payer {
276
277
277
278
/// Signals that no further retries for the given payment will occur.
278
279
fn abandon_payment ( & self , payment_id : PaymentId ) ;
280
+
281
+ /// Construct an [`InFlightHtlcs`] containing information about currently used up liquidity
282
+ /// across payments.
283
+ fn inflight_htlcs ( & self ) -> InFlightHtlcs ;
279
284
}
280
285
281
286
/// A trait defining behavior for a [`Router`] implementation that also supports scoring channels
@@ -532,7 +537,7 @@ where
532
537
533
538
let payer = self . payer . node_id ( ) ;
534
539
let first_hops = self . payer . first_hops ( ) ;
535
- let inflight_htlcs = self . create_inflight_map ( ) ;
540
+ let inflight_htlcs = self . payer . inflight_htlcs ( ) ;
536
541
let route = self . router . find_route (
537
542
& payer, & params, Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) , inflight_htlcs
538
543
) . map_err ( |e| PaymentError :: Routing ( e) ) ?;
@@ -635,7 +640,7 @@ where
635
640
636
641
let payer = self . payer . node_id ( ) ;
637
642
let first_hops = self . payer . first_hops ( ) ;
638
- let inflight_htlcs = self . create_inflight_map ( ) ;
643
+ let inflight_htlcs = self . payer . inflight_htlcs ( ) ;
639
644
640
645
let route = self . router . find_route (
641
646
& payer, & params, Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) , inflight_htlcs
@@ -690,23 +695,6 @@ where
690
695
pub fn remove_cached_payment ( & self , payment_hash : & PaymentHash ) {
691
696
self . payment_cache . lock ( ) . unwrap ( ) . remove ( payment_hash) ;
692
697
}
693
-
694
- /// Use path information in the payment_cache to construct a HashMap mapping a channel's short
695
- /// channel id and direction to the amount being sent through it.
696
- ///
697
- /// This function should be called whenever we need information about currently used up liquidity
698
- /// across payments.
699
- fn create_inflight_map ( & self ) -> InFlightHtlcs {
700
- let mut total_inflight_map = InFlightHtlcs :: new ( ) ;
701
- // Make an attempt at finding existing payment information from `payment_cache`.
702
- for payment_info in self . payment_cache . lock ( ) . unwrap ( ) . values ( ) {
703
- for path in & payment_info. paths {
704
- total_inflight_map. process_path ( path, self . payer . node_id ( ) ) ;
705
- }
706
- }
707
-
708
- total_inflight_map
709
- }
710
698
}
711
699
712
700
fn expiry_time_from_unix_epoch ( invoice : & Invoice ) -> Duration {
@@ -818,7 +806,6 @@ mod tests {
818
806
use std:: time:: { SystemTime , Duration } ;
819
807
use crate :: time_utils:: tests:: SinceEpoch ;
820
808
use crate :: DEFAULT_EXPIRY_TIME ;
821
- use lightning:: util:: errors:: APIError :: { ChannelUnavailable , MonitorUpdateInProgress } ;
822
809
823
810
fn invoice ( payment_preimage : PaymentPreimage ) -> Invoice {
824
811
let payment_hash = Sha256 :: hash ( & payment_preimage. 0 ) ;
@@ -1544,20 +1531,17 @@ mod tests {
1544
1531
1545
1532
let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1546
1533
let invoice = invoice ( payment_preimage) ;
1547
- let payment_hash = Some ( PaymentHash ( invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
1548
1534
let final_value_msat = invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1549
1535
1550
1536
let payer = TestPayer :: new ( ) . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1551
- let final_value_msat = invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1552
- let route = TestRouter :: route_for_value ( final_value_msat) ;
1553
1537
let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1554
1538
let logger = TestLogger :: new ( ) ;
1555
1539
let invoice_payer =
1556
1540
InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1557
1541
1558
- let payment_id = invoice_payer. pay_invoice ( & invoice) . unwrap ( ) ;
1542
+ invoice_payer. pay_invoice ( & invoice) . unwrap ( ) ;
1559
1543
1560
- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1544
+ let inflight_map = invoice_payer. payer . inflight_htlcs ( ) ;
1561
1545
// First path check
1562
1546
assert_eq ! ( inflight_map. 0 . get( & ( 0 , false ) ) . unwrap( ) . clone( ) , 94 ) ;
1563
1547
assert_eq ! ( inflight_map. 0 . get( & ( 1 , true ) ) . unwrap( ) . clone( ) , 84 ) ;
@@ -1566,20 +1550,6 @@ mod tests {
1566
1550
// Second path check
1567
1551
assert_eq ! ( inflight_map. 0 . get( & ( 3 , false ) ) . unwrap( ) . clone( ) , 74 ) ;
1568
1552
assert_eq ! ( inflight_map. 0 . get( & ( 4 , false ) ) . unwrap( ) . clone( ) , 64 ) ;
1569
-
1570
- invoice_payer. handle_event ( & Event :: PaymentPathSuccessful {
1571
- payment_id, payment_hash, path : route. paths [ 0 ] . clone ( )
1572
- } ) ;
1573
-
1574
- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1575
-
1576
- assert_eq ! ( inflight_map. 0 . get( & ( 0 , false ) ) , None ) ;
1577
- assert_eq ! ( inflight_map. 0 . get( & ( 1 , true ) ) , None ) ;
1578
- assert_eq ! ( inflight_map. 0 . get( & ( 2 , false ) ) , None ) ;
1579
-
1580
- // Second path should still be inflight
1581
- assert_eq ! ( inflight_map. 0 . get( & ( 3 , false ) ) . unwrap( ) . clone( ) , 74 ) ;
1582
- assert_eq ! ( inflight_map. 0 . get( & ( 4 , false ) ) . unwrap( ) . clone( ) , 64 )
1583
1553
}
1584
1554
1585
1555
#[ test]
@@ -1590,14 +1560,11 @@ mod tests {
1590
1560
1591
1561
let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1592
1562
let payment_invoice = invoice ( payment_preimage) ;
1593
- let payment_hash = Some ( PaymentHash ( payment_invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
1594
1563
let final_value_msat = payment_invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1595
1564
1596
1565
let payer = TestPayer :: new ( )
1597
1566
. expect_send ( Amount :: ForInvoice ( final_value_msat) )
1598
1567
. expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1599
- let final_value_msat = payment_invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1600
- let route = TestRouter :: route_for_value ( final_value_msat) ;
1601
1568
let scorer = TestScorer :: new ( )
1602
1569
// 1st invoice, 1st path
1603
1570
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
@@ -1607,9 +1574,9 @@ mod tests {
1607
1574
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1608
1575
. expect_usage ( ChannelUsage { amount_msat : 74 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1609
1576
// 2nd invoice, 1st path
1610
- . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1611
- . expect_usage ( ChannelUsage { amount_msat : 84 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1612
- . expect_usage ( ChannelUsage { amount_msat : 94 , inflight_htlc_msat : 0 , effective_capacity : EffectiveCapacity :: Unknown } )
1577
+ . expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 64 , effective_capacity : EffectiveCapacity :: Unknown } )
1578
+ . expect_usage ( ChannelUsage { amount_msat : 84 , inflight_htlc_msat : 84 , effective_capacity : EffectiveCapacity :: Unknown } )
1579
+ . expect_usage ( ChannelUsage { amount_msat : 94 , inflight_htlc_msat : 94 , effective_capacity : EffectiveCapacity :: Unknown } )
1613
1580
// 2nd invoice, 2nd path
1614
1581
. expect_usage ( ChannelUsage { amount_msat : 64 , inflight_htlc_msat : 64 , effective_capacity : EffectiveCapacity :: Unknown } )
1615
1582
. expect_usage ( ChannelUsage { amount_msat : 74 , inflight_htlc_msat : 74 , effective_capacity : EffectiveCapacity :: Unknown } ) ;
@@ -1618,16 +1585,12 @@ mod tests {
1618
1585
let invoice_payer =
1619
1586
InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1620
1587
1621
- // Succeed 1st path, leave 2nd path inflight
1622
- let payment_id = invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ;
1623
- invoice_payer. handle_event ( & Event :: PaymentPathSuccessful {
1624
- payment_id, payment_hash, path : route. paths [ 0 ] . clone ( )
1625
- } ) ;
1588
+ // Make first invoice payment.
1589
+ invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ;
1626
1590
1627
1591
// Let's pay a second invoice that will be using the same path. This should trigger the
1628
- // assertions that expect the last 4 ChannelUsage values above where TestScorer is initialized.
1629
- // Particularly, the 2nd path of the 1st payment, since it is not yet complete, should still
1630
- // have 64 msats inflight for paths considering the channel with scid of 1.
1592
+ // assertions that expect `ChannelUsage` values of the first invoice payment that is still
1593
+ // in-flight.
1631
1594
let payment_preimage_2 = PaymentPreimage ( [ 2 ; 32 ] ) ;
1632
1595
let payment_invoice_2 = invoice ( payment_preimage_2) ;
1633
1596
invoice_payer. pay_invoice ( & payment_invoice_2) . unwrap ( ) ;
@@ -1678,6 +1641,7 @@ mod tests {
1678
1641
1679
1642
// Fail 1st path, leave 2nd path inflight
1680
1643
let payment_id = Some ( invoice_payer. pay_invoice ( & payment_invoice) . unwrap ( ) ) ;
1644
+ invoice_payer. payer . fail_path ( & TestRouter :: path_for_value ( final_value_msat) ) ;
1681
1645
invoice_payer. handle_event ( & Event :: PaymentPathFailed {
1682
1646
payment_id,
1683
1647
payment_hash,
@@ -1690,6 +1654,7 @@ mod tests {
1690
1654
} ) ;
1691
1655
1692
1656
// Fails again the 1st path of our retry
1657
+ invoice_payer. payer . fail_path ( & TestRouter :: path_for_value ( final_value_msat / 2 ) ) ;
1693
1658
invoice_payer. handle_event ( & Event :: PaymentPathFailed {
1694
1659
payment_id,
1695
1660
payment_hash,
@@ -1705,66 +1670,6 @@ mod tests {
1705
1670
} ) ;
1706
1671
}
1707
1672
1708
- #[ test]
1709
- fn accounts_for_some_inflight_htlcs_sent_during_partial_failure ( ) {
1710
- let event_handled = core:: cell:: RefCell :: new ( false ) ;
1711
- let event_handler = |_: & _ | { * event_handled. borrow_mut ( ) = true ; } ;
1712
-
1713
- let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1714
- let invoice_to_pay = invoice ( payment_preimage) ;
1715
- let final_value_msat = invoice_to_pay. amount_milli_satoshis ( ) . unwrap ( ) ;
1716
-
1717
- let retry = TestRouter :: retry_for_invoice ( & invoice_to_pay) ;
1718
- let payer = TestPayer :: new ( )
1719
- . fails_with_partial_failure (
1720
- retry. clone ( ) , OnAttempt ( 1 ) ,
1721
- Some ( vec ! [
1722
- Err ( ChannelUnavailable { err: "abc" . to_string( ) } ) , Err ( MonitorUpdateInProgress )
1723
- ] ) )
1724
- . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1725
-
1726
- let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1727
- let logger = TestLogger :: new ( ) ;
1728
- let invoice_payer =
1729
- InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1730
-
1731
- invoice_payer. pay_invoice ( & invoice_to_pay) . unwrap ( ) ;
1732
- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1733
-
1734
- // Only the second path, which failed with `MonitorUpdateInProgress` should be added to our
1735
- // inflight map because retries are disabled.
1736
- assert_eq ! ( inflight_map. 0 . len( ) , 2 ) ;
1737
- }
1738
-
1739
- #[ test]
1740
- fn accounts_for_all_inflight_htlcs_sent_during_partial_failure ( ) {
1741
- let event_handled = core:: cell:: RefCell :: new ( false ) ;
1742
- let event_handler = |_: & _ | { * event_handled. borrow_mut ( ) = true ; } ;
1743
-
1744
- let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1745
- let invoice_to_pay = invoice ( payment_preimage) ;
1746
- let final_value_msat = invoice_to_pay. amount_milli_satoshis ( ) . unwrap ( ) ;
1747
-
1748
- let retry = TestRouter :: retry_for_invoice ( & invoice_to_pay) ;
1749
- let payer = TestPayer :: new ( )
1750
- . fails_with_partial_failure (
1751
- retry. clone ( ) , OnAttempt ( 1 ) ,
1752
- Some ( vec ! [
1753
- Ok ( ( ) ) , Err ( MonitorUpdateInProgress )
1754
- ] ) )
1755
- . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1756
-
1757
- let router = TestRouter :: new ( TestScorer :: new ( ) ) ;
1758
- let logger = TestLogger :: new ( ) ;
1759
- let invoice_payer =
1760
- InvoicePayer :: new ( & payer, router, & logger, event_handler, Retry :: Attempts ( 0 ) ) ;
1761
-
1762
- invoice_payer. pay_invoice ( & invoice_to_pay) . unwrap ( ) ;
1763
- let inflight_map = invoice_payer. create_inflight_map ( ) ;
1764
-
1765
- // All paths successful, hence we check of the existence of all 5 hops.
1766
- assert_eq ! ( inflight_map. 0 . len( ) , 5 ) ;
1767
- }
1768
1673
1769
1674
struct TestRouter {
1770
1675
scorer : RefCell < TestScorer > ,
@@ -2053,6 +1958,7 @@ mod tests {
2053
1958
expectations : core:: cell:: RefCell < VecDeque < Amount > > ,
2054
1959
attempts : core:: cell:: RefCell < usize > ,
2055
1960
failing_on_attempt : core:: cell:: RefCell < HashMap < usize , PaymentSendFailure > > ,
1961
+ inflight_htlcs_paths : core:: cell:: RefCell < Vec < Vec < RouteHop > > > ,
2056
1962
}
2057
1963
2058
1964
#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -2070,6 +1976,7 @@ mod tests {
2070
1976
expectations : core:: cell:: RefCell :: new ( VecDeque :: new ( ) ) ,
2071
1977
attempts : core:: cell:: RefCell :: new ( 0 ) ,
2072
1978
failing_on_attempt : core:: cell:: RefCell :: new ( HashMap :: new ( ) ) ,
1979
+ inflight_htlcs_paths : core:: cell:: RefCell :: new ( Vec :: new ( ) ) ,
2073
1980
}
2074
1981
}
2075
1982
@@ -2114,6 +2021,18 @@ mod tests {
2114
2021
panic ! ( "Unexpected amount: {:?}" , actual_value_msats) ;
2115
2022
}
2116
2023
}
2024
+
2025
+ fn process_route ( & self , route : & Route ) {
2026
+ for path in & route. paths {
2027
+ self . inflight_htlcs_paths . borrow_mut ( ) . push ( path. clone ( ) ) ;
2028
+ }
2029
+ }
2030
+
2031
+ fn fail_path ( & self , path : & Vec < RouteHop > ) {
2032
+ if let Some ( idx) = self . inflight_htlcs_paths . clone ( ) . into_inner ( ) . iter ( ) . position ( |p| p == path) {
2033
+ self . inflight_htlcs_paths . borrow_mut ( ) . swap_remove ( idx) ;
2034
+ }
2035
+ }
2117
2036
}
2118
2037
2119
2038
impl Drop for TestPayer {
@@ -2143,6 +2062,7 @@ mod tests {
2143
2062
_payment_secret : & Option < PaymentSecret > , _payment_id : PaymentId ,
2144
2063
) -> Result < ( ) , PaymentSendFailure > {
2145
2064
self . check_value_msats ( Amount :: ForInvoice ( route. get_total_amount ( ) ) ) ;
2065
+ self . process_route ( route) ;
2146
2066
self . check_attempts ( )
2147
2067
}
2148
2068
@@ -2157,10 +2077,19 @@ mod tests {
2157
2077
& self , route : & Route , _payment_id : PaymentId
2158
2078
) -> Result < ( ) , PaymentSendFailure > {
2159
2079
self . check_value_msats ( Amount :: OnRetry ( route. get_total_amount ( ) ) ) ;
2080
+ self . process_route ( route) ;
2160
2081
self . check_attempts ( )
2161
2082
}
2162
2083
2163
2084
fn abandon_payment ( & self , _payment_id : PaymentId ) { }
2085
+
2086
+ fn inflight_htlcs ( & self ) -> InFlightHtlcs {
2087
+ let mut inflight_htlcs = InFlightHtlcs :: new ( ) ;
2088
+ for path in self . inflight_htlcs_paths . clone ( ) . into_inner ( ) {
2089
+ inflight_htlcs. process_path ( & path, self . node_id ( ) ) ;
2090
+ }
2091
+ inflight_htlcs
2092
+ }
2164
2093
}
2165
2094
2166
2095
// *** Full Featured Functional Tests with a Real ChannelManager ***
0 commit comments